This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | namespace Transmission; |
||
3 | |||
4 | use Buzz\Message\Request; |
||
5 | use Buzz\Message\Response; |
||
6 | use Buzz\Client\Curl; |
||
7 | use Buzz\Client\ClientInterface; |
||
8 | |||
9 | /** |
||
10 | * The Client class is used to make API calls to the Transmission server |
||
11 | * |
||
12 | * @author Ramon Kleiss <[email protected]> |
||
13 | */ |
||
14 | class Client |
||
15 | { |
||
16 | /** |
||
17 | * @var string |
||
18 | */ |
||
19 | const DEFAULT_HOST = 'localhost'; |
||
20 | |||
21 | /** |
||
22 | * @var integer |
||
23 | */ |
||
24 | const DEFAULT_PORT = 9091; |
||
25 | |||
26 | /** |
||
27 | * @var string |
||
28 | */ |
||
29 | const DEFAULT_PATH = '/transmission/rpc'; |
||
30 | |||
31 | /** |
||
32 | * @var string |
||
33 | */ |
||
34 | const TOKEN_HEADER = 'X-Transmission-Session-Id'; |
||
35 | |||
36 | /** |
||
37 | * @var string |
||
38 | */ |
||
39 | protected $host = self::DEFAULT_HOST; |
||
40 | |||
41 | /** |
||
42 | * @var integer |
||
43 | */ |
||
44 | protected $port = self::DEFAULT_PORT; |
||
45 | |||
46 | /** |
||
47 | * @var string |
||
48 | */ |
||
49 | protected $path = self::DEFAULT_PATH; |
||
50 | |||
51 | /** |
||
52 | * @var string |
||
53 | */ |
||
54 | protected $token; |
||
55 | |||
56 | /** |
||
57 | * @var ClientInterface |
||
58 | */ |
||
59 | protected $client; |
||
60 | |||
61 | /** |
||
62 | * @var string |
||
63 | */ |
||
64 | protected $auth; |
||
65 | |||
66 | /** |
||
67 | * Constructor |
||
68 | * |
||
69 | * @param string $host The hostname of the Transmission server |
||
70 | * @param integer $port The port the Transmission server is listening on |
||
71 | * @param string $path The path to Transmission server rpc api |
||
72 | */ |
||
73 | public function __construct($host = null, $port = null, $path = null) |
||
74 | { |
||
75 | $this->token = null; |
||
76 | $this->client = new Curl(); |
||
77 | |||
78 | if ($host) $this->setHost($host); |
||
0 ignored issues
–
show
|
|||
79 | if ($port) $this->setPort($port); |
||
0 ignored issues
–
show
The expression
$port of type integer|null is loosely compared to true ; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.
In PHP, under loose comparison (like For 0 == false // true
0 == null // true
123 == false // false
123 == null // false
// It is often better to use strict comparison
0 === false // false
0 === null // false
![]() |
|||
80 | if ($path) $this->setPath($path); |
||
0 ignored issues
–
show
The expression
$path of type string|null is loosely compared to true ; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.
In PHP, under loose comparison (like For '' == false // true
'' == null // true
'ab' == false // false
'ab' == null // false
// It is often better to use strict comparison
'' === false // false
'' === null // false
![]() |
|||
81 | } |
||
82 | |||
83 | /** |
||
84 | * Authenticate against the Transmission server |
||
85 | * |
||
86 | * @param string $username |
||
87 | * @param string $password |
||
88 | */ |
||
89 | public function authenticate($username, $password) |
||
90 | { |
||
91 | $this->auth = base64_encode($username .':'. $password); |
||
92 | } |
||
93 | |||
94 | /** |
||
95 | * Make an API call |
||
96 | * |
||
97 | * @param string $method |
||
98 | * @param array $arguments |
||
99 | * @return \stdClass |
||
100 | * @throws \RuntimeException |
||
101 | */ |
||
102 | public function call($method, array $arguments) |
||
103 | { |
||
104 | list($request, $response) = $this->compose($method, $arguments); |
||
105 | |||
106 | try { |
||
107 | $this->getClient()->send($request, $response); |
||
108 | } catch (\Exception $e) { |
||
109 | throw new \RuntimeException( |
||
110 | 'Could not connect to Transmission', |
||
111 | 0, |
||
112 | $e |
||
113 | ); |
||
114 | } |
||
115 | |||
116 | return $this->validateResponse($response, $method, $arguments); |
||
117 | } |
||
118 | |||
119 | /** |
||
120 | * Get the URL used to connect to Transmission |
||
121 | * |
||
122 | * @return string |
||
123 | */ |
||
124 | public function getUrl() |
||
125 | { |
||
126 | return sprintf( |
||
127 | 'http://%s:%d', |
||
128 | $this->getHost(), |
||
129 | $this->getPort() |
||
130 | ); |
||
131 | } |
||
132 | |||
133 | /** |
||
134 | * Set the hostname of the Transmission server |
||
135 | * |
||
136 | * @param string $host |
||
137 | */ |
||
138 | public function setHost($host) |
||
139 | { |
||
140 | $this->host = (string) $host; |
||
141 | } |
||
142 | |||
143 | /** |
||
144 | * Get the hostname of the Transmission server |
||
145 | * |
||
146 | * @return string |
||
147 | */ |
||
148 | public function getHost() |
||
149 | { |
||
150 | return $this->host; |
||
151 | } |
||
152 | |||
153 | /** |
||
154 | * Set the port the Transmission server is listening on |
||
155 | * |
||
156 | * @param integer $port |
||
157 | */ |
||
158 | public function setPort($port) |
||
159 | { |
||
160 | $this->port = (integer) $port; |
||
161 | } |
||
162 | |||
163 | /** |
||
164 | * Get the port the Transmission server is listening on |
||
165 | * |
||
166 | * @return integer |
||
167 | */ |
||
168 | public function getPort() |
||
169 | { |
||
170 | return $this->port; |
||
171 | } |
||
172 | |||
173 | /** |
||
174 | * Set the path to Transmission server rpc api |
||
175 | * |
||
176 | * @param string $path |
||
177 | */ |
||
178 | public function setPath($path) |
||
179 | { |
||
180 | return $this->path = (string) $path; |
||
181 | } |
||
182 | |||
183 | /** |
||
184 | * Get the path to Transmission server rpc api |
||
185 | */ |
||
186 | public function getPath() |
||
187 | { |
||
188 | return $this->path; |
||
189 | } |
||
190 | |||
191 | /** |
||
192 | * Set the CSRF-token of the Transmission client |
||
193 | * |
||
194 | * @param string $token |
||
195 | */ |
||
196 | public function setToken($token) |
||
197 | { |
||
198 | $this->token = (string) $token; |
||
199 | } |
||
200 | |||
201 | /** |
||
202 | * Get the CSRF-token for the Transmission client |
||
203 | * |
||
204 | * @return string |
||
205 | */ |
||
206 | public function getToken() |
||
207 | { |
||
208 | return $this->token; |
||
209 | } |
||
210 | |||
211 | /** |
||
212 | * Set the Buzz client used to connect to Transmission |
||
213 | * |
||
214 | * @param ClientInterface $client |
||
215 | */ |
||
216 | public function setClient(ClientInterface $client) |
||
217 | { |
||
218 | $this->client = $client; |
||
219 | } |
||
220 | |||
221 | /** |
||
222 | * Get the Buzz client used to connect to Transmission |
||
223 | * |
||
224 | * @return ClientInterface |
||
225 | */ |
||
226 | public function getClient() |
||
227 | { |
||
228 | return $this->client; |
||
229 | } |
||
230 | |||
231 | /** |
||
232 | * @param string $method |
||
233 | * @param array $arguments |
||
234 | * @return array|Request[]|Response[] |
||
235 | */ |
||
236 | protected function compose($method, $arguments) |
||
237 | { |
||
238 | $request = new Request('POST', $this->getPath(), $this->getUrl()); |
||
239 | $request->addHeader(sprintf('%s: %s', self::TOKEN_HEADER, $this->getToken())); |
||
240 | $request->setContent(json_encode(array( |
||
241 | 'method' => $method, |
||
242 | 'arguments' => $arguments |
||
243 | ))); |
||
244 | |||
245 | if (is_string($this->auth)) { |
||
246 | $request->addHeader(sprintf('Authorization: Basic %s', $this->auth)); |
||
247 | } |
||
248 | |||
249 | return array($request, new Response()); |
||
250 | } |
||
251 | |||
252 | /** |
||
253 | * @param Response $response |
||
254 | * @param string $method |
||
255 | * @param array $arguments |
||
256 | * @return \stdClass |
||
257 | * @throws \RuntimeException |
||
258 | */ |
||
259 | protected function validateResponse($response, $method, $arguments) |
||
260 | { |
||
261 | if (!in_array($response->getStatusCode(), array(200, 401, 409))) { |
||
262 | throw new \RuntimeException('Unexpected response received from Transmission'); |
||
263 | } |
||
264 | |||
265 | if ($response->getStatusCode() == 401) { |
||
266 | throw new \RuntimeException('Access to Transmission requires authentication'); |
||
267 | } |
||
268 | |||
269 | if ($response->getStatusCode() == 409) { |
||
270 | $this->setToken($response->getHeader(self::TOKEN_HEADER)); |
||
0 ignored issues
–
show
It seems like
$response->getHeader(self::TOKEN_HEADER) targeting Buzz\Message\AbstractMessage::getHeader() can also be of type array or null ; however, Transmission\Client::setToken() does only seem to accept string , maybe add an additional type check?
This check looks at variables that are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble. ![]() |
|||
271 | |||
272 | return $this->call($method, $arguments); |
||
273 | } |
||
274 | |||
275 | return json_decode($response->getContent()); |
||
276 | } |
||
277 | } |
||
278 |
In PHP, under loose comparison (like
==
, or!=
, orswitch
conditions), values of different types might be equal.For
string
values, the empty string''
is a special case, in particular the following results might be unexpected: