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 | /** |
||
3 | * For the full copyright and license information, please view the LICENSE |
||
4 | * file that was distributed with this source code. |
||
5 | * |
||
6 | * @author Nikita Vershinin <[email protected]> |
||
7 | * @license MIT |
||
8 | */ |
||
9 | namespace OpenStackStorage; |
||
10 | |||
11 | define('CONTAINER_NAME_LIMIT', 256); |
||
12 | define('OBJECT_NAME_LIMIT', 1024); |
||
13 | define('META_NAME_LIMIT', 128); |
||
14 | define('META_VALUE_LIMIT', 256); |
||
15 | |||
16 | /** |
||
17 | * Manages the connection to the storage system and serves as a factory |
||
18 | * for \OpenStackStorage\Container instances. |
||
19 | */ |
||
20 | class Connection |
||
21 | { |
||
22 | |||
23 | /** |
||
24 | * Use Rackspace servicenet to access Cloud Files. |
||
25 | * |
||
26 | * @var boolean |
||
27 | */ |
||
28 | protected $useServicenet = false; |
||
29 | |||
30 | /** |
||
31 | * User-Agent for request. |
||
32 | * |
||
33 | * @var string |
||
34 | */ |
||
35 | protected $userAgent = 'PHP OpenStackStorage'; |
||
36 | |||
37 | /** |
||
38 | * Request timeout. |
||
39 | * |
||
40 | * @var integer |
||
41 | */ |
||
42 | protected $timeout = 5; |
||
43 | |||
44 | /** |
||
45 | * Authentication object. |
||
46 | * |
||
47 | * @var \OpenStackStorage\Authentication |
||
48 | */ |
||
49 | protected $auth = null; |
||
50 | |||
51 | /** |
||
52 | * Authentication has already been processed. |
||
53 | * |
||
54 | * @var boolean |
||
55 | */ |
||
56 | protected $isAuthenticated = false; |
||
57 | |||
58 | /** |
||
59 | * Authentication token. |
||
60 | * |
||
61 | * @var string |
||
62 | */ |
||
63 | protected $authToken = null; |
||
64 | |||
65 | /** |
||
66 | * Array with information about the connection URI. |
||
67 | * |
||
68 | * @var array |
||
69 | */ |
||
70 | protected $connectionUrlInfo = null; |
||
71 | |||
72 | /** |
||
73 | * HTTP-client to work with storage. |
||
74 | * |
||
75 | * @var \OpenStackStorage\Client |
||
76 | */ |
||
77 | protected $client = null; |
||
78 | |||
79 | /** |
||
80 | * CDN connection URL. |
||
81 | * |
||
82 | * @var string |
||
83 | */ |
||
84 | protected $cdnUrl = null; |
||
85 | |||
86 | /** |
||
87 | * Is the access via CDN enabled. |
||
88 | * |
||
89 | * @var boolean |
||
90 | */ |
||
91 | protected $cdnEnabled = false; |
||
92 | |||
93 | /** |
||
94 | * HTTP-client to work with storage. |
||
95 | * |
||
96 | * @var \OpenStackStorage\Client |
||
97 | */ |
||
98 | protected $cdnClient = null; |
||
99 | |||
100 | /** |
||
101 | * List of parameters that are allowed to be used in the GET-requests to |
||
102 | * fetch information about the containers: |
||
103 | * — limit For an integer value n, limits the number of results |
||
104 | * to n values. |
||
105 | * — marker Given a string value x, return container names greater |
||
106 | * in value than the specified marker. |
||
107 | * — end_marker Given a string value x, return container names less |
||
108 | * in value than the specified marker. |
||
109 | * — format Response format (json, xml, plain). |
||
110 | * |
||
111 | * @link http://docs.openstack.org/api/openstack-object-storage/1.0/content/s_listcontainers.html |
||
112 | * @var array |
||
113 | */ |
||
114 | protected static $allowedParameters = array( |
||
115 | 'limit', |
||
116 | 'marker', |
||
117 | 'end_marker', |
||
118 | 'format', |
||
119 | ); |
||
120 | |||
121 | /** |
||
122 | * Local cache of requests to fetch list of containers. |
||
123 | * |
||
124 | * @var array |
||
125 | */ |
||
126 | protected static $listContainersCache = array(); |
||
127 | |||
128 | /** |
||
129 | * The class constructor. |
||
130 | * |
||
131 | * @param string $username |
||
132 | * @param string $apiKey |
||
133 | * @param array $options |
||
134 | * @param integer $timeout |
||
135 | * @throws \InvalidArgumentException |
||
136 | */ |
||
137 | public function __construct($username, $apiKey, $options = array(), $timeout = 5) |
||
138 | { |
||
139 | $this->timeout = intval($timeout); |
||
140 | |||
141 | // If the environement variable RACKSPACE_SERVICENET is set (to |
||
142 | // anything) it will automatically set $useServicenet=true |
||
143 | if (array_key_exists('servicenet', $options)) { |
||
144 | $this->useServicenet = (boolean) $options['servicenet']; |
||
145 | } else { |
||
146 | $this->useServicenet = (boolean) getenv('RACKSPACE_SERVICENET'); |
||
147 | } |
||
148 | |||
149 | if (!empty($options['useragent'])) { |
||
150 | $this->userAgent = strval($options['useragent']); |
||
151 | } |
||
152 | |||
153 | // Authentication |
||
154 | if (empty($options['authurl'])) { |
||
155 | throw new \InvalidArgumentException( |
||
156 | 'Incorrect or invalid arguments supplied' |
||
157 | ); |
||
158 | } |
||
159 | |||
160 | $this->auth = new Authentication($username, $apiKey, $options['authurl'], $this->userAgent, $timeout); |
||
161 | } |
||
162 | |||
163 | /** |
||
164 | * Return the value of the $authToken property. |
||
165 | * |
||
166 | * @return string |
||
167 | */ |
||
168 | public function getAuthToken() |
||
169 | { |
||
170 | $this->authenticate(); |
||
171 | |||
172 | return $this->authToken; |
||
173 | } |
||
174 | |||
175 | /** |
||
176 | * Return the value of the $cdnEnabled property. |
||
177 | * |
||
178 | * @return boolean |
||
179 | */ |
||
180 | public function getCdnEnabled() |
||
181 | { |
||
182 | return $this->cdnEnabled; |
||
183 | } |
||
184 | |||
185 | /** |
||
186 | * Return the value of the $connection property. |
||
187 | * |
||
188 | * @return \OpenStackStorage\Client |
||
189 | */ |
||
190 | public function getClient() |
||
191 | { |
||
192 | return $this->client; |
||
193 | } |
||
194 | |||
195 | /** |
||
196 | * Return the value of the $timeout property. |
||
197 | * |
||
198 | * @return integer |
||
199 | */ |
||
200 | public function getTimeout() |
||
201 | { |
||
202 | return $this->timeout; |
||
203 | } |
||
204 | |||
205 | /** |
||
206 | * Return the value of the $userAgent property. |
||
207 | * |
||
208 | * @return string |
||
209 | */ |
||
210 | public function getUserAgent() |
||
211 | { |
||
212 | return $this->userAgent; |
||
213 | } |
||
214 | |||
215 | /** |
||
216 | * Performs an http request to the storage. |
||
217 | * |
||
218 | * @param string $method name of the method (i.e. GET, PUT, POST, etc) |
||
219 | * @param array $path list of tokens that will be added to connection |
||
220 | * URI string |
||
221 | * @param array $headers additional headers |
||
222 | * @param array $parameters additional parameters that will be added to the |
||
223 | * query string |
||
224 | * @return array |
||
225 | */ |
||
226 | public function makeRequest($method, array $path = array(), array $headers = array(), $parameters = array()) |
||
227 | { |
||
228 | $this->authenticate(); |
||
229 | |||
230 | return $this->makeRealRequest($this->client, $method, $this->getPathFromArray($path), $parameters, $headers); |
||
231 | } |
||
232 | |||
233 | /** |
||
234 | * Performs an http request to the CDN. |
||
235 | * |
||
236 | * @param string $method name of the method (i.e. GET, PUT, POST, etc) |
||
237 | * @param array $path list of tokens that will be added to connection |
||
238 | * URI string |
||
239 | * @param array $headers additional headers |
||
240 | * @return array |
||
241 | * @throws \OpenStackStorage\Exceptions\CDNNotEnabled |
||
242 | */ |
||
243 | public function makeCdnRequest($method, array $path = array(), array $headers = array()) |
||
244 | { |
||
245 | $this->authenticate(); |
||
246 | |||
247 | if (!$this->getCdnEnabled()) { |
||
248 | throw new Exceptions\CDNNotEnabled(); |
||
249 | } |
||
250 | |||
251 | return $this->makeRealRequest($this->cdnClient, $method, $this->getPathFromArray($path), $headers); |
||
252 | } |
||
253 | |||
254 | /** |
||
255 | * Return array with number of containers, total bytes in the account and |
||
256 | * account metadata. |
||
257 | * |
||
258 | * @return array |
||
259 | */ |
||
260 | public function getAccountInfo() |
||
261 | { |
||
262 | $response = $this->makeRequest(Client::HEAD); |
||
263 | $nbContainers = 0; |
||
264 | $totalSize = 0; |
||
265 | $metadata = array(); |
||
266 | |||
267 | foreach ($response['headers'] as $name => $value) { |
||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||
268 | $name = strtolower($name); |
||
269 | |||
270 | if (0 === strcmp($name, 'x-account-container-count')) { |
||
271 | $nbContainers = intval($value); |
||
272 | } elseif (0 === strcmp($name, 'x-account-bytes-used')) { |
||
273 | $totalSize = intval($value); |
||
274 | } elseif (0 === strpos($name, 'x-account-meta-')) { |
||
275 | $metadata[substr($name, 15)] = $value; |
||
276 | } |
||
277 | } |
||
278 | |||
279 | return array( |
||
280 | $nbContainers, |
||
281 | $totalSize, |
||
282 | $metadata |
||
283 | ); |
||
284 | } |
||
285 | |||
286 | /** |
||
287 | * Update account metadata. |
||
288 | * |
||
289 | * Example: |
||
290 | * <code> |
||
291 | * $connection->updateAccountMetadata(array( |
||
292 | * 'X-Account-Meta-Foo' => 'bar', |
||
293 | * )); |
||
294 | * </code> |
||
295 | * |
||
296 | * @param array $metadata |
||
297 | */ |
||
298 | public function updateAccountMetadata(array $metadata) |
||
299 | { |
||
300 | $this->makeRequest(Client::POST, array(), $metadata); |
||
301 | } |
||
302 | |||
303 | /** |
||
304 | * Create new container. |
||
305 | * |
||
306 | * If $errorOnExisting is true and container already exists, |
||
307 | * throws \OpenStackStorage\Exceptions\ContainerExists. |
||
308 | * |
||
309 | * @param string $name |
||
310 | * @param boolean $errorOnExisting |
||
311 | * @return \OpenStackStorage\Container |
||
312 | * @throws \OpenStackStorage\Exceptions\ContainerExists |
||
313 | */ |
||
314 | public function createContainer($name, $errorOnExisting = false) |
||
315 | { |
||
316 | $this->validateContainerName($name); |
||
317 | |||
318 | $response = $this->makeRequest(Client::PUT, array($name), array('Content-Length' => 0)); |
||
319 | if ($errorOnExisting && 202 == $response['status']) { |
||
320 | throw new Exceptions\ContainerExists($name); |
||
321 | } |
||
322 | |||
323 | return new Container($this, $name); |
||
324 | } |
||
325 | |||
326 | /** |
||
327 | * Delete container. |
||
328 | * |
||
329 | * @param \OpenStackStorage\Container|string $container |
||
330 | * @throws \OpenStackStorage\Exceptions\NoSuchContainer |
||
331 | * @throws \Exception|\OpenStackStorage\Exceptions\ResponseError |
||
332 | * @throws \OpenStackStorage\Exceptions\ContainerNotEmpty |
||
333 | */ |
||
334 | public function deleteContainer($container) |
||
335 | { |
||
336 | if (is_object($container) && $container instanceof Container) { |
||
337 | $name = $container->getName(); |
||
338 | } else { |
||
339 | $name = strval($container); |
||
340 | } |
||
341 | |||
342 | $this->validateContainerName($name); |
||
343 | |||
344 | try { |
||
345 | $this->makeRequest(Client::DELETE, array($name)); |
||
346 | } catch (Exceptions\ResponseError $e) { |
||
347 | switch ($e->getCode()) { |
||
348 | case 409: |
||
349 | throw new Exceptions\ContainerNotEmpty($name); |
||
350 | break; |
||
0 ignored issues
–
show
break; does not seem to be reachable.
This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed. Unreachable code is most often the result of function fx() {
try {
doSomething();
return true;
}
catch (\Exception $e) {
return false;
}
return false;
}
In the above example, the last ![]() |
|||
351 | case 404: |
||
352 | throw new Exceptions\NoSuchContainer(); |
||
353 | break; |
||
0 ignored issues
–
show
break; does not seem to be reachable.
This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed. Unreachable code is most often the result of function fx() {
try {
doSomething();
return true;
}
catch (\Exception $e) {
return false;
}
return false;
}
In the above example, the last ![]() |
|||
354 | default: |
||
355 | throw $e; |
||
356 | break; |
||
0 ignored issues
–
show
break; does not seem to be reachable.
This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed. Unreachable code is most often the result of function fx() {
try {
doSomething();
return true;
}
catch (\Exception $e) {
return false;
}
return false;
}
In the above example, the last ![]() |
|||
357 | } |
||
358 | } |
||
359 | |||
360 | if ($this->getCdnEnabled()) { |
||
361 | $this->makeCdnRequest( |
||
362 | Client::POST, |
||
363 | array($name), |
||
364 | array( |
||
365 | 'X-CDN-Enabled' => 'False', |
||
366 | ) |
||
367 | ); |
||
368 | } |
||
369 | } |
||
370 | |||
371 | /** |
||
372 | * Return container object. |
||
373 | * |
||
374 | * @param string $name |
||
375 | * @return \OpenStackStorage\Container |
||
376 | * @throws \OpenStackStorage\Exceptions\NoSuchContainer |
||
377 | * @throws \Exception|\OpenStackStorage\Exceptions\ResponseError |
||
378 | */ |
||
379 | public function getContainer($name) |
||
380 | { |
||
381 | $this->validateContainerName($name); |
||
382 | |||
383 | try { |
||
384 | $response = $this->makeRequest(Client::HEAD, array($name)); |
||
385 | } catch (Exceptions\ResponseError $e) { |
||
386 | if (404 == $e->getCode()) { |
||
387 | throw new Exceptions\NoSuchContainer(); |
||
388 | } |
||
389 | |||
390 | throw $e; |
||
391 | } |
||
392 | |||
393 | $nbObjects = $response['headers']['x-container-object-count']; |
||
394 | $sizeUsed = $response['headers']['x-container-bytes-used']; |
||
395 | $metadata = array(); |
||
396 | |||
397 | foreach ($response['headers'] as $k => $value) { |
||
0 ignored issues
–
show
|
|||
398 | if (0 === strpos($k, 'x-container-meta-')) { |
||
399 | $metadata[substr($k, 17)] = $value; |
||
400 | } |
||
401 | } |
||
402 | |||
403 | return new Container($this, $name, $nbObjects, $sizeUsed, $metadata); |
||
404 | } |
||
405 | |||
406 | /** |
||
407 | * Return array with containers. |
||
408 | * |
||
409 | * @param array $parameters |
||
410 | * @return \OpenStackStorage\Container[] |
||
411 | */ |
||
412 | public function getContainers(array $parameters = array()) |
||
413 | { |
||
414 | $result = array(); |
||
415 | |||
416 | foreach ($this->getContainersInfo($parameters) as $info) { |
||
0 ignored issues
–
show
|
|||
417 | $result[] = new Container($this, $info['name'], $info['count'], $info['bytes']); |
||
418 | } |
||
419 | |||
420 | return $result; |
||
421 | } |
||
422 | |||
423 | /** |
||
424 | * Return names of public containers. |
||
425 | * |
||
426 | * @return array |
||
427 | * @throws \OpenStackStorage\Exceptions\CDNNotEnabled |
||
428 | */ |
||
429 | public function getPublicContainersList() |
||
430 | { |
||
431 | if (!$this->getCdnEnabled()) { |
||
432 | throw new Exceptions\CDNNotEnabled(); |
||
433 | } |
||
434 | |||
435 | $response = $this->makeCdnRequest(Client::GET); |
||
436 | |||
437 | return explode("\n", trim($response['body'])); |
||
438 | } |
||
439 | |||
440 | /** |
||
441 | * Return information about containers. |
||
442 | * |
||
443 | * @see \OpenStackStorage\Connection::$allowedParameters |
||
444 | * @param array $parameters |
||
445 | * @return array |
||
446 | */ |
||
447 | public function getContainersInfo(array $parameters = array()) |
||
448 | { |
||
449 | $parameters['format'] = 'json'; |
||
450 | |||
451 | return $this->getContainersRawData($parameters); |
||
452 | } |
||
453 | |||
454 | /** |
||
455 | * Return names of containers. |
||
456 | * |
||
457 | * @see \OpenStackStorage\Connection::$allowedParameters |
||
458 | * @param array $parameters |
||
459 | * @return array |
||
460 | */ |
||
461 | public function getContainersList(array $parameters = array()) |
||
462 | { |
||
463 | $parameters['format'] = 'plain'; |
||
464 | |||
465 | return explode("\n", trim($this->getContainersRawData($parameters))); |
||
466 | } |
||
467 | |||
468 | /** |
||
469 | * Generate path for query string. |
||
470 | * |
||
471 | * @param array $path |
||
472 | * @return string |
||
473 | */ |
||
474 | protected function getPathFromArray(array $path = array()) |
||
475 | { |
||
476 | $tmp = array(); |
||
477 | |||
478 | foreach ($path as $value) { |
||
479 | $tmp[] = rawurlencode($value); |
||
480 | } |
||
481 | |||
482 | return sprintf( |
||
483 | '/%s/%s', |
||
484 | rtrim($this->connectionUrlInfo['path'], '/'), |
||
485 | str_replace('%2F', '/', implode('/', $tmp)) |
||
486 | ); |
||
487 | } |
||
488 | |||
489 | /** |
||
490 | * Authenticate and setup this instance with the values returned. |
||
491 | */ |
||
492 | protected function authenticate() |
||
493 | { |
||
494 | if (!$this->isAuthenticated) { |
||
495 | list($url, $this->cdnUrl, $this->authToken) = $this->auth->authenticate(); |
||
496 | if ($this->useServicenet) { |
||
497 | $url = str_replace('https://', 'https://snet-%s', $url); |
||
498 | } |
||
499 | |||
500 | $this->connectionUrlInfo = Utils::parseUrl($url); |
||
501 | $this->httpConnect(); |
||
502 | |||
503 | if ($this->cdnUrl) { |
||
0 ignored issues
–
show
The expression
$this->cdnUrl 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
![]() |
|||
504 | $this->cdnConnect(); |
||
505 | } |
||
506 | |||
507 | $this->isAuthenticated = true; |
||
508 | } |
||
509 | } |
||
510 | |||
511 | /** |
||
512 | * Setup the http connection instance. |
||
513 | */ |
||
514 | protected function httpConnect() |
||
515 | { |
||
516 | $this->client = new Client(array('timeout' => $this->timeout)); |
||
517 | $this->client->setUserAgent($this->userAgent); |
||
518 | $this->client->setBaseURL(sprintf( |
||
519 | '%s://%s:%d', |
||
520 | $this->connectionUrlInfo['scheme'], |
||
521 | $this->connectionUrlInfo['host'], |
||
522 | $this->connectionUrlInfo['port'] |
||
523 | )); |
||
524 | } |
||
525 | |||
526 | /** |
||
527 | * Setup the http connection instance for the CDN service. |
||
528 | */ |
||
529 | protected function cdnConnect() |
||
530 | { |
||
531 | $info = Utils::parseUrl($this->cdnUrl); |
||
532 | $this->cdnEnabled = true; |
||
533 | $this->cdnClient = new Client(array('timeout' => $this->timeout)); |
||
534 | $this->cdnClient->setUserAgent($this->userAgent); |
||
535 | $this->cdnClient->setBaseURL(sprintf( |
||
536 | '%s://%s:%d', |
||
537 | $info['scheme'], |
||
538 | $info['host'], |
||
539 | $info['port'] |
||
540 | )); |
||
541 | } |
||
542 | |||
543 | /** |
||
544 | * Performs the real http request. |
||
545 | * |
||
546 | * @param \OpenStackStorage\Client $client |
||
547 | * @param string $method |
||
548 | * @param string $path |
||
549 | * @param array $parameters |
||
550 | * @param array $headers |
||
551 | * @return array |
||
552 | * @throws \Exception |
||
553 | */ |
||
554 | protected function makeRealRequest(Client $client, $method, $path, $parameters = array(), array $headers = array()) |
||
555 | { |
||
556 | $headers['X-Auth-Token'] = $this->authToken; |
||
557 | |||
558 | return $client->sendRequest($path, $method, $parameters, $headers); |
||
559 | } |
||
560 | |||
561 | /** |
||
562 | * Validates the container name. |
||
563 | * |
||
564 | * @param string $name |
||
565 | * @throws \OpenStackStorage\Exceptions\InvalidContainerName |
||
566 | */ |
||
567 | protected function validateContainerName($name) |
||
568 | { |
||
569 | if (empty($name) |
||
570 | || (false !== strpos($name, '/')) |
||
571 | || strlen($name) > CONTAINER_NAME_LIMIT) { |
||
572 | throw new Exceptions\InvalidContainerName(); |
||
573 | } |
||
574 | } |
||
575 | |||
576 | /** |
||
577 | * Return a raw response string with containers data. |
||
578 | * |
||
579 | * @see \OpenStackStorage\Connection::$allowedParameters |
||
580 | * @param array $parameters |
||
581 | * @return string |
||
582 | */ |
||
583 | protected function getContainersRawData(array $parameters = array()) |
||
584 | { |
||
585 | $cacheKey = md5(json_encode($parameters)); |
||
586 | |||
587 | View Code Duplication | if (!array_key_exists($cacheKey, self::$listContainersCache)) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
588 | $tmp = array(); |
||
589 | |||
590 | foreach ($parameters as $k => $v) { |
||
591 | if (in_array($k, self::$allowedParameters)) { |
||
592 | $tmp[$k] = $v; |
||
593 | } |
||
594 | } |
||
595 | |||
596 | $response = $this->makeRequest(Client::GET, array(), array(), $tmp); |
||
597 | self::$listContainersCache[$cacheKey] = $response['body']; |
||
598 | } |
||
599 | |||
600 | return self::$listContainersCache[$cacheKey]; |
||
601 | } |
||
602 | } |
||
603 |