1<?php
2
3declare(strict_types=1);
4/**
5 * Calendar App
6 *
7 * @author Georg Ehrke
8 * @author Jakob Röhrl
9 * @author Christoph Wurst
10 *
11 * @copyright 2019 Georg Ehrke <oc.list@georgehrke.com>
12 * @copyright 2019 Jakob Röhrl <jakob.roehrl@web.de>
13 * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
14 *
15 * This library is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
17 * License as published by the Free Software Foundation; either
18 * version 3 of the License, or any later version.
19 *
20 * This library is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23 * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
24 *
25 * You should have received a copy of the GNU Affero General Public
26 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
27 *
28 */
29namespace OCA\Calendar\Controller;
30
31use OCP\AppFramework\Controller;
32use OCP\AppFramework\Http;
33use OCP\AppFramework\Http\JSONResponse;
34use OCP\Contacts\IManager;
35use OCP\IRequest;
36
37/**
38 * Class ContactController
39 *
40 * @package OCA\Calendar\Controller
41 */
42class ContactController extends Controller {
43
44	/** @var IManager */
45	private $contactsManager;
46
47	/**
48	 * ContactController constructor.
49	 *
50	 * @param string $appName
51	 * @param IRequest $request
52	 * @param IManager $contacts
53	 */
54	public function __construct(string $appName,
55								IRequest $request,
56								IManager $contacts) {
57		parent::__construct($appName, $request);
58		$this->contactsManager = $contacts;
59	}
60
61	/**
62	 * Search for a location based on a contact's name or address
63	 *
64	 * @param string $search Name or address to search for
65	 * @return JSONResponse
66	 *
67	 * @NoAdminRequired
68	 */
69	public function searchLocation(string $search):JSONResponse {
70		if (!$this->contactsManager->isEnabled()) {
71			return new JSONResponse();
72		}
73
74		$result = $this->contactsManager->search($search, ['FN', 'ADR']);
75
76		$contacts = [];
77		foreach ($result as $r) {
78			// Information about system users is fetched via DAV nowadays
79			if (isset($r['isLocalSystemBook']) && $r['isLocalSystemBook']) {
80				continue;
81			}
82
83			if (!isset($r['ADR'])) {
84				continue;
85			}
86
87			$name = $this->getNameFromContact($r);
88			if (\is_string($r['ADR'])) {
89				$r['ADR'] = [$r['ADR']];
90			}
91
92			$photo = isset($r['PHOTO'])
93				? $this->getPhotoUri($r['PHOTO'])
94				: null;
95
96			$addresses = [];
97			foreach ($r['ADR'] as $address) {
98				$addresses[] = trim(preg_replace("/\n+/", "\n", str_replace(';', "\n", $address)));
99			}
100
101			$contacts[] = [
102				'name' => $name,
103				'addresses' => $addresses,
104				'photo' => $photo,
105			];
106		}
107
108		return new JSONResponse($contacts);
109	}
110
111
112	/**
113	 * Search for a contact based on a contact's name or email-address
114	 *
115	 * @param string $search Name or email to search for
116	 * @return JSONResponse
117	 *
118	 * @NoAdminRequired
119	 */
120	public function searchAttendee(string $search):JSONResponse {
121		if (!$this->contactsManager->isEnabled()) {
122			return new JSONResponse();
123		}
124
125		$result = $this->contactsManager->search($search, ['FN', 'EMAIL']);
126
127		$contacts = [];
128		foreach ($result as $r) {
129			// Information about system users is fetched via DAV nowadays
130			if (isset($r['isLocalSystemBook']) && $r['isLocalSystemBook']) {
131				continue;
132			}
133
134			if (!isset($r['EMAIL'])) {
135				continue;
136			}
137
138			$name = $this->getNameFromContact($r);
139			if (\is_string($r['EMAIL'])) {
140				$r['EMAIL'] = [$r['EMAIL']];
141			}
142
143			$photo = isset($r['PHOTO'])
144				? $this->getPhotoUri($r['PHOTO'])
145				: null;
146
147			$lang = null;
148			if (isset($r['LANG'])) {
149				if (\is_array($r['LANG'])) {
150					$lang = $r['LANG'][0];
151				} else {
152					$lang = $r['LANG'];
153				}
154			}
155
156			$timezoneId = null;
157			if (isset($r['TZ'])) {
158				if (\is_array($r['TZ'])) {
159					$timezoneId = $r['TZ'][0];
160				} else {
161					$timezoneId = $r['TZ'];
162				}
163			}
164
165			$contacts[] = [
166				'name' => $name,
167				'emails' => $r['EMAIL'],
168				'lang' => $lang,
169				'tzid' => $timezoneId,
170				'photo' => $photo,
171			];
172		}
173
174		return new JSONResponse($contacts);
175	}
176
177	/**
178	 * Get a contact's photo based on their email-address
179	 *
180	 * @param string $search Exact email-address to match
181	 * @return JSONResponse
182	 *
183	 * @NoAdminRequired
184	 */
185	public function searchPhoto(string $search):JSONResponse {
186		if (!$this->contactsManager->isEnabled()) {
187			return new JSONResponse([], Http::STATUS_NOT_FOUND);
188		}
189
190		$result = $this->contactsManager->search($search, ['EMAIL']);
191
192		foreach ($result as $r) {
193			if (!isset($r['EMAIL'])) {
194				continue;
195			}
196
197			if (\is_string($r['EMAIL'])) {
198				$r['EMAIL'] = [$r['EMAIL']];
199			}
200
201			$match = false;
202			foreach ($r['EMAIL'] as $email) {
203				if ($email === $search) {
204					$match = true;
205				}
206			}
207
208			if (!$match) {
209				continue;
210			}
211
212			if (!isset($r['PHOTO'])) {
213				continue;
214			}
215
216			$name = $this->getNameFromContact($r);
217			$photo = $this->getPhotoUri($r['PHOTO']);
218			if (!$photo) {
219				continue;
220			}
221
222			return new JSONResponse([
223				'name' => $name,
224				'photo' => $photo,
225			]);
226		}
227
228		return new JSONResponse([], Http::STATUS_NOT_FOUND);
229	}
230
231	/**
232	 * Extract name from an array containing a contact's information
233	 *
234	 * @param array $r
235	 * @return string
236	 */
237	private function getNameFromContact(array $r):string {
238		return $r['FN'] ?? '';
239	}
240
241	/**
242	 * Get photo uri from contact
243	 *
244	 * @param string $raw
245	 * @return string|null
246	 */
247	private function getPhotoUri(string $raw):?string {
248		$uriPrefix = 'VALUE=uri:';
249		if (substr($raw, 0, strlen($uriPrefix)) === $uriPrefix) {
250			return substr($raw, strpos($raw, 'http'));
251		}
252
253		return null;
254	}
255}
256