From 19985dbb8c0aa66dc4bf7905abc1148de909097d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anton=20Luka=20=C5=A0ijanec?= Date: Tue, 11 Jan 2022 12:35:47 +0100 Subject: prvi-commit --- vendor/maxmind/web-service-common/CHANGELOG.md | 91 ++++ vendor/maxmind/web-service-common/LICENSE | 202 +++++++++ vendor/maxmind/web-service-common/README.md | 25 ++ vendor/maxmind/web-service-common/composer.json | 31 ++ .../maxmind/web-service-common/dev-bin/release.sh | 60 +++ .../src/Exception/AuthenticationException.php | 10 + .../src/Exception/HttpException.php | 40 ++ .../src/Exception/InsufficientFundsException.php | 10 + .../src/Exception/InvalidInputException.php | 12 + .../src/Exception/InvalidRequestException.php | 37 ++ .../src/Exception/IpAddressNotFoundException.php | 7 + .../src/Exception/PermissionRequiredException.php | 10 + .../src/Exception/WebServiceException.php | 10 + .../web-service-common/src/WebService/Client.php | 488 +++++++++++++++++++++ .../src/WebService/Http/CurlRequest.php | 136 ++++++ .../src/WebService/Http/Request.php | 29 ++ .../src/WebService/Http/RequestFactory.php | 49 +++ 17 files changed, 1247 insertions(+) create mode 100644 vendor/maxmind/web-service-common/CHANGELOG.md create mode 100644 vendor/maxmind/web-service-common/LICENSE create mode 100644 vendor/maxmind/web-service-common/README.md create mode 100644 vendor/maxmind/web-service-common/composer.json create mode 100644 vendor/maxmind/web-service-common/dev-bin/release.sh create mode 100644 vendor/maxmind/web-service-common/src/Exception/AuthenticationException.php create mode 100644 vendor/maxmind/web-service-common/src/Exception/HttpException.php create mode 100644 vendor/maxmind/web-service-common/src/Exception/InsufficientFundsException.php create mode 100644 vendor/maxmind/web-service-common/src/Exception/InvalidInputException.php create mode 100644 vendor/maxmind/web-service-common/src/Exception/InvalidRequestException.php create mode 100644 vendor/maxmind/web-service-common/src/Exception/IpAddressNotFoundException.php create mode 100644 vendor/maxmind/web-service-common/src/Exception/PermissionRequiredException.php create mode 100644 vendor/maxmind/web-service-common/src/Exception/WebServiceException.php create mode 100644 vendor/maxmind/web-service-common/src/WebService/Client.php create mode 100644 vendor/maxmind/web-service-common/src/WebService/Http/CurlRequest.php create mode 100644 vendor/maxmind/web-service-common/src/WebService/Http/Request.php create mode 100644 vendor/maxmind/web-service-common/src/WebService/Http/RequestFactory.php (limited to 'vendor/maxmind') diff --git a/vendor/maxmind/web-service-common/CHANGELOG.md b/vendor/maxmind/web-service-common/CHANGELOG.md new file mode 100644 index 0000000..6aaa749 --- /dev/null +++ b/vendor/maxmind/web-service-common/CHANGELOG.md @@ -0,0 +1,91 @@ +CHANGELOG +========= + +0.7.0 (2020-05-06) +------------------ + +* Responses with a 204 status code are accepted as successes. + +0.6.0 (2019-12-12) +------------------ + +* Curl handles are now reused across requests. Pull request by Willem + Stuursma-Ruwen. GitHub #24. +* PHP 5.6 is now required. + +0.5.0 (2018-02-12) +------------------ + +* Refer to account IDs using the terminology "account" rather than "user". + +0.4.0 (2017-07-10) +------------------ + +* PHP 5.4 is now required. + +0.3.1 (2016-08-10) +------------------ + +* On Mac OS X when using a curl built against SecureTransport, the certs + in the system's keychain will now be used instead of the CA bundle on + the file system. + +0.3.0 (2016-08-09) +------------------ + +* This package now uses `composer/ca-bundle` by default rather than a CA + bundle distributed with this package. `composer/ca-bundle` will first try + to use the system CA bundle and will fall back to the Mozilla CA bundle + when no system bundle is available. You may still specify your own bundle + using the `caBundle` option. + +0.2.1 (2016-06-13) +------------------ + +* Fix typo in code to copy cert to temp directory. + +0.2.0 (2016-06-10) +------------------ + +* Added handling of additional error codes that the web service may return. +* A `USER_ID_UNKNOWN` error will now throw a + `MaxMind\Exception\AuthenticationException`. +* Added support for `proxy` option. Closes #6. + +0.1.0 (2016-05-23) +------------------ + +* A `PERMISSION_REQUIRED` error will now throw a `PermissionRequiredException` + exception. +* Added a `.gitattributes` file to exclude tests from Composer releases. + GitHub #7. +* Updated included cert bundle. + +0.0.4 (2015-07-21) +------------------ + +* Added extremely basic tests for the curl calls. +* Fixed broken POSTs. + +0.0.3 (2015-06-30) +------------------ + +* Floats now work with the `timeout` and `connectTimeout` options. Fix by + Benjamin Pick. GitHub PR #2. +* `curl_error` is now used instead of `curl_strerror`. The latter is only + available for PHP 5.5 or later. Fix by Benjamin Pick. GitHub PR #1. + + +0.0.2 (2015-06-09) +------------------ + +* An exception is now immediately thrown curl error rather than letting later + status code checks throw an exception. This improves the exception message + greatly. +* If this library is inside a phar archive, the CA certs are copied out of the + archive to a temporary file so that curl can use them. + +0.0.1 (2015-06-01) +------------------ + +* Initial release. diff --git a/vendor/maxmind/web-service-common/LICENSE b/vendor/maxmind/web-service-common/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/vendor/maxmind/web-service-common/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/maxmind/web-service-common/README.md b/vendor/maxmind/web-service-common/README.md new file mode 100644 index 0000000..e3c64d3 --- /dev/null +++ b/vendor/maxmind/web-service-common/README.md @@ -0,0 +1,25 @@ +# Common Code for MaxMind Web Service Clients # + +This is _not_ intended for direct use by third parties. Rather, it is for +shared code between MaxMind's various web service client APIs. + +## Requirements ## + +The library requires PHP 5.6 or greater. + +There are several other dependencies as defined in the `composer.json` file. + +## Contributing ## + +Patches and pull requests are encouraged. All code should follow the PSR-2 +style guidelines. Please include unit tests whenever possible. + +## Versioning ## + +This API uses [Semantic Versioning](http://semver.org/). + +## Copyright and License ## + +This software is Copyright (c) 2015-2020 by MaxMind, Inc. + +This is free software, licensed under the Apache License, Version 2.0. diff --git a/vendor/maxmind/web-service-common/composer.json b/vendor/maxmind/web-service-common/composer.json new file mode 100644 index 0000000..6d1bbe4 --- /dev/null +++ b/vendor/maxmind/web-service-common/composer.json @@ -0,0 +1,31 @@ +{ + "name": "maxmind/web-service-common", + "description": "Internal MaxMind Web Service API", + "minimum-stability": "stable", + "homepage": "https://github.com/maxmind/web-service-common-php", + "type": "library", + "license": "Apache-2.0", + "authors": [ + { + "name": "Gregory Oschwald", + "email": "goschwald@maxmind.com" + } + ], + "require": { + "php": ">=5.6", + "composer/ca-bundle": "^1.0.3", + "ext-curl": "*", + "ext-json": "*" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "2.*", + "phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5 || ^7.0", + "squizlabs/php_codesniffer": "3.*" + }, + "autoload": { + "psr-4": { + "MaxMind\\Exception\\": "src/Exception", + "MaxMind\\WebService\\": "src/WebService" + } + } +} diff --git a/vendor/maxmind/web-service-common/dev-bin/release.sh b/vendor/maxmind/web-service-common/dev-bin/release.sh new file mode 100644 index 0000000..a5de030 --- /dev/null +++ b/vendor/maxmind/web-service-common/dev-bin/release.sh @@ -0,0 +1,60 @@ +#!/bin/bash + +set -eu -o pipefail + + +changelog=$(cat CHANGELOG.md) + +regex=' +([0-9]+\.[0-9]+\.[0-9]+) \(([0-9]{4}-[0-9]{2}-[0-9]{2})\) +-* + +((.| +)*) +' + +if [[ ! $changelog =~ $regex ]]; then + echo "Could not find date line in change log!" + exit 1 +fi + +version="${BASH_REMATCH[1]}" +date="${BASH_REMATCH[2]}" +notes="$(echo "${BASH_REMATCH[3]}" | sed -n -E '/^[0-9]+\.[0-9]+\.[0-9]+/,$!p')" + +if [[ "$date" != $(date +"%Y-%m-%d") ]]; then + echo "$date is not today!" + exit 1 +fi + +tag="v$version" + +if [ -n "$(git status --porcelain)" ]; then + echo ". is not clean." >&2 + exit 1 +fi + +php composer.phar self-update +php composer.phar update + +./vendor/bin/phpunit + +echo "Release notes for $tag:" +echo "$notes" + +read -e -p "Commit changes and push to origin? " should_push + +if [ "$should_push" != "y" ]; then + echo "Aborting" + exit 1 +fi + +git push + +message="$version + +$notes" + +hub release create -m "$message" "$tag" + +git push --tags diff --git a/vendor/maxmind/web-service-common/src/Exception/AuthenticationException.php b/vendor/maxmind/web-service-common/src/Exception/AuthenticationException.php new file mode 100644 index 0000000..54258ca --- /dev/null +++ b/vendor/maxmind/web-service-common/src/Exception/AuthenticationException.php @@ -0,0 +1,10 @@ +uri = $uri; + parent::__construct($message, $httpStatus, $previous); + } + + public function getUri() + { + return $this->uri; + } + + public function getStatusCode() + { + return $this->getCode(); + } +} diff --git a/vendor/maxmind/web-service-common/src/Exception/InsufficientFundsException.php b/vendor/maxmind/web-service-common/src/Exception/InsufficientFundsException.php new file mode 100644 index 0000000..4d6b3be --- /dev/null +++ b/vendor/maxmind/web-service-common/src/Exception/InsufficientFundsException.php @@ -0,0 +1,10 @@ +error = $error; + parent::__construct($message, $httpStatus, $uri, $previous); + } + + public function getErrorCode() + { + return $this->error; + } +} diff --git a/vendor/maxmind/web-service-common/src/Exception/IpAddressNotFoundException.php b/vendor/maxmind/web-service-common/src/Exception/IpAddressNotFoundException.php new file mode 100644 index 0000000..1a743a1 --- /dev/null +++ b/vendor/maxmind/web-service-common/src/Exception/IpAddressNotFoundException.php @@ -0,0 +1,7 @@ +accountId = $accountId; + $this->licenseKey = $licenseKey; + + $this->httpRequestFactory = isset($options['httpRequestFactory']) + ? $options['httpRequestFactory'] + : new RequestFactory(); + + if (isset($options['host'])) { + $this->host = $options['host']; + } + if (isset($options['userAgent'])) { + $this->userAgentPrefix = $options['userAgent'] . ' '; + } + + $this->caBundle = isset($options['caBundle']) ? + $this->caBundle = $options['caBundle'] : $this->getCaBundle(); + + if (isset($options['connectTimeout'])) { + $this->connectTimeout = $options['connectTimeout']; + } + if (isset($options['timeout'])) { + $this->timeout = $options['timeout']; + } + + if (isset($options['proxy'])) { + $this->proxy = $options['proxy']; + } + } + + /** + * @param string $service name of the service querying + * @param string $path the URI path to use + * @param array $input the data to be posted as JSON + * + * @throws InvalidInputException when the request has missing or invalid + * data + * @throws AuthenticationException when there is an issue authenticating the + * request + * @throws InsufficientFundsException when your account is out of funds + * @throws InvalidRequestException when the request is invalid for some + * other reason, e.g., invalid JSON in the POST. + * @throws HttpException when an unexpected HTTP error occurs + * @throws WebServiceException when some other error occurs. This also + * serves as the base class for the above exceptions. + * + * @return array The decoded content of a successful response + */ + public function post($service, $path, $input) + { + $requestBody = json_encode($input); + if ($requestBody === false) { + throw new InvalidInputException( + 'Error encoding input as JSON: ' + . $this->jsonErrorDescription() + ); + } + + $request = $this->createRequest( + $path, + ['Content-Type: application/json'] + ); + + list($statusCode, $contentType, $responseBody) = $request->post($requestBody); + + return $this->handleResponse( + $statusCode, + $contentType, + $responseBody, + $service, + $path + ); + } + + public function get($service, $path) + { + $request = $this->createRequest($path); + + list($statusCode, $contentType, $responseBody) = $request->get(); + + return $this->handleResponse( + $statusCode, + $contentType, + $responseBody, + $service, + $path + ); + } + + private function userAgent() + { + $curlVersion = curl_version(); + + return $this->userAgentPrefix . 'MaxMind-WS-API/' . self::VERSION . ' PHP/' . PHP_VERSION . + ' curl/' . $curlVersion['version']; + } + + private function createRequest($path, $headers = []) + { + array_push( + $headers, + 'Authorization: Basic ' + . base64_encode($this->accountId . ':' . $this->licenseKey), + 'Accept: application/json' + ); + + return $this->httpRequestFactory->request( + $this->urlFor($path), + [ + 'caBundle' => $this->caBundle, + 'connectTimeout' => $this->connectTimeout, + 'headers' => $headers, + 'proxy' => $this->proxy, + 'timeout' => $this->timeout, + 'userAgent' => $this->userAgent(), + ] + ); + } + + /** + * @param int $statusCode the HTTP status code of the response + * @param string $contentType the Content-Type of the response + * @param string $responseBody the response body + * @param string $service the name of the service + * @param string $path the path used in the request + * + * @throws AuthenticationException when there is an issue authenticating the + * request + * @throws InsufficientFundsException when your account is out of funds + * @throws InvalidRequestException when the request is invalid for some + * other reason, e.g., invalid JSON in the POST. + * @throws HttpException when an unexpected HTTP error occurs + * @throws WebServiceException when some other error occurs. This also + * serves as the base class for the above exceptions + * + * @return array The decoded content of a successful response + */ + private function handleResponse( + $statusCode, + $contentType, + $responseBody, + $service, + $path + ) { + if ($statusCode >= 400 && $statusCode <= 499) { + $this->handle4xx($statusCode, $contentType, $responseBody, $service, $path); + } elseif ($statusCode >= 500) { + $this->handle5xx($statusCode, $service, $path); + } elseif ($statusCode !== 200 && $statusCode !== 204) { + $this->handleUnexpectedStatus($statusCode, $service, $path); + } + + return $this->handleSuccess($statusCode, $responseBody, $service); + } + + /** + * @return string describing the JSON error + */ + private function jsonErrorDescription() + { + $errno = json_last_error(); + switch ($errno) { + case JSON_ERROR_DEPTH: + return 'The maximum stack depth has been exceeded.'; + case JSON_ERROR_STATE_MISMATCH: + return 'Invalid or malformed JSON.'; + case JSON_ERROR_CTRL_CHAR: + return 'Control character error.'; + case JSON_ERROR_SYNTAX: + return 'Syntax error.'; + case JSON_ERROR_UTF8: + return 'Malformed UTF-8 characters.'; + default: + return "Other JSON error ($errno)."; + } + } + + /** + * @param string $path the path to use in the URL + * + * @return string the constructed URL + */ + private function urlFor($path) + { + return 'https://' . $this->host . $path; + } + + /** + * @param int $statusCode the HTTP status code + * @param string $contentType the response content-type + * @param string $body the response body + * @param string $service the service name + * @param string $path the path used in the request + * + * @throws AuthenticationException + * @throws HttpException + * @throws InsufficientFundsException + * @throws InvalidRequestException + */ + private function handle4xx( + $statusCode, + $contentType, + $body, + $service, + $path + ) { + if (\strlen($body) === 0) { + throw new HttpException( + "Received a $statusCode error for $service with no body", + $statusCode, + $this->urlFor($path) + ); + } + if (!strstr($contentType, 'json')) { + throw new HttpException( + "Received a $statusCode error for $service with " . + 'the following body: ' . $body, + $statusCode, + $this->urlFor($path) + ); + } + + $message = json_decode($body, true); + if ($message === null) { + throw new HttpException( + "Received a $statusCode error for $service but could " . + 'not decode the response as JSON: ' + . $this->jsonErrorDescription() . ' Body: ' . $body, + $statusCode, + $this->urlFor($path) + ); + } + + if (!isset($message['code']) || !isset($message['error'])) { + throw new HttpException( + 'Error response contains JSON but it does not ' . + 'specify code or error keys: ' . $body, + $statusCode, + $this->urlFor($path) + ); + } + + $this->handleWebServiceError( + $message['error'], + $message['code'], + $statusCode, + $path + ); + } + + /** + * @param string $message the error message from the web service + * @param string $code the error code from the web service + * @param int $statusCode the HTTP status code + * @param string $path the path used in the request + * + * @throws AuthenticationException + * @throws InvalidRequestException + * @throws InsufficientFundsException + */ + private function handleWebServiceError( + $message, + $code, + $statusCode, + $path + ) { + switch ($code) { + case 'IP_ADDRESS_NOT_FOUND': + case 'IP_ADDRESS_RESERVED': + throw new IpAddressNotFoundException( + $message, + $code, + $statusCode, + $this->urlFor($path) + ); + case 'ACCOUNT_ID_REQUIRED': + case 'ACCOUNT_ID_UNKNOWN': + case 'AUTHORIZATION_INVALID': + case 'LICENSE_KEY_REQUIRED': + case 'USER_ID_REQUIRED': + case 'USER_ID_UNKNOWN': + throw new AuthenticationException( + $message, + $code, + $statusCode, + $this->urlFor($path) + ); + case 'OUT_OF_QUERIES': + case 'INSUFFICIENT_FUNDS': + throw new InsufficientFundsException( + $message, + $code, + $statusCode, + $this->urlFor($path) + ); + case 'PERMISSION_REQUIRED': + throw new PermissionRequiredException( + $message, + $code, + $statusCode, + $this->urlFor($path) + ); + default: + throw new InvalidRequestException( + $message, + $code, + $statusCode, + $this->urlFor($path) + ); + } + } + + /** + * @param int $statusCode the HTTP status code + * @param string $service the service name + * @param string $path the URI path used in the request + * + * @throws HttpException + */ + private function handle5xx($statusCode, $service, $path) + { + throw new HttpException( + "Received a server error ($statusCode) for $service", + $statusCode, + $this->urlFor($path) + ); + } + + /** + * @param int $statusCode the HTTP status code + * @param string $service the service name + * @param string $path the URI path used in the request + * + * @throws HttpException + */ + private function handleUnexpectedStatus($statusCode, $service, $path) + { + throw new HttpException( + 'Received an unexpected HTTP status ' . + "($statusCode) for $service", + $statusCode, + $this->urlFor($path) + ); + } + + /** + * @param int $statusCode the HTTP status code + * @param string $body the successful request body + * @param string $service the service name + * + * @throws WebServiceException if a response body is included but not + * expected, or is not expected but not + * included, or is expected and included + * but cannot be decoded as JSON + * + * @return array the decoded request body + */ + private function handleSuccess($statusCode, $body, $service) + { + // A 204 should have no response body + if ($statusCode === 204) { + if (\strlen($body) !== 0) { + throw new WebServiceException( + "Received a 204 response for $service along with an " . + "unexpected HTTP body: $body" + ); + } + + return null; + } + + // A 200 should have a valid JSON body + if (\strlen($body) === 0) { + throw new WebServiceException( + "Received a 200 response for $service but did not " . + 'receive a HTTP body.' + ); + } + + $decodedContent = json_decode($body, true); + if ($decodedContent === null) { + throw new WebServiceException( + "Received a 200 response for $service but could " . + 'not decode the response as JSON: ' + . $this->jsonErrorDescription() . ' Body: ' . $body + ); + } + + return $decodedContent; + } + + private function getCaBundle() + { + $curlVersion = curl_version(); + + // On OS X, when the SSL version is "SecureTransport", the system's + // keychain will be used. + if ($curlVersion['ssl_version'] === 'SecureTransport') { + return null; + } + $cert = CaBundle::getSystemCaRootBundlePath(); + + // Check if the cert is inside a phar. If so, we need to copy the cert + // to a temp file so that curl can see it. + if (substr($cert, 0, 7) === 'phar://') { + $tempDir = sys_get_temp_dir(); + $newCert = tempnam($tempDir, 'geoip2-'); + if ($newCert === false) { + throw new \RuntimeException( + "Unable to create temporary file in $tempDir" + ); + } + if (!copy($cert, $newCert)) { + throw new \RuntimeException( + "Could not copy $cert to $newCert: " + . var_export(error_get_last(), true) + ); + } + + // We use a shutdown function rather than the destructor as the + // destructor isn't called on a fatal error such as an uncaught + // exception. + register_shutdown_function( + function () use ($newCert) { + unlink($newCert); + } + ); + $cert = $newCert; + } + if (!file_exists($cert)) { + throw new \RuntimeException("CA cert does not exist at $cert"); + } + + return $cert; + } +} diff --git a/vendor/maxmind/web-service-common/src/WebService/Http/CurlRequest.php b/vendor/maxmind/web-service-common/src/WebService/Http/CurlRequest.php new file mode 100644 index 0000000..501b2af --- /dev/null +++ b/vendor/maxmind/web-service-common/src/WebService/Http/CurlRequest.php @@ -0,0 +1,136 @@ +url = $url; + $this->options = $options; + $this->ch = $options['curlHandle']; + } + + /** + * @param string $body + * + * @throws HttpException + * + * @return array + */ + public function post($body) + { + $curl = $this->createCurl(); + + curl_setopt($curl, CURLOPT_POST, true); + curl_setopt($curl, CURLOPT_POSTFIELDS, $body); + + return $this->execute($curl); + } + + public function get() + { + $curl = $this->createCurl(); + + curl_setopt($curl, CURLOPT_HTTPGET, true); + + return $this->execute($curl); + } + + /** + * @return resource + */ + private function createCurl() + { + curl_reset($this->ch); + + $opts = []; + $opts[CURLOPT_URL] = $this->url; + + if (!empty($this->options['caBundle'])) { + $opts[CURLOPT_CAINFO] = $this->options['caBundle']; + } + + $opts[CURLOPT_ENCODING] = ''; + $opts[CURLOPT_SSL_VERIFYHOST] = 2; + $opts[CURLOPT_FOLLOWLOCATION] = false; + $opts[CURLOPT_SSL_VERIFYPEER] = true; + $opts[CURLOPT_RETURNTRANSFER] = true; + + $opts[CURLOPT_HTTPHEADER] = $this->options['headers']; + $opts[CURLOPT_USERAGENT] = $this->options['userAgent']; + $opts[CURLOPT_PROXY] = $this->options['proxy']; + + // The defined()s are here as the *_MS opts are not available on older + // cURL versions + $connectTimeout = $this->options['connectTimeout']; + if (\defined('CURLOPT_CONNECTTIMEOUT_MS')) { + $opts[CURLOPT_CONNECTTIMEOUT_MS] = ceil($connectTimeout * 1000); + } else { + $opts[CURLOPT_CONNECTTIMEOUT] = ceil($connectTimeout); + } + + $timeout = $this->options['timeout']; + if (\defined('CURLOPT_TIMEOUT_MS')) { + $opts[CURLOPT_TIMEOUT_MS] = ceil($timeout * 1000); + } else { + $opts[CURLOPT_TIMEOUT] = ceil($timeout); + } + + curl_setopt_array($this->ch, $opts); + + return $this->ch; + } + + /** + * @param resource $curl + * + * @throws HttpException + * + * @return array + */ + private function execute($curl) + { + $body = curl_exec($curl); + if ($errno = curl_errno($curl)) { + $errorMessage = curl_error($curl); + + throw new HttpException( + "cURL error ({$errno}): {$errorMessage}", + 0, + $this->url + ); + } + + $statusCode = curl_getinfo($curl, CURLINFO_HTTP_CODE); + $contentType = curl_getinfo($curl, CURLINFO_CONTENT_TYPE); + + return [$statusCode, $contentType, $body]; + } +} diff --git a/vendor/maxmind/web-service-common/src/WebService/Http/Request.php b/vendor/maxmind/web-service-common/src/WebService/Http/Request.php new file mode 100644 index 0000000..283e05c --- /dev/null +++ b/vendor/maxmind/web-service-common/src/WebService/Http/Request.php @@ -0,0 +1,29 @@ +ch)) { + curl_close($this->ch); + } + } + + private function getCurlHandle() + { + if (empty($this->ch)) { + $this->ch = curl_init(); + } + + return $this->ch; + } + + /** + * @param string $url + * @param array $options + * + * @return Request + */ + public function request($url, $options) + { + $options['curlHandle'] = $this->getCurlHandle(); + + return new CurlRequest($url, $options); + } +} -- cgit v1.2.3