Spade

Mini Shell

Directory:~$ /home/lmsyaran/public_html/joomla4/
Upload File

[Home] [System Details] [Kill Me]
Current File:~$ /home/lmsyaran/public_html/joomla4/client.php.tar

home/lmsyaran/public_html/libraries/joomla/oauth1/client.php000064400000033642151155772320020271
0ustar00<?php
/**
 * @package     Joomla.Platform
 * @subpackage  OAuth1
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE
 */

defined('JPATH_PLATFORM') or die();

use Joomla\Registry\Registry;

/**
 * Joomla Platform class for interacting with an OAuth 1.0 and 1.0a server.
 *
 * @since       3.2.0
 * @deprecated  4.0  Use the `joomla/oauth1` framework package that will be
bundled instead
 */
abstract class JOAuth1Client
{
	/**
	 * @var    Registry  Options for the JOAuth1Client object.
	 * @since  3.2.0
	 */
	protected $options;

	/**
	 * @var    array  Contains access token key, secret and verifier.
	 * @since  3.2.0
	 */
	protected $token = array();

	/**
	 * @var    JHttp  The HTTP client object to use in sending HTTP requests.
	 * @since  3.2.0
	 */
	protected $client;

	/**
	 * @var    JInput The input object to use in retrieving GET/POST data.
	 * @since  3.2.0
	 */
	protected $input;

	/**
	 * @var    JApplicationWeb  The application object to send HTTP headers
for redirects.
	 * @since  3.2.0
	 */
	protected $application;

	/**
	 * @var   string  Selects which version of OAuth to use: 1.0 or 1.0a.
	 * @since 3.2.0
	 */
	protected $version;

	/**
	 * Constructor.
	 *
	 * @param   Registry         $options      OAuth1Client options object.
	 * @param   JHttp            $client       The HTTP client object.
	 * @param   JInput           $input        The input object
	 * @param   JApplicationWeb  $application  The application object
	 * @param   string           $version      Specify the OAuth version. By
default we are using 1.0a.
	 *
	 * @since   3.2.0
	 */
	public function __construct(Registry $options = null, JHttp $client =
null, JInput $input = null, JApplicationWeb $application = null,
		$version = null)
	{
		$this->options = isset($options) ? $options : new Registry;
		$this->client = isset($client) ? $client :
JHttpFactory::getHttp($this->options);
		$this->input = isset($input) ? $input :
JFactory::getApplication()->input;
		$this->application = isset($application) ? $application : new
JApplicationWeb;
		$this->version = isset($version) ? $version : '1.0a';
	}

	/**
	 * Method to for the oauth flow.
	 *
	 * @return  array  Contains access token key, secret and verifier.
	 *
	 * @since   3.2.0
	 * @throws  DomainException
	 */
	public function authenticate()
	{
		// Already got some credentials stored?
		if ($this->token)
		{
			$response = $this->verifyCredentials();

			if ($response)
			{
				return $this->token;
			}
			else
			{
				$this->token = null;
			}
		}

		// Check for callback.
		if (strcmp($this->version, '1.0a') === 0)
		{
			$verifier = $this->input->get('oauth_verifier');
		}
		else
		{
			$verifier = $this->input->get('oauth_token');
		}

		if (empty($verifier))
		{
			// Generate a request token.
			$this->_generateRequestToken();

			// Authenticate the user and authorise the app.
			$this->_authorise();
		}

		// Callback
		else
		{
			$session = JFactory::getSession();

			// Get token form session.
			$this->token = array('key' =>
$session->get('key', null, 'oauth_token'),
'secret' => $session->get('secret', null,
'oauth_token'));

			// Verify the returned request token.
			if (strcmp($this->token['key'],
$this->input->get('oauth_token')) !== 0)
			{
				throw new DomainException('Bad session!');
			}

			// Set token verifier for 1.0a.
			if (strcmp($this->version, '1.0a') === 0)
			{
				$this->token['verifier'] =
$this->input->get('oauth_verifier');
			}

			// Generate access token.
			$this->_generateAccessToken();

			// Return the access token.
			return $this->token;
		}
	}

	/**
	 * Method used to get a request token.
	 *
	 * @return  void
	 *
	 * @since   3.2.0
	 * @throws  DomainException
	 */
	private function _generateRequestToken()
	{
		// Set the callback URL.
		if ($this->getOption('callback'))
		{
			$parameters = array(
				'oauth_callback' =>
$this->getOption('callback'),
			);
		}
		else
		{
			$parameters = array();
		}

		// Make an OAuth request for the Request Token.
		$response =
$this->oauthRequest($this->getOption('requestTokenURL'),
'POST', $parameters);

		parse_str($response->body, $params);

		if (strcmp($this->version, '1.0a') === 0 &&
strcmp($params['oauth_callback_confirmed'], 'true') !==
0)
		{
			throw new DomainException('Bad request token!');
		}

		// Save the request token.
		$this->token = array('key' =>
$params['oauth_token'], 'secret' =>
$params['oauth_token_secret']);

		// Save the request token in session
		$session = JFactory::getSession();
		$session->set('key', $this->token['key'],
'oauth_token');
		$session->set('secret', $this->token['secret'],
'oauth_token');
	}

	/**
	 * Method used to authorise the application.
	 *
	 * @return  void
	 *
	 * @since   3.2.0
	 */
	private function _authorise()
	{
		$url = $this->getOption('authoriseURL') .
'?oauth_token=' . $this->token['key'];

		if ($this->getOption('scope'))
		{
			$scope = is_array($this->getOption('scope')) ?
implode(' ', $this->getOption('scope')) :
$this->getOption('scope');
			$url .= '&scope=' . urlencode($scope);
		}

		if ($this->getOption('sendheaders'))
		{
			$this->application->redirect($url);
		}
	}

	/**
	 * Method used to get an access token.
	 *
	 * @return  void
	 *
	 * @since   3.2.0
	 */
	private function _generateAccessToken()
	{
		// Set the parameters.
		$parameters = array(
			'oauth_token' => $this->token['key'],
		);

		if (strcmp($this->version, '1.0a') === 0)
		{
			$parameters = array_merge($parameters, array('oauth_verifier'
=> $this->token['verifier']));
		}

		// Make an OAuth request for the Access Token.
		$response =
$this->oauthRequest($this->getOption('accessTokenURL'),
'POST', $parameters);

		parse_str($response->body, $params);

		// Save the access token.
		$this->token = array('key' =>
$params['oauth_token'], 'secret' =>
$params['oauth_token_secret']);
	}

	/**
	 * Method used to make an OAuth request.
	 *
	 * @param   string  $url         The request URL.
	 * @param   string  $method      The request method.
	 * @param   array   $parameters  Array containing request parameters.
	 * @param   mixed   $data        The POST request data.
	 * @param   array   $headers     An array of name-value pairs to include
in the header of the request
	 *
	 * @return  JHttpResponse
	 *
	 * @since   3.2.0
	 * @throws  DomainException
	 */
	public function oauthRequest($url, $method, $parameters, $data = array(),
$headers = array())
	{
		// Set the parameters.
		$defaults = array(
			'oauth_consumer_key' =>
$this->getOption('consumer_key'),
			'oauth_signature_method' => 'HMAC-SHA1',
			'oauth_version' => '1.0',
			'oauth_nonce' => $this->generateNonce(),
			'oauth_timestamp' => time(),
		);

		$parameters = array_merge($parameters, $defaults);

		// Do not encode multipart parameters. Do not include $data in the
signature if $data is not array.
		if (isset($headers['Content-Type']) &&
strpos($headers['Content-Type'], 'multipart/form-data')
!== false || !is_array($data))
		{
			$oauth_headers = $parameters;
		}
		else
		{
			// Use all parameters for the signature.
			$oauth_headers = array_merge($parameters, $data);
		}

		// Sign the request.
		$oauth_headers = $this->_signRequest($url, $method, $oauth_headers);

		// Get parameters for the Authorisation header.
		if (is_array($data))
		{
			$oauth_headers = array_diff_key($oauth_headers, $data);
		}

		// Send the request.
		switch ($method)
		{
			case 'GET':
				$url = $this->toUrl($url, $data);
				$response = $this->client->get($url,
array('Authorization' =>
$this->_createHeader($oauth_headers)));
				break;
			case 'POST':
				$headers = array_merge($headers, array('Authorization' =>
$this->_createHeader($oauth_headers)));
				$response = $this->client->post($url, $data, $headers);
				break;
			case 'PUT':
				$headers = array_merge($headers, array('Authorization' =>
$this->_createHeader($oauth_headers)));
				$response = $this->client->put($url, $data, $headers);
				break;
			case 'DELETE':
				$headers = array_merge($headers, array('Authorization' =>
$this->_createHeader($oauth_headers)));
				$response = $this->client->delete($url, $headers);
				break;
		}

		// Validate the response code.
		$this->validateResponse($url, $response);

		return $response;
	}

	/**
	 * Method to validate a response.
	 *
	 * @param   string         $url       The request URL.
	 * @param   JHttpResponse  $response  The response to validate.
	 *
	 * @return  void
	 *
	 * @since   3.2.0
	 * @throws  DomainException
	 */
	abstract public function validateResponse($url, $response);

	/**
	 * Method used to create the header for the POST request.
	 *
	 * @param   array  $parameters  Array containing request parameters.
	 *
	 * @return  string  The header.
	 *
	 * @since   3.2.0
	 */
	private function _createHeader($parameters)
	{
		$header = 'OAuth ';

		foreach ($parameters as $key => $value)
		{
			if (!strcmp($header, 'OAuth '))
			{
				$header .= $key . '="' . $this->safeEncode($value) .
'"';
			}
			else
			{
				$header .= ', ' . $key . '="' . $value .
'"';
			}
		}

		return $header;
	}

	/**
	 * Method to create the URL formed string with the parameters.
	 *
	 * @param   string  $url         The request URL.
	 * @param   array   $parameters  Array containing request parameters.
	 *
	 * @return  string  The formed URL.
	 *
	 * @since   3.2.0
	 */
	public function toUrl($url, $parameters)
	{
		foreach ($parameters as $key => $value)
		{
			if (is_array($value))
			{
				foreach ($value as $v)
				{
					if (strpos($url, '?') === false)
					{
						$url .= '?' . $key . '=' . $v;
					}
					else
					{
						$url .= '&' . $key . '=' . $v;
					}
				}
			}
			else
			{
				if (strpos($value, ' ') !== false)
				{
					$value = $this->safeEncode($value);
				}

				if (strpos($url, '?') === false)
				{
					$url .= '?' . $key . '=' . $value;
				}
				else
				{
					$url .= '&' . $key . '=' . $value;
				}
			}
		}

		return $url;
	}

	/**
	 * Method used to sign requests.
	 *
	 * @param   string  $url         The URL to sign.
	 * @param   string  $method      The request method.
	 * @param   array   $parameters  Array containing request parameters.
	 *
	 * @return  array
	 *
	 * @since   3.2.0
	 */
	private function _signRequest($url, $method, $parameters)
	{
		// Create the signature base string.
		$base = $this->_baseString($url, $method, $parameters);

		$parameters['oauth_signature'] = $this->safeEncode(
			base64_encode(
				hash_hmac('sha1', $base, $this->_prepareSigningKey(),
true)
				)
			);

		return $parameters;
	}

	/**
	 * Prepare the signature base string.
	 *
	 * @param   string  $url         The URL to sign.
	 * @param   string  $method      The request method.
	 * @param   array   $parameters  Array containing request parameters.
	 *
	 * @return  string  The base string.
	 *
	 * @since   3.2.0
	 */
	private function _baseString($url, $method, $parameters)
	{
		// Sort the parameters alphabetically
		uksort($parameters, 'strcmp');

		// Encode parameters.
		foreach ($parameters as $key => $value)
		{
			$key = $this->safeEncode($key);

			if (is_array($value))
			{
				foreach ($value as $v)
				{
					$v = $this->safeEncode($v);
					$kv[] = "{$key}={$v}";
				}
			}
			else
			{
				$value = $this->safeEncode($value);
				$kv[] = "{$key}={$value}";
			}
		}
		// Form the parameter string.
		$params = implode('&', $kv);

		// Signature base string elements.
		$base = array(
			$method,
			$url,
			$params,
		);

		// Return the base string.
		return implode('&', $this->safeEncode($base));
	}

	/**
	 * Encodes the string or array passed in a way compatible with OAuth.
	 * If an array is passed each array value will will be encoded.
	 *
	 * @param   mixed  $data  The scalar or array to encode.
	 *
	 * @return  string  $data encoded in a way compatible with OAuth.
	 *
	 * @since   3.2.0
	 */
	public function safeEncode($data)
	{
		if (is_array($data))
		{
			return array_map(array($this, 'safeEncode'), $data);
		}
		elseif (is_scalar($data))
		{
			return str_ireplace(
				array('+', '%7E'),
				array(' ', '~'),
				rawurlencode($data)
				);
		}
		else
		{
			return '';
		}
	}

	/**
	 * Method used to generate the current nonce.
	 *
	 * @return  string  The current nonce.
	 *
	 * @since   3.2.0
	 */
	public static function generateNonce()
	{
		$mt = microtime();
		$rand = JCrypt::genRandomBytes();

		// The md5s look nicer than numbers.
		return md5($mt . $rand);
	}

	/**
	 * Prepares the OAuth signing key.
	 *
	 * @return  string  The prepared signing key.
	 *
	 * @since   3.2.0
	 */
	private function _prepareSigningKey()
	{
		return
$this->safeEncode($this->getOption('consumer_secret')) .
'&' . $this->safeEncode(($this->token) ?
$this->token['secret'] : '');
	}

	/**
	 * Returns an HTTP 200 OK response code and a representation of the
requesting user if authentication was successful;
	 * returns a 401 status code and an error message if not.
	 *
	 * @return  array  The decoded JSON response
	 *
	 * @since   3.2.0
	 */
	abstract public function verifyCredentials();

	/**
	 * Get an option from the JOauth1aClient instance.
	 *
	 * @param   string  $key  The name of the option to get
	 *
	 * @return  mixed  The option value
	 *
	 * @since   3.2.0
	 */
	public function getOption($key)
	{
		return $this->options->get($key);
	}

	/**
	 * Set an option for the JOauth1aClient instance.
	 *
	 * @param   string  $key    The name of the option to set
	 * @param   mixed   $value  The option value to set
	 *
	 * @return  JOAuth1Client  This object for method chaining
	 *
	 * @since   3.2.0
	 */
	public function setOption($key, $value)
	{
		$this->options->set($key, $value);

		return $this;
	}

	/**
	 * Get the oauth token key or secret.
	 *
	 * @return  array  The oauth token key and secret.
	 *
	 * @since   3.2.0
	 */
	public function getToken()
	{
		return $this->token;
	}

	/**
	 * Set the oauth token.
	 *
	 * @param   array  $token  The access token key and secret.
	 *
	 * @return  JOAuth1Client  This object for method chaining.
	 *
	 * @since   3.2.0
	 */
	public function setToken($token)
	{
		$this->token = $token;

		return $this;
	}
}
home/lmsyaran/public_html/j3/htaccess.back/joomla/oauth2/client.php000064400000022156151157626300021322
0ustar00<?php
/**
 * @package     Joomla.Platform
 * @subpackage  OAuth2
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE
 */

defined('JPATH_PLATFORM') or die;

use Joomla\Registry\Registry;

/**
 * Joomla Platform class for interacting with an OAuth 2.0 server.
 *
 * @since       3.1.4
 * @deprecated  4.0  Use the `joomla/oauth2` framework package that will be
bundled instead
 */
class JOAuth2Client
{
	/**
	 * @var    Registry  Options for the JOAuth2Client object.
	 * @since  3.1.4
	 */
	protected $options;

	/**
	 * @var    JHttp  The HTTP client object to use in sending HTTP requests.
	 * @since  3.1.4
	 */
	protected $http;

	/**
	 * @var    JInput  The input object to use in retrieving GET/POST data.
	 * @since  3.1.4
	 */
	protected $input;

	/**
	 * @var    JApplicationWeb  The application object to send HTTP headers
for redirects.
	 * @since  3.1.4
	 */
	protected $application;

	/**
	 * Constructor.
	 *
	 * @param   Registry         $options      JOAuth2Client options object
	 * @param   JHttp            $http         The HTTP client object
	 * @param   JInput           $input        The input object
	 * @param   JApplicationWeb  $application  The application object
	 *
	 * @since   3.1.4
	 */
	public function __construct(Registry $options = null, JHttp $http = null,
JInput $input = null, JApplicationWeb $application = null)
	{
		$this->options = isset($options) ? $options : new Registry;
		$this->http = isset($http) ? $http : new JHttp($this->options);
		$this->application = isset($application) ? $application : new
JApplicationWeb;
		$this->input = isset($input) ? $input :
$this->application->input;
	}

	/**
	 * Get the access token or redict to the authentication URL.
	 *
	 * @return  string  The access token
	 *
	 * @since   3.1.4
	 * @throws  RuntimeException
	 */
	public function authenticate()
	{
		if ($data['code'] = $this->input->get('code',
false, 'raw'))
		{
			$data['grant_type'] = 'authorization_code';
			$data['redirect_uri'] =
$this->getOption('redirecturi');
			$data['client_id'] =
$this->getOption('clientid');
			$data['client_secret'] =
$this->getOption('clientsecret');
			$response =
$this->http->post($this->getOption('tokenurl'), $data);

			if ($response->code >= 200 && $response->code < 400)
			{
				if (strpos($response->headers['Content-Type'],
'application/json') === 0)
				{
					$token = array_merge(json_decode($response->body, true),
array('created' => time()));
				}
				else
				{
					parse_str($response->body, $token);
					$token = array_merge($token, array('created' => time()));
				}

				$this->setToken($token);

				return $token;
			}
			else
			{
				throw new RuntimeException('Error code ' . $response->code
. ' received requesting access token: ' . $response->body .
'.');
			}
		}

		if ($this->getOption('sendheaders'))
		{
			$this->application->redirect($this->createUrl());
		}

		return false;
	}

	/**
	 * Verify if the client has been authenticated
	 *
	 * @return  boolean  Is authenticated
	 *
	 * @since   3.1.4
	 */
	public function isAuthenticated()
	{
		$token = $this->getToken();

		if (!$token || !array_key_exists('access_token', $token))
		{
			return false;
		}
		elseif (array_key_exists('expires_in', $token) &&
$token['created'] + $token['expires_in'] < time() +
20)
		{
			return false;
		}
		else
		{
			return true;
		}
	}

	/**
	 * Create the URL for authentication.
	 *
	 * @return  JHttpResponse  The HTTP response
	 *
	 * @since   3.1.4
	 * @throws  InvalidArgumentException
	 */
	public function createUrl()
	{
		if (!$this->getOption('authurl') ||
!$this->getOption('clientid'))
		{
			throw new InvalidArgumentException('Authorization URL and client_id
are required');
		}

		$url = $this->getOption('authurl');

		if (strpos($url, '?'))
		{
			$url .= '&';
		}
		else
		{
			$url .= '?';
		}

		$url .= 'response_type=code';
		$url .= '&client_id=' .
urlencode($this->getOption('clientid'));

		if ($this->getOption('redirecturi'))
		{
			$url .= '&redirect_uri=' .
urlencode($this->getOption('redirecturi'));
		}

		if ($this->getOption('scope'))
		{
			$scope = is_array($this->getOption('scope')) ?
implode(' ', $this->getOption('scope')) :
$this->getOption('scope');
			$url .= '&scope=' . urlencode($scope);
		}

		if ($this->getOption('state'))
		{
			$url .= '&state=' .
urlencode($this->getOption('state'));
		}

		if (is_array($this->getOption('requestparams')))
		{
			foreach ($this->getOption('requestparams') as $key =>
$value)
			{
				$url .= '&' . $key . '=' . urlencode($value);
			}
		}

		return $url;
	}

	/**
	 * Send a signed Oauth request.
	 *
	 * @param   string  $url      The URL for the request.
	 * @param   mixed   $data     The data to include in the request
	 * @param   array   $headers  The headers to send with the request
	 * @param   string  $method   The method with which to send the request
	 * @param   int     $timeout  The timeout for the request
	 *
	 * @return  string  The URL.
	 *
	 * @since   3.1.4
	 * @throws  InvalidArgumentException
	 * @throws  RuntimeException
	 */
	public function query($url, $data = null, $headers = array(), $method =
'get', $timeout = null)
	{
		$token = $this->getToken();

		if (array_key_exists('expires_in', $token) &&
$token['created'] + $token['expires_in'] < time() +
20)
		{
			if (!$this->getOption('userefresh'))
			{
				return false;
			}

			$token = $this->refreshToken($token['refresh_token']);
		}

		if (!$this->getOption('authmethod') ||
$this->getOption('authmethod') == 'bearer')
		{
			$headers['Authorization'] = 'Bearer ' .
$token['access_token'];
		}
		elseif ($this->getOption('authmethod') == 'get')
		{
			if (strpos($url, '?'))
			{
				$url .= '&';
			}
			else
			{
				$url .= '?';
			}

			$url .= $this->getOption('getparam') ?
$this->getOption('getparam') : 'access_token';
			$url .= '=' . $token['access_token'];
		}

		switch ($method)
		{
			case 'head':
			case 'get':
			case 'delete':
			case 'trace':
			$response = $this->http->$method($url, $headers, $timeout);
			break;
			case 'post':
			case 'put':
			case 'patch':
			$response = $this->http->$method($url, $data, $headers, $timeout);
			break;
			default:
			throw new InvalidArgumentException('Unknown HTTP request method:
' . $method . '.');
		}

		if ($response->code < 200 || $response->code >= 400)
		{
			throw new RuntimeException('Error code ' . $response->code
. ' received requesting data: ' . $response->body .
'.');
		}

		return $response;
	}

	/**
	 * Get an option from the JOAuth2Client instance.
	 *
	 * @param   string  $key  The name of the option to get
	 *
	 * @return  mixed  The option value
	 *
	 * @since   3.1.4
	 */
	public function getOption($key)
	{
		return $this->options->get($key);
	}

	/**
	 * Set an option for the JOAuth2Client instance.
	 *
	 * @param   string  $key    The name of the option to set
	 * @param   mixed   $value  The option value to set
	 *
	 * @return  JOAuth2Client  This object for method chaining
	 *
	 * @since   3.1.4
	 */
	public function setOption($key, $value)
	{
		$this->options->set($key, $value);

		return $this;
	}

	/**
	 * Get the access token from the JOAuth2Client instance.
	 *
	 * @return  array  The access token
	 *
	 * @since   3.1.4
	 */
	public function getToken()
	{
		return $this->getOption('accesstoken');
	}

	/**
	 * Set an option for the JOAuth2Client instance.
	 *
	 * @param   array  $value  The access token
	 *
	 * @return  JOAuth2Client  This object for method chaining
	 *
	 * @since   3.1.4
	 */
	public function setToken($value)
	{
		if (is_array($value) && !array_key_exists('expires_in',
$value) && array_key_exists('expires', $value))
		{
			$value['expires_in'] = $value['expires'];
			unset($value['expires']);
		}

		$this->setOption('accesstoken', $value);

		return $this;
	}

	/**
	 * Refresh the access token instance.
	 *
	 * @param   string  $token  The refresh token
	 *
	 * @return  array  The new access token
	 *
	 * @since   3.1.4
	 * @throws  Exception
	 * @throws  RuntimeException
	 */
	public function refreshToken($token = null)
	{
		if (!$this->getOption('userefresh'))
		{
			throw new RuntimeException('Refresh token is not supported for this
OAuth instance.');
		}

		if (!$token)
		{
			$token = $this->getToken();

			if (!array_key_exists('refresh_token', $token))
			{
				throw new RuntimeException('No refresh token is available.');
			}

			$token = $token['refresh_token'];
		}

		$data['grant_type'] = 'refresh_token';
		$data['refresh_token'] = $token;
		$data['client_id'] = $this->getOption('clientid');
		$data['client_secret'] =
$this->getOption('clientsecret');
		$response =
$this->http->post($this->getOption('tokenurl'), $data);

		if ($response->code >= 200 || $response->code < 400)
		{
			if (strpos($response->headers['Content-Type'],
'application/json') === 0)
			{
				$token = array_merge(json_decode($response->body, true),
array('created' => time()));
			}
			else
			{
				parse_str($response->body, $token);
				$token = array_merge($token, array('created' => time()));
			}

			$this->setToken($token);

			return $token;
		}
		else
		{
			throw new Exception('Error code ' . $response->code .
' received refreshing token: ' . $response->body .
'.');
		}
	}
}
home/lmsyaran/public_html/j3/htaccess.back/joomla/oauth1/client.php000064400000033642151157777700021336
0ustar00<?php
/**
 * @package     Joomla.Platform
 * @subpackage  OAuth1
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE
 */

defined('JPATH_PLATFORM') or die();

use Joomla\Registry\Registry;

/**
 * Joomla Platform class for interacting with an OAuth 1.0 and 1.0a server.
 *
 * @since       3.2.0
 * @deprecated  4.0  Use the `joomla/oauth1` framework package that will be
bundled instead
 */
abstract class JOAuth1Client
{
	/**
	 * @var    Registry  Options for the JOAuth1Client object.
	 * @since  3.2.0
	 */
	protected $options;

	/**
	 * @var    array  Contains access token key, secret and verifier.
	 * @since  3.2.0
	 */
	protected $token = array();

	/**
	 * @var    JHttp  The HTTP client object to use in sending HTTP requests.
	 * @since  3.2.0
	 */
	protected $client;

	/**
	 * @var    JInput The input object to use in retrieving GET/POST data.
	 * @since  3.2.0
	 */
	protected $input;

	/**
	 * @var    JApplicationWeb  The application object to send HTTP headers
for redirects.
	 * @since  3.2.0
	 */
	protected $application;

	/**
	 * @var   string  Selects which version of OAuth to use: 1.0 or 1.0a.
	 * @since 3.2.0
	 */
	protected $version;

	/**
	 * Constructor.
	 *
	 * @param   Registry         $options      OAuth1Client options object.
	 * @param   JHttp            $client       The HTTP client object.
	 * @param   JInput           $input        The input object
	 * @param   JApplicationWeb  $application  The application object
	 * @param   string           $version      Specify the OAuth version. By
default we are using 1.0a.
	 *
	 * @since   3.2.0
	 */
	public function __construct(Registry $options = null, JHttp $client =
null, JInput $input = null, JApplicationWeb $application = null,
		$version = null)
	{
		$this->options = isset($options) ? $options : new Registry;
		$this->client = isset($client) ? $client :
JHttpFactory::getHttp($this->options);
		$this->input = isset($input) ? $input :
JFactory::getApplication()->input;
		$this->application = isset($application) ? $application : new
JApplicationWeb;
		$this->version = isset($version) ? $version : '1.0a';
	}

	/**
	 * Method to for the oauth flow.
	 *
	 * @return  array  Contains access token key, secret and verifier.
	 *
	 * @since   3.2.0
	 * @throws  DomainException
	 */
	public function authenticate()
	{
		// Already got some credentials stored?
		if ($this->token)
		{
			$response = $this->verifyCredentials();

			if ($response)
			{
				return $this->token;
			}
			else
			{
				$this->token = null;
			}
		}

		// Check for callback.
		if (strcmp($this->version, '1.0a') === 0)
		{
			$verifier = $this->input->get('oauth_verifier');
		}
		else
		{
			$verifier = $this->input->get('oauth_token');
		}

		if (empty($verifier))
		{
			// Generate a request token.
			$this->_generateRequestToken();

			// Authenticate the user and authorise the app.
			$this->_authorise();
		}

		// Callback
		else
		{
			$session = JFactory::getSession();

			// Get token form session.
			$this->token = array('key' =>
$session->get('key', null, 'oauth_token'),
'secret' => $session->get('secret', null,
'oauth_token'));

			// Verify the returned request token.
			if (strcmp($this->token['key'],
$this->input->get('oauth_token')) !== 0)
			{
				throw new DomainException('Bad session!');
			}

			// Set token verifier for 1.0a.
			if (strcmp($this->version, '1.0a') === 0)
			{
				$this->token['verifier'] =
$this->input->get('oauth_verifier');
			}

			// Generate access token.
			$this->_generateAccessToken();

			// Return the access token.
			return $this->token;
		}
	}

	/**
	 * Method used to get a request token.
	 *
	 * @return  void
	 *
	 * @since   3.2.0
	 * @throws  DomainException
	 */
	private function _generateRequestToken()
	{
		// Set the callback URL.
		if ($this->getOption('callback'))
		{
			$parameters = array(
				'oauth_callback' =>
$this->getOption('callback'),
			);
		}
		else
		{
			$parameters = array();
		}

		// Make an OAuth request for the Request Token.
		$response =
$this->oauthRequest($this->getOption('requestTokenURL'),
'POST', $parameters);

		parse_str($response->body, $params);

		if (strcmp($this->version, '1.0a') === 0 &&
strcmp($params['oauth_callback_confirmed'], 'true') !==
0)
		{
			throw new DomainException('Bad request token!');
		}

		// Save the request token.
		$this->token = array('key' =>
$params['oauth_token'], 'secret' =>
$params['oauth_token_secret']);

		// Save the request token in session
		$session = JFactory::getSession();
		$session->set('key', $this->token['key'],
'oauth_token');
		$session->set('secret', $this->token['secret'],
'oauth_token');
	}

	/**
	 * Method used to authorise the application.
	 *
	 * @return  void
	 *
	 * @since   3.2.0
	 */
	private function _authorise()
	{
		$url = $this->getOption('authoriseURL') .
'?oauth_token=' . $this->token['key'];

		if ($this->getOption('scope'))
		{
			$scope = is_array($this->getOption('scope')) ?
implode(' ', $this->getOption('scope')) :
$this->getOption('scope');
			$url .= '&scope=' . urlencode($scope);
		}

		if ($this->getOption('sendheaders'))
		{
			$this->application->redirect($url);
		}
	}

	/**
	 * Method used to get an access token.
	 *
	 * @return  void
	 *
	 * @since   3.2.0
	 */
	private function _generateAccessToken()
	{
		// Set the parameters.
		$parameters = array(
			'oauth_token' => $this->token['key'],
		);

		if (strcmp($this->version, '1.0a') === 0)
		{
			$parameters = array_merge($parameters, array('oauth_verifier'
=> $this->token['verifier']));
		}

		// Make an OAuth request for the Access Token.
		$response =
$this->oauthRequest($this->getOption('accessTokenURL'),
'POST', $parameters);

		parse_str($response->body, $params);

		// Save the access token.
		$this->token = array('key' =>
$params['oauth_token'], 'secret' =>
$params['oauth_token_secret']);
	}

	/**
	 * Method used to make an OAuth request.
	 *
	 * @param   string  $url         The request URL.
	 * @param   string  $method      The request method.
	 * @param   array   $parameters  Array containing request parameters.
	 * @param   mixed   $data        The POST request data.
	 * @param   array   $headers     An array of name-value pairs to include
in the header of the request
	 *
	 * @return  JHttpResponse
	 *
	 * @since   3.2.0
	 * @throws  DomainException
	 */
	public function oauthRequest($url, $method, $parameters, $data = array(),
$headers = array())
	{
		// Set the parameters.
		$defaults = array(
			'oauth_consumer_key' =>
$this->getOption('consumer_key'),
			'oauth_signature_method' => 'HMAC-SHA1',
			'oauth_version' => '1.0',
			'oauth_nonce' => $this->generateNonce(),
			'oauth_timestamp' => time(),
		);

		$parameters = array_merge($parameters, $defaults);

		// Do not encode multipart parameters. Do not include $data in the
signature if $data is not array.
		if (isset($headers['Content-Type']) &&
strpos($headers['Content-Type'], 'multipart/form-data')
!== false || !is_array($data))
		{
			$oauth_headers = $parameters;
		}
		else
		{
			// Use all parameters for the signature.
			$oauth_headers = array_merge($parameters, $data);
		}

		// Sign the request.
		$oauth_headers = $this->_signRequest($url, $method, $oauth_headers);

		// Get parameters for the Authorisation header.
		if (is_array($data))
		{
			$oauth_headers = array_diff_key($oauth_headers, $data);
		}

		// Send the request.
		switch ($method)
		{
			case 'GET':
				$url = $this->toUrl($url, $data);
				$response = $this->client->get($url,
array('Authorization' =>
$this->_createHeader($oauth_headers)));
				break;
			case 'POST':
				$headers = array_merge($headers, array('Authorization' =>
$this->_createHeader($oauth_headers)));
				$response = $this->client->post($url, $data, $headers);
				break;
			case 'PUT':
				$headers = array_merge($headers, array('Authorization' =>
$this->_createHeader($oauth_headers)));
				$response = $this->client->put($url, $data, $headers);
				break;
			case 'DELETE':
				$headers = array_merge($headers, array('Authorization' =>
$this->_createHeader($oauth_headers)));
				$response = $this->client->delete($url, $headers);
				break;
		}

		// Validate the response code.
		$this->validateResponse($url, $response);

		return $response;
	}

	/**
	 * Method to validate a response.
	 *
	 * @param   string         $url       The request URL.
	 * @param   JHttpResponse  $response  The response to validate.
	 *
	 * @return  void
	 *
	 * @since   3.2.0
	 * @throws  DomainException
	 */
	abstract public function validateResponse($url, $response);

	/**
	 * Method used to create the header for the POST request.
	 *
	 * @param   array  $parameters  Array containing request parameters.
	 *
	 * @return  string  The header.
	 *
	 * @since   3.2.0
	 */
	private function _createHeader($parameters)
	{
		$header = 'OAuth ';

		foreach ($parameters as $key => $value)
		{
			if (!strcmp($header, 'OAuth '))
			{
				$header .= $key . '="' . $this->safeEncode($value) .
'"';
			}
			else
			{
				$header .= ', ' . $key . '="' . $value .
'"';
			}
		}

		return $header;
	}

	/**
	 * Method to create the URL formed string with the parameters.
	 *
	 * @param   string  $url         The request URL.
	 * @param   array   $parameters  Array containing request parameters.
	 *
	 * @return  string  The formed URL.
	 *
	 * @since   3.2.0
	 */
	public function toUrl($url, $parameters)
	{
		foreach ($parameters as $key => $value)
		{
			if (is_array($value))
			{
				foreach ($value as $v)
				{
					if (strpos($url, '?') === false)
					{
						$url .= '?' . $key . '=' . $v;
					}
					else
					{
						$url .= '&' . $key . '=' . $v;
					}
				}
			}
			else
			{
				if (strpos($value, ' ') !== false)
				{
					$value = $this->safeEncode($value);
				}

				if (strpos($url, '?') === false)
				{
					$url .= '?' . $key . '=' . $value;
				}
				else
				{
					$url .= '&' . $key . '=' . $value;
				}
			}
		}

		return $url;
	}

	/**
	 * Method used to sign requests.
	 *
	 * @param   string  $url         The URL to sign.
	 * @param   string  $method      The request method.
	 * @param   array   $parameters  Array containing request parameters.
	 *
	 * @return  array
	 *
	 * @since   3.2.0
	 */
	private function _signRequest($url, $method, $parameters)
	{
		// Create the signature base string.
		$base = $this->_baseString($url, $method, $parameters);

		$parameters['oauth_signature'] = $this->safeEncode(
			base64_encode(
				hash_hmac('sha1', $base, $this->_prepareSigningKey(),
true)
				)
			);

		return $parameters;
	}

	/**
	 * Prepare the signature base string.
	 *
	 * @param   string  $url         The URL to sign.
	 * @param   string  $method      The request method.
	 * @param   array   $parameters  Array containing request parameters.
	 *
	 * @return  string  The base string.
	 *
	 * @since   3.2.0
	 */
	private function _baseString($url, $method, $parameters)
	{
		// Sort the parameters alphabetically
		uksort($parameters, 'strcmp');

		// Encode parameters.
		foreach ($parameters as $key => $value)
		{
			$key = $this->safeEncode($key);

			if (is_array($value))
			{
				foreach ($value as $v)
				{
					$v = $this->safeEncode($v);
					$kv[] = "{$key}={$v}";
				}
			}
			else
			{
				$value = $this->safeEncode($value);
				$kv[] = "{$key}={$value}";
			}
		}
		// Form the parameter string.
		$params = implode('&', $kv);

		// Signature base string elements.
		$base = array(
			$method,
			$url,
			$params,
		);

		// Return the base string.
		return implode('&', $this->safeEncode($base));
	}

	/**
	 * Encodes the string or array passed in a way compatible with OAuth.
	 * If an array is passed each array value will will be encoded.
	 *
	 * @param   mixed  $data  The scalar or array to encode.
	 *
	 * @return  string  $data encoded in a way compatible with OAuth.
	 *
	 * @since   3.2.0
	 */
	public function safeEncode($data)
	{
		if (is_array($data))
		{
			return array_map(array($this, 'safeEncode'), $data);
		}
		elseif (is_scalar($data))
		{
			return str_ireplace(
				array('+', '%7E'),
				array(' ', '~'),
				rawurlencode($data)
				);
		}
		else
		{
			return '';
		}
	}

	/**
	 * Method used to generate the current nonce.
	 *
	 * @return  string  The current nonce.
	 *
	 * @since   3.2.0
	 */
	public static function generateNonce()
	{
		$mt = microtime();
		$rand = JCrypt::genRandomBytes();

		// The md5s look nicer than numbers.
		return md5($mt . $rand);
	}

	/**
	 * Prepares the OAuth signing key.
	 *
	 * @return  string  The prepared signing key.
	 *
	 * @since   3.2.0
	 */
	private function _prepareSigningKey()
	{
		return
$this->safeEncode($this->getOption('consumer_secret')) .
'&' . $this->safeEncode(($this->token) ?
$this->token['secret'] : '');
	}

	/**
	 * Returns an HTTP 200 OK response code and a representation of the
requesting user if authentication was successful;
	 * returns a 401 status code and an error message if not.
	 *
	 * @return  array  The decoded JSON response
	 *
	 * @since   3.2.0
	 */
	abstract public function verifyCredentials();

	/**
	 * Get an option from the JOauth1aClient instance.
	 *
	 * @param   string  $key  The name of the option to get
	 *
	 * @return  mixed  The option value
	 *
	 * @since   3.2.0
	 */
	public function getOption($key)
	{
		return $this->options->get($key);
	}

	/**
	 * Set an option for the JOauth1aClient instance.
	 *
	 * @param   string  $key    The name of the option to set
	 * @param   mixed   $value  The option value to set
	 *
	 * @return  JOAuth1Client  This object for method chaining
	 *
	 * @since   3.2.0
	 */
	public function setOption($key, $value)
	{
		$this->options->set($key, $value);

		return $this;
	}

	/**
	 * Get the oauth token key or secret.
	 *
	 * @return  array  The oauth token key and secret.
	 *
	 * @since   3.2.0
	 */
	public function getToken()
	{
		return $this->token;
	}

	/**
	 * Set the oauth token.
	 *
	 * @param   array  $token  The access token key and secret.
	 *
	 * @return  JOAuth1Client  This object for method chaining.
	 *
	 * @since   3.2.0
	 */
	public function setToken($token)
	{
		$this->token = $token;

		return $this;
	}
}
home/lmsyaran/public_html/j3/libraries/joomla/oauth1/client.php000064400000033642151160261200020567
0ustar00<?php
/**
 * @package     Joomla.Platform
 * @subpackage  OAuth1
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE
 */

defined('JPATH_PLATFORM') or die();

use Joomla\Registry\Registry;

/**
 * Joomla Platform class for interacting with an OAuth 1.0 and 1.0a server.
 *
 * @since       3.2.0
 * @deprecated  4.0  Use the `joomla/oauth1` framework package that will be
bundled instead
 */
abstract class JOAuth1Client
{
	/**
	 * @var    Registry  Options for the JOAuth1Client object.
	 * @since  3.2.0
	 */
	protected $options;

	/**
	 * @var    array  Contains access token key, secret and verifier.
	 * @since  3.2.0
	 */
	protected $token = array();

	/**
	 * @var    JHttp  The HTTP client object to use in sending HTTP requests.
	 * @since  3.2.0
	 */
	protected $client;

	/**
	 * @var    JInput The input object to use in retrieving GET/POST data.
	 * @since  3.2.0
	 */
	protected $input;

	/**
	 * @var    JApplicationWeb  The application object to send HTTP headers
for redirects.
	 * @since  3.2.0
	 */
	protected $application;

	/**
	 * @var   string  Selects which version of OAuth to use: 1.0 or 1.0a.
	 * @since 3.2.0
	 */
	protected $version;

	/**
	 * Constructor.
	 *
	 * @param   Registry         $options      OAuth1Client options object.
	 * @param   JHttp            $client       The HTTP client object.
	 * @param   JInput           $input        The input object
	 * @param   JApplicationWeb  $application  The application object
	 * @param   string           $version      Specify the OAuth version. By
default we are using 1.0a.
	 *
	 * @since   3.2.0
	 */
	public function __construct(Registry $options = null, JHttp $client =
null, JInput $input = null, JApplicationWeb $application = null,
		$version = null)
	{
		$this->options = isset($options) ? $options : new Registry;
		$this->client = isset($client) ? $client :
JHttpFactory::getHttp($this->options);
		$this->input = isset($input) ? $input :
JFactory::getApplication()->input;
		$this->application = isset($application) ? $application : new
JApplicationWeb;
		$this->version = isset($version) ? $version : '1.0a';
	}

	/**
	 * Method to for the oauth flow.
	 *
	 * @return  array  Contains access token key, secret and verifier.
	 *
	 * @since   3.2.0
	 * @throws  DomainException
	 */
	public function authenticate()
	{
		// Already got some credentials stored?
		if ($this->token)
		{
			$response = $this->verifyCredentials();

			if ($response)
			{
				return $this->token;
			}
			else
			{
				$this->token = null;
			}
		}

		// Check for callback.
		if (strcmp($this->version, '1.0a') === 0)
		{
			$verifier = $this->input->get('oauth_verifier');
		}
		else
		{
			$verifier = $this->input->get('oauth_token');
		}

		if (empty($verifier))
		{
			// Generate a request token.
			$this->_generateRequestToken();

			// Authenticate the user and authorise the app.
			$this->_authorise();
		}

		// Callback
		else
		{
			$session = JFactory::getSession();

			// Get token form session.
			$this->token = array('key' =>
$session->get('key', null, 'oauth_token'),
'secret' => $session->get('secret', null,
'oauth_token'));

			// Verify the returned request token.
			if (strcmp($this->token['key'],
$this->input->get('oauth_token')) !== 0)
			{
				throw new DomainException('Bad session!');
			}

			// Set token verifier for 1.0a.
			if (strcmp($this->version, '1.0a') === 0)
			{
				$this->token['verifier'] =
$this->input->get('oauth_verifier');
			}

			// Generate access token.
			$this->_generateAccessToken();

			// Return the access token.
			return $this->token;
		}
	}

	/**
	 * Method used to get a request token.
	 *
	 * @return  void
	 *
	 * @since   3.2.0
	 * @throws  DomainException
	 */
	private function _generateRequestToken()
	{
		// Set the callback URL.
		if ($this->getOption('callback'))
		{
			$parameters = array(
				'oauth_callback' =>
$this->getOption('callback'),
			);
		}
		else
		{
			$parameters = array();
		}

		// Make an OAuth request for the Request Token.
		$response =
$this->oauthRequest($this->getOption('requestTokenURL'),
'POST', $parameters);

		parse_str($response->body, $params);

		if (strcmp($this->version, '1.0a') === 0 &&
strcmp($params['oauth_callback_confirmed'], 'true') !==
0)
		{
			throw new DomainException('Bad request token!');
		}

		// Save the request token.
		$this->token = array('key' =>
$params['oauth_token'], 'secret' =>
$params['oauth_token_secret']);

		// Save the request token in session
		$session = JFactory::getSession();
		$session->set('key', $this->token['key'],
'oauth_token');
		$session->set('secret', $this->token['secret'],
'oauth_token');
	}

	/**
	 * Method used to authorise the application.
	 *
	 * @return  void
	 *
	 * @since   3.2.0
	 */
	private function _authorise()
	{
		$url = $this->getOption('authoriseURL') .
'?oauth_token=' . $this->token['key'];

		if ($this->getOption('scope'))
		{
			$scope = is_array($this->getOption('scope')) ?
implode(' ', $this->getOption('scope')) :
$this->getOption('scope');
			$url .= '&scope=' . urlencode($scope);
		}

		if ($this->getOption('sendheaders'))
		{
			$this->application->redirect($url);
		}
	}

	/**
	 * Method used to get an access token.
	 *
	 * @return  void
	 *
	 * @since   3.2.0
	 */
	private function _generateAccessToken()
	{
		// Set the parameters.
		$parameters = array(
			'oauth_token' => $this->token['key'],
		);

		if (strcmp($this->version, '1.0a') === 0)
		{
			$parameters = array_merge($parameters, array('oauth_verifier'
=> $this->token['verifier']));
		}

		// Make an OAuth request for the Access Token.
		$response =
$this->oauthRequest($this->getOption('accessTokenURL'),
'POST', $parameters);

		parse_str($response->body, $params);

		// Save the access token.
		$this->token = array('key' =>
$params['oauth_token'], 'secret' =>
$params['oauth_token_secret']);
	}

	/**
	 * Method used to make an OAuth request.
	 *
	 * @param   string  $url         The request URL.
	 * @param   string  $method      The request method.
	 * @param   array   $parameters  Array containing request parameters.
	 * @param   mixed   $data        The POST request data.
	 * @param   array   $headers     An array of name-value pairs to include
in the header of the request
	 *
	 * @return  JHttpResponse
	 *
	 * @since   3.2.0
	 * @throws  DomainException
	 */
	public function oauthRequest($url, $method, $parameters, $data = array(),
$headers = array())
	{
		// Set the parameters.
		$defaults = array(
			'oauth_consumer_key' =>
$this->getOption('consumer_key'),
			'oauth_signature_method' => 'HMAC-SHA1',
			'oauth_version' => '1.0',
			'oauth_nonce' => $this->generateNonce(),
			'oauth_timestamp' => time(),
		);

		$parameters = array_merge($parameters, $defaults);

		// Do not encode multipart parameters. Do not include $data in the
signature if $data is not array.
		if (isset($headers['Content-Type']) &&
strpos($headers['Content-Type'], 'multipart/form-data')
!== false || !is_array($data))
		{
			$oauth_headers = $parameters;
		}
		else
		{
			// Use all parameters for the signature.
			$oauth_headers = array_merge($parameters, $data);
		}

		// Sign the request.
		$oauth_headers = $this->_signRequest($url, $method, $oauth_headers);

		// Get parameters for the Authorisation header.
		if (is_array($data))
		{
			$oauth_headers = array_diff_key($oauth_headers, $data);
		}

		// Send the request.
		switch ($method)
		{
			case 'GET':
				$url = $this->toUrl($url, $data);
				$response = $this->client->get($url,
array('Authorization' =>
$this->_createHeader($oauth_headers)));
				break;
			case 'POST':
				$headers = array_merge($headers, array('Authorization' =>
$this->_createHeader($oauth_headers)));
				$response = $this->client->post($url, $data, $headers);
				break;
			case 'PUT':
				$headers = array_merge($headers, array('Authorization' =>
$this->_createHeader($oauth_headers)));
				$response = $this->client->put($url, $data, $headers);
				break;
			case 'DELETE':
				$headers = array_merge($headers, array('Authorization' =>
$this->_createHeader($oauth_headers)));
				$response = $this->client->delete($url, $headers);
				break;
		}

		// Validate the response code.
		$this->validateResponse($url, $response);

		return $response;
	}

	/**
	 * Method to validate a response.
	 *
	 * @param   string         $url       The request URL.
	 * @param   JHttpResponse  $response  The response to validate.
	 *
	 * @return  void
	 *
	 * @since   3.2.0
	 * @throws  DomainException
	 */
	abstract public function validateResponse($url, $response);

	/**
	 * Method used to create the header for the POST request.
	 *
	 * @param   array  $parameters  Array containing request parameters.
	 *
	 * @return  string  The header.
	 *
	 * @since   3.2.0
	 */
	private function _createHeader($parameters)
	{
		$header = 'OAuth ';

		foreach ($parameters as $key => $value)
		{
			if (!strcmp($header, 'OAuth '))
			{
				$header .= $key . '="' . $this->safeEncode($value) .
'"';
			}
			else
			{
				$header .= ', ' . $key . '="' . $value .
'"';
			}
		}

		return $header;
	}

	/**
	 * Method to create the URL formed string with the parameters.
	 *
	 * @param   string  $url         The request URL.
	 * @param   array   $parameters  Array containing request parameters.
	 *
	 * @return  string  The formed URL.
	 *
	 * @since   3.2.0
	 */
	public function toUrl($url, $parameters)
	{
		foreach ($parameters as $key => $value)
		{
			if (is_array($value))
			{
				foreach ($value as $v)
				{
					if (strpos($url, '?') === false)
					{
						$url .= '?' . $key . '=' . $v;
					}
					else
					{
						$url .= '&' . $key . '=' . $v;
					}
				}
			}
			else
			{
				if (strpos($value, ' ') !== false)
				{
					$value = $this->safeEncode($value);
				}

				if (strpos($url, '?') === false)
				{
					$url .= '?' . $key . '=' . $value;
				}
				else
				{
					$url .= '&' . $key . '=' . $value;
				}
			}
		}

		return $url;
	}

	/**
	 * Method used to sign requests.
	 *
	 * @param   string  $url         The URL to sign.
	 * @param   string  $method      The request method.
	 * @param   array   $parameters  Array containing request parameters.
	 *
	 * @return  array
	 *
	 * @since   3.2.0
	 */
	private function _signRequest($url, $method, $parameters)
	{
		// Create the signature base string.
		$base = $this->_baseString($url, $method, $parameters);

		$parameters['oauth_signature'] = $this->safeEncode(
			base64_encode(
				hash_hmac('sha1', $base, $this->_prepareSigningKey(),
true)
				)
			);

		return $parameters;
	}

	/**
	 * Prepare the signature base string.
	 *
	 * @param   string  $url         The URL to sign.
	 * @param   string  $method      The request method.
	 * @param   array   $parameters  Array containing request parameters.
	 *
	 * @return  string  The base string.
	 *
	 * @since   3.2.0
	 */
	private function _baseString($url, $method, $parameters)
	{
		// Sort the parameters alphabetically
		uksort($parameters, 'strcmp');

		// Encode parameters.
		foreach ($parameters as $key => $value)
		{
			$key = $this->safeEncode($key);

			if (is_array($value))
			{
				foreach ($value as $v)
				{
					$v = $this->safeEncode($v);
					$kv[] = "{$key}={$v}";
				}
			}
			else
			{
				$value = $this->safeEncode($value);
				$kv[] = "{$key}={$value}";
			}
		}
		// Form the parameter string.
		$params = implode('&', $kv);

		// Signature base string elements.
		$base = array(
			$method,
			$url,
			$params,
		);

		// Return the base string.
		return implode('&', $this->safeEncode($base));
	}

	/**
	 * Encodes the string or array passed in a way compatible with OAuth.
	 * If an array is passed each array value will will be encoded.
	 *
	 * @param   mixed  $data  The scalar or array to encode.
	 *
	 * @return  string  $data encoded in a way compatible with OAuth.
	 *
	 * @since   3.2.0
	 */
	public function safeEncode($data)
	{
		if (is_array($data))
		{
			return array_map(array($this, 'safeEncode'), $data);
		}
		elseif (is_scalar($data))
		{
			return str_ireplace(
				array('+', '%7E'),
				array(' ', '~'),
				rawurlencode($data)
				);
		}
		else
		{
			return '';
		}
	}

	/**
	 * Method used to generate the current nonce.
	 *
	 * @return  string  The current nonce.
	 *
	 * @since   3.2.0
	 */
	public static function generateNonce()
	{
		$mt = microtime();
		$rand = JCrypt::genRandomBytes();

		// The md5s look nicer than numbers.
		return md5($mt . $rand);
	}

	/**
	 * Prepares the OAuth signing key.
	 *
	 * @return  string  The prepared signing key.
	 *
	 * @since   3.2.0
	 */
	private function _prepareSigningKey()
	{
		return
$this->safeEncode($this->getOption('consumer_secret')) .
'&' . $this->safeEncode(($this->token) ?
$this->token['secret'] : '');
	}

	/**
	 * Returns an HTTP 200 OK response code and a representation of the
requesting user if authentication was successful;
	 * returns a 401 status code and an error message if not.
	 *
	 * @return  array  The decoded JSON response
	 *
	 * @since   3.2.0
	 */
	abstract public function verifyCredentials();

	/**
	 * Get an option from the JOauth1aClient instance.
	 *
	 * @param   string  $key  The name of the option to get
	 *
	 * @return  mixed  The option value
	 *
	 * @since   3.2.0
	 */
	public function getOption($key)
	{
		return $this->options->get($key);
	}

	/**
	 * Set an option for the JOauth1aClient instance.
	 *
	 * @param   string  $key    The name of the option to set
	 * @param   mixed   $value  The option value to set
	 *
	 * @return  JOAuth1Client  This object for method chaining
	 *
	 * @since   3.2.0
	 */
	public function setOption($key, $value)
	{
		$this->options->set($key, $value);

		return $this;
	}

	/**
	 * Get the oauth token key or secret.
	 *
	 * @return  array  The oauth token key and secret.
	 *
	 * @since   3.2.0
	 */
	public function getToken()
	{
		return $this->token;
	}

	/**
	 * Set the oauth token.
	 *
	 * @param   array  $token  The access token key and secret.
	 *
	 * @return  JOAuth1Client  This object for method chaining.
	 *
	 * @since   3.2.0
	 */
	public function setToken($token)
	{
		$this->token = $token;

		return $this;
	}
}