diff options
Diffstat (limited to 'lib/tmhoauth/tmhOAuth.php')
-rw-r--r-- | lib/tmhoauth/tmhOAuth.php | 726 |
1 files changed, 0 insertions, 726 deletions
diff --git a/lib/tmhoauth/tmhOAuth.php b/lib/tmhoauth/tmhOAuth.php deleted file mode 100644 index 643ad09e7..000000000 --- a/lib/tmhoauth/tmhOAuth.php +++ /dev/null @@ -1,726 +0,0 @@ -<?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.4 - * - * 03 March 2011 - */ -class tmhOAuth { - /** - * Creates a new tmhOAuth object - * - * @param string $config, the configuration to use for this request - */ - function __construct($config) { - $this->params = array(); - $this->auto_fixed_time = false; - - // default configuration options - $this->config = array_merge( - array( - 'consumer_key' => '', - 'consumer_secret' => '', - 'user_token' => '', - 'user_secret' => '', - 'use_ssl' => true, - 'host' => 'api.twitter.com', - 'debug' => false, - '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_version' => '1.0', - - // you probably don't want to change any of these curl values - 'curl_connecttimeout' => 30, - 'curl_timeout' => 10, - // for security you may want to set this to TRUE. If you do you need - // to install the servers certificate in your local certificate store. - 'curl_ssl_verifypeer' => false, - '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 - - // streaming API - 'is_streaming' => false, - 'streaming_eol' => "\r\n", - 'streaming_metrics_interval' => 60, - ), - $config - ); - } - - /** - * 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 - */ - 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); - $this->config['nonce'] = md5(substr(microtime() . 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 - */ - 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 $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' => 'HMAC-SHA1', - ); - - // 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 - */ - 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 a class variable - * @author themattharris - */ - 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. - * - * @param string $url the request URL - * @return void value is stored to a class variable - * @author themattharris - */ - private function prepare_url($url) { - $parts = parse_url($url); - - $port = @$parts['port']; - $scheme = $parts['scheme']; - $host = $parts['host']; - $path = @$parts['path']; - - $port or $port = ($scheme == 'https') ? '443' : '80'; - - if (($scheme == 'https' && $port != '443') - || ($scheme == 'http' && $port != '80')) { - $host = "$host:$port"; - } - $this->url = "$scheme://$host$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 class variables - */ - 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); - $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']); - } - - // 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 a class variables - */ - 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 a class variables - */ - private function prepare_base_string() { - $base = array( - $this->method, - $this->url, - $this->signing_params - ); - $this->base_string = implode('&', $this->safe_encode($base)); - } - - /** - * Prepares the Authorization header - * - * @return void prepared authorization header is stored in a class variables - */ - private function prepare_auth_header() { - $this->headers = array(); - uksort($this->auth_params, 'strcmp'); - 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. - */ - 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 - * @param string $useauth whether to use authentication when making the request. Default true. - * @param string $multipart whether this request contains multipart data. Default false - */ - function request($method, $url, $params=array(), $useauth=true, $multipart=false) { - $this->config['multipart'] = $multipart; - - $this->create_nonce(); - $this->create_timestamp(); - - $this->sign($method, $url, $params, $useauth); - return $this->curlit($multipart); - } - - /** - * Make an HTTP request using this library. This method is different to 'request' - * because on a 401 error it will retry the request. - * - * When a 401 error is returned it is possible the timestamp of the client is - * too different to that of the API server. In this situation it is recommended - * the request is retried with the OAuth timestamp set to the same as the API - * server. This method will automatically try that technique. - * - * 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 - * @param string $useauth whether to use authentication when making the request. Default true. - * @param string $multipart whether this request contains multipart data. Default false - */ - function auto_fix_time_request($method, $url, $params=array(), $useauth=true, $multipart=false) { - $this->request($method, $url, $params, $useauth, $multipart); - - // if we're not doing auth the timestamp isn't important - if ( ! $useauth) - return; - - // some error that isn't a 401 - if ($this->response['code'] != 401) - return; - - // some error that is a 401 but isn't because the OAuth token and signature are incorrect - // TODO: this check is horrid but helps avoid requesting twice when the username and password are wrong - if (stripos($this->response['response'], 'password') !== false) - return; - - // force the timestamp to be the same as the Twitter servers, and re-request - $this->auto_fixed_time = true; - $this->config['force_timestamp'] = true; - $this->config['timestamp'] = strtotime($this->response['headers']['date']); - $this->request($method, $url, $params, $useauth, $multipart); - } - - /** - * 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. - */ - function streaming_request($method, $url, $params=array(), $callback='') { - if ( ! empty($callback) ) { - if ( ! function_exists($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. - */ - 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 - */ - 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']; - - return implode('/', array( - $proto, - $this->config['host'], - $request . $format - )); - } - - /** - * 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 the string length of the header - */ - private function curlHeader($ch, $header) { - $i = strpos($header, ':'); - if ( ! empty($i) ) { - $key = str_replace('-', '_', strtolower(substr($header, 0, $i))); - $value = trim(substr($header, $i + 2)); - $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 - */ - 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 ( ! function_exists($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 - * - * @return void response data is stored in the class variable 'response' - */ - private function curlit() { - // 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; - } - - if (@$this->config['prevent_request']) - return; - - // configure curl - $c = curl_init(); - curl_setopt($c, CURLOPT_USERAGENT, "themattharris' HTTP Client"); - curl_setopt($c, CURLOPT_CONNECTTIMEOUT, $this->config['curl_connecttimeout']); - curl_setopt($c, CURLOPT_TIMEOUT, $this->config['curl_timeout']); - curl_setopt($c, CURLOPT_RETURNTRANSFER, TRUE); - curl_setopt($c, CURLOPT_SSL_VERIFYPEER, $this->config['curl_ssl_verifypeer']); - curl_setopt($c, CURLOPT_FOLLOWLOCATION, $this->config['curl_followlocation']); - curl_setopt($c, CURLOPT_PROXY, $this->config['curl_proxy']); - curl_setopt($c, CURLOPT_URL, $this->url); - // process the headers - curl_setopt($c, CURLOPT_HEADERFUNCTION, array($this, 'curlHeader')); - curl_setopt($c, CURLOPT_HEADER, FALSE); - curl_setopt($c, CURLINFO_HEADER_OUT, true); - - 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); - 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); - } else { - // CURL will set length to -1 when there is no data, which breaks Twitter - $this->headers[] = 'Content-Type:'; - $this->headers[] = 'Content-Length:'; - } - - // CURL defaults to setting this to Expect: 100-Continue which Twitter rejects - $this->headers[] = 'Expect:'; - - if ( ! empty($this->headers)) - curl_setopt($c, CURLOPT_HTTPHEADER, $this->headers); - - // do it! - $response = curl_exec($c); - $code = curl_getinfo($c, CURLINFO_HTTP_CODE); - $info = curl_getinfo($c); - curl_close($c); - - // store the response - $this->response['code'] = $code; - $this->response['response'] = $response; - $this->response['info'] = $info; - return $code; - } - - /** - * Debug function for printing the content of an object - * - * @param mixes $obj - */ - function pr($obj) { - $cli = (PHP_SAPI == 'cli' && empty($_SERVER['REMOTE_ADDR'])); - if (!$cli) - echo '<pre style="word-wrap: break-word">'; - if ( is_object($obj) ) - print_r($obj); - elseif ( is_array($obj) ) - print_r($obj); - else - echo $obj; - if (!$cli) - echo '</pre>'; - } - - /** - * Returns the current URL. This is instead of PHP_SELF which is unsafe - * - * @param bool $dropqs whether to drop the querystring or not. Default true - * @return string the current URL - */ - function php_self($dropqs=true) { - $url = sprintf('%s://%s%s', - empty($_SERVER['HTTPS']) ? 'http' : 'https', - $_SERVER['SERVER_NAME'], - $_SERVER['REQUEST_URI'] - ); - - $parts = parse_url($url); - - $port = $_SERVER['SERVER_PORT']; - $scheme = $parts['scheme']; - $host = $parts['host']; - $path = @$parts['path']; - $qs = @$parts['query']; - - $port or $port = ($scheme == 'https') ? '443' : '80'; - - if (($scheme == 'https' && $port != '443') - || ($scheme == 'http' && $port != '80')) { - $host = "$host:$port"; - } - $url = "$scheme://$host$path"; - if ( ! $dropqs) - return "{$url}?{$qs}"; - else - return $url; - } - - /** - * Entifies the tweet using the given entities element - * - * @param array $tweet the json converted to normalised array - * @return the tweet text with entities replaced with hyperlinks - */ - function entify($tweet) { - $keys = array(); - $replacements = array(); - $is_retweet = false; - - if (isset($tweet['retweeted_status'])) { - $tweet = $tweet['retweeted_status']; - $is_retweet = true; - } - - if (!isset($tweet['entities'])) { - return $tweet['text']; - } - - // prepare the entities - foreach ($tweet['entities'] as $type => $things) { - foreach ($things as $entity => $value) { - $tweet_link = "<a href=\"http://twitter.com/{$value['screen_name']}/statuses/{$tweet['id']}\">{$tweet['created_at']}</a>"; - - switch ($type) { - case 'hashtags': - $href = "<a href=\"http://search.twitter.com/search?q=%23{$value['text']}\">#{$value['text']}</a>"; - break; - case 'user_mentions': - $href = "@<a href=\"http://twitter.com/{$value['screen_name']}\" title=\"{$value['name']}\">{$value['screen_name']}</a>"; - break; - case 'urls': - $url = empty($value['expanded_url']) ? $value['url'] : $value['expanded_url']; - $display = isset($value['display_url']) ? $value['display_url'] : str_replace('http://', '', $url); - // Not all pages are served in UTF-8 so you may need to do this ... - $display = urldecode(str_replace('%E2%80%A6', '…', urlencode($display))); - $href = "<a href=\"{$value['url']}\">{$display}</a>"; - break; - } - $keys[$value['indices']['0']] = substr( - $tweet['text'], - $value['indices']['0'], - $value['indices']['1'] - $value['indices']['0'] - ); - $replacements[$value['indices']['0']] = $href; - } - } - - ksort($replacements); - $replacements = array_reverse($replacements, true); - $entified_tweet = $tweet['text']; - foreach ($replacements as $k => $v) { - $entified_tweet = substr_replace($entified_tweet, $v, $k, strlen($keys[$k])); - } - return $entified_tweet; - } -} - -?>
\ No newline at end of file |