Mercurial > hg > ywww
comparison twitter/EpiOAuth.php @ 6:077b0a0a3e6d
remaining originals according to dependency walk
author | Robert Boland <robert@markup.co.uk> |
---|---|
date | Thu, 16 Feb 2017 22:29:02 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
5:55445b456ad0 | 6:077b0a0a3e6d |
---|---|
1 <?php | |
2 class EpiOAuth | |
3 { | |
4 public $version = '1.0'; | |
5 | |
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 $debug = false; | |
16 protected $useSSL = false; | |
17 protected $headers = array(); | |
18 protected $userAgent = 'EpiOAuth (http://github.com/jmathai/twitter-async/tree/)'; | |
19 protected $connectionTimeout = 5; | |
20 protected $requestTimeout = 30; | |
21 | |
22 public function addHeader($header) | |
23 { | |
24 if(is_array($header) && !empty($header)) | |
25 $this->headers = array_merge($this->headers, $header); | |
26 elseif(!empty($header)) | |
27 $this->headers[] = $header; | |
28 } | |
29 | |
30 public function getAccessToken($params = null) | |
31 { | |
32 $resp = $this->httpRequest('POST', $this->getUrl($this->accessTokenUrl), $params); | |
33 return new EpiOAuthResponse($resp); | |
34 } | |
35 | |
36 public function getAuthenticateUrl($token = null, $params = null) | |
37 { | |
38 $token = $token ? $token : $this->getRequestToken($params); | |
39 if (is_object($token)) $token = $token->oauth_token; | |
40 $addlParams = empty($params) ? '' : '&'.http_build_query($params, '', '&'); | |
41 return $this->getUrl($this->authenticateUrl) . '?oauth_token=' . $token . $addlParams; | |
42 } | |
43 | |
44 public function getAuthorizeUrl($token = null, $params = null) | |
45 { | |
46 $token = $token ? $token : $this->getRequestToken($params); | |
47 if (is_object($token)) $token = $token->oauth_token; | |
48 return $this->getUrl($this->authorizeUrl) . '?oauth_token=' . $token; | |
49 } | |
50 | |
51 // DEPRECATED in favor of getAuthorizeUrl() | |
52 public function getAuthorizationUrl($token = null) | |
53 { | |
54 return $this->getAuthorizeUrl($token); | |
55 } | |
56 | |
57 public function getRequestToken($params = null) | |
58 { | |
59 $resp = $this->httpRequest('POST', $this->getUrl($this->requestTokenUrl), $params); | |
60 return new EpiOAuthResponse($resp); | |
61 } | |
62 | |
63 public function getUrl($url) | |
64 { | |
65 if($this->useSSL === true) | |
66 return preg_replace('/^http:/', 'https:', $url); | |
67 | |
68 return $url; | |
69 } | |
70 | |
71 public function httpRequest($method = null, $url = null, $params = null, $isMultipart = false) | |
72 { | |
73 if(empty($method) || empty($url)) | |
74 return false; | |
75 | |
76 if(empty($params['oauth_signature'])) | |
77 $params = $this->prepareParameters($method, $url, $params); | |
78 | |
79 switch($method) | |
80 { | |
81 case 'GET': | |
82 return $this->httpGet($url, $params); | |
83 break; | |
84 case 'POST': | |
85 return $this->httpPost($url, $params, $isMultipart); | |
86 break; | |
87 case 'DELETE': | |
88 return $this->httpDelete($url, $params); | |
89 break; | |
90 | |
91 } | |
92 } | |
93 | |
94 public function setDebug($bool=false) | |
95 { | |
96 $this->debug = (bool)$bool; | |
97 } | |
98 | |
99 public function setTimeout($requestTimeout = null, $connectionTimeout = null) | |
100 { | |
101 if($requestTimeout !== null) | |
102 $this->requestTimeout = floatval($requestTimeout); | |
103 if($connectionTimeout !== null) | |
104 $this->connectionTimeout = floatval($connectionTimeout); | |
105 } | |
106 | |
107 public function setToken($token = null, $secret = null) | |
108 { | |
109 $this->token = $token; | |
110 $this->tokenSecret = $secret; | |
111 } | |
112 | |
113 public function useSSL($use = false) | |
114 { | |
115 $this->useSSL = (bool)$use; | |
116 } | |
117 | |
118 protected function addDefaultHeaders($url, $oauthHeaders) | |
119 { | |
120 $_h = array('Expect:'); | |
121 $urlParts = parse_url($url); | |
122 $oauth = 'Authorization: OAuth realm="' . $urlParts['scheme'] . '://' . $urlParts['host'] . $urlParts['path'] . '",'; | |
123 foreach($oauthHeaders as $name => $value) | |
124 { | |
125 $oauth .= "{$name}=\"{$value}\","; | |
126 } | |
127 $_h[] = substr($oauth, 0, -1); | |
128 $_h[] = "User-Agent: {$this->userAgent}"; | |
129 $this->addHeader($_h); | |
130 } | |
131 | |
132 protected function buildHttpQueryRaw($params) | |
133 { | |
134 $retval = ''; | |
135 foreach((array)$params as $key => $value) | |
136 $retval .= "{$key}={$value}&"; | |
137 $retval = substr($retval, 0, -1); | |
138 return $retval; | |
139 } | |
140 | |
141 protected function curlInit($url) | |
142 { | |
143 $ch = curl_init($url); | |
144 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); | |
145 curl_setopt($ch, CURLOPT_HTTPHEADER, $this->headers); | |
146 curl_setopt($ch, CURLOPT_TIMEOUT, $this->requestTimeout); | |
147 curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->connectionTimeout); | |
148 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); | |
149 if(isset($_SERVER ['SERVER_ADDR']) && !empty($_SERVER['SERVER_ADDR']) && $_SERVER['SERVER_ADDR'] != '127.0.0.1') | |
150 curl_setopt($ch, CURLOPT_INTERFACE, $_SERVER ['SERVER_ADDR']); | |
151 | |
152 if($this->useSSL === true) | |
153 { | |
154 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); | |
155 curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); | |
156 } | |
157 return $ch; | |
158 } | |
159 | |
160 protected function emptyHeaders() | |
161 { | |
162 $this->headers = array(); | |
163 } | |
164 | |
165 protected function encode_rfc3986($string) | |
166 { | |
167 return str_replace('+', ' ', str_replace('%7E', '~', rawurlencode(($string)))); | |
168 } | |
169 | |
170 protected function generateNonce() | |
171 { | |
172 if(isset($this->nonce)) // for unit testing | |
173 return $this->nonce; | |
174 | |
175 return md5(uniqid(rand(), true)); | |
176 } | |
177 | |
178 // parameters should already have been passed through prepareParameters | |
179 // no need to double encode | |
180 protected function generateSignature($method = null, $url = null, $params = null) | |
181 { | |
182 if(empty($method) || empty($url)) | |
183 return false; | |
184 | |
185 // concatenating and encode | |
186 $concatenatedParams = $this->encode_rfc3986($this->buildHttpQueryRaw($params)); | |
187 | |
188 // normalize url | |
189 $normalizedUrl = $this->encode_rfc3986($this->normalizeUrl($url)); | |
190 $method = $this->encode_rfc3986($method); // don't need this but why not? | |
191 | |
192 $signatureBaseString = "{$method}&{$normalizedUrl}&{$concatenatedParams}"; | |
193 return $this->signString($signatureBaseString); | |
194 } | |
195 | |
196 protected function httpDelete($url, $params) { | |
197 $this->addDefaultHeaders($url, $params['oauth']); | |
198 $ch = $this->curlInit($url); | |
199 curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE'); | |
200 curl_setopt($ch, CURLOPT_POSTFIELDS, $this->buildHttpQueryRaw($params['request'])); | |
201 $resp = $this->curl->addCurl($ch); | |
202 $this->emptyHeaders(); | |
203 return $resp; | |
204 } | |
205 | |
206 protected function httpGet($url, $params = null) | |
207 { | |
208 if(count($params['request']) > 0) | |
209 { | |
210 $url .= '?'; | |
211 foreach($params['request'] as $k => $v) | |
212 { | |
213 $url .= "{$k}={$v}&"; | |
214 } | |
215 $url = substr($url, 0, -1); | |
216 } | |
217 $this->addDefaultHeaders($url, $params['oauth']); | |
218 $ch = $this->curlInit($url); | |
219 $resp = $this->curl->addCurl($ch); | |
220 $this->emptyHeaders(); | |
221 | |
222 return $resp; | |
223 } | |
224 | |
225 protected function httpPost($url, $params = null, $isMultipart) | |
226 { | |
227 $this->addDefaultHeaders($url, $params['oauth']); | |
228 $ch = $this->curlInit($url); | |
229 curl_setopt($ch, CURLOPT_POST, 1); | |
230 // php's curl extension automatically sets the content type | |
231 // based on whether the params are in string or array form | |
232 if($isMultipart) | |
233 curl_setopt($ch, CURLOPT_POSTFIELDS, $params['request']); | |
234 else | |
235 curl_setopt($ch, CURLOPT_POSTFIELDS, $this->buildHttpQueryRaw($params['request'])); | |
236 $resp = $this->curl->addCurl($ch); | |
237 $this->emptyHeaders(); | |
238 | |
239 return $resp; | |
240 } | |
241 | |
242 protected function normalizeUrl($url = null) | |
243 { | |
244 $urlParts = parse_url($url); | |
245 $scheme = strtolower($urlParts['scheme']); | |
246 $host = strtolower($urlParts['host']); | |
247 $port = isset($urlParts['port']) ? intval($urlParts['port']) : 0; | |
248 | |
249 $retval = strtolower($scheme) . '://' . strtolower($host); | |
250 | |
251 if(!empty($port) && (($scheme === 'http' && $port != 80) || ($scheme === 'https' && $port != 443))) | |
252 $retval .= ":{$port}"; | |
253 | |
254 $retval .= $urlParts['path']; | |
255 if(!empty($urlParts['query'])) | |
256 { | |
257 $retval .= "?{$urlParts['query']}"; | |
258 } | |
259 | |
260 return $retval; | |
261 } | |
262 | |
263 protected function isMultipart($params = null) | |
264 { | |
265 if($params) | |
266 { | |
267 foreach($params as $k => $v) | |
268 { | |
269 if(strncmp('@',$k,1) === 0) | |
270 return true; | |
271 } | |
272 } | |
273 return false; | |
274 } | |
275 | |
276 protected function prepareParameters($method = null, $url = null, $params = null) | |
277 { | |
278 if(empty($method) || empty($url)) | |
279 return false; | |
280 | |
281 $oauth['oauth_consumer_key'] = $this->consumerKey; | |
282 $oauth['oauth_token'] = $this->token; | |
283 $oauth['oauth_nonce'] = $this->generateNonce(); | |
284 $oauth['oauth_timestamp'] = !isset($this->timestamp) ? time() : $this->timestamp; // for unit test | |
285 $oauth['oauth_signature_method'] = $this->signatureMethod; | |
286 if(isset($params['oauth_verifier'])) | |
287 { | |
288 $oauth['oauth_verifier'] = $params['oauth_verifier']; | |
289 unset($params['oauth_verifier']); | |
290 } | |
291 $oauth['oauth_version'] = $this->version; | |
292 // encode all oauth values | |
293 foreach($oauth as $k => $v) | |
294 $oauth[$k] = $this->encode_rfc3986($v); | |
295 // encode all non '@' params | |
296 // keep sigParams for signature generation (exclude '@' params) | |
297 // rename '@key' to 'key' | |
298 $sigParams = array(); | |
299 $hasFile = false; | |
300 if(is_array($params)) | |
301 { | |
302 foreach($params as $k => $v) | |
303 { | |
304 if(strncmp('@',$k,1) !== 0) | |
305 { | |
306 $sigParams[$k] = $this->encode_rfc3986($v); | |
307 $params[$k] = $this->encode_rfc3986($v); | |
308 } | |
309 else | |
310 { | |
311 $params[substr($k, 1)] = $v; | |
312 unset($params[$k]); | |
313 $hasFile = true; | |
314 } | |
315 } | |
316 | |
317 if($hasFile === true) | |
318 $sigParams = array(); | |
319 } | |
320 | |
321 $sigParams = array_merge($oauth, (array)$sigParams); | |
322 | |
323 // sorting | |
324 ksort($sigParams); | |
325 | |
326 // signing | |
327 $oauth['oauth_signature'] = $this->encode_rfc3986($this->generateSignature($method, $url, $sigParams)); | |
328 return array('request' => $params, 'oauth' => $oauth); | |
329 } | |
330 | |
331 protected function signString($string = null) | |
332 { | |
333 $retval = false; | |
334 switch($this->signatureMethod) | |
335 { | |
336 case 'HMAC-SHA1': | |
337 $key = $this->encode_rfc3986($this->consumerSecret) . '&' . $this->encode_rfc3986($this->tokenSecret); | |
338 $retval = base64_encode(hash_hmac('sha1', $string, $key, true)); | |
339 break; | |
340 } | |
341 | |
342 return $retval; | |
343 } | |
344 | |
345 public function __construct($consumerKey, $consumerSecret, $signatureMethod='HMAC-SHA1') | |
346 { | |
347 $this->consumerKey = $consumerKey; | |
348 $this->consumerSecret = $consumerSecret; | |
349 $this->signatureMethod = $signatureMethod; | |
350 $this->curl = EpiCurl::getInstance(); | |
351 } | |
352 } | |
353 | |
354 class EpiOAuthResponse | |
355 { | |
356 private $__resp; | |
357 protected $debug = false; | |
358 | |
359 public function __construct($resp) | |
360 { | |
361 $this->__resp = $resp; | |
362 } | |
363 | |
364 public function __get($name) | |
365 { | |
366 if($this->__resp->code != 200) | |
367 EpiOAuthException::raise($this->__resp, $this->debug); | |
368 | |
369 parse_str($this->__resp->data, $result); | |
370 foreach($result as $k => $v) | |
371 { | |
372 $this->$k = $v; | |
373 } | |
374 | |
375 return isset($result[$name]) ? $result[$name] : null; | |
376 } | |
377 | |
378 public function __toString() | |
379 { | |
380 return $this->__resp->data; | |
381 } | |
382 } | |
383 | |
384 class EpiOAuthException extends Exception | |
385 { | |
386 public static function raise($response, $debug) | |
387 { | |
388 $message = $response->responseText; | |
389 | |
390 switch($response->code) | |
391 { | |
392 case 400: | |
393 throw new EpiOAuthBadRequestException($message, $response->code); | |
394 case 401: | |
395 throw new EpiOAuthUnauthorizedException($message, $response->code); | |
396 default: | |
397 throw new EpiOAuthException($message, $response->code); | |
398 } | |
399 } | |
400 } | |
401 class EpiOAuthBadRequestException extends EpiOAuthException{} | |
402 class EpiOAuthUnauthorizedException extends EpiOAuthException{} | |
403 |