8889841cPK[yHttpClient/Options.phpnu[options = $options; } /** * Get API version. * * @return string */ public function getVersion() { return isset($this->options['version']) ? $this->options['version'] : self::VERSION; } /** * Check if need to verify SSL. * * @return bool */ public function verifySsl() { return isset($this->options['verify_ssl']) ? (bool) $this->options['verify_ssl'] : true; } /** * Only use OAuth. * * @return bool */ public function isOAuthOnly() { return isset($this->options['oauth_only']) ? (bool) $this->options['oauth_only'] : false; } /** * Get timeout. * * @return int */ public function getTimeout() { return isset($this->options['timeout']) ? (int) $this->options['timeout'] : self::TIMEOUT; } /** * Basic Authentication as query string. * Some old servers are not able to use CURLOPT_USERPWD. * * @return bool */ public function isQueryStringAuth() { return isset($this->options['query_string_auth']) ? (bool) $this->options['query_string_auth'] : false; } /** * Check if is WP REST API. * * @return bool */ public function isWPAPI() { return isset($this->options['wp_api']) ? (bool) $this->options['wp_api'] : true; } /** * Custom API Prefix for WP API. * * @return string */ public function apiPrefix() { return isset($this->options['wp_api_prefix']) ? $this->options['wp_api_prefix'] : self::WP_API_PREFIX; } /** * oAuth timestamp. * * @return string */ public function oauthTimestamp() { return isset($this->options['oauth_timestamp']) ? $this->options['oauth_timestamp'] : \time(); } /** * Custom user agent. * * @return string */ public function userAgent() { return isset($this->options['user_agent']) ? $this->options['user_agent'] : self::USER_AGENT; } /** * Get follow redirects. * * @return bool */ public function getFollowRedirects() { return isset($this->options['follow_redirects']) ? (bool) $this->options['follow_redirects'] : false; } /** * Check is it needed to mask all non-GET/POST methods (PUT/DELETE/etc.) by using POST method with added * query parameter ?_method=METHOD into URL. * * @return bool */ public function isMethodOverrideQuery() { return isset($this->options['method_override_query']) && $this->options['method_override_query']; } /** * Check is it needed to mask all non-GET/POST methods (PUT/DELETE/etc.) by using POST method with added * "X-HTTP-Method-Override: METHOD" HTTP header into request. * * @return bool */ public function isMethodOverrideHeader() { return isset($this->options['method_override_header']) && $this->options['method_override_header']; } } PK[ aGGHttpClient/Response.phpnu[code = $code; $this->headers = $headers; $this->body = $body; } /** * To string. * * @return string */ public function __toString() { return \json_encode([ 'code' => $this->code, 'headers' => $this->headers, 'body' => $this->body, ]); } /** * Set code. * * @param int $code Response code. */ public function setCode($code) { $this->code = (int) $code; } /** * Set headers. * * @param array $headers Response headers. */ public function setHeaders($headers) { $this->headers = $headers; } /** * Set body. * * @param string $body Response body. */ public function setBody($body) { $this->body = $body; } /** * Get code. * * @return int */ public function getCode() { return $this->code; } /** * Get headers. * * @return array $headers Response headers. */ public function getHeaders() { return $this->headers; } /** * Get body. * * @return string $body Response body. */ public function getBody() { return $this->body; } } PK[%-V2V2HttpClient/HttpClient.phpnu[options = new Options($options); $this->url = $this->buildApiUrl($url); $this->consumerKey = $consumerKey; $this->consumerSecret = $consumerSecret; } /** * Check if is under SSL. * * @return bool */ protected function isSsl() { return 'https://' === \substr($this->url, 0, 8); } /** * Build API URL. * * @param string $url Store URL. * * @return string */ protected function buildApiUrl($url) { $api = $this->options->isWPAPI() ? $this->options->apiPrefix() : '/wc-api/'; return \rtrim($url, '/') . $api . $this->options->getVersion() . '/'; } /** * Build URL. * * @param string $url URL. * @param array $parameters Query string parameters. * * @return string */ protected function buildUrlQuery($url, $parameters = []) { if (!empty($parameters)) { if (false !== strpos($url, '?')) { $url .= '&' . \http_build_query($parameters); } else { $url .= '?' . \http_build_query($parameters); } } return $url; } /** * Authenticate. * * @param string $url Request URL. * @param string $method Request method. * @param array $parameters Request parameters. * * @return array */ protected function authenticate($url, $method, $parameters = []) { // Setup authentication. if (!$this->options->isOAuthOnly() && $this->isSsl()) { $basicAuth = new BasicAuth( $this->ch, $this->consumerKey, $this->consumerSecret, $this->options->isQueryStringAuth(), $parameters ); $parameters = $basicAuth->getParameters(); } else { $oAuth = new OAuth( $url, $this->consumerKey, $this->consumerSecret, $this->options->getVersion(), $method, $parameters, $this->options->oauthTimestamp() ); $parameters = $oAuth->getParameters(); } return $parameters; } /** * Setup method. * * @param string $method Request method. */ protected function setupMethod($method) { if ('POST' == $method) { \curl_setopt($this->ch, CURLOPT_POST, true); } elseif (\in_array($method, ['PUT', 'DELETE', 'OPTIONS'])) { \curl_setopt($this->ch, CURLOPT_CUSTOMREQUEST, $method); } } /** * Get request headers. * * @param bool $sendData If request send data or not. * * @return array */ protected function getRequestHeaders($sendData = false) { $headers = [ 'Accept' => 'application/json', 'User-Agent' => $this->options->userAgent() . '/' . Client::VERSION, ]; if ($sendData) { $headers['Content-Type'] = 'application/json;charset=utf-8'; } return $headers; } /** * Create request. * * @param string $endpoint Request endpoint. * @param string $method Request method. * @param array $data Request data. * @param array $parameters Request parameters. * * @return Request */ protected function createRequest($endpoint, $method, $data = [], $parameters = []) { $body = ''; $url = $this->url . $endpoint; $hasData = !empty($data); $headers = $this->getRequestHeaders($hasData); // HTTP method override feature which masks PUT and DELETE HTTP methods as POST method with added // ?_method=PUT query parameter and/or X-HTTP-Method-Override HTTP header. if (!in_array($method, ['GET', 'POST'])) { $usePostMethod = false; if ($this->options->isMethodOverrideQuery()) { $parameters = array_merge(['_method' => $method], $parameters); $usePostMethod = true; } if ($this->options->isMethodOverrideHeader()) { $headers['X-HTTP-Method-Override'] = $method; $usePostMethod = true; } if ($usePostMethod) { $method = 'POST'; } } // Setup authentication. $parameters = $this->authenticate($url, $method, $parameters); // Setup method. $this->setupMethod($method); // Include post fields. if ($hasData) { $body = \json_encode($data); \curl_setopt($this->ch, CURLOPT_POSTFIELDS, $body); } $this->request = new Request( $this->buildUrlQuery($url, $parameters), $method, $parameters, $headers, $body ); return $this->getRequest(); } /** * Get response headers. * * @return array */ protected function getResponseHeaders() { $headers = []; $lines = \explode("\n", $this->responseHeaders); $lines = \array_filter($lines, 'trim'); foreach ($lines as $index => $line) { // Remove HTTP/xxx params. if (strpos($line, ': ') === false) { continue; } list($key, $value) = \explode(': ', $line); $headers[$key] = isset($headers[$key]) ? $headers[$key] . ', ' . trim($value) : trim($value); } return $headers; } /** * Create response. * * @return Response */ protected function createResponse() { // Set response headers. $this->responseHeaders = ''; \curl_setopt($this->ch, CURLOPT_HEADERFUNCTION, function ($_, $headers) { $this->responseHeaders .= $headers; return \strlen($headers); }); // Get response data. $body = \curl_exec($this->ch); $code = \curl_getinfo($this->ch, CURLINFO_HTTP_CODE); $headers = $this->getResponseHeaders(); // Register response. $this->response = new Response($code, $headers, $body); return $this->getResponse(); } /** * Set default cURL settings. */ protected function setDefaultCurlSettings() { $verifySsl = $this->options->verifySsl(); $timeout = $this->options->getTimeout(); $followRedirects = $this->options->getFollowRedirects(); \curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, $verifySsl); if (!$verifySsl) { \curl_setopt($this->ch, CURLOPT_SSL_VERIFYHOST, $verifySsl); } if ($followRedirects) { \curl_setopt($this->ch, CURLOPT_FOLLOWLOCATION, true); } \curl_setopt($this->ch, CURLOPT_CONNECTTIMEOUT, $timeout); \curl_setopt($this->ch, CURLOPT_TIMEOUT, $timeout); \curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true); \curl_setopt($this->ch, CURLOPT_HTTPHEADER, $this->request->getRawHeaders()); \curl_setopt($this->ch, CURLOPT_URL, $this->request->getUrl()); foreach ($this->customCurlOptions as $customCurlOptionKey => $customCurlOptionValue) { \curl_setopt($this->ch, $customCurlOptionKey, $customCurlOptionValue); } } /** * Look for errors in the request. * * @param array $parsedResponse Parsed body response. */ protected function lookForErrors($parsedResponse) { // Any non-200/201/202 response code indicates an error. if (!\in_array($this->response->getCode(), ['200', '201', '202'])) { $errors = isset($parsedResponse->errors) ? $parsedResponse->errors : $parsedResponse; $errorMessage = ''; $errorCode = ''; if (is_array($errors)) { $errorMessage = $errors[0]->message; $errorCode = $errors[0]->code; } elseif (isset($errors->message, $errors->code)) { $errorMessage = $errors->message; $errorCode = $errors->code; } throw new HttpClientException( \sprintf('Error: %s [%s]', $errorMessage, $errorCode), $this->response->getCode(), $this->request, $this->response ); } } /** * Process response. * * @return \stdClass */ protected function processResponse() { $body = $this->response->getBody(); // Look for UTF-8 BOM and remove. if (0 === strpos(bin2hex(substr($body, 0, 4)), 'efbbbf')) { $body = substr($body, 3); } $parsedResponse = \json_decode($body); // Test if return a valid JSON. if (JSON_ERROR_NONE !== json_last_error()) { $message = function_exists('json_last_error_msg') ? json_last_error_msg() : 'Invalid JSON returned'; throw new HttpClientException( sprintf('JSON ERROR: %s', $message), $this->response->getCode(), $this->request, $this->response ); } $this->lookForErrors($parsedResponse); return $parsedResponse; } /** * Make requests. * * @param string $endpoint Request endpoint. * @param string $method Request method. * @param array $data Request data. * @param array $parameters Request parameters. * * @return \stdClass */ public function request($endpoint, $method, $data = [], $parameters = []) { // Initialize cURL. $this->ch = \curl_init(); // Set request args. $request = $this->createRequest($endpoint, $method, $data, $parameters); // Default cURL settings. $this->setDefaultCurlSettings(); // Get response. $response = $this->createResponse(); // Check for cURL errors. if (\curl_errno($this->ch)) { throw new HttpClientException('cURL Error: ' . \curl_error($this->ch), 0, $request, $response); } \curl_close($this->ch); return $this->processResponse(); } /** * Get request data. * * @return Request */ public function getRequest() { return $this->request; } /** * Get response data. * * @return Response */ public function getResponse() { return $this->response; } /** * Set custom cURL options to use in requests. * * @param array $curlOptions */ public function setCustomCurlOptions(array $curlOptions) { $this->customCurlOptions = $curlOptions; } } PK[B#N11"HttpClient/HttpClientException.phpnu[request = $request; $this->response = $response; } /** * Get request data. * * @return Request */ public function getRequest() { return $this->request; } /** * Get response data. * * @return Response */ public function getResponse() { return $this->response; } } PK[O;yHttpClient/OAuth.phpnu[url = $url; $this->consumerKey = $consumerKey; $this->consumerSecret = $consumerSecret; $this->apiVersion = $apiVersion; $this->method = $method; $this->parameters = $parameters; $this->timestamp = $timestamp; } /** * Encode according to RFC 3986. * * @param string|array $value Value to be normalized. * * @return string */ protected function encode($value) { if (is_array($value)) { return array_map([$this, 'encode'], $value); } else { return str_replace(['+', '%7E'], [' ', '~'], rawurlencode($value)); } } /** * Normalize parameters. * * @param array $parameters Parameters to normalize. * * @return array */ protected function normalizeParameters($parameters) { $normalized = []; foreach ($parameters as $key => $value) { // Percent symbols (%) must be double-encoded. $key = $this->encode($key); $value = $this->encode($value); $normalized[$key] = $value; } return $normalized; } /** * Process filters. * * @param array $parameters Request parameters. * * @return array */ protected function processFilters($parameters) { if (isset($parameters['filter'])) { $filters = $parameters['filter']; unset($parameters['filter']); foreach ($filters as $filter => $value) { $parameters['filter[' . $filter . ']'] = $value; } } return $parameters; } /** * Get secret. * * @return string */ protected function getSecret() { $secret = $this->consumerSecret; // Fix secret for v3 or later. if (!\in_array($this->apiVersion, ['v1', 'v2'])) { $secret .= '&'; } return $secret; } /** * Generate oAuth1.0 signature. * * @param array $parameters Request parameters including oauth. * * @return string */ protected function generateOauthSignature($parameters) { $baseRequestUri = \rawurlencode($this->url); // Extract filters. $parameters = $this->processFilters($parameters); // Normalize parameter key/values and sort them. $parameters = $this->normalizeParameters($parameters); $parameters = $this->getSortedParameters($parameters); // Set query string. $queryString = \implode('%26', $this->joinWithEqualsSign($parameters)); // Join with ampersand. $stringToSign = $this->method . '&' . $baseRequestUri . '&' . $queryString; $secret = $this->getSecret(); return \base64_encode(\hash_hmac(self::HASH_ALGORITHM, $stringToSign, $secret, true)); } /** * Creates an array of urlencoded strings out of each array key/value pairs. * * @param array $params Array of parameters to convert. * @param array $queryParams Array to extend. * @param string $key Optional Array key to append * @return string Array of urlencoded strings */ protected function joinWithEqualsSign($params, $queryParams = [], $key = '') { foreach ($params as $paramKey => $paramValue) { if ($key) { $paramKey = $key . '%5B' . $paramKey . '%5D'; // Handle multi-dimensional array. } if (is_array($paramValue)) { $queryParams = $this->joinWithEqualsSign($paramValue, $queryParams, $paramKey); } else { $string = $paramKey . '=' . $paramValue; // Join with equals sign. $queryParams[] = $this->encode($string); } } return $queryParams; } /** * Sort parameters. * * @param array $parameters Parameters to sort in byte-order. * * @return array */ protected function getSortedParameters($parameters) { \uksort($parameters, 'strcmp'); foreach ($parameters as $key => $value) { if (\is_array($value)) { \uksort($parameters[$key], 'strcmp'); } } return $parameters; } /** * Get oAuth1.0 parameters. * * @return string */ public function getParameters() { $parameters = \array_merge($this->parameters, [ 'oauth_consumer_key' => $this->consumerKey, 'oauth_timestamp' => $this->timestamp, 'oauth_nonce' => \sha1(\microtime()), 'oauth_signature_method' => 'HMAC-' . self::HASH_ALGORITHM, ]); // The parameters above must be included in the signature generation. $parameters['oauth_signature'] = $this->generateOauthSignature($parameters); return $this->getSortedParameters($parameters); } } PK[NtHttpClient/BasicAuth.phpnu[ch = $ch; $this->consumerKey = $consumerKey; $this->consumerSecret = $consumerSecret; $this->doQueryString = $doQueryString; $this->parameters = $parameters; $this->processAuth(); } /** * Process auth. */ protected function processAuth() { if ($this->doQueryString) { $this->parameters['consumer_key'] = $this->consumerKey; $this->parameters['consumer_secret'] = $this->consumerSecret; } else { \curl_setopt($this->ch, CURLOPT_USERPWD, $this->consumerKey . ':' . $this->consumerSecret); } } /** * Get parameters. * * @return array */ public function getParameters() { return $this->parameters; } } PK[8> > HttpClient/Request.phpnu[url = $url; $this->method = $method; $this->parameters = $parameters; $this->headers = $headers; $this->body = $body; } /** * Set url. * * @param string $url Request url. */ public function setUrl($url) { $this->url = $url; } /** * Set method. * * @param string $method Request method. */ public function setMethod($method) { $this->method = $method; } /** * Set parameters. * * @param array $parameters Request paramenters. */ public function setParameters($parameters) { $this->parameters = $parameters; } /** * Set headers. * * @param array $headers Request headers. */ public function setHeaders($headers) { $this->headers = $headers; } /** * Set body. * * @param string $body Request body. */ public function setBody($body) { $this->body = $body; } /** * Get url. * * @return string */ public function getUrl() { return $this->url; } /** * Get method. * * @return string */ public function getMethod() { return $this->method; } /** * Get parameters. * * @return array */ public function getParameters() { return $this->parameters; } /** * Get headers. * * @return array */ public function getHeaders() { return $this->headers; } /** * Get raw headers. * * @return array */ public function getRawHeaders() { $headers = []; foreach ($this->headers as $key => $value) { $headers[] = $key . ': ' . $value; } return $headers; } /** * Get body. * * @return string */ public function getBody() { return $this->body; } } PK[#UO O Client.phpnu[http = new HttpClient($url, $consumerKey, $consumerSecret, $options); } /** * POST method. * * @param string $endpoint API endpoint. * @param array $data Request data. * * @return \stdClass */ public function post($endpoint, $data) { return $this->http->request($endpoint, 'POST', $data); } /** * PUT method. * * @param string $endpoint API endpoint. * @param array $data Request data. * * @return \stdClass */ public function put($endpoint, $data) { return $this->http->request($endpoint, 'PUT', $data); } /** * GET method. * * @param string $endpoint API endpoint. * @param array $parameters Request parameters. * * @return \stdClass */ public function get($endpoint, $parameters = []) { return $this->http->request($endpoint, 'GET', [], $parameters); } /** * DELETE method. * * @param string $endpoint API endpoint. * @param array $parameters Request parameters. * * @return \stdClass */ public function delete($endpoint, $parameters = []) { return $this->http->request($endpoint, 'DELETE', [], $parameters); } /** * OPTIONS method. * * @param string $endpoint API endpoint. * * @return \stdClass */ public function options($endpoint) { return $this->http->request($endpoint, 'OPTIONS', [], []); } } PK[yHttpClient/Options.phpnu[PK[ aGGHttpClient/Response.phpnu[PK[%-V2V2HttpClient/HttpClient.phpnu[PK[B#N11"GKHttpClient/HttpClientException.phpnu[PK[O;yPHttpClient/OAuth.phpnu[PK[NtjHttpClient/BasicAuth.phpnu[PK[8> > rHttpClient/Request.phpnu[PK[#UO O Client.phpnu[PK