GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Pull Request — master (#552)
by
unknown
02:20
created

TwitterOAuth::oauth2()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 13
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 11
nc 1
nop 2
1
<?php
2
/**
3
 * The most popular PHP library for use with the Twitter OAuth REST API.
4
 *
5
 * @license MIT
6
 */
7
namespace Abraham\TwitterOAuth;
8
9
use Abraham\TwitterOAuth\Util\JsonDecoder;
10
11
/**
12
 * TwitterOAuth class for interacting with the Twitter API.
13
 *
14
 * @author Abraham Williams <[email protected]>
15
 */
16
class TwitterOAuth extends Config
17
{
18
    const API_VERSION = '1.1';
19
    const API_HOST = 'https://api.twitter.com';
20
    const UPLOAD_HOST = 'https://upload.twitter.com';
21
    const UPLOAD_CHUNK = 40960; // 1024 * 40
22
23
    /** @var Response details about the result of the last request */
24
    private $response;
25
    /** @var string|null Application bearer token */
26
    private $bearer;
27
    /** @var Consumer Twitter application details */
28
    private $consumer;
29
    /** @var Token|null User access token details */
30
    private $token;
31
    /** @var HmacSha1 OAuth 1 signature type used by Twitter */
32
    private $signatureMethod;
33
34
    /**
35
     * Constructor
36
     *
37
     * @param string      $consumerKey      The Application Consumer Key
38
     * @param string      $consumerSecret   The Application Consumer Secret
39
     * @param string|null $oauthToken       The Client Token (optional)
40
     * @param string|null $oauthTokenSecret The Client Token Secret (optional)
41
     */
42
    public function __construct($consumerKey, $consumerSecret, $oauthToken = null, $oauthTokenSecret = null)
43
    {
44
        $this->resetLastResponse();
45
        $this->signatureMethod = new HmacSha1();
46
        $this->consumer = new Consumer($consumerKey, $consumerSecret);
47
        if (!empty($oauthToken) && !empty($oauthTokenSecret)) {
48
            $this->token = new Token($oauthToken, $oauthTokenSecret);
49
        }
50
        if (empty($oauthToken) && !empty($oauthTokenSecret)) {
51
            $this->bearer = $oauthTokenSecret;
52
        }
53
    }
54
55
    /**
56
     * @param string $oauthToken
57
     * @param string $oauthTokenSecret
58
     */
59
    public function setOauthToken($oauthToken, $oauthTokenSecret)
60
    {
61
        $this->token = new Token($oauthToken, $oauthTokenSecret);
62
    }
63
64
    /**
65
     * @return string|null
66
     */
67
    public function getLastApiPath()
68
    {
69
        return $this->response->getApiPath();
70
    }
71
72
    /**
73
     * @return int
74
     */
75
    public function getLastHttpCode()
76
    {
77
        return $this->response->getHttpCode();
78
    }
79
80
    /**
81
     * @return array
82
     */
83
    public function getLastXHeaders()
84
    {
85
        return $this->response->getXHeaders();
86
    }
87
88
    /**
89
     * @return array|object|null
90
     */
91
    public function getLastBody()
92
    {
93
        return $this->response->getBody();
94
    }
95
96
    /**
97
     * Resets the last response cache.
98
     */
99
    public function resetLastResponse()
100
    {
101
        $this->response = new Response();
102
    }
103
104
    /**
105
     * Make URLs for user browser navigation.
106
     *
107
     * @param string $path
108
     * @param array  $parameters
109
     *
110
     * @return string
111
     */
112
    public function url($path, array $parameters)
113
    {
114
        $this->resetLastResponse();
115
        $this->response->setApiPath($path);
116
        $query = http_build_query($parameters);
117
        return sprintf('%s/%s?%s', self::API_HOST, $path, $query);
118
    }
119
120
    /**
121
     * Make /oauth/* requests to the API.
122
     *
123
     * @param string $path
124
     * @param array  $parameters
125
     *
126
     * @return array
127
     * @throws TwitterOAuthException
128
     */
129
    public function oauth($path, array $parameters = [])
130
    {
131
        $response = [];
132
        $this->resetLastResponse();
133
        $this->response->setApiPath($path);
134
        $url = sprintf('%s/%s', self::API_HOST, $path);
135
        $result = $this->oAuthRequest($url, 'POST', $parameters);
136
137
        if ($this->getLastHttpCode() != 200) {
138
            throw new TwitterOAuthException($result);
139
        }
140
141
        parse_str($result, $response);
142
        $this->response->setBody($response);
143
144
        return $response;
145
    }
146
147
    /**
148
     * Make /oauth2/* requests to the API.
149
     *
150
     * @param string $path
151
     * @param array  $parameters
152
     *
153
     * @return array|object
154
     */
155
    public function oauth2($path, array $parameters = [])
156
    {
157
        $method = 'POST';
158
        $this->resetLastResponse();
159
        $this->response->setApiPath($path);
160
        $url = sprintf('%s/%s', self::API_HOST, $path);
161
        $request = Request::fromConsumerAndToken($this->consumer, $this->token, $method, $url, $parameters);
162
        $authorization = 'Authorization: Basic ' . $this->encodeAppAuthorization($this->consumer);
163
        $result = $this->request($request->getNormalizedHttpUrl(), $method, $authorization, $parameters);
164
        $response = JsonDecoder::decode($result, $this->decodeJsonAsArray);
165
        $this->response->setBody($response);
166
        return $response;
167
    }
168
169
    /**
170
     * Make GET requests to the API.
171
     *
172
     * @param string $path
173
     * @param array  $parameters
174
     *
175
     * @return array|object
176
     */
177
    public function get($path, array $parameters = [])
178
    {
179
        return $this->http('GET', self::API_HOST, $path, $parameters);
180
    }
181
182
    /**
183
     * Make POST requests to the API.
184
     *
185
     * @param string $path
186
     * @param array  $parameters
187
     *
188
     * @return array|object
189
     */
190
    public function post($path, array $parameters = [])
191
    {
192
        return $this->http('POST', self::API_HOST, $path, $parameters);
193
    }
194
195
    /**
196
     * Make DELETE requests to the API.
197
     *
198
     * @param string $path
199
     * @param array  $parameters
200
     *
201
     * @return array|object
202
     */
203
    public function delete($path, array $parameters = [])
204
    {
205
        return $this->http('DELETE', self::API_HOST, $path, $parameters);
206
    }
207
208
    /**
209
     * Make PUT requests to the API.
210
     *
211
     * @param string $path
212
     * @param array  $parameters
213
     *
214
     * @return array|object
215
     */
216
    public function put($path, array $parameters = [])
217
    {
218
        return $this->http('PUT', self::API_HOST, $path, $parameters);
219
    }
220
221
    /**
222
     * Upload media to upload.twitter.com.
223
     *
224
     * @param string $path
225
     * @param array  $parameters
226
     * @param boolean  $chunked
227
     *
228
     * @return array|object
229
     */
230
    public function upload($path, array $parameters = [], $chunked = false)
231
    {
232
        if ($chunked) {
233
            return $this->uploadMediaChunked($path, $parameters);
234
        } else {
235
            return $this->uploadMediaNotChunked($path, $parameters);
236
        }
237
    }
238
239
    /**
240
     * Private method to upload media (not chunked) to upload.twitter.com.
241
	 * UPDATE per https://dev.twitter.com/rest/reference/post/media/upload to use media_data for base64 encoded filesize
242
	 * and check if parameter is a file path if not assume it's base64_encode already
243
     *
244
     * @param string $path
245
     * @param array  $parameters
246
     *
247
     * @return array|object
248
	 * @updatedby Martin Barker 
249
	 * @updated 3rd March 2017
250
     */
251
    private function uploadMediaNotChunked($path, array $parameters)
252
    {
253
		
254
		$base = "";
255
		if(ctype_print($parameters['media'])){
256
			if(file_exists($parameters['media'])){
257
				$file = file_get_contents($parameters['media']);
258
				$base = base64_encode($file);
259
			}else{
260
				$base = $parameters['media'];
261
			}
262
		}else{
263
			$base = base64_encode($parameters['media']);
264
		}
265
		unset $parameters['media'];
0 ignored issues
show
Bug introduced by
This code did not parse for me. Apparently, there is an error somewhere around this line:

Syntax error, unexpected T_VARIABLE, expecting '('
Loading history...
266
		
267
        $parameters['media_data'] = $base;
268
        return $this->http('POST', self::UPLOAD_HOST, $path, $parameters);
269
    }
270
271
    /**
272
     * Private method to upload media (chunked) to upload.twitter.com.
273
     *
274
     * @param string $path
275
     * @param array  $parameters
276
     *
277
     * @return array|object
278
     */
279
    private function uploadMediaChunked($path, array $parameters)
280
    {
281
        $init = $this->http('POST', self::UPLOAD_HOST, $path, $this->mediaInitParameters($parameters));
282
        // Append
283
        $segment_index = 0;
284
        $media = fopen($parameters['media'], 'rb');
285
        while (!feof($media))
286
        {
287
            $this->http('POST', self::UPLOAD_HOST, 'media/upload', [
288
                'command' => 'APPEND',
289
                'media_id' => $init->media_id_string,
290
                'segment_index' => $segment_index++,
291
                'media_data' => base64_encode(fread($media, self::UPLOAD_CHUNK))
292
            ]);
293
        }
294
        fclose($media);
295
        // Finalize
296
        $finalize = $this->http('POST', self::UPLOAD_HOST, 'media/upload', [
297
            'command' => 'FINALIZE',
298
            'media_id' => $init->media_id_string
299
        ]);
300
        return $finalize;
301
    }
302
303
    /**
304
     * Private method to get params for upload media chunked init.
305
     * Twitter docs: https://dev.twitter.com/rest/reference/post/media/upload-init.html
306
     *
307
     * @param array  $parameters
308
     *
309
     * @return array
310
     */
311
    private function mediaInitParameters(array $parameters)
312
    {
313
        $return = [
314
            'command' => 'INIT',
315
            'media_type' => $parameters['media_type'],
316
            'total_bytes' => filesize($parameters['media'])
317
        ];
318
        if (isset($parameters['additional_owners'])) {
319
            $return['additional_owners'] = $parameters['additional_owners'];
320
        }
321
        if (isset($parameters['media_category'])) {
322
            $return['media_category'] = $parameters['media_category'];
323
        }
324
        return $return;
325
    }
326
327
    /**
328
     * @param string $method
329
     * @param string $host
330
     * @param string $path
331
     * @param array  $parameters
332
     *
333
     * @return array|object
334
     */
335
    private function http($method, $host, $path, array $parameters)
336
    {
337
        $this->resetLastResponse();
338
        $url = sprintf('%s/%s/%s.json', $host, self::API_VERSION, $path);
339
        $this->response->setApiPath($path);
340
        $result = $this->oAuthRequest($url, $method, $parameters);
341
        $response = JsonDecoder::decode($result, $this->decodeJsonAsArray);
342
        $this->response->setBody($response);
343
        return $response;
344
    }
345
346
    /**
347
     * Format and sign an OAuth / API request
348
     *
349
     * @param string $url
350
     * @param string $method
351
     * @param array  $parameters
352
     *
353
     * @return string
354
     * @throws TwitterOAuthException
355
     */
356
    private function oAuthRequest($url, $method, array $parameters)
357
    {
358
        $request = Request::fromConsumerAndToken($this->consumer, $this->token, $method, $url, $parameters);
359
        if (array_key_exists('oauth_callback', $parameters)) {
360
            // Twitter doesn't like oauth_callback as a parameter.
361
            unset($parameters['oauth_callback']);
362
        }
363
        if ($this->bearer === null) {
364
            $request->signRequest($this->signatureMethod, $this->consumer, $this->token);
365
            $authorization = $request->toHeader();
366
        } else {
367
            $authorization = 'Authorization: Bearer ' . $this->bearer;
368
        }
369
        return $this->request($request->getNormalizedHttpUrl(), $method, $authorization, $parameters);
370
    }
371
372
    /**
373
     * Make an HTTP request
374
     *
375
     * @param string $url
376
     * @param string $method
377
     * @param string $authorization
378
     * @param array $postfields
379
     *
380
     * @return string
381
     * @throws TwitterOAuthException
382
     */
383
    private function request($url, $method, $authorization, array $postfields)
384
    {
385
        /* Curl settings */
386
        $options = [
387
            // CURLOPT_VERBOSE => true,
388
            CURLOPT_CAINFO => __DIR__ . DIRECTORY_SEPARATOR . 'cacert.pem',
389
            CURLOPT_CONNECTTIMEOUT => $this->connectionTimeout,
390
            CURLOPT_HEADER => true,
391
            CURLOPT_HTTPHEADER => ['Accept: application/json', $authorization, 'Expect:'],
392
            CURLOPT_RETURNTRANSFER => true,
393
            CURLOPT_SSL_VERIFYHOST => 2,
394
            CURLOPT_SSL_VERIFYPEER => true,
395
            CURLOPT_TIMEOUT => $this->timeout,
396
            CURLOPT_URL => $url,
397
            CURLOPT_USERAGENT => $this->userAgent,
398
        ];
399
400
        /* Remove CACert file when in a PHAR file. */
401
        if ($this->pharRunning()) {
402
            unset($options[CURLOPT_CAINFO]);
403
        }
404
405
        if($this->gzipEncoding) {
406
            $options[CURLOPT_ENCODING] = 'gzip';
407
        }
408
409
        if (!empty($this->proxy)) {
410
            $options[CURLOPT_PROXY] = $this->proxy['CURLOPT_PROXY'];
411
            $options[CURLOPT_PROXYUSERPWD] = $this->proxy['CURLOPT_PROXYUSERPWD'];
412
            $options[CURLOPT_PROXYPORT] = $this->proxy['CURLOPT_PROXYPORT'];
413
            $options[CURLOPT_PROXYAUTH] = CURLAUTH_BASIC;
414
            $options[CURLOPT_PROXYTYPE] = CURLPROXY_HTTP;
415
        }
416
417
        switch ($method) {
418
            case 'GET':
419
                break;
420
            case 'POST':
421
                $options[CURLOPT_POST] = true;
422
                $options[CURLOPT_POSTFIELDS] = Util::buildHttpQuery($postfields);
423
                break;
424
            case 'DELETE':
425
                $options[CURLOPT_CUSTOMREQUEST] = 'DELETE';
426
                break;
427
            case 'PUT':
428
                $options[CURLOPT_CUSTOMREQUEST] = 'PUT';
429
                break;
430
        }
431
432
        if (in_array($method, ['GET', 'PUT', 'DELETE']) && !empty($postfields)) {
433
            $options[CURLOPT_URL] .= '?' . Util::buildHttpQuery($postfields);
434
        }
435
436
437
        $curlHandle = curl_init();
438
        curl_setopt_array($curlHandle, $options);
439
        $response = curl_exec($curlHandle);
440
441
        // Throw exceptions on cURL errors.
442
        if (curl_errno($curlHandle) > 0) {
443
            throw new TwitterOAuthException(curl_error($curlHandle), curl_errno($curlHandle));
444
        }
445
446
        $this->response->setHttpCode(curl_getinfo($curlHandle, CURLINFO_HTTP_CODE));
447
        $parts = explode("\r\n\r\n", $response);
448
        $responseBody = array_pop($parts);
449
        $responseHeader = array_pop($parts);
450
        $this->response->setHeaders($this->parseHeaders($responseHeader));
451
452
        curl_close($curlHandle);
453
454
        return $responseBody;
455
    }
456
457
    /**
458
     * Get the header info to store.
459
     *
460
     * @param string $header
461
     *
462
     * @return array
463
     */
464
    private function parseHeaders($header)
465
    {
466
        $headers = [];
467
        foreach (explode("\r\n", $header) as $line) {
468
            if (strpos($line, ':') !== false) {
469
                list ($key, $value) = explode(': ', $line);
470
                $key = str_replace('-', '_', strtolower($key));
471
                $headers[$key] = trim($value);
472
            }
473
        }
474
        return $headers;
475
    }
476
477
    /**
478
     * Encode application authorization header with base64.
479
     *
480
     * @param Consumer $consumer
481
     *
482
     * @return string
483
     */
484
    private function encodeAppAuthorization(Consumer $consumer)
485
    {
486
        $key = rawurlencode($consumer->key);
487
        $secret = rawurlencode($consumer->secret);
488
        return base64_encode($key . ':' . $secret);
489
    }
490
491
    /**
492
     * Is the code running from a Phar module.
493
     *
494
     * @return boolean
495
     */
496
    private function pharRunning()
497
    {
498
        return class_exists('Phar') && \Phar::running(false) !== '';
499
    }
500
}
501