public function propPatch($path, DAV\PropPatch $propPatch) { $node = $this->server->tree->getNodeForPath($path); // The File object is the only thing we can change properties on: if (!$node instanceof \SambaDAV\File) { return; } // These properties are silently ignored for now; // smbclient has no 'touch' command; for documentation purposes: // {urn:schemas-microsoft-com:}Win32CreationTime // {urn:schemas-microsoft-com:}Win32LastAccessTime // {urn:schemas-microsoft-com:}Win32LastModifiedTime $handled = ['{DAV:}ishidden', '{DAV:}isreadonly', '{urn:schemas-microsoft-com:}Win32FileAttributes']; $propPatch->handle($handled, [$node, 'updateProperties']); }
/** * This method intercepts PROPPATCH methods and make sure the * group-member-set is updated correctly. * * @param string $path * @param DAV\PropPatch $propPatch * @return void */ function propPatch($path, DAV\PropPatch $propPatch) { $propPatch->handle('{DAV:}group-member-set', function ($value) use($path) { if (is_null($value)) { $memberSet = []; } elseif ($value instanceof DAV\Property\HrefList) { $memberSet = array_map([$this->server, 'calculateUri'], $value->getHrefs()); } else { throw new DAV\Exception('The group-member-set property MUST be an instance of Sabre\\DAV\\Property\\HrefList or null'); } $node = $this->server->tree->getNodeForPath($path); if (!$node instanceof IPrincipal) { // Fail return false; } $node->setGroupMemberSet($memberSet); // We must also clear our cache, just in case $this->principalMembershipCache = []; return true; }); }
/** * Updates a subscription * * The list of mutations is stored in a Sabre\DAV\PropPatch object. * To do the actual updates, you must tell this object which properties * you're going to process with the handle() method. * * Calling the handle method is like telling the PropPatch object "I * promise I can handle updating this property". * * Read the PropPatch documentation for more info and examples. * * @param mixed $subscriptionId * @param \Sabre\DAV\PropPatch $propPatch * @return void */ function updateSubscription($subscriptionId, DAV\PropPatch $propPatch) { $supportedProperties = array_keys($this->subscriptionPropertyMap); $supportedProperties[] = '{http://calendarserver.org/ns/}source'; $propPatch->handle($supportedProperties, function ($mutations) use($subscriptionId) { $newValues = []; foreach ($mutations as $propertyName => $propertyValue) { if ($propertyName === '{http://calendarserver.org/ns/}source') { $newValues['source'] = $propertyValue->getHref(); } else { $fieldName = $this->subscriptionPropertyMap[$propertyName]; $newValues[$fieldName] = $propertyValue; } } $query = $this->db->getQueryBuilder(); $query->update('calendarsubscriptions')->set('lastmodified', $query->createNamedParameter(time())); foreach ($newValues as $fieldName => $value) { $query->set($fieldName, $query->createNamedParameter($value)); } $query->where($query->expr()->eq('id', $query->createNamedParameter($subscriptionId)))->execute(); return true; }); }
/** * This method is called during property updates. * * @param string $path * @param PropPatch $propPatch * @return void */ function propPatch($path, PropPatch $propPatch) { // Mapping the old property to the new property. $propPatch->handle('{http://calendarserver.org/ns/}calendar-availability', function ($value) use($path) { $availProp = '{' . self::NS_CALDAV . '}calendar-availability'; $subPropPatch = new PropPatch([$availProp => $value]); $this->server->emit('propPatch', [$path, $subPropPatch]); $subPropPatch->commit(); return $subPropPatch->getResult()[$availProp]; }); }
/** * This method is trigged when a user attempts to update a node's * properties. * * A previous draft of the sharing spec stated that it was possible to use * PROPPATCH to remove 'shared-owner' from the resourcetype, thus unsharing * the calendar. * * Even though this is no longer in the current spec, we keep this around * because OS X 10.7 may still make use of this feature. * * @param string $path * @param DAV\PropPatch $propPatch * @return void */ function propPatch($path, DAV\PropPatch $propPatch) { $node = $this->server->tree->getNodeForPath($path); if (!$node instanceof ISharedCalendar) { return; } if ($node->getShareAccess() === \Sabre\DAV\Sharing\Plugin::ACCESS_SHAREDOWNER || $node->getShareAccess() === \Sabre\DAV\Sharing\Plugin::ACCESS_NOTSHARED) { $propPatch->handle('{DAV:}resourcetype', function ($value) use($node) { if ($value->is('{' . Plugin::NS_CALENDARSERVER . '}shared-owner')) { return false; } $shares = $node->getInvites(); foreach ($shares as $share) { $share->access = DAV\Sharing\Plugin::ACCESS_NOACCESS; } $node->updateInvites($shares); return true; }); } }
/** * This event is triggered when a PROPPATCH method is executed * * @param string $path * @param DAV\PropPatch $propPatch * @return bool */ function propPatch($path, DAV\PropPatch $propPatch) { $node = $this->server->tree->getNodeForPath($path); if (!$node instanceof UserAddressBooks) { return true; } $meCard = '{http://calendarserver.org/ns/}me-card'; $propPatch->handle($meCard, function ($value) use($node) { if ($value instanceof DAV\Property\IHref) { $value = $value->getHref(); $value = $this->server->calculateUri($value); } elseif (!is_null($value)) { return 400; } $innerResult = $this->server->updateProperties($node->getOwner(), ['{http://sabredav.org/ns}vcard-url' => $value]); return $innerResult['{http://sabredav.org/ns}vcard-url']; }); }
/** * Update ownCloud-specific properties * * @param string $path * @param PropPatch $propPatch * * @return void */ public function handleUpdateProperties($path, PropPatch $propPatch) { $propPatch->handle(self::GETLASTMODIFIED_PROPERTYNAME, function ($time) use($path) { if (empty($time)) { return false; } $node = $this->tree->getNodeForPath($path); if (is_null($node)) { return 404; } $node->touch($time); return true; }); $propPatch->handle(self::GETETAG_PROPERTYNAME, function ($etag) use($path) { if (empty($etag)) { return false; } $node = $this->tree->getNodeForPath($path); if (is_null($node)) { return 404; } if ($node->setEtag($etag) !== -1) { return true; } return false; }); }
/** * @inheritdoc */ function propPatch(PropPatch $propPatch) { $propPatch->handle(self::PROPERTY_NAME_READ_MARKER, [$this, 'setReadMarker']); }
/** * Updates tag attributes * * @param string $path * @param PropPatch $propPatch * * @return void */ public function handleUpdateProperties($path, PropPatch $propPatch) { $propPatch->handle([self::DISPLAYNAME_PROPERTYNAME, self::USERVISIBLE_PROPERTYNAME, self::USERASSIGNABLE_PROPERTYNAME, self::GROUPS_PROPERTYNAME], function ($props) use($path) { $node = $this->server->tree->getNodeForPath($path); if (!$node instanceof SystemTagNode) { return; } $tag = $node->getSystemTag(); $name = $tag->getName(); $userVisible = $tag->isUserVisible(); $userAssignable = $tag->isUserAssignable(); $updateTag = false; if (isset($props[self::DISPLAYNAME_PROPERTYNAME])) { $name = $props[self::DISPLAYNAME_PROPERTYNAME]; $updateTag = true; } if (isset($props[self::USERVISIBLE_PROPERTYNAME])) { $propValue = $props[self::USERVISIBLE_PROPERTYNAME]; $userVisible = $propValue !== 'false' && $propValue !== '0'; $updateTag = true; } if (isset($props[self::USERASSIGNABLE_PROPERTYNAME])) { $propValue = $props[self::USERASSIGNABLE_PROPERTYNAME]; $userAssignable = $propValue !== 'false' && $propValue !== '0'; $updateTag = true; } if (isset($props[self::GROUPS_PROPERTYNAME])) { if (!$this->groupManager->isAdmin($this->userSession->getUser()->getUID())) { // property only available for admins throw new Forbidden(); } $propValue = $props[self::GROUPS_PROPERTYNAME]; $groupIds = explode('|', $propValue); $this->tagManager->setTagGroups($tag, $groupIds); } if ($updateTag) { $node->update($name, $userVisible, $userAssignable); } return true; }); }
/** * Updates one ore more webdav properties on a principal. * * The list of mutations is stored in a Sabre\DAV\PropPatch object. * To do the actual updates, you must tell this object which properties * you're going to process with the handle() method. * * Calling the handle method is like telling the PropPatch object "I * promise I can handle updating this property". * * Read the PropPatch documenation for more info and examples. * * @param string $path * @param DAV\PropPatch $propPatch */ function updatePrincipal($path, DAV\PropPatch $propPatch) { $propPatch->handle(array_keys($this->fieldMap), function ($properties) use($path) { $query = "UPDATE " . $this->tableName . " SET "; $first = true; $values = []; foreach ($properties as $key => $value) { $dbField = $this->fieldMap[$key]['dbField']; if (!$first) { $query .= ', '; } $first = false; $query .= $dbField . ' = :' . $dbField; $values[$dbField] = $value; } $query .= " WHERE uri = :uri"; $values['uri'] = $path; $connection = $this->entityManager->getConnection(); $connection->executeUpdate($query, $values); return true; }); }
/** * Updates a calendars properties * * The properties array uses the propertyName in clark-notation as key, * and the array value for the property value. In the case a property * should be deleted, the property value will be null. * * This method must be atomic. If one property cannot be changed, the * entire operation must fail. * * If the operation was successful, true can be returned. * If the operation failed, false can be returned. * * Deletion of a non-existant property is always succesful. * * Lastly, it is optional to return detailed information about any * failures. In this case an array should be returned with the following * structure: * * array( * 403 => array( * '{DAV:}displayname' => null, * ), * 424 => array( * '{DAV:}owner' => null, * ) * ) * * In this example it was forbidden to update {DAV:}displayname. * (403 Forbidden), which in turn also caused {DAV:}owner to fail * (424 Failed Dependency) because the request needs to be atomic. * * @param string $calendarId * @param array $properties * @return bool|array */ public function updateCalendar($calendarId, \Sabre\DAV\PropPatch $propPatch) { $supportedProperties = array_keys($this->propertyMap); $supportedProperties[] = '{' . \Sabre\CalDAV\Plugin::NS_CALDAV . '}schedule-calendar-transp'; $propPatch->handle($supportedProperties, function ($mutations) use($calendarId) { $newValues = array(); $bChange = false; foreach ($mutations as $propertyName => $propertyValue) { switch ($propertyName) { case '{' . \Sabre\CalDAV\Plugin::NS_CALDAV . '}schedule-calendar-transp': $fieldName = 'transparent'; $newValues[$fieldName] = $propertyValue->getValue() === 'transparent'; break; default: $fieldName = $this->propertyMap[$propertyName]; $newValues[$fieldName] = $propertyValue; break; } $bChange = true; } //\OCP\Util::writeLog('calendar',' change Found: '.$bChange, \OCP\Util::DEBUG); // Success if (!isset($newValues['displayname'])) { $newValues['displayname'] = null; } if (!isset($newValues['timezone'])) { $newValues['timezone'] = null; } if (!isset($newValues['calendarorder'])) { $newValues['calendarorder'] = null; } if (!isset($newValues['calendarcolor'])) { $newValues['calendarcolor'] = null; } if (!is_null($newValues['calendarcolor']) && strlen($newValues['calendarcolor']) == 9) { $newValues['calendarcolor'] = substr($newValues['calendarcolor'], 0, 7); } $this->calendarConnector->edit($calendarId, $newValues['displayname'], null, $newValues['timezone'], $newValues['calendarorder'], $newValues['calendarcolor']); return true; }); }
/** * {@inheritdoc} */ public function updateCalendar($calendarId, PropPatch $propPatch) { $supportedProperties = array_keys($this->propertyMap); $supportedProperties[] = '{' . Plugin::NS_CALDAV . '}schedule-calendar-transp'; $manager = $this->manager; $propPatch->handle($supportedProperties, function ($mutations) use($calendarId, $manager) { $newValues = []; foreach ($mutations as $propertyName => $propertyValue) { switch ($propertyName) { case '{' . Plugin::NS_CALDAV . '}schedule-calendar-transp': $fieldName = 'transparent'; $newValues[$fieldName] = $propertyValue->getValue() === 'transparent'; break; default: $fieldName = $this->propertyMap[$propertyName]; $newValues[$fieldName] = $propertyValue; break; } } $calendar = $manager->findById('public', 'calendar', $calendarId); foreach ($newValues as $name => $value) { $calendar->{$name} = $value; } if ($calendar->displayname != $newValues['displayname']) { $newValues['slug'] = true; $calendar->slug = $this->generateSlug($calendar->displayname, 'calendar'); } $manager->updateOne('public', 'calendar', $calendar, array_keys($newValues)); $this->addChange($calendarId, '', 2); return true; }); }
/** * Updates properties for an address book. * * The list of mutations is stored in a Sabre\DAV\PropPatch object. * To do the actual updates, you must tell this object which properties * you're going to process with the handle() method. * * Calling the handle method is like telling the PropPatch object "I * promise I can handle updating this property". * * Read the PropPatch documenation for more info and examples. * * @param string $addressBookId * @param \Sabre\DAV\PropPatch $propPatch */ public function updateAddressBook($addressBookId, \Sabre\DAV\PropPatch $propPatch) { $supportedProperties = ['{DAV:}displayname', '{' . CardDAV\Plugin::NS_CARDDAV . '}addressbook-description']; $addressbook = $this->_em->getRepository($this->addressbooks_class)->find($addressBookId); if (!$addressbook) { return; } $propPatch->handle($supportedProperties, function ($mutations) use($addressbook) { $updates = []; foreach ($mutations as $property => $newValue) { switch ($property) { case '{DAV:}displayname': $updates['setLabel'] = $newValue; break; case '{' . CardDAV\Plugin::NS_CARDDAV . '}addressbook-description': $updates['setDescription'] = $newValue; break; } } foreach ($updates as $setter => $value) { if (method_exists($addressbook, $setter)) { $addressbook->{$setter}($value); } } $this->_em->persist($addressbook); $this->_em->flush(); return true; }); }
/** * Triggered by a `PROPPATCH` or a `MKCOL`. The goal is to respectively * update or create the user in the database. * * @param string $path Path. * @param SabreDav\PropPatch $propPatch The `PROPPATCH` object. * @return void */ function propPatch($path, SabreDav\PropPatch $propPatch) { $username = substr($path, strlen('principals/')); $database = $this->database; $propPatch->handle(['{http://sabredav.org/ns}password'], function ($properties) use($username, $database) { $statement = $database->prepare('REPLACE INTO users (username, digesta1) ' . 'VALUES (:username, :digest)'); $password = Plugin::hashPassword($properties['{http://sabredav.org/ns}password']); return $statement->execute(['username' => $username, 'digest' => $password]); }); }
/** * Updates tags and favorites properties, if applicable. * * @param string $path * @param PropPatch $propPatch * * @return void */ public function handleUpdateProperties($path, PropPatch $propPatch) { $propPatch->handle(self::TAGS_PROPERTYNAME, function ($tagList) use($path) { $node = $this->tree->getNodeForPath($path); if (is_null($node)) { return 404; } $this->updateTags($node->getId(), $tagList->getTags()); return true; }); $propPatch->handle(self::FAVORITE_PROPERTYNAME, function ($favState) use($path) { $node = $this->tree->getNodeForPath($path); if (is_null($node)) { return 404; } if ((int) $favState === 1 || $favState === 'true') { $this->getTagger()->tagAs($node->getId(), self::TAG_FAVORITE); } else { $this->getTagger()->unTag($node->getId(), self::TAG_FAVORITE); } if (is_null($favState)) { // confirm deletion return 204; } return 200; }); }
/** * Updates a subscription * * The list of mutations is stored in a Sabre\DAV\PropPatch object. * To do the actual updates, you must tell this object which properties * you're going to process with the handle() method. * * Calling the handle method is like telling the PropPatch object "I * promise I can handle updating this property". * * Read the PropPatch documenation for more info and examples. * * @param mixed $subscriptionId * @param \Sabre\DAV\PropPatch $propPatch * @return void */ function updateSubscription($subscriptionId, DAV\PropPatch $propPatch) { $supportedProperties = array_keys($this->subscriptionPropertyMap); $supportedProperties[] = '{http://calendarserver.org/ns/}source'; $propPatch->handle($supportedProperties, function ($mutations) use($subscriptionId) { $newValues = []; foreach ($mutations as $propertyName => $propertyValue) { if ($propertyName === '{http://calendarserver.org/ns/}source') { $newValues['source'] = $propertyValue->getHref(); } else { $fieldName = $this->subscriptionPropertyMap[$propertyName]; $newValues[$fieldName] = $propertyValue; } } // Now we're generating the sql query. $valuesSql = []; foreach ($newValues as $fieldName => $value) { $valuesSql[] = $fieldName . ' = ?'; } $stmt = $this->pdo->prepare("UPDATE " . $this->calendarSubscriptionsTableName . " SET " . implode(', ', $valuesSql) . ", lastmodified = ? WHERE id = ?"); $newValues['lastmodified'] = time(); $newValues['id'] = $subscriptionId; $stmt->execute(array_values($newValues)); return true; }); }
/** * Updates properties on this node. * * This method received a PropPatch object, which contains all the * information about the update. * * To update specific properties, call the 'handle' method on this object. * Read the PropPatch documentation for more information. * * @param PropPatch $propPatch * @return void */ function propPatch(PropPatch $propPatch) { // other properties than 'message' are read only $propPatch->handle('{' . self::NS_OWNCLOUD . '}message', [$this, 'updateComment']); }
/** * Updates one ore more webdav properties on a principal. * * The list of mutations is stored in a Sabre\DAV\PropPatch object. * To do the actual updates, you must tell this object which properties * you're going to process with the handle() method. * * Calling the handle method is like telling the PropPatch object "I * promise I can handle updating this property". * * Read the PropPatch documenation for more info and examples. * * @param string $path * @param \Sabre\DAV\PropPatch $propPatch */ function updatePrincipal($path, \Sabre\DAV\PropPatch $propPatch) { $propPatch->handle(array_keys($this->fieldMap), function ($properties) use($path) { $query = "UPDATE " . $this->tableName . " SET "; $first = true; $values = []; foreach ($properties as $key => $value) { $dbField = $this->fieldMap[$key]['dbField']; if (!$first) { $query .= ', '; } $first = false; $query .= $dbField . ' = :' . $dbField; $values[$dbField] = $value; } $query .= " WHERE uri = :uri"; $values['uri'] = $path; $stmt = $this->pdo->prepare($query); $stmt->execute($values); return true; }); }
/** * Updates properties on this node. * * This method received a PropPatch object, which contains all the * information about the update. * * To update specific properties, call the 'handle' method on this object. * Read the PropPatch documentation for more information. * * @param PropPatch $propPatch * @return void */ function propPatch(PropPatch $propPatch) { // other properties than 'message' are read only $propPatch->handle(self::PROPERTY_NAME_MESSAGE, [$this, 'updateComment']); }
/** * This method is trigged when a user attempts to update a node's * properties. * * A previous draft of the sharing spec stated that it was possible to use * PROPPATCH to remove 'shared-owner' from the resourcetype, thus unsharing * the calendar. * * Even though this is no longer in the current spec, we keep this around * because OS X 10.7 may still make use of this feature. * * @param string $path * @param DAV\PropPatch $propPatch * @return void */ function propPatch($path, DAV\PropPatch $propPatch) { $node = $this->server->tree->getNodeForPath($path); if (!$node instanceof IShareableCalendar) { return; } $propPatch->handle('{DAV:}resourcetype', function ($value) use($node) { if ($value->is('{' . Plugin::NS_CALENDARSERVER . '}shared-owner')) { return false; } $shares = $node->getShares(); $remove = []; foreach ($shares as $share) { $remove[] = $share['href']; } $node->updateShares([], $remove); return true; }); }
/** * Updates properties for an address book. * * The list of mutations is stored in a Sabre\DAV\PropPatch object. * To do the actual updates, you must tell this object which properties * you're going to process with the handle() method. * * Calling the handle method is like telling the PropPatch object "I * promise I can handle updating this property". * * Read the PropPatch documenation for more info and examples. * * @param string $addressBookId * @param \Sabre\DAV\PropPatch $propPatch * @return void */ function updateAddressBook($addressBookId, \Sabre\DAV\PropPatch $propPatch) { $supportedProperties = ['{DAV:}displayname', '{' . CardDAV\Plugin::NS_CARDDAV . '}addressbook-description']; $propPatch->handle($supportedProperties, function ($mutations) use($addressBookId) { $updates = []; foreach ($mutations as $property => $newValue) { switch ($property) { case '{DAV:}displayname': $updates['displayname'] = $newValue; break; case '{' . CardDAV\Plugin::NS_CARDDAV . '}addressbook-description': $updates['description'] = $newValue; break; } } $query = 'UPDATE ' . $this->addressBooksTableName . ' SET '; $first = true; foreach ($updates as $key => $value) { if ($first) { $first = false; } else { $query .= ', '; } $query .= ' `' . $key . '` = :' . $key . ' '; } $query .= ' WHERE id = :addressbookid'; $stmt = $this->pdo->prepare($query); $updates['addressbookid'] = $addressBookId; $stmt->execute($updates); $this->addChange($addressBookId, "", 2); return true; }); }
/** * Updates tag attributes * * @param string $path * @param PropPatch $propPatch * * @return void */ public function handleUpdateProperties($path, PropPatch $propPatch) { $propPatch->handle([self::DISPLAYNAME_PROPERTYNAME, self::USERVISIBLE_PROPERTYNAME, self::USERASSIGNABLE_PROPERTYNAME], function ($props) use($path) { $node = $this->server->tree->getNodeForPath($path); if (!$node instanceof SystemTagNode) { return; } $tag = $node->getSystemTag(); $name = $tag->getName(); $userVisible = $tag->isUserVisible(); $userAssignable = $tag->isUserAssignable(); if (isset($props[self::DISPLAYNAME_PROPERTYNAME])) { $name = $props[self::DISPLAYNAME_PROPERTYNAME]; } if (isset($props[self::USERVISIBLE_PROPERTYNAME])) { $userVisible = (bool) $props[self::USERVISIBLE_PROPERTYNAME]; } if (isset($props[self::USERASSIGNABLE_PROPERTYNAME])) { $userAssignable = (bool) $props[self::USERASSIGNABLE_PROPERTYNAME]; } $node->update($name, $userVisible, $userAssignable); return true; }); }
/** * Updates properties for an address book. * * The list of mutations is stored in a Sabre\DAV\PropPatch object. * To do the actual updates, you must tell this object which properties * you're going to process with the handle() method. * * Calling the handle method is like telling the PropPatch object "I * promise I can handle updating this property". * * Read the PropPatch documentation for more info and examples. * * @param string $addressBookId * @param \Sabre\DAV\PropPatch $propPatch * @return void */ function updateAddressBook($addressBookId, \Sabre\DAV\PropPatch $propPatch) { $supportedProperties = ['{DAV:}displayname', '{' . Plugin::NS_CARDDAV . '}addressbook-description']; $propPatch->handle($supportedProperties, function ($mutations) use($addressBookId) { $updates = []; foreach ($mutations as $property => $newValue) { switch ($property) { case '{DAV:}displayname': $updates['displayname'] = $newValue; break; case '{' . Plugin::NS_CARDDAV . '}addressbook-description': $updates['description'] = $newValue; break; } } $query = $this->db->getQueryBuilder(); $query->update('addressbooks'); foreach ($updates as $key => $value) { $query->set($key, $query->createNamedParameter($value)); } $query->where($query->expr()->eq('id', $query->createNamedParameter($addressBookId)))->execute(); $this->addChange($addressBookId, "", 2); return true; }); }
/** * Updates one ore more webdav properties on a principal. * * The list of mutations is stored in a Sabre\DAV\PropPatch object. * To do the actual updates, you must tell this object which properties * you're going to process with the handle() method. * * Calling the handle method is like telling the PropPatch object "I * promise I can handle updating this property". * * Read the PropPatch documenation for more info and examples. * * @param string $path * @param \Sabre\DAV\PropPatch $propPatch */ public function updatePrincipal($path, \Sabre\DAV\PropPatch $propPatch) { $principal = $this->getPrincipalByPath($path, true); if (empty($principal)) { return; } $propPatch->handle(array_keys($this->fieldMap), function ($properties) use($principal) { foreach ($properties as $key => $value) { $setter = $this->fieldMap[$key]['setter']; $principal->{$setter}($value); } $this->_em->flush(); return true; }); }