Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 354 lines (301 sloc) 9.86 kb
556f8ea @jmathai Adding EpiOAuth and EpiTwitter classes.
authored
1 <?php
2 class EpiOAuth
3 {
4 public $version = '1.0';
5
6 protected $requestTokenUrl;
7 protected $accessTokenUrl;
6392fde @jmathai Adding exceptions to EpiOAuth and implementing them in EpiTwitter.
authored
8 protected $authenticateUrl;
556f8ea @jmathai Adding EpiOAuth and EpiTwitter classes.
authored
9 protected $authorizeUrl;
10 protected $consumerKey;
11 protected $consumerSecret;
12 protected $token;
13 protected $tokenSecret;
14 protected $signatureMethod;
8cf70e2 @jmathai Merging in emmartin's changes and moving ssl logic into EpiOAuth class.
authored
15 protected $useSSL = false;
21f91ce @jmathai Adding ability to add custom headers to curl calls.
authored
16 protected $headers = array();
17 protected $userAgent = 'EpiOAuth (http://github.com/jmathai/twitter-async/tree/)';
0cac48d @jmathai Adding implicit blocking in destructor so that all calls are ensured to ...
authored
18 protected $connectionTimeout = 5;
19 protected $requestTimeout = 30;
21f91ce @jmathai Adding ability to add custom headers to curl calls.
authored
20
21 public function addHeader($header)
22 {
23 if(is_array($header) && !empty($header))
24 $this->headers = array_merge($this->headers, $header);
25 elseif(!empty($header))
26 $this->headers[] = $header;
27 }
556f8ea @jmathai Adding EpiOAuth and EpiTwitter classes.
authored
28
0b05e54 getAccessToken() now accepts $params to pass in the query. Now you can s...
Jon Canady authored
29 public function getAccessToken($params = null)
556f8ea @jmathai Adding EpiOAuth and EpiTwitter classes.
authored
30 {
0b05e54 getAccessToken() now accepts $params to pass in the query. Now you can s...
Jon Canady authored
31 $resp = $this->httpRequest('GET', $this->getUrl($this->accessTokenUrl), $params);
556f8ea @jmathai Adding EpiOAuth and EpiTwitter classes.
authored
32 return new EpiOAuthResponse($resp);
33 }
34
e4ae371 @jmathai Added support for the force_login parameter for /oauth/authenticate.
authored
35 public function getAuthenticateUrl($token = null, $params = null)
556f8ea @jmathai Adding EpiOAuth and EpiTwitter classes.
authored
36 {
385a782 @jmathai Added proper support for the oauth_callback parameter.
authored
37 $token = $token ? $token : $this->getRequestToken($params);
1912d06 @jmathai Patching http_build_query for PHP < 5.1.2
authored
38 $addlParams = empty($params) ? '' : '&'.http_build_query($params, '', '&');
e4ae371 @jmathai Added support for the force_login parameter for /oauth/authenticate.
authored
39 return $this->getUrl($this->authenticateUrl) . '?oauth_token=' . $token->oauth_token . $addlParams;
6392fde @jmathai Adding exceptions to EpiOAuth and implementing them in EpiTwitter.
authored
40 }
556f8ea @jmathai Adding EpiOAuth and EpiTwitter classes.
authored
41
385a782 @jmathai Added proper support for the oauth_callback parameter.
authored
42 public function getAuthorizeUrl($token = null, $params = null)
e4ae371 @jmathai Added support for the force_login parameter for /oauth/authenticate.
authored
43 {
385a782 @jmathai Added proper support for the oauth_callback parameter.
authored
44 $token = $token ? $token : $this->getRequestToken($params);
45 return $this->getUrl($this->authorizeUrl) . '?oauth_token=' . $token->oauth_token;
e4ae371 @jmathai Added support for the force_login parameter for /oauth/authenticate.
authored
46 }
47
48 // DEPRECATED in favor of getAuthorizeUrl()
5188b40 @ericmmartin Added token param to get*Url methods.
ericmmartin authored
49 public function getAuthorizationUrl($token = null)
6392fde @jmathai Adding exceptions to EpiOAuth and implementing them in EpiTwitter.
authored
50 {
385a782 @jmathai Added proper support for the oauth_callback parameter.
authored
51 return $this->getAuthorizeUrl($token);
556f8ea @jmathai Adding EpiOAuth and EpiTwitter classes.
authored
52 }
53
21f91ce @jmathai Adding ability to add custom headers to curl calls.
authored
54 public function getRequestToken($params = null)
556f8ea @jmathai Adding EpiOAuth and EpiTwitter classes.
authored
55 {
91e359c @jmathai Adding support for oauth_callback and adding unit tests.
authored
56 $resp = $this->httpRequest('GET', $this->getUrl($this->requestTokenUrl), $params);
556f8ea @jmathai Adding EpiOAuth and EpiTwitter classes.
authored
57 return new EpiOAuthResponse($resp);
58 }
59
8cf70e2 @jmathai Merging in emmartin's changes and moving ssl logic into EpiOAuth class.
authored
60 public function getUrl($url)
61 {
62 if($this->useSSL === true)
ab5079e @ericmmartin Undefined errors described in issue #9
ericmmartin authored
63 return preg_replace('/^http:/', 'https:', $url);
8cf70e2 @jmathai Merging in emmartin's changes and moving ssl logic into EpiOAuth class.
authored
64
65 return $url;
66 }
67
5fc33a5 @jmathai Adding support for multipart image uploads. It's 1/2 working.
authored
68 public function httpRequest($method = null, $url = null, $params = null, $isMultipart = false)
556f8ea @jmathai Adding EpiOAuth and EpiTwitter classes.
authored
69 {
70 if(empty($method) || empty($url))
71 return false;
72
73 if(empty($params['oauth_signature']))
74 $params = $this->prepareParameters($method, $url, $params);
75
76 switch($method)
77 {
d1636aa @jmathai Fixed a bug with the signature not always being properly encoded.
authored
78 case 'GET':
79 return $this->httpGet($url, $params);
80 break;
556f8ea @jmathai Adding EpiOAuth and EpiTwitter classes.
authored
81 case 'POST':
5fc33a5 @jmathai Adding support for multipart image uploads. It's 1/2 working.
authored
82 return $this->httpPost($url, $params, $isMultipart);
556f8ea @jmathai Adding EpiOAuth and EpiTwitter classes.
authored
83 break;
84 }
85 }
86
0cac48d @jmathai Adding implicit blocking in destructor so that all calls are ensured to ...
authored
87 public function setTimeout($requestTimeout = null, $connectionTimeout = null)
21f91ce @jmathai Adding ability to add custom headers to curl calls.
authored
88 {
0cac48d @jmathai Adding implicit blocking in destructor so that all calls are ensured to ...
authored
89 if($requestTimeout !== null)
90 $this->requestTimeout = floatval($requestTimeout);
91 if($connectionTimeout !== null)
92 $this->connectionTimeout = floatval($connectionTimeout);
21f91ce @jmathai Adding ability to add custom headers to curl calls.
authored
93 }
94
042c806 @jmathai Fixed bug relating to invalid encoding for OAuth signatures on POST call...
authored
95 public function setToken($token = null, $secret = null)
556f8ea @jmathai Adding EpiOAuth and EpiTwitter classes.
authored
96 {
97 $this->token = $token;
98 $this->tokenSecret = $secret;
99 }
100
8cf70e2 @jmathai Merging in emmartin's changes and moving ssl logic into EpiOAuth class.
authored
101 public function useSSL($use = false)
556f8ea @jmathai Adding EpiOAuth and EpiTwitter classes.
authored
102 {
8cf70e2 @jmathai Merging in emmartin's changes and moving ssl logic into EpiOAuth class.
authored
103 $this->useSSL = (bool)$use;
556f8ea @jmathai Adding EpiOAuth and EpiTwitter classes.
authored
104 }
105
21f91ce @jmathai Adding ability to add custom headers to curl calls.
authored
106 protected function addDefaultHeaders($url, $oauthHeaders)
556f8ea @jmathai Adding EpiOAuth and EpiTwitter classes.
authored
107 {
042c806 @jmathai Fixed bug relating to invalid encoding for OAuth signatures on POST call...
authored
108 $_h = array('Expect:');
13fc3de @jmathai Fixed bug where the OAuth realm was incorrect for GET requests with para...
authored
109 $urlParts = parse_url($url);
8cf70e2 @jmathai Merging in emmartin's changes and moving ssl logic into EpiOAuth class.
authored
110 $oauth = 'Authorization: OAuth realm="' . $urlParts['scheme'] . '://' . $urlParts['host'] . $urlParts['path'] . '",';
042c806 @jmathai Fixed bug relating to invalid encoding for OAuth signatures on POST call...
authored
111 foreach($oauthHeaders as $name => $value)
112 {
113 $oauth .= "{$name}=\"{$value}\",";
114 }
115 $_h[] = substr($oauth, 0, -1);
21f91ce @jmathai Adding ability to add custom headers to curl calls.
authored
116 $_h[] = "User-Agent: {$this->userAgent}";
117 $this->addHeader($_h);
042c806 @jmathai Fixed bug relating to invalid encoding for OAuth signatures on POST call...
authored
118 }
119
ccb2ab5 @jmathai Multipart calls working for udpating profile image.
authored
120 protected function buildHttpQueryRaw($params)
121 {
122 $retval = '';
123 foreach((array)$params as $key => $value)
124 $retval .= "{$key}={$value}&";
125 $retval = substr($retval, 0, -1);
126 return $retval;
127 }
128
8cf70e2 @jmathai Merging in emmartin's changes and moving ssl logic into EpiOAuth class.
authored
129 protected function curlInit($url)
130 {
131 $ch = curl_init($url);
132 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
21f91ce @jmathai Adding ability to add custom headers to curl calls.
authored
133 curl_setopt($ch, CURLOPT_HTTPHEADER, $this->headers);
0cac48d @jmathai Adding implicit blocking in destructor so that all calls are ensured to ...
authored
134 curl_setopt($ch, CURLOPT_TIMEOUT, $this->requestTimeout);
135 curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->connectionTimeout);
a46c330 @jmathai Thanks @mulka. Fixed bug with wrong constant for CURLOPT_FOLLOWLOCATION.
authored
136 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
8cf70e2 @jmathai Merging in emmartin's changes and moving ssl logic into EpiOAuth class.
authored
137 if($this->useSSL === true)
138 {
139 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
140 curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
141 }
142 return $ch;
143 }
144
889fee8 @jmathai Restting headers after each call.
authored
145 protected function emptyHeaders()
146 {
147 $this->headers = array();
148 }
149
8cf70e2 @jmathai Merging in emmartin's changes and moving ssl logic into EpiOAuth class.
authored
150 protected function encode_rfc3986($string)
151 {
152 return str_replace('+', ' ', str_replace('%7E', '~', rawurlencode(($string))));
153 }
154
042c806 @jmathai Fixed bug relating to invalid encoding for OAuth signatures on POST call...
authored
155 protected function generateNonce()
156 {
157 if(isset($this->nonce)) // for unit testing
158 return $this->nonce;
159
556f8ea @jmathai Adding EpiOAuth and EpiTwitter classes.
authored
160 return md5(uniqid(rand(), true));
161 }
162
ccb2ab5 @jmathai Multipart calls working for udpating profile image.
authored
163 // parameters should already have been passed through prepareParameters
164 // no need to double encode
042c806 @jmathai Fixed bug relating to invalid encoding for OAuth signatures on POST call...
authored
165 protected function generateSignature($method = null, $url = null, $params = null)
556f8ea @jmathai Adding EpiOAuth and EpiTwitter classes.
authored
166 {
167 if(empty($method) || empty($url))
168 return false;
169
ccb2ab5 @jmathai Multipart calls working for udpating profile image.
authored
170 // concatenating and encode
171 $concatenatedParams = $this->encode_rfc3986($this->buildHttpQueryRaw($params));
556f8ea @jmathai Adding EpiOAuth and EpiTwitter classes.
authored
172
173 // normalize url
868a15d @jmathai Fixed encode function to support rfc3986.
authored
174 $normalizedUrl = $this->encode_rfc3986($this->normalizeUrl($url));
175 $method = $this->encode_rfc3986($method); // don't need this but why not?
556f8ea @jmathai Adding EpiOAuth and EpiTwitter classes.
authored
176
177 $signatureBaseString = "{$method}&{$normalizedUrl}&{$concatenatedParams}";
178 return $this->signString($signatureBaseString);
179 }
180
042c806 @jmathai Fixed bug relating to invalid encoding for OAuth signatures on POST call...
authored
181 protected function httpGet($url, $params = null)
d1636aa @jmathai Fixed a bug with the signature not always being properly encoded.
authored
182 {
042c806 @jmathai Fixed bug relating to invalid encoding for OAuth signatures on POST call...
authored
183 if(count($params['request']) > 0)
d1636aa @jmathai Fixed a bug with the signature not always being properly encoded.
authored
184 {
185 $url .= '?';
042c806 @jmathai Fixed bug relating to invalid encoding for OAuth signatures on POST call...
authored
186 foreach($params['request'] as $k => $v)
d1636aa @jmathai Fixed a bug with the signature not always being properly encoded.
authored
187 {
188 $url .= "{$k}={$v}&";
189 }
190 $url = substr($url, 0, -1);
191 }
21f91ce @jmathai Adding ability to add custom headers to curl calls.
authored
192 $this->addDefaultHeaders($url, $params['oauth']);
8cf70e2 @jmathai Merging in emmartin's changes and moving ssl logic into EpiOAuth class.
authored
193 $ch = $this->curlInit($url);
d1636aa @jmathai Fixed a bug with the signature not always being properly encoded.
authored
194 $resp = $this->curl->addCurl($ch);
889fee8 @jmathai Restting headers after each call.
authored
195 $this->emptyHeaders();
d1636aa @jmathai Fixed a bug with the signature not always being properly encoded.
authored
196
197 return $resp;
198 }
199
5fc33a5 @jmathai Adding support for multipart image uploads. It's 1/2 working.
authored
200 protected function httpPost($url, $params = null, $isMultipart)
d1636aa @jmathai Fixed a bug with the signature not always being properly encoded.
authored
201 {
21f91ce @jmathai Adding ability to add custom headers to curl calls.
authored
202 $this->addDefaultHeaders($url, $params['oauth']);
8cf70e2 @jmathai Merging in emmartin's changes and moving ssl logic into EpiOAuth class.
authored
203 $ch = $this->curlInit($url);
042c806 @jmathai Fixed bug relating to invalid encoding for OAuth signatures on POST call...
authored
204 curl_setopt($ch, CURLOPT_POST, 1);
5fc33a5 @jmathai Adding support for multipart image uploads. It's 1/2 working.
authored
205 // php's curl extension automatically sets the content type
206 // based on whether the params are in string or array form
207 if($isMultipart)
208 curl_setopt($ch, CURLOPT_POSTFIELDS, $params['request']);
209 else
ccb2ab5 @jmathai Multipart calls working for udpating profile image.
authored
210 curl_setopt($ch, CURLOPT_POSTFIELDS, $this->buildHttpQueryRaw($params['request']));
d1636aa @jmathai Fixed a bug with the signature not always being properly encoded.
authored
211 $resp = $this->curl->addCurl($ch);
889fee8 @jmathai Restting headers after each call.
authored
212 $this->emptyHeaders();
213
d1636aa @jmathai Fixed a bug with the signature not always being properly encoded.
authored
214 return $resp;
215 }
216
042c806 @jmathai Fixed bug relating to invalid encoding for OAuth signatures on POST call...
authored
217 protected function normalizeUrl($url = null)
556f8ea @jmathai Adding EpiOAuth and EpiTwitter classes.
authored
218 {
219 $urlParts = parse_url($url);
220 $scheme = strtolower($urlParts['scheme']);
221 $host = strtolower($urlParts['host']);
ab5079e @ericmmartin Undefined errors described in issue #9
ericmmartin authored
222 $port = isset($urlParts['port']) ? intval($urlParts['port']) : 0;
556f8ea @jmathai Adding EpiOAuth and EpiTwitter classes.
authored
223
8cf70e2 @jmathai Merging in emmartin's changes and moving ssl logic into EpiOAuth class.
authored
224 $retval = strtolower($scheme) . '://' . strtolower($host);
225
226 if(!empty($port) && (($scheme === 'http' && $port != 80) || ($scheme === 'https' && $port != 443)))
556f8ea @jmathai Adding EpiOAuth and EpiTwitter classes.
authored
227 $retval .= ":{$port}";
8cf70e2 @jmathai Merging in emmartin's changes and moving ssl logic into EpiOAuth class.
authored
228
556f8ea @jmathai Adding EpiOAuth and EpiTwitter classes.
authored
229 $retval .= $urlParts['path'];
230 if(!empty($urlParts['query']))
231 {
232 $retval .= "?{$urlParts['query']}";
233 }
234
235 return $retval;
236 }
237
042c806 @jmathai Fixed bug relating to invalid encoding for OAuth signatures on POST call...
authored
238 protected function prepareParameters($method = null, $url = null, $params = null)
556f8ea @jmathai Adding EpiOAuth and EpiTwitter classes.
authored
239 {
240 if(empty($method) || empty($url))
241 return false;
242
042c806 @jmathai Fixed bug relating to invalid encoding for OAuth signatures on POST call...
authored
243 $oauth['oauth_consumer_key'] = $this->consumerKey;
244 $oauth['oauth_token'] = $this->token;
245 $oauth['oauth_nonce'] = $this->generateNonce();
246 $oauth['oauth_timestamp'] = !isset($this->timestamp) ? time() : $this->timestamp; // for unit test
247 $oauth['oauth_signature_method'] = $this->signatureMethod;
248 $oauth['oauth_version'] = $this->version;
5fc33a5 @jmathai Adding support for multipart image uploads. It's 1/2 working.
authored
249 // encode all oauth values
ccb2ab5 @jmathai Multipart calls working for udpating profile image.
authored
250 foreach($oauth as $k => $v)
251 $oauth[$k] = $this->encode_rfc3986($v);
252 // encode all non '@' params
253 // keep sigParams for signature generation (exclude '@' params)
254 // rename '@key' to 'key'
255 $sigParams = array();
19d52c4 @jmathai Adding some test code to resolve invalid signature message when passing ...
authored
256 $hasFile = false;
042c806 @jmathai Fixed bug relating to invalid encoding for OAuth signatures on POST call...
authored
257 if(is_array($params))
5fc33a5 @jmathai Adding support for multipart image uploads. It's 1/2 working.
authored
258 {
259 foreach($params as $k => $v)
260 {
261 if(strncmp('@',$k,1) !== 0)
262 {
ccb2ab5 @jmathai Multipart calls working for udpating profile image.
authored
263 $sigParams[$k] = $this->encode_rfc3986($v);
264 $params[$k] = $this->encode_rfc3986($v);
5fc33a5 @jmathai Adding support for multipart image uploads. It's 1/2 working.
authored
265 }
266 else
267 {
268 $params[substr($k, 1)] = $v;
269 unset($params[$k]);
19d52c4 @jmathai Adding some test code to resolve invalid signature message when passing ...
authored
270 $hasFile = true;
5fc33a5 @jmathai Adding support for multipart image uploads. It's 1/2 working.
authored
271 }
272 }
19d52c4 @jmathai Adding some test code to resolve invalid signature message when passing ...
authored
273
274 if($hasFile === true)
275 $sigParams = array();
5fc33a5 @jmathai Adding support for multipart image uploads. It's 1/2 working.
authored
276 }
277
278 $sigParams = array_merge($oauth, (array)$sigParams);
556f8ea @jmathai Adding EpiOAuth and EpiTwitter classes.
authored
279
280 // sorting
5fc33a5 @jmathai Adding support for multipart image uploads. It's 1/2 working.
authored
281 ksort($sigParams);
556f8ea @jmathai Adding EpiOAuth and EpiTwitter classes.
authored
282
283 // signing
5fc33a5 @jmathai Adding support for multipart image uploads. It's 1/2 working.
authored
284 $oauth['oauth_signature'] = $this->encode_rfc3986($this->generateSignature($method, $url, $sigParams));
042c806 @jmathai Fixed bug relating to invalid encoding for OAuth signatures on POST call...
authored
285 return array('request' => $params, 'oauth' => $oauth);
556f8ea @jmathai Adding EpiOAuth and EpiTwitter classes.
authored
286 }
287
042c806 @jmathai Fixed bug relating to invalid encoding for OAuth signatures on POST call...
authored
288 protected function signString($string = null)
556f8ea @jmathai Adding EpiOAuth and EpiTwitter classes.
authored
289 {
290 $retval = false;
291 switch($this->signatureMethod)
292 {
293 case 'HMAC-SHA1':
868a15d @jmathai Fixed encode function to support rfc3986.
authored
294 $key = $this->encode_rfc3986($this->consumerSecret) . '&' . $this->encode_rfc3986($this->tokenSecret);
042c806 @jmathai Fixed bug relating to invalid encoding for OAuth signatures on POST call...
authored
295 $retval = base64_encode(hash_hmac('sha1', $string, $key, true));
556f8ea @jmathai Adding EpiOAuth and EpiTwitter classes.
authored
296 break;
297 }
298
299 return $retval;
300 }
301
042c806 @jmathai Fixed bug relating to invalid encoding for OAuth signatures on POST call...
authored
302 public function __construct($consumerKey, $consumerSecret, $signatureMethod='HMAC-SHA1')
556f8ea @jmathai Adding EpiOAuth and EpiTwitter classes.
authored
303 {
042c806 @jmathai Fixed bug relating to invalid encoding for OAuth signatures on POST call...
authored
304 $this->consumerKey = $consumerKey;
305 $this->consumerSecret = $consumerSecret;
306 $this->signatureMethod = $signatureMethod;
556f8ea @jmathai Adding EpiOAuth and EpiTwitter classes.
authored
307 $this->curl = EpiCurl::getInstance();
308 }
309 }
310
311 class EpiOAuthResponse
312 {
d1636aa @jmathai Fixed a bug with the signature not always being properly encoded.
authored
313 private $__resp;
556f8ea @jmathai Adding EpiOAuth and EpiTwitter classes.
authored
314
315 public function __construct($resp)
316 {
d1636aa @jmathai Fixed a bug with the signature not always being properly encoded.
authored
317 $this->__resp = $resp;
556f8ea @jmathai Adding EpiOAuth and EpiTwitter classes.
authored
318 }
319
320 public function __get($name)
321 {
6392fde @jmathai Adding exceptions to EpiOAuth and implementing them in EpiTwitter.
authored
322 if($this->__resp->code != 200)
323 EpiOAuthException::raise($this->__resp->data, $this->__resp->code);
556f8ea @jmathai Adding EpiOAuth and EpiTwitter classes.
authored
324
d1636aa @jmathai Fixed a bug with the signature not always being properly encoded.
authored
325 parse_str($this->__resp->data, $result);
556f8ea @jmathai Adding EpiOAuth and EpiTwitter classes.
authored
326 foreach($result as $k => $v)
327 {
328 $this->$k = $v;
329 }
330
331 return $result[$name];
332 }
333 }
6392fde @jmathai Adding exceptions to EpiOAuth and implementing them in EpiTwitter.
authored
334
335 class EpiOAuthException extends Exception
336 {
337 public static function raise($message, $code)
338 {
339 switch($code)
340 {
341 case 400:
342 throw new EpiOAuthBadRequestException($message, $code);
343 case 401:
344 throw new EpiOAuthUnauthorizedException($message, $code);
345 default:
346 throw new EpiOAuthException($message, $code);
347 }
348 }
349 }
350
351
352 class EpiOAuthBadRequestException extends EpiOAuthException{}
353 class EpiOAuthUnauthorizedException extends EpiOAuthException{}
Something went wrong with that request. Please try again.