Completed
Push — master ( 03449d...db6361 )
by Lukas
44s queued 24s
created

DiscoveryManager::isSafeUrl()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * @author Lukas Reschke <[email protected]>
4
 *
5
 * @copyright Copyright (c) 2016, ownCloud, Inc.
6
 * @license AGPL-3.0
7
 *
8
 * This code is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Affero General Public License, version 3,
10
 * as published by the Free Software Foundation.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
 * GNU Affero General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Affero General Public License, version 3,
18
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
19
 *
20
 */
21
22
namespace OCA\FederatedFileSharing;
23
24
use GuzzleHttp\Exception\ClientException;
25
use GuzzleHttp\Exception\ConnectException;
26
use OCP\Http\Client\IClient;
27
use OCP\Http\Client\IClientService;
28
use OCP\ICache;
29
use OCP\ICacheFactory;
30
31
/**
32
 * Class DiscoveryManager handles the discovery of endpoints used by Federated
33
 * Cloud Sharing.
34
 *
35
 * @package OCA\FederatedFileSharing
36
 */
37
class DiscoveryManager {
38
	/** @var ICache */
39
	private $cache;
40
	/** @var IClient */
41
	private $client;
42
43
	/**
44
	 * @param ICacheFactory $cacheFactory
45
	 * @param IClientService $clientService
46
	 */
47
	public function __construct(ICacheFactory $cacheFactory,
48
								IClientService $clientService) {
49
		$this->cache = $cacheFactory->create('ocs-discovery');
50
		$this->client = $clientService->newClient();
51
	}
52
53
	/**
54
	 * Returns whether the specified URL includes only safe characters, if not
55
	 * returns false
56
	 *
57
	 * @param string $url
58
	 * @return bool
59
	 */
60
	private function isSafeUrl($url) {
61
		return (bool)preg_match('/^[\/\.A-Za-z0-9]+$/', $url);
62
	}
63
64
	/**
65
	 * Discover the actual data and do some naive caching to ensure that the data
66
	 * is not requested multiple times.
67
	 *
68
	 * If no valid discovery data is found the Nextcloud defaults are returned.
69
	 *
70
	 * @param string $remote
71
	 * @return array
72
	 */
73
	private function discover($remote) {
74
		// Check if something is in the cache
75
		if($cacheData = $this->cache->get($remote)) {
76
			return json_decode($cacheData, true);
77
		}
78
79
		// Default response body
80
		$discoveredServices = [
81
			'webdav' => '/public.php/webdav',
82
			'share' => '/ocs/v1.php/cloud/shares',
83
		];
84
85
		// Read the data from the response body
86
		try {
87
			$response = $this->client->get($remote . '/ocs-provider/', [
88
				'timeout' => 10,
89
				'connect_timeout' => 10,
90
			]);
91
			if($response->getStatusCode() === 200) {
92
				$decodedService = json_decode($response->getBody(), true);
93
				if(is_array($decodedService)) {
94
					$endpoints = [
95
						'webdav',
96
						'share',
97
					];
98
99
					foreach($endpoints as $endpoint) {
100
						if(isset($decodedService['services']['FEDERATED_SHARING']['endpoints'][$endpoint])) {
101
							$endpointUrl = (string)$decodedService['services']['FEDERATED_SHARING']['endpoints'][$endpoint];
102
							if($this->isSafeUrl($endpointUrl)) {
103
								$discoveredServices[$endpoint] = $endpointUrl;
104
							}
105
						}
106
					}
107
				}
108
			}
109
		} catch (ClientException $e) {
0 ignored issues
show
Bug introduced by
The class GuzzleHttp\Exception\ClientException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
110
			// Don't throw any exception since exceptions are handled before
111
		} catch (ConnectException $e) {
0 ignored issues
show
Bug introduced by
The class GuzzleHttp\Exception\ConnectException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
112
			// Don't throw any exception since exceptions are handled before
113
		}
114
115
		// Write into cache
116
		$this->cache->set($remote, json_encode($discoveredServices));
117
		return $discoveredServices;
118
	}
119
120
	/**
121
	 * Return the public WebDAV endpoint used by the specified remote
122
	 *
123
	 * @param string $host
124
	 * @return string
125
	 */
126
	public function getWebDavEndpoint($host) {
127
		return $this->discover($host)['webdav'];
128
	}
129
130
	/**
131
	 * Return the sharing endpoint used by the specified remote
132
	 *
133
	 * @param string $host
134
	 * @return string
135
	 */
136
	public function getShareEndpoint($host) {
137
		return $this->discover($host)['share'];
138
	}
139
}
140