Add upstream

This commit is contained in:
root
2019-10-24 00:12:05 +02:00
parent 85d41e4216
commit ac980f592c
3504 changed files with 1049983 additions and 29971 deletions

View File

@@ -0,0 +1,479 @@
<?php
/**
* Abstract OAuth consumer
* @author Ben Tadiar <ben@handcraftedbyben.co.uk>
* @link https://github.com/benthedesigner/dropbox
* @package Dropbox\OAuth
* @subpackage Consumer
*/
abstract class Dropbox_ConsumerAbstract
{
// Dropbox web endpoint. v2 API has just dropped the 1/ suffix to the below.
const WEB_URL = 'https://www.dropbox.com/';
// OAuth flow methods
const AUTHORISE_METHOD = 'oauth2/authorize';
// Beware - the documentation in one place says oauth2/token/revoke, but that appears to be wrong
const DEAUTHORISE_METHOD = '2/auth/token/revoke';
const ACCESS_TOKEN_METHOD = 'oauth2/token';
// The next endpoint only exists with APIv1
const OAUTH_UPGRADE = 'oauth2/token_from_oauth1';
/**
* Signature method, either PLAINTEXT or HMAC-SHA1
* @var string
*/
private $sigMethod = 'PLAINTEXT';
/**
* Output file handle
* @var null|resource
*/
protected $outFile = null;
/**
* Input file handle
* @var null|resource
*/
protected $inFile = null;
/**
* Authenticate using 3-legged OAuth flow, firstly
* checking we don't already have tokens to use
* @return void
*/
protected function authenticate()
{
global $updraftplus;
$access_token = $this->storage->get('access_token');
//Check if the new token type is set if not they need to be upgraded to OAuth2
if (!empty($access_token) && isset($access_token->oauth_token) && !isset($access_token->token_type)) {
$updraftplus->log('OAuth v1 token found: upgrading to v2');
$this->upgradeOAuth();
$updraftplus->log('OAuth token upgrade successful');
}
if (empty($access_token) || !isset($access_token->oauth_token)) {
try {
$this->getAccessToken();
} catch(Exception $e) {
$excep_class = get_class($e);
// 04-Sep-2015 - Dropbox started throwing a 400, which caused a Dropbox_BadRequestException which previously wasn't being caught
if ('Dropbox_BadRequestException' == $excep_class || 'Dropbox_Exception' == $excep_class) {
global $updraftplus;
$updraftplus->log($e->getMessage().' - need to reauthenticate this site with Dropbox (if this fails, then you can also try wiping your settings from the Expert Settings section)');
//$this->getRequestToken();
$this->authorise();
} else {
throw $e;
}
}
}
}
/**
* Upgrade the user's OAuth1 token to a OAuth2 token
* @return void
*/
private function upgradeOAuth()
{
// N.B. This call only exists under API v1 - i.e. there is no APIv2 equivalent. Hence the APIv1 endpoint (API_URL) is used, and not the v2 (API_URL_V2)
$url = 'https://api.dropbox.com/1/' . self::OAUTH_UPGRADE;
$response = $this->fetch('POST', $url, '');
$token = new stdClass();
/*
oauth token secret and oauth token were needed by oauth1
these are replaced in oauth2 with an access token
currently they are still there just in case a method somewhere is expecting them to both be set
as far as I can tell only the oauth token is used
after more testing token secret can be removed.
*/
$token->oauth_token_secret = $response['body']->access_token;
$token->oauth_token = $response['body']->access_token;
$token->token_type = $response['body']->token_type;
$this->storage->set($token, 'access_token');
$this->storage->set('true','upgraded');
$this->storage->do_unset('request_token');
}
/**
* Obtain user authorisation
* The user will be redirected to Dropbox' web endpoint
* @link http://tools.ietf.org/html/rfc5849#section-2.2
* @return void
*/
private function authorise()
{
// Only redirect if not using CLI
if (PHP_SAPI !== 'cli' && (!defined('DOING_CRON') || !DOING_CRON) && (!defined('DOING_AJAX') || !DOING_AJAX)) {
$url = $this->getAuthoriseUrl();
if (!headers_sent()) {
header('Location: ' . $url);
exit;
} else {
throw new Dropbox_Exception(sprintf(__('The %s authentication could not go ahead, because something else on your site is breaking it. Try disabling your other plugins and switching to a default theme. (Specifically, you are looking for the component that sends output (most likely PHP warnings/errors) before the page begins. Turning off any debugging settings may also help).', 'updraftplus'), 'Dropbox'));
}
?><?php
return false;
}
global $updraftplus;
$updraftplus->log('Dropbox reauthorisation needed; but we are running from cron, AJAX or the CLI, so this is not possible');
$this->storage->do_unset('access_token');
throw new Dropbox_Exception(sprintf(__('You need to re-authenticate with %s, as your existing credentials are not working.', 'updraftplus'), 'Dropbox'));
#$updraftplus->log(sprintf(__('You need to re-authenticate with %s, as your existing credentials are not working.', 'updraftplus'), 'Dropbox'), 'error');
return false;
}
/**
* Build the user authorisation URL
* @return string
*/
public function getAuthoriseUrl()
{
/*
Generate a random key to be passed to Dropbox and stored in session to be checked to prevent CSRF
Uses OpenSSL or Mcrypt or defaults to pure PHP implementaion if neither are available.
*/
global $updraftplus;
if (!function_exists('crypt_random_string')) $updraftplus->ensure_phpseclib('Crypt_Random');
$CSRF = base64_encode(crypt_random_string(16));
$this->storage->set($CSRF,'CSRF');
// Prepare request parameters
/*
For OAuth v2 Dropbox needs to use a authorisation url that matches one that is set inside the
Dropbox developer console. In order to check this it needs the client ID for the OAuth v2 app
This will use the default one unless the user is using their own Dropbox App
For users that use their own Dropbox App there is also no need to provide the callbackhome as
part of the CSRF as there is no need to go to auth.updraftplus.com also the redirect uri can
then be set to the home as default
Check if the key has dropbox: if so then remove it to stop the request from being invalid
*/
$appkey = $this->storage->get('appkey');
if (!empty($appkey) && 'dropbox:' == substr($appkey, 0, 8)) {
$key = substr($appkey, 8);
} else if (!empty($appkey)) {
$key = $appkey;
}
if ('' != $this->instance_id) $this->instance_id = ':'.$this->instance_id;
$params = array(
'client_id' => empty($key) ? $this->oauth2_id : $key,
'response_type' => 'code',
'redirect_uri' => empty($key) ? $this->callback : $this->callbackhome,
'state' => empty($key) ? "POST:".$CSRF.$this->instance_id.$this->callbackhome : $CSRF.$this->instance_id,
);
// Build the URL and redirect the user
$query = '?' . http_build_query($params, '', '&');
$url = self::WEB_URL . self::AUTHORISE_METHOD . $query;
return $url;
}
protected function deauthenticate()
{
$url = UpdraftPlus_Dropbox_API::API_URL_V2 . self::DEAUTHORISE_METHOD;
$response = $this->fetch('POST', $url, '', array('api_v2' => true));
$this->storage->delete();
}
/**
* Acquire an access token
* Tokens acquired at this point should be stored to
* prevent having to request new tokens for each API call
* @link http://tools.ietf.org/html/rfc5849#section-2.3
*/
public function getAccessToken()
{
// If this is non-empty, then we just received a code. It is stored in 'code' - our next job is to put it into the proper place.
$code = $this->storage->get('code');
/*
Checks to see if the user is using their own Dropbox App if so then they need to get
a request token. If they are using our App then we just need to save these details
*/
if (!empty($code)){
$appkey = $this->storage->get('appkey');
if (!empty($appkey)){
// Get the signed request URL
$url = UpdraftPlus_Dropbox_API::API_URL_V2 . self::ACCESS_TOKEN_METHOD;
$params = array(
'code' => $code,
'grant_type' => 'authorization_code',
'redirect_uri' => $this->callbackhome,
'client_id' => $this->consumerKey,
'client_secret' => $this->consumerSecret,
);
$response = $this->fetch('POST', $url, '' , $params);
$code = json_decode(json_encode($response['body']),true);
} else {
$code = base64_decode($code);
$code = json_decode($code, true);
}
/*
Again oauth token secret and oauth token were needed by oauth1
these are replaced in oauth2 with an access token
currently they are still there just in case a method somewhere is expecting them to both be set
as far as I can tell only the oauth token is used
after more testing token secret can be removed.
*/
$token = new stdClass();
$token->oauth_token_secret = $code['access_token'];
$token->oauth_token = $code['access_token'];
$token->account_id = $code['account_id'];
$token->token_type = $code['token_type'];
$token->uid = $code['uid'];
$this->storage->set($token, 'access_token');
$this->storage->do_unset('upgraded');
//reset code
$this->storage->do_unset('code');
} else {
throw new Dropbox_BadRequestException("No Dropbox Code found, will try to get one now", 400);
}
}
/**
* Get the request/access token
* This will return the access/request token depending on
* which stage we are at in the OAuth flow, or a dummy object
* if we have not yet started the authentication process
* @return object stdClass
*/
private function getToken()
{
if (!$token = $this->storage->get('access_token')) {
if (!$token = $this->storage->get('request_token')) {
$token = new stdClass();
$token->oauth_token = null;
$token->oauth_token_secret = null;
}
}
return $token;
}
/**
* Generate signed request URL
* See inline comments for description
* @link http://tools.ietf.org/html/rfc5849#section-3.4
* @param string $method HTTP request method
* @param string $url API endpoint to send the request to
* @param string $call API call to send
* @param array $additional Additional parameters as an associative array
* @return array
*/
protected function getSignedRequest($method, $url, $call, array $additional = array())
{
// Get the request/access token
$token = $this->getToken();
// Prepare the standard request parameters differently for OAuth1 and OAuth2; we still need OAuth1 to make the request to the upgrade token endpoint
if (isset($token->token_type)) {
$params = array(
'access_token' => $token->oauth_token,
);
/*
To keep this API backwards compatible with the API v1 endpoints all v2 endpoints will also send to this method a api_v2 parameter this will then return just the access token as the signed request is not needed for any calls.
*/
if (isset($additional['api_v2']) && $additional['api_v2'] == true) {
unset($additional['api_v2']);
if (isset($additional['timeout'])) unset($additional['timeout']);
if (isset($additional['content_download']) && $additional['content_download'] == true) {
unset($additional['content_download']);
$extra_headers = array();
if (isset($additional['headers'])) {
foreach ($additional['headers'] as $key => $header) {
$extra_headers[] = $header;
}
unset($additional['headers']);
}
$headers = array(
'Authorization: Bearer '.$params['access_token'],
'Content-Type:',
'Dropbox-API-Arg: '.json_encode($additional),
);
$headers = array_merge($headers, $extra_headers);
$additional = '';
} else if (isset($additional['content_upload']) && $additional['content_upload'] == true) {
unset($additional['content_upload']);
$headers = array(
'Authorization: Bearer '.$params['access_token'],
'Content-Type: application/octet-stream',
'Dropbox-API-Arg: '.json_encode($additional),
);
$additional = '';
} else {
$headers = array(
'Authorization: Bearer '.$params['access_token'],
'Content-Type: application/json',
);
}
return array(
'url' => $url . $call,
'postfields' => $additional,
'headers' => $headers,
);
}
} else {
// Generate a random string for the request
$nonce = md5(microtime(true) . uniqid('', true));
$params = array(
'oauth_consumer_key' => $this->consumerKey,
'oauth_token' => $token->oauth_token,
'oauth_signature_method' => $this->sigMethod,
'oauth_version' => '1.0',
// Generate nonce and timestamp if signature method is HMAC-SHA1
'oauth_timestamp' => ($this->sigMethod == 'HMAC-SHA1') ? time() : null,
'oauth_nonce' => ($this->sigMethod == 'HMAC-SHA1') ? $nonce : null,
);
}
// Merge with the additional request parameters
$params = array_merge($params, $additional);
ksort($params);
// URL encode each parameter to RFC3986 for use in the base string
$encoded = array();
foreach($params as $param => $value) {
if ($value !== null) {
// If the value is a file upload (prefixed with @), replace it with
// the destination filename, the file path will be sent in POSTFIELDS
if (isset($value[0]) && $value[0] === '@') $value = $params['filename'];
# Prevent spurious PHP warning by only doing non-arrays
if (!is_array($value)) $encoded[] = $this->encode($param) . '=' . $this->encode($value);
} else {
unset($params[$param]);
}
}
// Build the first part of the string
$base = $method . '&' . $this->encode($url . $call) . '&';
// Re-encode the encoded parameter string and append to $base
$base .= $this->encode(implode('&', $encoded));
// Concatenate the secrets with an ampersand
$key = $this->consumerSecret . '&' . $token->oauth_token_secret;
// Get the signature string based on signature method
$signature = $this->getSignature($base, $key);
$params['oauth_signature'] = $signature;
// Build the signed request URL
$query = '?' . http_build_query($params, '', '&');
return array(
'url' => $url . $call . $query,
'postfields' => $params,
);
}
/**
* Generate the oauth_signature for a request
* @param string $base Signature base string, used by HMAC-SHA1
* @param string $key Concatenated consumer and token secrets
*/
private function getSignature($base, $key)
{
switch ($this->sigMethod) {
case 'PLAINTEXT':
$signature = $key;
break;
case 'HMAC-SHA1':
$signature = base64_encode(hash_hmac('sha1', $base, $key, true));
break;
}
return $signature;
}
/**
* Set the OAuth signature method
* @param string $method Either PLAINTEXT or HMAC-SHA1
* @return void
*/
public function setSignatureMethod($method)
{
$method = strtoupper($method);
switch ($method) {
case 'PLAINTEXT':
case 'HMAC-SHA1':
$this->sigMethod = $method;
break;
default:
throw new Dropbox_Exception('Unsupported signature method ' . $method);
}
}
/**
* Set the output file
* @param resource Resource to stream response data to
* @return void
*/
public function setOutFile($handle)
{
if (!is_resource($handle) || get_resource_type($handle) != 'stream') {
throw new Dropbox_Exception('Outfile must be a stream resource');
}
$this->outFile = $handle;
}
/**
* Set the input file
* @param resource Resource to read data from
* @return void
*/
public function setInFile($handle) {
$this->inFile = $handle;
}
/**
* Parse response parameters for a token into an object
* Dropbox returns tokens in the response parameters, and
* not a JSON encoded object as per other API requests
* @link http://oauth.net/core/1.0/#response_parameters
* @param string $response
* @return object stdClass
*/
private function parseTokenString($response)
{
$parts = explode('&', $response);
$token = new stdClass();
foreach ($parts as $part) {
list($k, $v) = explode('=', $part, 2);
$k = strtolower($k);
$token->$k = $v;
}
return $token;
}
/**
* Encode a value to RFC3986
* This is a convenience method to decode ~ symbols encoded
* by rawurldecode. This will encode all characters except
* the unreserved set, ALPHA, DIGIT, '-', '.', '_', '~'
* @link http://tools.ietf.org/html/rfc5849#section-3.6
* @param mixed $value
*/
private function encode($value)
{
return str_replace('%7E', '~', rawurlencode($value));
}
}

View File

@@ -0,0 +1,299 @@
<?php
/**
* OAuth consumer using PHP cURL
* @author Ben Tadiar <ben@handcraftedbyben.co.uk>
* @link https://github.com/benthedesigner/dropbox
* @package Dropbox\OAuth
* @subpackage Consumer
*/
class Dropbox_Curl extends Dropbox_ConsumerAbstract
{
/**
* Default cURL options
* @var array
*/
protected $defaultOptions = array(
CURLOPT_VERBOSE => true,
CURLOPT_HEADER => true,
CURLINFO_HEADER_OUT => false,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
);
/**
* Store the last response form the API
* @var mixed
*/
protected $lastResponse = null;
/**
* Set properties and begin authentication
* @param string $key
* @param string $secret
* @param \Dropbox\OAuth\Consumer\StorageInterface $storage
* @param string $callback
*/
public function __construct($key, $oauth2_id, $secret, Dropbox_StorageInterface $storage, $callback = null, $callbackhome = null, $deauthenticate = false, $instance_id = '')
{
// Check the cURL extension is loaded
if (!extension_loaded('curl')) {
throw new Dropbox_Exception('The cURL OAuth consumer requires the cURL extension. Please speak to your web hosting provider so that this missing PHP component can be installed.');
}
$this->consumerKey = $key;
$this->oauth2_id = $oauth2_id;
$this->consumerSecret = $secret;
$this->storage = $storage;
$this->callback = $callback;
$this->callbackhome = $callbackhome;
$this->instance_id = $instance_id;
if ($deauthenticate) {
$this->deauthenticate();
} else {
$this->authenticate();
}
}
/**
* Execute an API call
* @todo Improve error handling
* @param string $method The HTTP method
* @param string $url The API endpoint
* @param string $call The API method to call
* @param array $additional Additional parameters
* @return string|object stdClass
*/
public function fetch($method, $url, $call, array $additional = array())
{
// Get the signed request URL
$request = $this->getSignedRequest($method, $url, $call, $additional);
// Initialise and execute a cURL request
$handle = curl_init($request['url']);
// Get the default options array
$options = $this->defaultOptions;
if (!UpdraftPlus_Options::get_updraft_option('updraft_ssl_useservercerts')) {
$options[CURLOPT_CAINFO] = UPDRAFTPLUS_DIR.'/includes/cacert.pem';
}
if (UpdraftPlus_Options::get_updraft_option('updraft_ssl_disableverify')) {
$options[CURLOPT_SSL_VERIFYPEER] = false;
} else {
$options[CURLOPT_SSL_VERIFYPEER] = true;
}
if (!class_exists('WP_HTTP_Proxy')) require_once(ABSPATH.WPINC.'/class-http.php');
$proxy = new WP_HTTP_Proxy();
if ($proxy->is_enabled()) {
# WP_HTTP_Proxy returns empty strings if nothing is set
$user = $proxy->username();
$pass = $proxy->password();
$host = $proxy->host();
$port = (int)$proxy->port();
if (empty($port)) $port = 8080;
if (!empty($host) && $proxy->send_through_proxy($request['url'])) {
$options[CURLOPT_PROXY] = $host;
$options[CURLOPT_PROXYTYPE] = CURLPROXY_HTTP;
$options[CURLOPT_PROXYPORT] = $port;
if (!empty($user) && !empty($pass)) {
$options[CURLOPT_PROXYAUTH] = CURLAUTH_ANY;
$options[CURLOPT_PROXYUSERPWD] = sprintf('%s:%s', $user, $pass);
}
}
}
/*
Add check to see if it's an API v2 call if so then json encode the contents. This is so that it is backwards compatible with API v1 endpoints.
*/
if (isset($additional['api_v2']) && !empty($request['postfields'])) {
$request['postfields'] = json_encode($request['postfields']);
} elseif (empty($request['postfields'])) {
// if the postfields are empty then we don't want to send the application/json header if it's set as Dropbox will return an error
$key = array_search('Content-Type: application/json', $request['headers']);
if (false !== $key) unset($request['headers'][$key]);
}
if (isset($request['headers']) && !empty($request['headers'])) $options[CURLOPT_HTTPHEADER] = $request['headers'];
if ($method == 'GET' && $this->outFile) { // GET
$options[CURLOPT_RETURNTRANSFER] = false;
$options[CURLOPT_HEADER] = false;
$options[CURLOPT_FILE] = $this->outFile;
$options[CURLOPT_BINARYTRANSFER] = true;
$options[CURLOPT_FAILONERROR] = true;
$this->outFile = null;
} elseif ($method == 'POST' && $this->outFile) { // POST
$options[CURLOPT_POST] = true;
$options[CURLOPT_RETURNTRANSFER] = false;
$options[CURLOPT_HEADER] = false;
$options[CURLOPT_FILE] = $this->outFile;
$options[CURLOPT_BINARYTRANSFER] = true;
$options[CURLOPT_FAILONERROR] = true;
$this->outFile = null;
} elseif ($method == 'POST' && $this->inFile) { // POST
$options[CURLOPT_POST] = true;
$options[CURLOPT_POSTFIELDS] = $this->inFile;
} elseif ($method == 'POST') { // POST
$options[CURLOPT_POST] = true;
$options[CURLOPT_POSTFIELDS] = $request['postfields'];
} elseif ($method == 'PUT' && $this->inFile) { // PUT
$options[CURLOPT_PUT] = true;
$options[CURLOPT_INFILE] = $this->inFile;
// @todo Update so the data is not loaded into memory to get its size
$options[CURLOPT_INFILESIZE] = strlen(stream_get_contents($this->inFile));
fseek($this->inFile, 0);
$this->inFile = null;
}
if (isset($additional['timeout'])) {
$options[CURLOPT_TIMEOUT] = $additional['timeout'];
}
// Set the cURL options at once
curl_setopt_array($handle, $options);
// Execute, get any error and close
$response = curl_exec($handle);
$error = curl_error($handle);
$getinfo = curl_getinfo($handle);
curl_close($handle);
//Check if a cURL error has occured
if ($response === false) {
throw new Dropbox_CurlException($error);
} else {
// Parse the response if it is a string
if (is_string($response)) {
$response = $this->parse($response);
}
// Set the last response
$this->lastResponse = $response;
$code = (!empty($response['code'])) ? $response['code'] : $getinfo['http_code'];
// The API doesn't return an error message for the 304 status code...
// 304's are only returned when the path supplied during metadata calls has not been modified
if ($code == 304) {
$response['body'] = new stdClass;
$response['body']->error = 'The folder contents have not changed';
}
// Check if an error occurred and throw an Exception
if (!empty($response['body']->error) || $code >= 400) {
// Dropbox returns error messages inconsistently...
if (!empty($response['body']->error) && $response['body']->error instanceof stdClass) {
$array = array_values((array) $response['body']->error);
//Dropbox API v2 only throws 409 errors if this error is a incorrect_offset then we need the entire error array not just the message. PHP Exception messages have to be a string so JSON encode the array.
if (strpos($array[0] , 'incorrect_offset') !== false) {
$message = json_encode($array);
} elseif (strpos($array[0] , 'lookup_failed') !== false ) {
//re-structure the array so it is correctly formatted for API
//Note: Dropbox v2 returns different errors at different stages hence this fix
$correctOffset = array(
'0' => $array[1]->{'.tag'},
'1' => $array[1]->correct_offset
);
$message = json_encode($correctOffset);
} else {
$message = $array[0];
}
} elseif (!empty($response['body']->error)) {
$message = $response['body']->error;
} elseif (is_string($response['body'])) {
// 31 Mar 2017 - This case has been found to exist; though the docs imply that there's always an 'error' property and that what is returned in JSON, we found a case of this being returned just as a simple string, but detectable via an HTTP 400: Error in call to API function "files/upload_session/append_v2": HTTP header "Dropbox-API-Arg": cursor.offset: expected integer, got string
$message = $response['body'];
} else {
$message = "HTTP bad response code: $code";
}
// Throw an Exception with the appropriate with the appropriate message and code
switch ($code) {
case 304:
throw new Dropbox_NotModifiedException($message, 304);
case 400:
throw new Dropbox_BadRequestException($message, 400);
case 404:
throw new Dropbox_NotFoundException($message, 404);
case 406:
throw new Dropbox_NotAcceptableException($message, 406);
case 415:
throw new Dropbox_UnsupportedMediaTypeException($message, 415);
case 401:
//401 means oauth token is expired continue to manually handle the exception depending on the situation
break;
case 409:
//409 in API V2 every error will return with a 409 to find out what the error is the error description should be checked.
throw new Dropbox_Exception($message, $code);
default:
throw new Dropbox_Exception($message, $code);
}
}
return $response;
}
}
/**
* Parse a cURL response
* @param string $response
* @return array
*/
private function parse($response)
{
// Explode the response into headers and body parts (separated by double EOL)
list($headers, $response) = explode("\r\n\r\n", $response, 2);
// Explode response headers
$lines = explode("\r\n", $headers);
// If the status code is 100, the API server must send a final response
// We need to explode the response again to get the actual response
if (preg_match('#^HTTP/[\.\d]+ 100#i', $lines[0])) {
list($headers, $response) = explode("\r\n\r\n", $response, 2);
$lines = explode("\r\n", $headers);
}
// Get the HTTP response code from the first line
$first = array_shift($lines);
$pattern = '#^HTTP/[\.\d]+ ([0-9]{3})#i';
preg_match($pattern, $first, $matches);
$code = $matches[1];
// Parse the remaining headers into an associative array
$headers = array();
foreach ($lines as $line) {
list($k, $v) = explode(': ', $line, 2);
$headers[strtolower($k)] = $v;
}
// If the response body is not a JSON encoded string
// we'll return the entire response body
if (!$body = json_decode($response)) {
$body = $response;
}
if (is_string($body)) {
$body_lines = explode("\r\n", $body);
if (preg_match('#^HTTP/[\.\d]+ 100#i', $body_lines[0]) && preg_match('#^HTTP/\d#i', $body_lines[2])) {
return $this->parse($body);
}
}
return array('code' => $code, 'body' => $body, 'headers' => $headers);
}
/**
* Return the response for the last API request
* @return mixed
*/
public function getlastResponse()
{
return $this->lastResponse;
}
}

View File

@@ -0,0 +1,80 @@
<?php
/**
* OAuth consumer using the WordPress API
* @author David Anderson <david@updraftplus.com>
* @link https://github.com/DavidAnderson684/Dropbox
* @package Dropbox\OAuth
* @subpackage Consumer
*/
class Dropbox_ConsumerWordPress extends Dropbox_ConsumerAbstract
{
/**
* Set properties and begin authentication
* @param string $key
* @param string $secret
* @param \Dropbox\OAuth\Consumer\StorageInterface $storage
* @param string $callback
*/
public function __construct($key, $secret, Dropbox_StorageInterface $storage, $callback = null)
{
// Check we are in a WordPress environment
if (!defined('ABSPATH')) {
throw new Dropbox_Exception('The WordPress OAuth consumer requires a WordPress environment');
}
$this->consumerKey = $key;
$this->consumerSecret = $secret;
$this->storage = $storage;
$this->callback = $callback;
$this->authenticate();
}
/**
* Execute an API call
* @param string $method The HTTP method
* @param string $url The API endpoint
* @param string $call The API method to call
* @param array $additional Additional parameters
* @return array
*/
public function fetch($method, $url, $call, array $additional = array())
{
// Get the signed request URL
$request = $this->getSignedRequest($method, $url, $call, $additional);
if ($method == 'GET') {
$args = array ( );
$response = wp_remote_get($request['url'], $args);
$this->outFile = null;
} elseif ($method == 'POST') {
$args = array( 'body' => $request['postfields'] );
$response = wp_remote_post($request['url'], $args );
} elseif ($method == 'PUT' && $this->inFile) {
return new WP_Error('unsupported', "WordPress does not have a native HTTP PUT function");
}
// If the response body is not a JSON encoded string
// we'll return the entire response body
// Important to do this first, as the next section relies on the decoding having taken place
if (!$body = json_decode(wp_remote_retrieve_body($response))) {
$body = wp_remote_retrieve_body($response);
}
// Check if an error occurred and throw an Exception. This is part of the authentication process - don't modify.
if (!empty($body->error)) {
$message = $body->error . ' (Status Code: ' . wp_remote_retrieve_response_code($response) . ')';
throw new Dropbox_Exception($message);
}
if (is_wp_error($response)) {
$message = $response->get_error_message();
throw new Dropbox_Exception($message);
}
$results = array ( 'body' => $body, 'code' => wp_remote_retrieve_response_code($response), 'headers' => $response['headers'] );
return $results;
}
}