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