Completed
Pull Request — master (#559)
by
unknown
01:24
created

Signature::parseQueryString()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
rs 9.9332
c 0
b 0
f 0
cc 3
nc 3
nop 1
1
<?php
2
3
namespace OAuth\OAuth1\Signature;
4
5
use OAuth\Common\Consumer\CredentialsInterface;
6
use OAuth\Common\Http\Uri\UriInterface;
7
use OAuth\OAuth1\Signature\Exception\UnsupportedHashAlgorithmException;
8
9
class Signature implements SignatureInterface
10
{
11
    /**
12
     * @var Credentials
13
     */
14
    protected $credentials;
15
16
    /**
17
     * @var string
18
     */
19
    protected $algorithm;
20
21
    /**
22
     * @var string
23
     */
24
    protected $tokenSecret = null;
25
26
    /**
27
     * @param CredentialsInterface $credentials
28
     */
29
    public function __construct(CredentialsInterface $credentials)
30
    {
31
        $this->credentials = $credentials;
0 ignored issues
show
Documentation Bug introduced by
It seems like $credentials of type object<OAuth\Common\Cons...r\CredentialsInterface> is incompatible with the declared type object<OAuth\OAuth1\Signature\Credentials> of property $credentials.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
32
    }
33
34
    /**
35
     * @param string $algorithm
36
     */
37
    public function setHashingAlgorithm($algorithm)
38
    {
39
        $this->algorithm = $algorithm;
40
    }
41
42
    /**
43
     * @param string $token
44
     */
45
    public function setTokenSecret($token)
46
    {
47
        $this->tokenSecret = $token;
48
    }
49
50
    /**
51
     * @param UriInterface $uri
52
     * @param array        $params
53
     * @param string       $method
54
     *
55
     * @return string
56
     */
57
    public function getSignature(UriInterface $uri, array $params, $method = 'POST')
58
    {
59
        $queryStringData = $this->parseQueryString($uri->getQuery());
60
61
        foreach (array_merge($queryStringData, $params) as $key => $value) {
62
            $signatureData[rawurlencode($key)] = rawurlencode(strtr($value, ' ', '+'));
0 ignored issues
show
Coding Style Comprehensibility introduced by
$signatureData was never initialized. Although not strictly required by PHP, it is generally a good practice to add $signatureData = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
63
        }
64
65
        uksort($signatureData, 'strnatcmp');
66
67
        // determine base uri
68
        $baseUri = $uri->getScheme() . '://' . $uri->getRawAuthority();
69
70
        if ('/' === $uri->getPath()) {
71
            $baseUri .= $uri->hasExplicitTrailingHostSlash() ? '/' : '';
72
        } else {
73
            $baseUri .= $uri->getPath();
74
        }
75
76
        $baseString = strtoupper($method) . '&';
77
        $baseString .= rawurlencode($baseUri) . '&';
78
        $baseString .= rawurlencode($this->buildSignatureDataString($signatureData));
79
80
        return base64_encode($this->hash($baseString));
81
    }
82
83
    /**
84
     * A userland implementation of parse_str that treats arrays as string keys
85
     *
86
     * @param string $query
87
     *
88
     * @return array
89
     */
90
    protected function parseQueryString($query)
91
    {
92
        $result = [];
93
        $params = explode('&', $query);
94
        foreach ($params as $param) {
95
            $parts = explode('=', $param, 2);
96
            $result[rawurldecode($parts[0])] = isset($parts[1]) ? urldecode($parts[1]) : '';
97
        }
98
        return $result;
99
    }
100
101
    /**
102
     * @param array $signatureData
103
     *
104
     * @return string
105
     */
106
    protected function buildSignatureDataString(array $signatureData)
107
    {
108
        $signatureString = '';
109
        $delimiter = '';
110
        foreach ($signatureData as $key => $value) {
111
            $signatureString .= $delimiter . $key . '=' . $value;
112
113
            $delimiter = '&';
114
        }
115
116
        return $signatureString;
117
    }
118
119
    /**
120
     * @return string
121
     */
122
    protected function getSigningKey()
123
    {
124
        $signingKey = rawurlencode($this->credentials->getConsumerSecret()) . '&';
125
        if ($this->tokenSecret !== null) {
126
            $signingKey .= rawurlencode($this->tokenSecret);
127
        }
128
129
        return $signingKey;
130
    }
131
132
    /**
133
     * @param string $data
134
     *
135
     * @return string
136
     *
137
     * @throws UnsupportedHashAlgorithmException
138
     */
139
    protected function hash($data)
140
    {
141
        switch (strtoupper($this->algorithm)) {
142
            case 'HMAC-SHA1':
143
                return hash_hmac('sha1', $data, $this->getSigningKey(), true);
144
            default:
145
                throw new UnsupportedHashAlgorithmException(
146
                    'Unsupported hashing algorithm (' . $this->algorithm . ') used.'
147
                );
148
        }
149
    }
150
}
151