1<?php 2/** 3 * @author Thomas Müller <thomas.mueller@tmit.eu> 4 * 5 * @copyright Copyright (c) 2018, ownCloud GmbH 6 * @license AGPL-3.0 7 * 8 * This code is free software: you can redistribute it and/or modify 9 * it under the terms of the GNU Affero General Public License, version 3, 10 * as published by the Free Software Foundation. 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, version 3, 18 * along with this program. If not, see <http://www.gnu.org/licenses/> 19 * 20 */ 21namespace OCA\DAV\CardDAV; 22 23use OCA\DAV\DAV\Sharing\IShareable; 24use Sabre\CardDAV\Card; 25use Sabre\DAV\Exception\Forbidden; 26use Sabre\DAV\Exception\NotFound; 27use Sabre\DAV\PropPatch; 28 29class AddressBook extends \Sabre\CardDAV\AddressBook implements IShareable { 30 31 /** 32 * Updates the list of shares. 33 * 34 * The first array is a list of people that are to be added to the 35 * addressbook. 36 * 37 * Every element in the add array has the following properties: 38 * * href - A url. Usually a mailto: address 39 * * commonName - Usually a first and last name, or false 40 * * summary - A description of the share, can also be false 41 * * readOnly - A boolean value 42 * 43 * Every element in the remove array is just the address string. 44 * 45 * @param array $add 46 * @param array $remove 47 * @return void 48 */ 49 public function updateShares(array $add, array $remove) { 50 /** @var CardDavBackend $cardDavBackend */ 51 $cardDavBackend = $this->carddavBackend; 52 '@phan-var CardDavBackend $cardDavBackend'; 53 $cardDavBackend->updateShares($this, $add, $remove); 54 } 55 56 /** 57 * Returns the list of people whom this addressbook is shared with. 58 * 59 * Every element in this array should have the following properties: 60 * * href - Often a mailto: address 61 * * commonName - Optional, for example a first + last name 62 * * status - See the Sabre\CalDAV\SharingPlugin::STATUS_ constants. 63 * * readOnly - boolean 64 * * summary - Optional, a description for the share 65 * 66 * @return array 67 */ 68 public function getShares() { 69 /** @var CardDavBackend $cardDavBackend */ 70 $cardDavBackend = $this->carddavBackend; 71 '@phan-var CardDavBackend $cardDavBackend'; 72 return $cardDavBackend->getShares($this->getResourceId()); 73 } 74 75 public function getACL() { 76 $acl = [ 77 [ 78 'privilege' => '{DAV:}read', 79 'principal' => $this->getOwner(), 80 'protected' => true, 81 ]]; 82 $acl[] = [ 83 'privilege' => '{DAV:}write', 84 'principal' => $this->getOwner(), 85 'protected' => true, 86 ]; 87 if ($this->getOwner() !== parent::getOwner()) { 88 $acl[] = [ 89 'privilege' => '{DAV:}read', 90 'principal' => parent::getOwner(), 91 'protected' => true, 92 ]; 93 if ($this->canWrite()) { 94 $acl[] = [ 95 'privilege' => '{DAV:}write', 96 'principal' => parent::getOwner(), 97 'protected' => true, 98 ]; 99 } 100 } 101 if ($this->getOwner() === 'principals/system/system') { 102 $acl[] = [ 103 'privilege' => '{DAV:}read', 104 'principal' => '{DAV:}authenticated', 105 'protected' => true, 106 ]; 107 } 108 109 /** @var CardDavBackend $cardDavBackend */ 110 $cardDavBackend = $this->carddavBackend; 111 '@phan-var CardDavBackend $cardDavBackend'; 112 return $cardDavBackend->applyShareAcl($this->getResourceId(), $acl); 113 } 114 115 public function getChildACL() { 116 return $this->getACL(); 117 } 118 119 public function getChild($name) { 120 $obj = $this->carddavBackend->getCard($this->addressBookInfo['id'], $name); 121 if (!$obj) { 122 throw new NotFound('Card not found'); 123 } 124 $obj['acl'] = $this->getChildACL(); 125 return new Card($this->carddavBackend, $this->addressBookInfo, $obj); 126 } 127 128 /** 129 * @return int 130 */ 131 public function getResourceId() { 132 return $this->addressBookInfo['id']; 133 } 134 135 public function getOwner() { 136 if (isset($this->addressBookInfo['{http://owncloud.org/ns}owner-principal'])) { 137 return $this->addressBookInfo['{http://owncloud.org/ns}owner-principal']; 138 } 139 return parent::getOwner(); 140 } 141 142 public function delete() { 143 if (isset($this->addressBookInfo['{http://owncloud.org/ns}owner-principal'])) { 144 $principal = 'principal:' . parent::getOwner(); 145 $shares = $this->getShares(); 146 $shares = \array_filter($shares, function ($share) use ($principal) { 147 return $share['href'] === $principal; 148 }); 149 if (empty($shares)) { 150 throw new Forbidden(); 151 } 152 153 /** @var CardDavBackend $cardDavBackend */ 154 $cardDavBackend = $this->carddavBackend; 155 '@phan-var CardDavBackend $cardDavBackend'; 156 $cardDavBackend->updateShares($this, [], [ 157 $principal 158 ]); 159 return; 160 } 161 parent::delete(); 162 } 163 164 public function propPatch(PropPatch $propPatch) { 165 if (isset($this->addressBookInfo['{http://owncloud.org/ns}owner-principal'])) { 166 throw new Forbidden(); 167 } 168 parent::propPatch($propPatch); 169 } 170 171 public function getContactsGroups() { 172 /** @var CardDavBackend $cardDavBackend */ 173 $cardDavBackend = $this->carddavBackend; 174 '@phan-var CardDavBackend $cardDavBackend'; 175 176 return $cardDavBackend->collectCardProperties($this->getResourceId(), 'CATEGORIES'); 177 } 178 179 private function canWrite() { 180 if (isset($this->addressBookInfo['{http://owncloud.org/ns}read-only'])) { 181 return !$this->addressBookInfo['{http://owncloud.org/ns}read-only']; 182 } 183 return true; 184 } 185} 186