From 6513e26a74389a5a8e23f30ece6da7c3e52d17c4 Mon Sep 17 00:00:00 2001 From: Dmitrii Romanov Date: Wed, 18 Jan 2017 23:10:36 +0300 Subject: [PATCH] Removed dependency on cURL --- composer.json | 4 +- src/core/DeCaptchaAbstract.php | 88 ++++++++++++++++------------------ src/core/DeCaptchaBase.php | 1 + src/core/DeCaptchaErrors.php | 5 -- 4 files changed, 45 insertions(+), 53 deletions(-) diff --git a/composer.json b/composer.json index 4abf96e..3904bcc 100644 --- a/composer.json +++ b/composer.json @@ -12,8 +12,8 @@ "minimum-stability": "stable", "require": { "php": ">=5.6.0", - "ext-curl": "*", - "ext-json": "*" + "ext-json": "*", + "guzzlehttp/guzzle": "^6.5" }, "require-dev": { "phpunit/phpunit": "^4.8.30" diff --git a/src/core/DeCaptchaAbstract.php b/src/core/DeCaptchaAbstract.php index a61709b..c9a5961 100644 --- a/src/core/DeCaptchaAbstract.php +++ b/src/core/DeCaptchaAbstract.php @@ -3,6 +3,7 @@ namespace jumper423\decaptcha\core; use Exception; +use GuzzleHttp\Client; /** * Class DeCaptchaAbstract. @@ -17,8 +18,8 @@ abstract class DeCaptchaAbstract implements DeCaptchaInterface const ACTION_METHOD = 3; const ACTION_JSON = 4; - const ACTION_METHOD_POST = 1; - const ACTION_METHOD_GET = 2; + const ACTION_METHOD_POST = 'post'; + const ACTION_METHOD_GET = 'get'; const DECODE_FORMAT = 1; const DECODE_ACTION = 2; @@ -71,6 +72,23 @@ abstract class DeCaptchaAbstract implements DeCaptchaInterface protected $actions = []; protected $paramsNames = []; + /** + * @var Client + */ + protected $client = null; + + public function __construct() + { + $this->client = new Client([ + 'timeout' => 30, + 'connect_timeout' => 30, + 'headers' => [ + 'Accept-Encoding' => 'gzip,deflate', + 'User-Agent' => 'DeCaptcha', + ], + ]); + } + protected function resetLimits() { foreach ($this->limitSettings as $action => $value) { @@ -219,7 +237,7 @@ public function setParam($param, $value) * @param $spec * @param $coding * - * @return \CURLFile|mixed|null|string + * @return mixed|null|string */ public function getParamSpec($param, $spec = null, $coding = null) { @@ -239,7 +257,7 @@ public function getParamSpec($param, $spec = null, $coding = null) return base64_encode(file_get_contents($this->params[$param])); } - return (version_compare(PHP_VERSION, '5.5.0') >= 0) ? new \CURLFile($this->getFilePath($this->params[$param])) : '@'.$this->getFilePath($this->params[$param]); + return '@'.$this->getFilePath($this->params[$param]); case static::PARAM_SPEC_API_KEY: return is_callable($this->params[$param]) ? $this->params[$param]() : $this->params[$param]; case static::PARAM_SPEC_CAPTCHA: @@ -321,10 +339,10 @@ protected function getParams($action, $field = null) */ protected function getResponse($action) { - return $this->curlResponse( + return $this->sendRequest( + $this->actions[$action][static::ACTION_METHOD], $this->getActionUrl($action), $this->getParams($action), - array_key_exists(static::ACTION_METHOD, $this->actions[$action]) && $this->actions[$action][static::ACTION_METHOD] === static::ACTION_METHOD_POST, array_key_exists(static::ACTION_JSON, $this->actions[$action]) && $this->actions[$action][static::ACTION_JSON] === true ); } @@ -350,53 +368,31 @@ protected function executionDelayed($delay = 0, $callback = null) } /** - * @param string $url - * @param array $data - * @param bool $isPost - * @param bool $isJson + * @param string $method Request method + * @param string $url Request URL + * @param array|string $data Request payload + * @param bool $isJson Whether request payload should be serialized as JSON * - * @throws DeCaptchaErrors + * @throws \InvalidArgumentException Invalid arguments combination * * @return string */ - protected function curlResponse($url, $data, $isPost = true, $isJson = false) + protected function sendRequest($method, $url, $data, $isJson = false) { - $curl = curl_init(); - if ($isJson) { - $data = json_encode($data); - } elseif (!$isPost) { - $uri = []; - foreach ($data as $key => $value) { - $uri[] = "$key=$value"; - } - $url .= '?'.implode('&', $uri); + if ($method === static::ACTION_METHOD_GET && $isJson) { + throw new \InvalidArgumentException('JSON encoding with GET requests is not supported.'); } - curl_setopt($curl, CURLOPT_URL, $url); - if (!$isJson && version_compare(PHP_VERSION, '5.5.0') >= 0 && version_compare(PHP_VERSION, '7.0') < 0 && defined('CURLOPT_SAFE_UPLOAD')) { - curl_setopt($curl, CURLOPT_SAFE_UPLOAD, false); - } - curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); - curl_setopt($curl, CURLOPT_ENCODING, 'gzip,deflate'); - curl_setopt($curl, CURLOPT_TIMEOUT, 30); - curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 30); - curl_setopt($curl, CURLOPT_POST, $isPost); - if ($isPost) { - curl_setopt($curl, CURLOPT_POSTFIELDS, $data); - } - if ($isJson) { - curl_setopt($curl, CURLOPT_HTTPHEADER, [ - 'Content-Type: application/json; charset=utf-8', - 'Accept: application/json', - 'Content-Length: '.strlen($data), - ]); - } - $result = curl_exec($curl); - if (curl_errno($curl)) { - throw new DeCaptchaErrors(DeCaptchaErrors::ERROR_CURL, curl_error($curl), $this->errorLang); - } - curl_close($curl); - return $result; + $options = []; + + $encType = $isJson ? 'json' : 'query'; + $options[$encType] = $data; + + $response = $this->client->request($method, $url, $options); + + $body = $response->getBody(); + + return (string) $body; } abstract public function getCode(); diff --git a/src/core/DeCaptchaBase.php b/src/core/DeCaptchaBase.php index 75a2a77..51c63df 100644 --- a/src/core/DeCaptchaBase.php +++ b/src/core/DeCaptchaBase.php @@ -107,6 +107,7 @@ class DeCaptchaBase extends DeCaptchaAbstract implements DeCaptchaInterface */ public function __construct($params) { + parent::__construct(); $this->setParams($params); $this->wiki = new DeCaptchaWiki($this); $this->init(); diff --git a/src/core/DeCaptchaErrors.php b/src/core/DeCaptchaErrors.php index 641d6bc..e197dcd 100644 --- a/src/core/DeCaptchaErrors.php +++ b/src/core/DeCaptchaErrors.php @@ -30,7 +30,6 @@ class DeCaptchaErrors extends Exception const ERROR_WRITE_ACCESS_FILE = 14; const ERROR_FILE_IS_NOT_LOADED = 15; const ERROR_FILE_NOT_FOUND = 16; - const ERROR_CURL = 17; const ERROR_PARAM_REQUIRE = 18; const ERROR_CAPTCHAIMAGE_BLOCKED = 19; const IP_BANNED = 20; @@ -144,10 +143,6 @@ class DeCaptchaErrors extends Exception self::LANG_RU => 'Файл не найден', self::LANG_EN => 'File not found', ], - self::ERROR_CURL => [ - self::LANG_RU => 'Ошибка CURL', - self::LANG_EN => 'Error CURL', - ], self::ERROR_PARAM_REQUIRE => [ self::LANG_RU => 'Обязательное поле не заполнено', self::LANG_EN => 'Required field is not filled',