/** * 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 */ public function updateAddressBook($addressBookId, \Sabre\DAV\PropPatch $propPatch) { foreach ($this->addressBooks as &$book) { if ($book['id'] !== $addressBookId) { continue; } $propPatch->handleRemaining(function ($mutations) use(&$book) { foreach ($mutations as $key => $value) { $book[$key] = $value; } return true; }); } }
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']); }
/** * Updates properties for a path * * This method received a PropPatch object, which contains all the * information about the update. * * Usually you would want to call 'handleRemaining' on this object, to get; * a list of all properties that need to be stored. * * @param string $path * @param PropPatch $propPatch * @return void */ function propPatch($path, PropPatch $propPatch) { $propPatch->handleRemaining(function ($properties) use($path) { $updateStmt = $this->pdo->prepare("REPLACE INTO propertystorage (path, name, value) VALUES (?, ?, ?)"); $deleteStmt = $this->pdo->prepare("DELETE FROM propertystorage WHERE path = ? AND name = ?"); foreach ($properties as $name => $value) { if (!is_null($value)) { $updateStmt->execute([$path, $name, $value]); } else { $deleteStmt->execute([$path, $name]); } } 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', '{' . 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 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 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) { $propPatch->handleRemaining(function (array $properties) { $resourceData = $this->getResourceData(); foreach ($properties as $propertyName => $propertyValue) { // If it was null, we need to delete the property if (is_null($propertyValue)) { unset($resourceData['properties'][$propertyName]); } else { $resourceData['properties'][$propertyName] = $propertyValue; } } $this->putResourceData($resourceData); return true; }); }
/** * Updates properties for a path * * This method received a PropPatch object, which contains all the * information about the update. * * Usually you would want to call 'handleRemaining' on this object, to get; * a list of all properties that need to be stored. * * @param string $path * @param PropPatch $propPatch * @return void */ function propPatch($path, PropPatch $propPatch) { if (!isset($this->data[$path])) { $this->data[$path] = []; } $propPatch->handleRemaining(function ($properties) use($path) { foreach ($properties as $propName => $propValue) { if (is_null($propValue)) { unset($this->data[$path][$propName]); } else { $this->data[$path][$propName] = $propValue; } 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 array $mutations * @return bool|array */ public function propPatch(PropPatch $proppatch) { $proppatch->handleRemaining(function ($updateProperties) { switch ($this->failMode) { case 'updatepropsfalse': return false; case 'updatepropsarray': $r = []; foreach ($updateProperties as $k => $v) { $r[$k] = 402; } return $r; case 'updatepropsobj': return new \STDClass(); } }); }
/** * Updates an addressbook's properties * * See \Sabre\DAV\IProperties for a description of the mutations array, as * well as the return value. * * @param mixed $addressbookid * @see \Sabre\DAV\IProperties::updateProperties * @return bool|array */ public function updateAddressBook($addressbookid, PropPatch $propPatch) { $changes = array(); $mutations = $propPatch->getRemainingMutations(); foreach ($mutations as $property => $newvalue) { switch ($property) { case '{DAV:}displayname': $changes['displayname'] = $newvalue; break; case '{' . \Sabre\CardDAV\Plugin::NS_CARDDAV . '}addressbook-description': $changes['description'] = $newvalue; break; default: // If any unsupported values were being updated, we must // let the entire request fail. return false; } } list($id, $backend) = $this->getBackendForAddressBook($addressbookid); return $backend->updateAddressBook($id, $changes); }
/** * Updates properties for a calendar. * * 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 $calendarId * @param \Sabre\DAV\PropPatch $propPatch * @return void */ function updateCalendar($calendarId, \Sabre\DAV\PropPatch $propPatch) { $propPatch->handleRemaining(function ($props) use($calendarId) { foreach ($this->calendars as $k => $calendar) { if ($calendar['id'] === $calendarId) { foreach ($props as $propName => $propValue) { if (is_null($propValue)) { unset($this->calendars[$k][$propName]); } else { $this->calendars[$k][$propName] = $propValue; } } 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) { $value = null; foreach ($this->principals as $principalIndex => $value) { if ($value['uri'] === $path) { $principal = $value; break; } } if (!$principal) { return; } $propPatch->handleRemaining(function ($mutations) use($principal, $principalIndex) { foreach ($mutations as $prop => $value) { if (is_null($value) && isset($principal[$prop])) { unset($principal[$prop]); } else { $principal[$prop] = $value; } } $this->principals[$principalIndex] = $principal; 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']); }
/** * 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']); }
/** * This method updates a resource's properties * * The properties array must be a list of properties. Array-keys are * property names in clarknotation, array-values are it's values. * If a property must be deleted, the value should be null. * * Note that this request should either completely succeed, or * completely fail. * * The response is an array with properties for keys, and http status codes * as their values. * * @param string $path * @param array $properties * @return array */ function updateProperties($path, array $properties) { $propPatch = new PropPatch($properties); $this->emit('propPatch', [$path, $propPatch]); $propPatch->commit(); return $propPatch->getResult(); }
/** * Updates properties for a path * * This method received a PropPatch object, which contains all the * information about the update. * * Usually you would want to call 'handleRemaining' on this object, to get; * a list of all properties that need to be stored. * * @param string $path * @param PropPatch $propPatch * @return void */ function propPatch($path, PropPatch $propPatch) { $propPatch->handleRemaining(function ($properties) use($path) { $updateStmt = $this->pdo->prepare("REPLACE INTO " . $this->tableName . " (path, name, valuetype, value) VALUES (?, ?, ?, ?)"); $deleteStmt = $this->pdo->prepare("DELETE FROM " . $this->tableName . " WHERE path = ? AND name = ?"); foreach ($properties as $name => $value) { if (!is_null($value)) { if (is_scalar($value)) { $valueType = self::VT_STRING; } elseif ($value instanceof Complex) { $valueType = self::VT_XML; $value = $value->getXml(); } else { $valueType = self::VT_OBJECT; $value = serialize($value); } $updateStmt->execute([$path, $name, $valueType, $value]); } else { $deleteStmt->execute([$path, $name]); } } return true; }); }
/** * This method is called during property updates. * * Here we check if a user attempted to update a protected property and * ensure that the process fails if this is the case. * * @param string $path * @param PropPatch $propPatch * @return void */ function propPatchProtectedPropertyCheck($path, PropPatch $propPatch) { // Comparing the mutation list to the list of propetected properties. $mutations = $propPatch->getMutations(); $protected = array_intersect($this->server->protectedProperties, array_keys($mutations)); if ($protected) { $propPatch->setResultCode($protected, 403); } }
/** * 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 a path * * @param string $path * @param PropPatch $propPatch * * @return void */ public function propPatch($path, PropPatch $propPatch) { $node = $this->tree->getNodeForPath($path); if (!$node instanceof Node) { return; } $propPatch->handleRemaining(function ($changedProps) use($node) { return $this->updateProperties($node, $changedProps); }); }
/** * Updates properties for a path * * This method received a PropPatch object, which contains all the * information about the update. * * Usually you would want to call 'handleRemaining' on this object, to get; * a list of all properties that need to be stored. * * @param string $path * @param PropPatch $propPatch * @return void */ function propPatch($path, PropPatch $propPatch) { $propPatch->handleRemaining(function ($properties) use($path) { if ($this->pdo->getAttribute(\PDO::ATTR_DRIVER_NAME) === 'pgsql') { $updateSql = <<<SQL INSERT INTO {$this->tableName} (path, name, valuetype, value) VALUES (:path, :name, :valuetype, :value) ON CONFLICT (path, name) DO UPDATE SET valuetype = :valuetype, value = :value SQL; } else { $updateSql = <<<SQL REPLACE INTO {$this->tableName} (path, name, valuetype, value) VALUES (:path, :name, :valuetype, :value) SQL; } $updateStmt = $this->pdo->prepare($updateSql); $deleteStmt = $this->pdo->prepare("DELETE FROM " . $this->tableName . " WHERE path = ? AND name = ?"); foreach ($properties as $name => $value) { if (!is_null($value)) { if (is_scalar($value)) { $valueType = self::VT_STRING; } elseif ($value instanceof Complex) { $valueType = self::VT_XML; $value = $value->getXml(); } else { $valueType = self::VT_OBJECT; $value = serialize($value); } $updateStmt->bindParam('path', $path, \PDO::PARAM_STR); $updateStmt->bindParam('name', $name, \PDO::PARAM_STR); $updateStmt->bindParam('valuetype', $valueType, \PDO::PARAM_INT); $updateStmt->bindParam('value', $value, \PDO::PARAM_LOB); $updateStmt->execute(); } else { $deleteStmt->execute([$path, $name]); } } return true; }); }
/** * 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 properties for a path * * @param string $path * @param PropPatch $propPatch * * @return void */ public function propPatch($path, PropPatch $propPatch) { $propPatch->handleRemaining(function ($changedProps) use($path) { return $this->updateProperties($path, $changedProps); }); }
function propPatch(PropPatch $propPatch) { $mutations = $propPatch->getMutations(); // If this is a shared calendar, the user can only change the enabled property, to hide it. if (isset($this->calendarInfo['{http://owncloud.org/ns}owner-principal']) && (sizeof($mutations) !== 1 || !isset($mutations['{http://owncloud.org/ns}calendar-enabled']))) { throw new Forbidden(); } parent::propPatch($propPatch); }
/** * 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; }); }
/** * 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; }); }
/** * 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; }); }
/** * 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']; }); }
/** * 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']); }
/** * 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; }); }
/** * 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]; }); }