Completed
Pull Request — master (#32303)
by Victor
10:42
created

DiscoveryManager::getOcmShareEndPoint()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * @author Joas Schilling <[email protected]>
4
 * @author Lukas Reschke <[email protected]>
5
 * @author Thomas Müller <[email protected]>
6
 * @author Vincent Petry <[email protected]>
7
 *
8
 * @copyright Copyright (c) 2018, ownCloud GmbH
9
 * @license AGPL-3.0
10
 *
11
 * This code is free software: you can redistribute it and/or modify
12
 * it under the terms of the GNU Affero General Public License, version 3,
13
 * as published by the Free Software Foundation.
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
 * GNU Affero General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU Affero General Public License, version 3,
21
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
22
 *
23
 */
24
25
namespace OCA\FederatedFileSharing;
26
27
use GuzzleHttp\Exception\ClientException;
28
use GuzzleHttp\Exception\ConnectException;
29
use OCP\Http\Client\IClient;
30
use OCP\Http\Client\IClientService;
31
use OCP\ICache;
32
use OCP\ICacheFactory;
33
34
/**
35
 * Class DiscoveryManager handles the discovery of endpoints used by Federated
36
 * Cloud Sharing.
37
 *
38
 * @package OCA\FederatedFileSharing
39
 */
40
class DiscoveryManager {
41
	/** @var ICache */
42
	private $cache;
43
	/** @var IClient */
44
	private $client;
45
	/** @var bool */
46
	public $underTest = false;
47
48
	/**
49
	 * @param ICacheFactory $cacheFactory
50
	 * @param IClientService $clientService
51
	 */
52
	public function __construct(ICacheFactory $cacheFactory,
53
								IClientService $clientService) {
54
		$this->cache = $cacheFactory->create('ocs-discovery');
55
		$this->client = $clientService->newClient();
56
	}
57
58
	/**
59
	 * Returns whether the specified URL includes only safe characters, if not
60
	 * returns false
61
	 *
62
	 * @param string $url
63
	 * @return bool
64
	 */
65
	private function isSafeUrl($url) {
66
		return (bool)\preg_match('/^[\/\.A-Za-z0-9]+$/', $url);
67
	}
68
69
	/**
70
	 * Discover the actual data and do some naive caching to ensure that the data
71
	 * is not requested multiple times.
72
	 *
73
	 * If no valid discovery data is found the ownCloud defaults are returned.
74
	 *
75
	 * @param string $remote
76
	 * @return array
77
	 */
78
	private function discover($remote) {
79
		// Check if something is in the cache
80
		if ($cacheData = $this->cache->get($remote)) {
81
			return \json_decode($cacheData, true);
82
		}
83
84
		// Default response body
85
		$discoveredServices = [
86
			'webdav' => '/public.php/webdav',
87
			'share' => '/ocs/v1.php/cloud/shares',
88
		];
89
90
		if (\defined('PHPUNIT_RUN') && !$this->underTest) {
91
			return $discoveredServices;
92
		}
93
		// Read the data from the response body
94
		try {
95
			$response = $this->client->get($remote . '/ocs-provider/', [
96
				'timeout' => 10,
97
				'connect_timeout' => 10,
98
			]);
99
			if ($response->getStatusCode() === 200) {
100
				$decodedService = \json_decode($response->getBody(), true);
101
				if (\is_array($decodedService)) {
102
					$endpoints = [
103
						'webdav',
104
						'share',
105
					];
106
107
					foreach ($endpoints as $endpoint) {
108
						if (isset($decodedService['services']['FEDERATED_SHARING']['endpoints'][$endpoint])) {
109
							$endpointUrl = (string)$decodedService['services']['FEDERATED_SHARING']['endpoints'][$endpoint];
110
							if ($this->isSafeUrl($endpointUrl)) {
111
								$discoveredServices[$endpoint] = $endpointUrl;
112
							}
113
						}
114
					}
115
				}
116
			}
117
		} catch (ClientException $e) {
118
			// Don't throw any exception since exceptions are handled before
119
		} catch (ConnectException $e) {
120
			// Don't throw any exception since exceptions are handled before
121
		}
122
123
		// Write into cache
124
		$this->cache->set($remote, \json_encode($discoveredServices));
125
		return $discoveredServices;
126
	}
127
128
	/**
129
	 * Discover the actual data and do some naive caching to ensure that the data
130
	 * is not requested multiple times.
131
	 *
132
	 * If no valid discovery data is found the ownCloud defaults are returned.
133
	 *
134
	 * @param string $remote
135
	 * @return array
136
	 */
137
	private function ocmDiscover($remote) {
138
		// Check if something is in the cache
139
		if ($cacheData = $this->cache->get('OCM' . $remote)) {
140
			return \json_decode($cacheData, true);
141
		}
142
143
		// Default response body
144
		$discoveredServices = [
145
			'webdav' => '/public.php/webdav',
146
			'ocm' => '/index.php/apps/federatedfilesharing',
147
		];
148
149
		if (\defined('PHPUNIT_RUN') && !$this->underTest) {
150
			return $discoveredServices;
151
		}
152
		// Read the data from the response body
153
		try {
154
			$response = $this->client->get($remote . '/ocm-provider/', [
155
				'timeout' => 10,
156
				'connect_timeout' => 10,
157
			]);
158
			if ($response->getStatusCode() === 200) {
159
				$decodedService = \json_decode($response->getBody(), true);
160
				if (\is_array($decodedService)) {
161
					$discoveredServices['ocm'] = $decodedService['endPoint'];
162
					$shareTypes = $discoveredServices['shareTypes'];
163
					foreach ($shareTypes as $type) {
164
						if ($type['name']=='file') {
165
							$discoveredServices['webdav'] = $type['protocols']['webdav'];
166
						}
167
					}
168
				}
169
			}
170
		} catch (ClientException $e) {
171
			// Don't throw any exception since exceptions are handled before
172
		} catch (ConnectException $e) {
173
			// Don't throw any exception since exceptions are handled before
174
		}
175
176
		// Write into cache
177
		$this->cache->set('OCM' . $remote, \json_encode($discoveredServices));
178
		return $discoveredServices;
179
	}
180
181
	/**
182
	 * Return the public WebDAV endpoint used by the specified remote
183
	 *
184
	 * @param string $host
185
	 * @return string
186
	 */
187
	public function getWebDavEndpoint($host) {
188
		return $this->discover($host)['webdav'];
189
	}
190
191
	/**
192
	 * Return the sharing endpoint used by the specified remote
193
	 *
194
	 * @param string $host
195
	 * @return string
196
	 */
197
	public function getShareEndpoint($host) {
198
		return $this->discover($host)['share'];
199
	}
200
201
	public function getOcmWebDavEndPoint($host) {
202
		\OC::$server->getLogger()->warning("{$this->ocmDiscover($host)['webdav']}");
203
		return $this->ocmDiscover($host)['webdav'];
204
	}
205
206
	public function getOcmShareEndPoint($host) {
207
		\OC::$server->getLogger()->warning("{$this->ocmDiscover($host)['ocm']}");
208
		return $this->ocmDiscover($host)['ocm'];
209
	}
210
}
211