Completed
Push — master ( dccb89...31024b )
by Morris
12:39
created

DiscoveryService::discover()   B

Complexity

Conditions 4
Paths 7

Size

Total Lines 28
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 16
nc 7
nop 2
dl 0
loc 28
rs 8.5806
c 0
b 0
f 0
1
<?php
2
/**
3
 * @copyright Copyright (c) 2017 Bjoern Schiessle <[email protected]>
4
 *
5
 * @license GNU AGPL version 3 or any later version
6
 *
7
 * This program is free software: you can redistribute it and/or modify
8
 * it under the terms of the GNU Affero General Public License as
9
 * published by the Free Software Foundation, either version 3 of the
10
 * License, or (at your option) any later version.
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
18
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
 *
20
 */
21
22
23
namespace OC\OCS;
24
25
use OCP\AppFramework\Http;
26
use OCP\Http\Client\IClient;
27
use OCP\Http\Client\IClientService;
28
use OCP\ICache;
29
use OCP\ICacheFactory;
30
use OCP\OCS\IDiscoveryService;
31
32
class DiscoveryService implements IDiscoveryService {
33
34
	/** @var ICache */
35
	private $cache;
36
37
	/** @var IClient */
38
	private $client;
39
40
	/**
41
	 * @param ICacheFactory $cacheFactory
42
	 * @param IClientService $clientService
43
	 */
44
	public function __construct(ICacheFactory $cacheFactory,
45
								IClientService $clientService
46
	) {
47
		$this->cache = $cacheFactory->create('ocs-discovery');
48
		$this->client = $clientService->newClient();
49
	}
50
51
52
	/**
53
	 * Discover OCS end-points
54
	 *
55
	 * If no valid discovery data is found the defaults are returned
56
	 *
57
	 * @param string $remote
58
	 * @param string $service the service you want to discover
59
	 * @return array
60
	 */
61
	public function discover($remote, $service) {
62
		// Check the cache first
63
		$cacheData = $this->cache->get($remote . '#' . $service);
64
		if($cacheData) {
65
			return json_decode($cacheData, true);
66
		}
67
68
		$discoveredServices = [];
69
70
		// query the remote server for available services
71
		try {
72
			$response = $this->client->get($remote . '/ocs-provider/', [
73
				'timeout' => 10,
74
				'connect_timeout' => 10,
75
			]);
76
			if($response->getStatusCode() === Http::STATUS_OK) {
77
				$decodedServices = json_decode($response->getBody(), true);
78
				$discoveredServices = $this->getEndpoints($decodedServices, $service);
79
			}
80
		} catch (\Exception $e) {
81
			// if we couldn't discover the service or any end-points we return a empty array
82
			return [];
83
		}
84
85
		// Write into cache
86
		$this->cache->set($remote . '#' . $service, json_encode($discoveredServices));
87
		return $discoveredServices;
88
	}
89
90
	/**
91
	 * get requested end-points from the requested service
92
	 *
93
	 * @param $decodedServices
94
	 * @param $service
95
	 * @return array
96
	 */
97
	protected function getEndpoints($decodedServices, $service) {
98
99
		$discoveredServices = [];
100
101
		if(is_array($decodedServices) &&
102
			isset($decodedServices['services'][$service]['endpoints'])
103
		) {
104
			foreach ($decodedServices['services'][$service]['endpoints'] as $endpoint => $url) {
105
				if($this->isSafeUrl($url)) {
106
					$discoveredServices[$endpoint] = $url;
107
				}
108
			}
109
		}
110
111
		return $discoveredServices;
112
	}
113
114
	/**
115
	 * Returns whether the specified URL includes only safe characters, if not
116
	 * returns false
117
	 *
118
	 * @param string $url
119
	 * @return bool
120
	 */
121
	protected function isSafeUrl($url) {
122
		return (bool)preg_match('/^[\/\.\-A-Za-z0-9]+$/', $url);
123
	}
124
125
}
126