New Extension: tweet-posts-0.01-beta.zip
[vanilla-miry.git] / extensions / TweetPosts / TwitterLib / EpiOAuth.php
blobff2c61832835fa48da5010653f5b982c462ffdac
1 <?php
2 class EpiOAuth
4 public $version = '1.0';
6 protected $requestTokenUrl;
7 protected $accessTokenUrl;
8 protected $authenticateUrl;
9 protected $authorizeUrl;
10 protected $consumerKey;
11 protected $consumerSecret;
12 protected $token;
13 protected $tokenSecret;
14 protected $signatureMethod;
15 protected $useSSL = false;
16 protected $headers = array();
17 protected $userAgent = 'EpiOAuth (http://github.com/jmathai/twitter-async/tree/)';
18 protected $timeout = 30;
20 public function addHeader($header)
22 if(is_array($header) && !empty($header))
23 $this->headers = array_merge($this->headers, $header);
24 elseif(!empty($header))
25 $this->headers[] = $header;
28 public function getAccessToken($params = null)
30 $resp = $this->httpRequest('GET', $this->getUrl($this->accessTokenUrl), $params);
31 return new EpiOAuthResponse($resp);
34 public function getAuthenticateUrl($token = null, $params = null)
36 $token = $token ? $token : $this->getRequestToken();
37 $addlParams = empty($params) ? '' : '&'.http_build_query($params);
38 return $this->getUrl($this->authenticateUrl) . '?oauth_token=' . $token->oauth_token . $addlParams;
41 public function getAuthorizeUrl($token = null)
43 return $this->getAuthorizationUrl($token);
46 // DEPRECATED in favor of getAuthorizeUrl()
47 public function getAuthorizationUrl($token = null)
49 $token = $token ? $token : $this->getRequestToken();
50 return $this->getUrl($this->authorizeUrl) . '?oauth_token=' . $token->oauth_token;
53 public function getRequestToken($params = null)
55 $resp = $this->httpRequest('GET', $this->getUrl($this->requestTokenUrl), $params);
56 return new EpiOAuthResponse($resp);
59 public function getUrl($url)
61 if($this->useSSL === true)
62 return preg_replace('/^http:/', 'https:', $url);
64 return $url;
67 public function httpRequest($method = null, $url = null, $params = null, $isMultipart = false)
69 if(empty($method) || empty($url))
70 return false;
72 if(empty($params['oauth_signature']))
73 $params = $this->prepareParameters($method, $url, $params);
75 switch($method)
77 case 'GET':
78 return $this->httpGet($url, $params);
79 break;
80 case 'POST':
81 return $this->httpPost($url, $params, $isMultipart);
82 break;
86 public function setTimeout($timeout)
88 $this->timeout = floatval($timeout);
91 public function setToken($token = null, $secret = null)
93 $this->token = $token;
94 $this->tokenSecret = $secret;
97 public function useSSL($use = false)
99 $this->useSSL = (bool)$use;
102 protected function addDefaultHeaders($url, $oauthHeaders)
104 $_h = array('Expect:');
105 $urlParts = parse_url($url);
106 $oauth = 'Authorization: OAuth realm="' . $urlParts['scheme'] . '://' . $urlParts['host'] . $urlParts['path'] . '",';
107 foreach($oauthHeaders as $name => $value)
109 $oauth .= "{$name}=\"{$value}\",";
111 $_h[] = substr($oauth, 0, -1);
112 $_h[] = "User-Agent: {$this->userAgent}";
113 $this->addHeader($_h);
116 protected function buildHttpQueryRaw($params)
118 $retval = '';
119 foreach((array)$params as $key => $value)
120 $retval .= "{$key}={$value}&";
121 $retval = substr($retval, 0, -1);
122 return $retval;
125 protected function curlInit($url)
127 $ch = curl_init($url);
128 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
129 curl_setopt($ch, CURLOPT_HTTPHEADER, $this->headers);
130 curl_setopt($ch, CURLOPT_TIMEOUT, $this->timeout);
131 if($this->useSSL === true)
133 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
134 curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
136 return $ch;
139 protected function encode_rfc3986($string)
141 return str_replace('+', ' ', str_replace('%7E', '~', rawurlencode(($string))));
144 protected function generateNonce()
146 if(isset($this->nonce)) // for unit testing
147 return $this->nonce;
149 return md5(uniqid(rand(), true));
152 // parameters should already have been passed through prepareParameters
153 // no need to double encode
154 protected function generateSignature($method = null, $url = null, $params = null)
156 if(empty($method) || empty($url))
157 return false;
159 // concatenating and encode
160 $concatenatedParams = $this->encode_rfc3986($this->buildHttpQueryRaw($params));
162 // normalize url
163 $normalizedUrl = $this->encode_rfc3986($this->normalizeUrl($url));
164 $method = $this->encode_rfc3986($method); // don't need this but why not?
166 $signatureBaseString = "{$method}&{$normalizedUrl}&{$concatenatedParams}";
167 return $this->signString($signatureBaseString);
170 protected function httpGet($url, $params = null)
172 if(count($params['request']) > 0)
174 $url .= '?';
175 foreach($params['request'] as $k => $v)
177 $url .= "{$k}={$v}&";
179 $url = substr($url, 0, -1);
181 $this->addDefaultHeaders($url, $params['oauth']);
182 $ch = $this->curlInit($url);
183 $resp = $this->curl->addCurl($ch);
185 return $resp;
188 protected function httpPost($url, $params = null, $isMultipart)
190 $this->addDefaultHeaders($url, $params['oauth']);
191 $ch = $this->curlInit($url);
192 curl_setopt($ch, CURLOPT_POST, 1);
193 // php's curl extension automatically sets the content type
194 // based on whether the params are in string or array form
195 if($isMultipart)
196 curl_setopt($ch, CURLOPT_POSTFIELDS, $params['request']);
197 else
198 curl_setopt($ch, CURLOPT_POSTFIELDS, $this->buildHttpQueryRaw($params['request']));
199 $resp = $this->curl->addCurl($ch);
200 return $resp;
203 protected function normalizeUrl($url = null)
205 $urlParts = parse_url($url);
206 $scheme = strtolower($urlParts['scheme']);
207 $host = strtolower($urlParts['host']);
208 $port = isset($urlParts['port']) ? intval($urlParts['port']) : 0;
210 $retval = strtolower($scheme) . '://' . strtolower($host);
212 if(!empty($port) && (($scheme === 'http' && $port != 80) || ($scheme === 'https' && $port != 443)))
213 $retval .= ":{$port}";
215 $retval .= $urlParts['path'];
216 if(!empty($urlParts['query']))
218 $retval .= "?{$urlParts['query']}";
221 return $retval;
224 protected function prepareParameters($method = null, $url = null, $params = null)
226 if(empty($method) || empty($url))
227 return false;
229 $oauth['oauth_consumer_key'] = $this->consumerKey;
230 $oauth['oauth_token'] = $this->token;
231 $oauth['oauth_nonce'] = $this->generateNonce();
232 $oauth['oauth_timestamp'] = !isset($this->timestamp) ? time() : $this->timestamp; // for unit test
233 $oauth['oauth_signature_method'] = $this->signatureMethod;
234 $oauth['oauth_version'] = $this->version;
235 // encode all oauth values
236 foreach($oauth as $k => $v)
237 $oauth[$k] = $this->encode_rfc3986($v);
238 // encode all non '@' params
239 // keep sigParams for signature generation (exclude '@' params)
240 // rename '@key' to 'key'
241 $sigParams = array();
242 $hasFile = false;
243 if(is_array($params))
245 foreach($params as $k => $v)
247 if(strncmp('@',$k,1) !== 0)
249 $sigParams[$k] = $this->encode_rfc3986($v);
250 $params[$k] = $this->encode_rfc3986($v);
252 else
254 $params[substr($k, 1)] = $v;
255 unset($params[$k]);
256 $hasFile = true;
260 if($hasFile === true)
261 $sigParams = array();
264 $sigParams = array_merge($oauth, (array)$sigParams);
266 // sorting
267 ksort($sigParams);
269 // signing
270 $oauth['oauth_signature'] = $this->encode_rfc3986($this->generateSignature($method, $url, $sigParams));
271 return array('request' => $params, 'oauth' => $oauth);
274 protected function signString($string = null)
276 $retval = false;
277 switch($this->signatureMethod)
279 case 'HMAC-SHA1':
280 $key = $this->encode_rfc3986($this->consumerSecret) . '&' . $this->encode_rfc3986($this->tokenSecret);
281 $retval = base64_encode(hash_hmac('sha1', $string, $key, true));
282 break;
285 return $retval;
288 public function __construct($consumerKey, $consumerSecret, $signatureMethod='HMAC-SHA1')
290 $this->consumerKey = $consumerKey;
291 $this->consumerSecret = $consumerSecret;
292 $this->signatureMethod = $signatureMethod;
293 $this->curl = EpiCurl::getInstance();
297 class EpiOAuthResponse
299 private $__resp;
301 public function __construct($resp)
303 $this->__resp = $resp;
306 public function __get($name)
308 if($this->__resp->code != 200)
309 EpiOAuthException::raise($this->__resp->data, $this->__resp->code);
311 parse_str($this->__resp->data, $result);
312 foreach($result as $k => $v)
314 $this->$k = $v;
317 return $result[$name];
321 class EpiOAuthException extends Exception
323 public static function raise($message, $code)
325 switch($code)
327 case 400:
328 throw new EpiOAuthBadRequestException($message, $code);
329 case 401:
330 throw new EpiOAuthUnauthorizedException($message, $code);
331 default:
332 throw new EpiOAuthException($message, $code);
338 class EpiOAuthBadRequestException extends EpiOAuthException{}
339 class EpiOAuthUnauthorizedException extends EpiOAuthException{}