File: C:/xampp/htdocs/wordpress/wp-content/pluginsBK/wp-to-twitter/tmhOAuth/tmhOAuth.php
<?php
/**
* tmhOAuth
*
* An OAuth 1.0A library written in PHP.
* The library supports file uploading using multipart/form as well as general
* REST requests. OAuth authentication is sent using the an Authorization Header.
*
* @author themattharris
* @version 0.7.5
*
* 20 February 2013
*/
class tmhOAuth {
const VERSION = '0.7.5';
var $response = array();
/**
* Creates a new tmhOAuth object
*
* @param string $config , the configuration to use for this request
*
* @return void
*/
public function __construct( $config = array() ) {
$this->params = array();
$this->headers = array();
$this->auto_fixed_time = false;
$this->buffer = null;
// default configuration options
$this->config = array_merge(
array(
// leave 'user_agent' blank for default, otherwise set this to
// something that clearly identifies your app
'user_agent' => '',
// default timezone for requests
'timezone' => 'UTC',
'use_ssl' => true,
'host' => 'api.twitter.com',
'consumer_key' => '',
'consumer_secret' => '',
'user_token' => '',
'user_secret' => '',
'force_nonce' => false,
'nonce' => false,
// used for checking signatures. leave as false for auto
'force_timestamp' => false,
'timestamp' => false,
// used for checking signatures. leave as false for auto
// oauth signing variables that are not dynamic
'oauth_version' => '1.0',
'oauth_signature_method' => 'HMAC-SHA1',
// you probably don't want to change any of these curl values
'curl_connecttimeout' => 30,
'curl_timeout' => 10,
// for security this should always be set to 2.
'curl_ssl_verifyhost' => 2,
// for security this should always be set to true.
'curl_ssl_verifypeer' => true,
// you can get the latest cacert.pem from here http://curl.haxx.se/ca/cacert.pem
'curl_cainfo' => dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'cacert.pem',
'curl_capath' => dirname( __FILE__ ),
'curl_followlocation' => false,
// whether to follow redirects or not
// support for proxy servers
'curl_proxy' => false,
// really you don't want to use this if you are using streaming
'curl_proxyuserpwd' => false,
// format username:password for proxy, if required
'curl_encoding' => '',
// leave blank for all supported formats, else use gzip, deflate, identity
// streaming API
'is_streaming' => false,
'streaming_eol' => "\r\n",
'streaming_metrics_interval' => 60,
// header or querystring. You should always use header!
// this is just to help me debug other developers implementations
'as_header' => true,
'debug' => false,
),
$config
);
$this->set_user_agent();
date_default_timezone_set( $this->config['timezone'] );
}
/**
* Sets the useragent for PHP to use
* If '$this->config['user_agent']' already has a value it is used instead of one
* being generated.
*
* @return void value is stored to the config array class variable
*/
private function set_user_agent() {
if ( ! empty( $this->config['user_agent'] ) ) {
return;
}
if ( $this->config['curl_ssl_verifyhost'] && $this->config['curl_ssl_verifypeer'] ) {
$ssl = '+SSL';
} else {
$ssl = '-SSL';
}
$ua = 'tmhOAuth ' . self::VERSION . $ssl . ' - //github.com/themattharris/tmhOAuth';
$this->config['user_agent'] = $ua;
}
/**
* Generates a random OAuth nonce.
* If 'force_nonce' is true a nonce is not generated and the value in the configuration will be retained.
*
* @param string $length how many characters the nonce should be before MD5 hashing. default 12
* @param string $include_time whether to include time at the beginning of the nonce. default true
*
* @return void value is stored to the config array class variable
*/
private function create_nonce( $length = 12, $include_time = true ) {
if ( $this->config['force_nonce'] == false ) {
$sequence = array_merge( range( 0, 9 ), range( 'A', 'Z' ), range( 'a', 'z' ) );
$length = $length > count( $sequence ) ? count( $sequence ) : $length;
shuffle( $sequence );
$prefix = $include_time ? microtime() : '';
$this->config['nonce'] = md5( substr( $prefix . implode( '', $sequence ), 0, $length ) );
}
}
/**
* Generates a timestamp.
* If 'force_timestamp' is true a nonce is not generated and the value in the configuration will be retained.
*
* @return void value is stored to the config array class variable
*/
private function create_timestamp() {
$this->config['timestamp'] = ( $this->config['force_timestamp'] == false ? time() : $this->config['timestamp'] );
}
/**
* 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 $data encoded in a way compatible with OAuth
*/
private function safe_encode( $data ) {
if ( is_array( $data ) ) {
return array_map( array( $this, 'safe_encode' ), $data );
} else if ( is_scalar( $data ) ) {
return str_ireplace(
array( '+', '%7E' ),
array( ' ', '~' ),
rawurlencode( $data )
);
} else {
return '';
}
}
/**
* Decodes the string or array from it's URL encoded form
* If an array is passed each array value will will be decoded.
*
* @param mixed $data the scalar or array to decode
*
* @return string $data decoded from the URL encoded form
*/
private function safe_decode( $data ) {
if ( is_array( $data ) ) {
return array_map( array( $this, 'safe_decode' ), $data );
} else if ( is_scalar( $data ) ) {
return rawurldecode( $data );
} else {
return '';
}
}
/**
* Returns an array of the standard OAuth parameters.
*
* @return array all required OAuth parameters, safely encoded
*/
private function get_defaults() {
$defaults = array(
'oauth_version' => $this->config['oauth_version'],
'oauth_nonce' => $this->config['nonce'],
'oauth_timestamp' => $this->config['timestamp'],
'oauth_consumer_key' => $this->config['consumer_key'],
'oauth_signature_method' => $this->config['oauth_signature_method'],
);
// include the user token if it exists
if ( $this->config['user_token'] ) {
$defaults['oauth_token'] = $this->config['user_token'];
}
// safely encode
foreach ( $defaults as $k => $v ) {
$_defaults[ $this->safe_encode( $k ) ] = $this->safe_encode( $v );
}
return $_defaults;
}
/**
* Extracts and decodes OAuth parameters from the passed string
*
* @param string $body the response body from an OAuth flow method
*
* @return array the response body safely decoded to an array of key => values
*/
public function extract_params( $body ) {
$kvs = explode( '&', $body );
$decoded = array();
foreach ( $kvs as $kv ) {
$kv = explode( '=', $kv, 2 );
$kv[0] = $this->safe_decode( $kv[0] );
$kv[1] = $this->safe_decode( $kv[1] );
$decoded[ $kv[0] ] = $kv[1];
}
return $decoded;
}
/**
* Prepares the HTTP method for use in the base string by converting it to
* uppercase.
*
* @param string $method an HTTP method such as GET or POST
*
* @return void value is stored to the class variable 'method'
*/
private function prepare_method( $method ) {
$this->method = strtoupper( $method );
}
/**
* Prepares the URL for use in the base string by ripping it apart and
* reconstructing it.
*
* Ref: 3.4.1.2
*
* @param string $url the request URL
*
* @return void value is stored to the class variable 'url'
*/
private function prepare_url( $url ) {
$parts = parse_url( $url );
$port = isset( $parts['port'] ) ? $parts['port'] : false;
$scheme = $parts['scheme'];
$host = $parts['host'];
$path = isset( $parts['path'] ) ? $parts['path'] : false;
$port or $port = ( $scheme == 'https' ) ? '443' : '80';
if ( ( $scheme == 'https' && $port != '443' )
|| ( $scheme == 'http' && $port != '80' )
) {
$host = "$host:$port";
}
// the scheme and host MUST be lowercase
$this->url = strtolower( "$scheme://$host" );
// but not the path
$this->url .= $path;
}
/**
* Prepares all parameters for the base string and request.
* Multipart parameters are ignored as they are not defined in the specification,
* all other types of parameter are encoded for compatibility with OAuth.
*
* @param array $params the parameters for the request
*
* @return void prepared values are stored in the class variable 'signing_params'
*/
private function prepare_params( $params ) {
// do not encode multipart parameters, leave them alone
if ( $this->config['multipart'] ) {
$this->request_params = $params;
$params = array();
}
// signing parameters are request parameters + OAuth default parameters
$this->signing_params = array_merge( $this->get_defaults(), (array) $params );
// Remove oauth_signature if present
// Ref: Spec: 9.1.1 ("The oauth_signature parameter MUST be excluded.")
if ( isset( $this->signing_params['oauth_signature'] ) ) {
unset( $this->signing_params['oauth_signature'] );
}
// Parameters are sorted by name, using lexicographical byte value ordering.
// Ref: Spec: 9.1.1 (1)
uksort( $this->signing_params, 'strcmp' );
// encode. Also sort the signed parameters from the POST parameters
foreach ( $this->signing_params as $k => $v ) {
$k = $this->safe_encode( $k );
if ( is_array( $v ) ) {
$v = implode( ',', $v );
}
$v = $this->safe_encode( $v );
$_signing_params[ $k ] = $v;
$kv[] = "{$k}={$v}";
}
// auth params = the default oauth params which are present in our collection of signing params
$this->auth_params = array_intersect_key( $this->get_defaults(), $_signing_params );
if ( isset( $_signing_params['oauth_callback'] ) ) {
$this->auth_params['oauth_callback'] = $_signing_params['oauth_callback'];
unset( $_signing_params['oauth_callback'] );
}
if ( isset( $_signing_params['oauth_verifier'] ) ) {
$this->auth_params['oauth_verifier'] = $_signing_params['oauth_verifier'];
unset( $_signing_params['oauth_verifier'] );
}
// request_params is already set if we're doing multipart, if not we need to set them now
if ( ! $this->config['multipart'] ) {
$this->request_params = array_diff_key( $_signing_params, $this->get_defaults() );
}
// create the parameter part of the base string
$this->signing_params = implode( '&', $kv );
}
/**
* Prepares the OAuth signing key
*
* @return void prepared signing key is stored in the class variable 'signing_key'
*/
private function prepare_signing_key() {
$this->signing_key = $this->safe_encode( $this->config['consumer_secret'] ) . '&' . $this->safe_encode( $this->config['user_secret'] );
}
/**
* Prepare the base string.
* Ref: Spec: 9.1.3 ("Concatenate Request Elements")
*
* @return void prepared base string is stored in the class variable 'base_string'
*/
private function prepare_base_string() {
$url = $this->url;
# if the host header is set we need to rewrite the basestring to use
# that, instead of the request host. otherwise the signature won't match
# on the server side
if ( ! empty( $this->custom_headers['Host'] ) ) {
$url = str_ireplace(
$this->config['host'],
$this->custom_headers['Host'],
$url
);
}
$base = array(
$this->method,
$url,
$this->signing_params
);
$this->base_string = implode( '&', $this->safe_encode( $base ) );
}
/**
* Prepares the Authorization header
*
* @return void prepared authorization header is stored in the class variable headers['Authorization']
*/
private function prepare_auth_header() {
unset( $this->headers['Authorization'] );
uksort( $this->auth_params, 'strcmp' );
if ( ! $this->config['as_header'] ) :
$this->request_params = array_merge( $this->request_params, $this->auth_params );
return;
endif;
foreach ( $this->auth_params as $k => $v ) {
$kv[] = "{$k}=\"{$v}\"";
}
$this->auth_header = 'OAuth ' . implode( ', ', $kv );
$this->headers['Authorization'] = $this->auth_header;
}
/**
* Signs the request and adds the OAuth signature. This runs all the request
* parameter preparation methods.
*
* @param string $method the HTTP method being used. e.g. POST, GET, HEAD etc
* @param string $url the request URL without query string parameters
* @param array $params the request parameters as an array of key=value pairs
* @param string $useauth whether to use authentication when making the request.
*
* @return void
*/
private function sign( $method, $url, $params, $useauth ) {
$this->prepare_method( $method );
$this->prepare_url( $url );
$this->prepare_params( $params );
// we don't sign anything is we're not using auth
if ( $useauth ) {
$this->prepare_base_string();
$this->prepare_signing_key();
$this->auth_params['oauth_signature'] = $this->safe_encode(
base64_encode(
hash_hmac(
'sha1', $this->base_string, $this->signing_key, true
) ) );
$this->prepare_auth_header();
}
}
/**
* Make an HTTP request using this library. This method doesn't return anything.
* Instead the response should be inspected directly.
*
* @param string $method the HTTP method being used. e.g. POST, GET, HEAD etc
* @param string $url the request URL without query string parameters
* @param array $params the request parameters as an array of key=value pairs. Default empty array
* @param string $useauth whether to use authentication when making the request. Default true
* @param string $multipart whether this request contains multipart data. Default false
* @param array $headers any custom headers to send with the request. Default empty array
*
* @return int the http response code for the request. 0 is returned if a connection could not be made
*/
public function request( $method, $url, $params = array(), $useauth = true, $multipart = false, $headers = array() ) {
// reset the request headers (we don't want to reuse them)
$this->headers = array();
$this->custom_headers = $headers;
$this->config['multipart'] = $multipart;
$this->create_nonce();
$this->create_timestamp();
$this->sign( $method, $url, $params, $useauth );
if ( ! empty( $this->custom_headers ) ) {
$this->headers = array_merge( (array) $this->headers, (array) $this->custom_headers );
}
return $this->curlit();
}
/**
* Make a long poll HTTP request using this library. This method is
* different to the other request methods as it isn't supposed to disconnect
*
* Using this method expects a callback which will receive the streaming
* responses.
*
* @param string $method the HTTP method being used. e.g. POST, GET, HEAD etc
* @param string $url the request URL without query string parameters
* @param array $params the request parameters as an array of key=value pairs
* @param string $callback the callback function to stream the buffer to.
*
* @return void
*/
public function streaming_request( $method, $url, $params = array(), $callback = '' ) {
if ( ! empty( $callback ) ) {
if ( ! is_callable( $callback ) ) {
return false;
}
$this->config['streaming_callback'] = $callback;
}
$this->metrics['start'] = time();
$this->metrics['interval_start'] = $this->metrics['start'];
$this->metrics['tweets'] = 0;
$this->metrics['last_tweets'] = 0;
$this->metrics['bytes'] = 0;
$this->metrics['last_bytes'] = 0;
$this->config['is_streaming'] = true;
$this->request( $method, $url, $params );
}
/**
* Handles the updating of the current Streaming API metrics.
*
* @return array the metrics for the streaming api connection
*/
private function update_metrics() {
$now = time();
if ( ( $this->metrics['interval_start'] + $this->config['streaming_metrics_interval'] ) > $now ) {
return false;
}
$this->metrics['tps'] = round( ( $this->metrics['tweets'] - $this->metrics['last_tweets'] ) / $this->config['streaming_metrics_interval'], 2 );
$this->metrics['bps'] = round( ( $this->metrics['bytes'] - $this->metrics['last_bytes'] ) / $this->config['streaming_metrics_interval'], 2 );
$this->metrics['last_bytes'] = $this->metrics['bytes'];
$this->metrics['last_tweets'] = $this->metrics['tweets'];
$this->metrics['interval_start'] = $now;
return $this->metrics;
}
/**
* Utility function to create the request URL in the requested format
*
* @param string $request the API method without extension
* @param string $format the format of the response. Default json. Set to an empty string to exclude the format
*
* @return string the concatenation of the host, API version, API method and format
*/
public function url( $request, $format = 'json' ) {
$format = strlen( $format ) > 0 ? ".$format" : '';
$proto = $this->config['use_ssl'] ? 'https:/' : 'http:/';
// backwards compatibility with v0.1
if ( isset( $this->config['v'] ) ) {
$this->config['host'] = $this->config['host'] . '/' . $this->config['v'];
}
$request = ltrim( $request, '/' );
$pos = strlen( $request ) - strlen( $format );
if ( substr( $request, $pos ) === $format ) {
$request = substr_replace( $request, '', $pos );
}
return implode( '/', array(
$proto,
$this->config['host'],
$request . $format
) );
}
/**
* Public access to the private safe decode/encode methods
*
* @param string $text the text to transform
* @param string $mode the transformation mode. either encode or decode
*
* @return string $text transformed by the given $mode
*/
public function transformText( $text, $mode = 'encode' ) {
return $this->{"safe_$mode"}( $text );
}
/**
* Utility function to parse the returned curl headers and store them in the
* class array variable.
*
* @param object $ch curl handle
* @param string $header the response headers
*
* @return string the length of the header
*/
private function curlHeader( $ch, $header ) {
$this->response['raw'] .= $header;
list( $key, $value ) = array_pad( explode( ':', $header, 2 ), 2, null );
$key = trim( $key );
$value = trim( $value );
if ( ! isset( $this->response['headers'][ $key ] ) ) {
$this->response['headers'][ $key ] = $value;
} else {
if ( ! is_array( $this->response['headers'][ $key ] ) ) {
$this->response['headers'][ $key ] = array( $this->response['headers'][ $key ] );
}
$this->response['headers'][ $key ][] = $value;
}
return strlen( $header );
}
/**
* Utility function to parse the returned curl buffer and store them until
* an EOL is found. The buffer for curl is an undefined size so we need
* to collect the content until an EOL is found.
*
* This function calls the previously defined streaming callback method.
*
* @param object $ch curl handle
* @param string $data the current curl buffer
*
* @return int the length of the data string processed in this function
*/
private function curlWrite( $ch, $data ) {
$l = strlen( $data );
if ( strpos( $data, $this->config['streaming_eol'] ) === false ) {
$this->buffer .= $data;
return $l;
}
$buffered = explode( $this->config['streaming_eol'], $data );
$content = $this->buffer . $buffered[0];
$this->metrics['tweets'] ++;
$this->metrics['bytes'] += strlen( $content );
if ( ! is_callable( $this->config['streaming_callback'] ) ) {
return 0;
}
$metrics = $this->update_metrics();
$stop = call_user_func(
$this->config['streaming_callback'],
$content,
strlen( $content ),
$metrics
);
$this->buffer = $buffered[1];
if ( $stop ) {
return 0;
}
return $l;
}
/**
* Makes a curl request. Takes no parameters as all should have been prepared
* by the request method
*
* the response data is stored in the class variable 'response'
*
* @return int the http response code for the request. 0 is returned if a connection could not be made
*/
private function curlit() {
$this->response['raw'] = '';
// method handling
switch ( $this->method ) {
case 'POST':
break;
default:
// GET, DELETE request so convert the parameters to a querystring
if ( ! empty( $this->request_params ) ) {
foreach ( $this->request_params as $k => $v ) {
// Multipart params haven't been encoded yet.
// Not sure why you would do a multipart GET but anyway, here's the support for it
if ( $this->config['multipart'] ) {
$params[] = $this->safe_encode( $k ) . '=' . $this->safe_encode( $v );
} else {
$params[] = $k . '=' . $v;
}
}
$qs = implode( '&', $params );
$this->url = strlen( $qs ) > 0 ? $this->url . '?' . $qs : $this->url;
$this->request_params = array();
}
break;
}
// configure curl
$c = curl_init();
curl_setopt_array( $c, array(
CURLOPT_USERAGENT => $this->config['user_agent'],
CURLOPT_CONNECTTIMEOUT => $this->config['curl_connecttimeout'],
CURLOPT_TIMEOUT => $this->config['curl_timeout'],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYPEER => $this->config['curl_ssl_verifypeer'],
CURLOPT_SSL_VERIFYHOST => $this->config['curl_ssl_verifyhost'],
CURLOPT_FOLLOWLOCATION => $this->config['curl_followlocation'],
CURLOPT_PROXY => $this->config['curl_proxy'],
CURLOPT_ENCODING => $this->config['curl_encoding'],
CURLOPT_URL => $this->url,
// process the headers
CURLOPT_HEADERFUNCTION => array( $this, 'curlHeader' ),
CURLOPT_HEADER => false,
CURLINFO_HEADER_OUT => true,
) );
if ( $this->config['curl_cainfo'] !== false ) {
curl_setopt( $c, CURLOPT_CAINFO, $this->config['curl_cainfo'] );
}
if ( $this->config['curl_capath'] !== false ) {
curl_setopt( $c, CURLOPT_CAPATH, $this->config['curl_capath'] );
}
if ( $this->config['curl_proxyuserpwd'] !== false ) {
curl_setopt( $c, CURLOPT_PROXYUSERPWD, $this->config['curl_proxyuserpwd'] );
}
if ( $this->config['is_streaming'] ) {
// process the body
$this->response['content-length'] = 0;
curl_setopt( $c, CURLOPT_TIMEOUT, 0 );
curl_setopt( $c, CURLOPT_WRITEFUNCTION, array( $this, 'curlWrite' ) );
}
switch ( $this->method ) {
case 'GET':
break;
case 'POST':
curl_setopt( $c, CURLOPT_POST, true );
curl_setopt( $c, CURLOPT_POSTFIELDS, $this->request_params );
break;
default:
curl_setopt( $c, CURLOPT_CUSTOMREQUEST, $this->method );
}
if ( ! empty( $this->request_params ) ) {
// if not doing multipart we need to implode the parameters
if ( ! $this->config['multipart'] ) {
foreach ( $this->request_params as $k => $v ) {
$ps[] = "{$k}={$v}";
}
$this->request_params = implode( '&', $ps );
}
curl_setopt( $c, CURLOPT_POSTFIELDS, $this->request_params );
}
if ( ! empty( $this->headers ) ) {
foreach ( $this->headers as $k => $v ) {
$headers[] = trim( $k . ': ' . $v );
}
curl_setopt( $c, CURLOPT_HTTPHEADER, $headers );
}
if ( isset( $this->config['prevent_request'] ) && ( true == $this->config['prevent_request'] ) ) {
return 0;
}
// do it!
$response = curl_exec( $c );
$code = curl_getinfo( $c, CURLINFO_HTTP_CODE );
$info = curl_getinfo( $c );
$error = curl_error( $c );
$errno = curl_errno( $c );
curl_close( $c );
// store the response
$this->response['code'] = $code;
$this->response['response'] = $response;
$this->response['info'] = $info;
$this->response['error'] = $error;
$this->response['errno'] = $errno;
if ( ! isset( $this->response['raw'] ) ) {
$this->response['raw'] = '';
}
$this->response['raw'] .= $response;
return $code;
}
}