Test Setup Failed
Push — master ( ec638a...cb9435 )
by Julito
51:10
created

OAuthSimple   D

Complexity

Total Complexity 84

Size/Duplication

Total Lines 500
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Importance

Changes 0
Metric Value
dl 0
loc 500
rs 4.8717
c 0
b 0
f 0
wmc 84
lcom 1
cbo 1

How to fix   Complexity   

Complex Class

Complex classes like OAuthSimple often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use OAuthSimple, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * OAuthSimple - A simpler version of OAuth
4
 *
5
 * https://github.com/jrconlin/oauthsimple
6
 *
7
 * @author     jr conlin <[email protected]>
8
 * @copyright  unitedHeroes.net 2011
9
 * @version    1.3
10
 * @license    See license.txt
11
 *
12
 */
13
14
class OAuthSimple {
15
    private $_secrets;
16
    private $_default_signature_method;
17
    private $_action;
18
    private $_nonce_chars;
19
20
    /**
21
	 * Constructor
22
     *
23
	 * @access public
24
     * @param api_key (String) The API Key (sometimes referred to as the consumer key) This value is usually supplied by the site you wish to use.
25
     * @param shared_secret (String) The shared secret. This value is also usually provided by the site you wish to use.
26
	 * @return OAuthSimple (Object)
27
     */
28
    function __construct ($APIKey = "", $sharedSecret=""){
29
30
        if (!empty($APIKey))
31
		{
32
			$this->_secrets['consumer_key'] = $APIKey;
33
		}
34
35
        if (!empty($sharedSecret))
36
		{
37
			$this->_secrets['shared_secret'] = $sharedSecret;
38
		}
39
40
        $this->_default_signature_method = "HMAC-SHA1";
41
        $this->_action = "GET";
42
        $this->_nonce_chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
43
44
        return $this;
45
    }
46
47
    /**
48
	 * Reset the parameters and URL
49
	 *
50
	 * @access public
51
	 * @return OAuthSimple (Object)
52
	 */
53
    public function reset() {
54
        $this->_parameters = Array();
55
        $this->path = NULL;
56
        $this->sbs = NULL;
57
58
        return $this;
59
    }
60
61
    /**
62
	 * Set the parameters either from a hash or a string
63
	 *
64
	 * @access public
65
	 * @param(string, object) List of parameters for the call, this can either be a URI string (e.g. "foo=bar&gorp=banana" or an object/hash)
66
	 * @return OAuthSimple (Object)
67
	 */
68
    public function setParameters ($parameters=Array()) {
69
70
        if (is_string($parameters))
71
		{
72
			$parameters = $this->_parseParameterString($parameters);
73
		}
74
        if (empty($this->_parameters))
75
		{
76
			$this->_parameters = $parameters;
77
		}
78
        else if (!empty($parameters))
79
		{
80
			$this->_parameters = array_merge($this->_parameters,$parameters);
81
		}
82
        if (empty($this->_parameters['oauth_nonce']))
83
		{
84
			$this->_getNonce();
85
		}
86
        if (empty($this->_parameters['oauth_timestamp']))
87
		{
88
			 $this->_getTimeStamp();
89
		}
90
        if (empty($this->_parameters['oauth_consumer_key']))
91
		{
92
			$this->_getApiKey();
93
		}
94
        if (empty($this->_parameters['oauth_token']))
95
		{
96
			  $this->_getAccessToken();
97
		}
98
        if (empty($this->_parameters['oauth_signature_method']))
99
		{
100
            $this->setSignatureMethod();
101
		}
102
        if (empty($this->_parameters['oauth_version']))
103
		{
104
            $this->_parameters['oauth_version']="1.0";
105
		}
106
107
        return $this;
108
    }
109
110
    /**
111
	 * Convenience method for setParameters
112
	 *
113
	 * @access public
114
	 * @see setParameters
115
	 */
116
    public function setQueryString ($parameters)
117
    {
118
        return $this->setParameters($parameters);
119
    }
120
121
    /**
122
	 * Set the target URL (does not include the parameters)
123
	 *
124
     * @param path (String) the fully qualified URI (excluding query arguments) (e.g "http://example.org/foo")
125
	 * @return OAuthSimple (Object)
126
     */
127
    public function setURL ($path)
128
	{
129
        if (empty($path))
130
		{
131
            throw new OAuthSimpleException('No path specified for OAuthSimple.setURL');
132
		}
133
        $this->_path=$path;
134
135
        return $this;
136
    }
137
138
    /**
139
	 * Convenience method for setURL
140
     *
141
     * @param path (String)
142
	 * @see setURL
143
     */
144
    public function setPath ($path)
145
    {
146
        return $this->_path=$path;
147
    }
148
149
    /**
150
	 * Set the "action" for the url, (e.g. GET,POST, DELETE, etc.)
151
     *
152
     * @param action (String) HTTP Action word.
153
	 * @return OAuthSimple (Object)
154
     */
155
    public function setAction ($action)
156
    {
157
        if (empty($action))
158
		{
159
			$action = 'GET';
160
		}
161
        $action = strtoupper($action);
162
        if (preg_match('/[^A-Z]/',$action))
163
		{
164
            throw new OAuthSimpleException('Invalid action specified for OAuthSimple.setAction');
165
		}
166
        $this->_action = $action;
167
168
        return $this;
169
    }
170
171
    /**
172
	 * Set the signatures (as well as validate the ones you have)
173
     *
174
     * @param signatures (object) object/hash of the token/signature pairs {api_key:, shared_secret:, oauth_token: oauth_secret:}
175
	 * @return OAuthSimple (Object)
176
     */
177
    public function signatures ($signatures)
178
    {
179
        if (!empty($signatures) && !is_array($signatures))
180
		{
181
            throw new OAuthSimpleException('Must pass dictionary array to OAuthSimple.signatures');
182
		}
183
        if (!empty($signatures))
184
        {
185
            if (empty($this->_secrets))
186
            {
187
                $this->_secrets=Array();
188
            }
189
            $this->_secrets=array_merge($this->_secrets,$signatures);
190
        }
191
        if (isset($this->_secrets['api_key']))
192
		{
193
            $this->_secrets['consumer_key'] = $this->_secrets['api_key'];
194
		}
195
        if (isset($this->_secrets['access_token']))
196
		{
197
            $this->_secrets['oauth_token'] = $this->_secrets['access_token'];
198
		}
199
        if (isset($this->_secrets['access_secret']))
200
		{
201
            $this->_secrets['shared_secret'] = $this->_secrets['access_secret'];
202
        }
203
        if (isset($this->_secrets['oauth_token_secret']))
204
		{
205
            $this->_secrets['oauth_secret'] = $this->_secrets['oauth_token_secret'];
206
		}
207
        if (empty($this->_secrets['consumer_key']))
208
		{
209
            throw new OAuthSimpleException('Missing required consumer_key in OAuthSimple.signatures');
210
        }
211
        if (empty($this->_secrets['shared_secret']))
212
		{
213
            throw new OAuthSimpleException('Missing requires shared_secret in OAuthSimple.signatures');
214
		}
215
        if (!empty($this->_secrets['oauth_token']) && empty($this->_secrets['oauth_secret']))
216
		{
217
            throw new OAuthSimpleException('Missing oauth_secret for supplied oauth_token in OAuthSimple.signatures');
218
		}
219
220
        return $this;
221
    }
222
223
    public function setTokensAndSecrets($signatures)
224
    {
225
        return $this->signatures($signatures);
226
    }
227
228
    /**
229
	 * Set the signature method (currently only Plaintext or SHA-MAC1)
230
     *
231
     * @param method (String) Method of signing the transaction (only PLAINTEXT and SHA-MAC1 allowed for now)
232
	 * @return OAuthSimple (Object)
233
    */
234
    public function setSignatureMethod ($method="")
235
	{
236
        if (empty($method))
237
		{
238
            $method = $this->_default_signature_method;
239
		}
240
        $method = strtoupper($method);
241
        switch($method)
242
        {
243
            case 'PLAINTEXT':
244
            case 'HMAC-SHA1':
245
                $this->_parameters['oauth_signature_method']=$method;
246
				break;
247
            default:
248
                throw new OAuthSimpleException ("Unknown signing method $method specified for OAuthSimple.setSignatureMethod");
249
				break;
250
        }
251
252
		return $this;
253
    }
254
255
    /** sign the request
256
     *
257
     * note: all arguments are optional, provided you've set them using the
258
     * other helper functions.
259
     *
260
     * @param args (Array) hash of arguments for the call {action, path, parameters (array), method, signatures (array)} all arguments are optional.
261
	 * @return (Array) signed values
262
     */
263
    public function sign($args=array())
264
    {
265
        if (!empty($args['action']))
266
		{
267
            $this->setAction($args['action']);
268
		}
269
        if (!empty($args['path']))
270
		{
271
            $this->setPath($args['path']);
272
        }
273
        if (!empty($args['method']))
274
		{
275
            $this->setSignatureMethod($args['method']);
276
		}
277
        if (!empty($args['signatures']))
278
		{
279
            $this->signatures($args['signatures']);
280
		}
281
        if (empty($args['parameters']))
282
		{
283
            $args['parameters']=array();
284
		}
285
        $this->setParameters($args['parameters']);
286
        $normParams = $this->_normalizedParameters();
287
288
        return Array (
289
            'parameters' => $this->_parameters,
290
            'signature' => self::_oauthEscape($this->_parameters['oauth_signature']),
291
            'signed_url' => $this->_path . '?' . $normParams,
292
            'header' => $this->getHeaderString(),
293
            'sbs'=> $this->sbs
294
            );
295
    }
296
297
    /**
298
	 * Return a formatted "header" string
299
     *
300
     * NOTE: This doesn't set the "Authorization: " prefix, which is required.
301
     * It's not set because various set header functions prefer different
302
     * ways to do that.
303
     *
304
     * @param args (Array)
305
	 * @return $result (String)
306
    */
307
    public function getHeaderString ($args=array())
308
    {
309
        if (empty($this->_parameters['oauth_signature']))
310
		{
311
            $this->sign($args);
312
		}
313
        $result = 'OAuth ';
314
315
        foreach ($this->_parameters as $pName => $pValue)
316
        {
317
            if (strpos($pName,'oauth_') !== 0)
318
			{
319
                continue;
320
			}
321
            if (is_array($pValue))
322
            {
323
                foreach ($pValue as $val)
324
                {
325
                    $result .= $pName .'="' . self::_oauthEscape($val) . '", ';
326
                }
327
            }
328
            else
329
            {
330
                $result .= $pName . '="' . self::_oauthEscape($pValue) . '", ';
331
            }
332
        }
333
334
        return preg_replace('/, $/','',$result);
335
    }
336
337
    private function _parseParameterString ($paramString)
338
    {
339
        $elements = explode('&',$paramString);
340
        $result = array();
341
        foreach ($elements as $element)
342
        {
343
            list ($key,$token) = explode('=',$element);
344
            if ($token)
345
			{
346
                $token = urldecode($token);
347
			}
348
            if (!empty($result[$key]))
349
            {
350
                if (!is_array($result[$key]))
351
				{
352
                    $result[$key] = array($result[$key],$token);
353
				}
354
                else
355
				{
356
                    array_push($result[$key],$token);
357
				}
358
            }
359
            else
360
                $result[$key]=$token;
361
        }
362
        return $result;
363
    }
364
365
366
    private static function _oauthEscape($string)
367
    {
368
        if ($string === 0) { return 0; }
369
		if ($string == '0') { return '0'; }
370
        if (strlen($string) == 0) { return ''; }
371
        if (is_array($string)) {
372
            throw new OAuthSimpleException('Array passed to _oauthEscape');
373
		}
374
        $string = urlencode($string);
375
376
	    //FIX: urlencode of ~ and '+'
377
        $string = str_replace(
378
            Array('%7E','+'  ), // Replace these
379
            Array('~',  '%20'), // with these
380
            $string);
381
382
        return $string;
383
    }
384
385
    private function _getNonce($length=5)
386
    {
387
        $result = '';
388
        $cLength = strlen($this->_nonce_chars);
389
        for ($i=0; $i < $length; $i++)
390
        {
391
            $rnum = rand(0,$cLength - 1);
392
            $result .= substr($this->_nonce_chars,$rnum,1);
393
        }
394
        $this->_parameters['oauth_nonce'] = $result;
395
396
        return $result;
397
    }
398
399
    private function _getApiKey()
400
    {
401
        if (empty($this->_secrets['consumer_key']))
402
        {
403
            throw new OAuthSimpleException('No consumer_key set for OAuthSimple');
404
        }
405
        $this->_parameters['oauth_consumer_key']=$this->_secrets['consumer_key'];
406
407
        return $this->_parameters['oauth_consumer_key'];
408
    }
409
410
    private function _getAccessToken()
411
    {
412
        if (!isset($this->_secrets['oauth_secret']))
413
		{
414
            return '';
415
		}
416
        if (!isset($this->_secrets['oauth_token']))
417
		{
418
            throw new OAuthSimpleException('No access token (oauth_token) set for OAuthSimple.');
419
		}
420
        $this->_parameters['oauth_token'] = $this->_secrets['oauth_token'];
421
422
        return $this->_parameters['oauth_token'];
423
    }
424
425
    private function _getTimeStamp()
426
    {
427
        return $this->_parameters['oauth_timestamp'] = time();
428
    }
429
430
    private function _normalizedParameters()
431
    {
432
		$normalized_keys = array();
433
		$return_array = array();
434
435
        foreach ( $this->_parameters as $paramName=>$paramValue) {
436
            if (preg_match('/w+_secret/', $paramName) OR
437
                $paramName == "oauth_signature") {
438
                    continue;
439
                }
440
            // Read parameters from a file. Hope you're practicing safe PHP.
441
            //if (strpos($paramValue, '@') !== 0 && !file_exists(substr($paramValue, 1)))
442
			//{
443
				if (is_array($paramValue))
444
				{
445
					$normalized_keys[self::_oauthEscape($paramName)] = array();
446
					foreach($paramValue as $item)
447
					{
448
						array_push($normalized_keys[self::_oauthEscape($paramName)],  self::_oauthEscape($item));
449
					}
450
				}
451
				else
452
				{
453
					$normalized_keys[self::_oauthEscape($paramName)] = self::_oauthEscape($paramValue);
454
				}
455
			//}
456
        }
457
458
		ksort($normalized_keys);
459
460
		foreach($normalized_keys as $key=>$val)
461
		{
462
			if (is_array($val))
463
			{
464
				sort($val);
465
				foreach($val as $element)
466
				{
467
					array_push($return_array, $key . "=" . $element);
468
				}
469
			}
470
			else
471
			{
472
				array_push($return_array, $key .'='. $val);
473
			}
474
475
        }
476
        $presig = join("&", $return_array);
477
        $sig = $this->_generateSignature($presig);
478
        $this->_parameters['oauth_signature']=$sig;
479
        array_push($return_array, "oauth_signature=$sig");
480
		return join("&", $return_array);
481
    }
482
483
484
    private function _generateSignature ($parameters="")
485
    {
486
        $secretKey = '';
487
		if(isset($this->_secrets['shared_secret']))
488
		{
489
			$secretKey = self::_oauthEscape($this->_secrets['shared_secret']);
490
		}
491
492
		$secretKey .= '&';
493
		if(isset($this->_secrets['oauth_secret']))
494
		{
495
            $secretKey .= self::_oauthEscape($this->_secrets['oauth_secret']);
496
        }
497
        if(!empty($parameters)){
498
            $parameters = urlencode($parameters);
499
        }
500
        switch($this->_parameters['oauth_signature_method'])
501
        {
502
            case 'PLAINTEXT':
503
                return urlencode($secretKey);;
504
            case 'HMAC-SHA1':
505
                $this->sbs = self::_oauthEscape($this->_action).'&'.self::_oauthEscape($this->_path).'&'.$parameters;
506
507
                return base64_encode(hash_hmac('sha1',$this->sbs,$secretKey,TRUE));
508
            default:
509
                throw new OAuthSimpleException('Unknown signature method for OAuthSimple');
510
				break;
511
        }
512
    }
513
}
514
515
class OAuthSimpleException extends Exception {
516
517
	public function __construct($err, $isDebug = FALSE)
518
	{
519
		self::log_error($err);
520
		if ($isDebug)
521
		{
522
			self::display_error($err, TRUE);
523
		}
524
	}
525
526
	public static function log_error($err)
527
	{
528
		error_log($err, 0);
529
	}
530
531
	public static function display_error($err, $kill = FALSE)
532
	{
533
		print_r($err);
534
		if ($kill === FALSE)
535
		{
536
			die();
537
		}
538
	}
539
}
540