Passed
Push — master ( 81722d...5a22b0 )
by Blizzz
14:50 queued 11s
created

CloudIdManager::removeProtocolFromUrl()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 5
nc 3
nop 1
dl 0
loc 8
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * @copyright Copyright (c) 2017, Robin Appelman <[email protected]>
7
 *
8
 * @author Arthur Schiwon <[email protected]>
9
 * @author Christoph Wurst <[email protected]>
10
 * @author Guillaume Virlet <[email protected]>
11
 * @author Joas Schilling <[email protected]>
12
 * @author Robin Appelman <[email protected]>
13
 * @author Roeland Jago Douma <[email protected]>
14
 *
15
 * @license GNU AGPL version 3 or any later version
16
 *
17
 * This program is free software: you can redistribute it and/or modify
18
 * it under the terms of the GNU Affero General Public License as
19
 * published by the Free Software Foundation, either version 3 of the
20
 * License, or (at your option) any later version.
21
 *
22
 * This program is distributed in the hope that it will be useful,
23
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25
 * GNU Affero General Public License for more details.
26
 *
27
 * You should have received a copy of the GNU Affero General Public License
28
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
29
 *
30
 */
31
namespace OC\Federation;
32
33
use OCP\Contacts\IManager;
34
use OCP\Federation\ICloudId;
35
use OCP\Federation\ICloudIdManager;
36
use OCP\IURLGenerator;
37
use OCP\IUserManager;
38
39
class CloudIdManager implements ICloudIdManager {
40
	/** @var IManager */
41
	private $contactsManager;
42
	/** @var IURLGenerator */
43
	private $urlGenerator;
44
	/** @var IUserManager */
45
	private $userManager;
46
47
	public function __construct(IManager $contactsManager, IURLGenerator $urlGenerator, IUserManager $userManager) {
48
		$this->contactsManager = $contactsManager;
49
		$this->urlGenerator = $urlGenerator;
50
		$this->userManager = $userManager;
51
	}
52
53
	/**
54
	 * @param string $cloudId
55
	 * @return ICloudId
56
	 * @throws \InvalidArgumentException
57
	 */
58
	public function resolveCloudId(string $cloudId): ICloudId {
59
		// TODO magic here to get the url and user instead of just splitting on @
60
61
		if (!$this->isValidCloudId($cloudId)) {
62
			throw new \InvalidArgumentException('Invalid cloud id');
63
		}
64
65
		// Find the first character that is not allowed in user names
66
		$id = $this->fixRemoteURL($cloudId);
67
		$posSlash = strpos($id, '/');
68
		$posColon = strpos($id, ':');
69
70
		if ($posSlash === false && $posColon === false) {
71
			$invalidPos = \strlen($id);
72
		} elseif ($posSlash === false) {
73
			$invalidPos = $posColon;
74
		} elseif ($posColon === false) {
75
			$invalidPos = $posSlash;
76
		} else {
77
			$invalidPos = min($posSlash, $posColon);
78
		}
79
80
		$lastValidAtPos = strrpos($id, '@', $invalidPos - strlen($id));
81
82
		if ($lastValidAtPos !== false) {
83
			$user = substr($id, 0, $lastValidAtPos);
84
			$remote = substr($id, $lastValidAtPos + 1);
85
			if (!empty($user) && !empty($remote)) {
86
				return new CloudId($id, $user, $remote, $this->getDisplayNameFromContact($id));
87
			}
88
		}
89
		throw new \InvalidArgumentException('Invalid cloud id');
90
	}
91
92
	protected function getDisplayNameFromContact(string $cloudId): ?string {
93
		$addressBookEntries = $this->contactsManager->search($cloudId, ['CLOUD']);
94
		foreach ($addressBookEntries as $entry) {
95
			if (isset($entry['CLOUD'])) {
96
				foreach ($entry['CLOUD'] as $cloudID) {
97
					if ($cloudID === $cloudId) {
98
						// Warning, if user decides to make his full name local only,
99
						// no FN is found on federated servers
100
						if (isset($entry['FN'])) {
101
							return $entry['FN'];
102
						} else {
103
							return $cloudID;
104
						}
105
					}
106
				}
107
			}
108
		}
109
		return null;
110
	}
111
112
	/**
113
	 * @param string $user
114
	 * @param string|null $remote
115
	 * @return CloudId
116
	 */
117
	public function getCloudId(string $user, ?string $remote): ICloudId {
118
		if ($remote === null) {
119
			$remote = rtrim($this->removeProtocolFromUrl($this->urlGenerator->getAbsoluteURL('/')), '/');
120
			$fixedRemote = $this->fixRemoteURL($remote);
121
			$localUser = $this->userManager->get($user);
122
			$displayName = !is_null($localUser) ? $localUser->getDisplayName() : '';
123
		} else {
124
			// TODO check what the correct url is for remote (asking the remote)
125
			$fixedRemote = $this->fixRemoteURL($remote);
126
			$host = $this->removeProtocolFromUrl($fixedRemote);
127
			$displayName = $this->getDisplayNameFromContact($user . '@' . $host);
128
		}
129
		$id = $user . '@' . $remote;
130
		return new CloudId($id, $user, $fixedRemote, $displayName);
131
	}
132
133
	/**
134
	 * @param string $url
135
	 * @return string
136
	 */
137
	private function removeProtocolFromUrl($url) {
138
		if (strpos($url, 'https://') === 0) {
139
			return substr($url, strlen('https://'));
140
		} elseif (strpos($url, 'http://') === 0) {
141
			return substr($url, strlen('http://'));
142
		}
143
144
		return $url;
145
	}
146
147
	/**
148
	 * Strips away a potential file names and trailing slashes:
149
	 * - http://localhost
150
	 * - http://localhost/
151
	 * - http://localhost/index.php
152
	 * - http://localhost/index.php/s/{shareToken}
153
	 *
154
	 * all return: http://localhost
155
	 *
156
	 * @param string $remote
157
	 * @return string
158
	 */
159
	protected function fixRemoteURL(string $remote): string {
160
		$remote = str_replace('\\', '/', $remote);
161
		if ($fileNamePosition = strpos($remote, '/index.php')) {
162
			$remote = substr($remote, 0, $fileNamePosition);
163
		}
164
		$remote = rtrim($remote, '/');
165
166
		return $remote;
167
	}
168
169
	/**
170
	 * @param string $cloudId
171
	 * @return bool
172
	 */
173
	public function isValidCloudId(string $cloudId): bool {
174
		return strpos($cloudId, '@') !== false;
175
	}
176
}
177