ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
Plugin.php
Go to the documentation of this file.
1 <?php
2 
3 namespace Sabre\DAV\Sync;
4 
5 use Sabre\DAV;
8 
21 class Plugin extends DAV\ServerPlugin {
22 
28  protected $server;
29 
30  const SYNCTOKEN_PREFIX = 'http://sabre.io/ns/sync/';
31 
40  function getPluginName() {
41 
42  return 'sync';
43 
44  }
45 
54  function initialize(DAV\Server $server) {
55 
56  $this->server = $server;
57  $server->xml->elementMap['{DAV:}sync-collection'] = 'Sabre\\DAV\\Xml\\Request\\SyncCollectionReport';
58 
59  $self = $this;
60 
61  $server->on('report', function($reportName, $dom, $uri) use ($self) {
62 
63  if ($reportName === '{DAV:}sync-collection') {
64  $this->server->transactionType = 'report-sync-collection';
65  $self->syncCollection($uri, $dom);
66  return false;
67  }
68 
69  });
70 
71  $server->on('propFind', [$this, 'propFind']);
72  $server->on('validateTokens', [$this, 'validateTokens']);
73 
74  }
75 
86  function getSupportedReportSet($uri) {
87 
88  $node = $this->server->tree->getNodeForPath($uri);
89  if ($node instanceof ISyncCollection && $node->getSyncToken()) {
90  return [
91  '{DAV:}sync-collection',
92  ];
93  }
94 
95  return [];
96 
97  }
98 
99 
107  function syncCollection($uri, SyncCollectionReport $report) {
108 
109  // Getting the data
110  $node = $this->server->tree->getNodeForPath($uri);
111  if (!$node instanceof ISyncCollection) {
112  throw new DAV\Exception\ReportNotSupported('The {DAV:}sync-collection REPORT is not supported on this url.');
113  }
114  $token = $node->getSyncToken();
115  if (!$token) {
116  throw new DAV\Exception\ReportNotSupported('No sync information is available at this node');
117  }
118 
119  $syncToken = $report->syncToken;
120  if (!is_null($syncToken)) {
121  // Sync-token must start with our prefix
122  if (substr($syncToken, 0, strlen(self::SYNCTOKEN_PREFIX)) !== self::SYNCTOKEN_PREFIX) {
123  throw new DAV\Exception\InvalidSyncToken('Invalid or unknown sync token');
124  }
125 
126  $syncToken = substr($syncToken, strlen(self::SYNCTOKEN_PREFIX));
127 
128  }
129  $changeInfo = $node->getChanges($syncToken, $report->syncLevel, $report->limit);
130 
131  if (is_null($changeInfo)) {
132 
133  throw new DAV\Exception\InvalidSyncToken('Invalid or unknown sync token');
134 
135  }
136 
137  // Encoding the response
139  $changeInfo['syncToken'],
140  $uri,
141  $changeInfo['added'],
142  $changeInfo['modified'],
143  $changeInfo['deleted'],
144  $report->properties
145  );
146 
147  }
148 
160  protected function sendSyncCollectionResponse($syncToken, $collectionUrl, array $added, array $modified, array $deleted, array $properties) {
161 
162 
163  $fullPaths = [];
164 
165  // Pre-fetching children, if this is possible.
166  foreach (array_merge($added, $modified) as $item) {
167  $fullPath = $collectionUrl . '/' . $item;
168  $fullPaths[] = $fullPath;
169  }
170 
171  $responses = [];
172  foreach ($this->server->getPropertiesForMultiplePaths($fullPaths, $properties) as $fullPath => $props) {
173 
174  // The 'Property_Response' class is responsible for generating a
175  // single {DAV:}response xml element.
176  $responses[] = new DAV\Xml\Element\Response($fullPath, $props);
177 
178  }
179 
180 
181 
182  // Deleted items also show up as 'responses'. They have no properties,
183  // and a single {DAV:}status element set as 'HTTP/1.1 404 Not Found'.
184  foreach ($deleted as $item) {
185 
186  $fullPath = $collectionUrl . '/' . $item;
187  $responses[] = new DAV\Xml\Element\Response($fullPath, [], 404);
188 
189  }
190  $multiStatus = new DAV\Xml\Response\MultiStatus($responses, self::SYNCTOKEN_PREFIX . $syncToken);
191 
192  $this->server->httpResponse->setStatus(207);
193  $this->server->httpResponse->setHeader('Content-Type', 'application/xml; charset=utf-8');
194  $this->server->httpResponse->setBody(
195  $this->server->xml->write('{DAV:}multistatus', $multiStatus, $this->server->getBaseUri())
196  );
197 
198  }
199 
208  function propFind(DAV\PropFind $propFind, DAV\INode $node) {
209 
210  $propFind->handle('{DAV:}sync-token', function() use ($node) {
211  if (!$node instanceof ISyncCollection || !$token = $node->getSyncToken()) {
212  return;
213  }
214  return self::SYNCTOKEN_PREFIX . $token;
215  });
216 
217  }
218 
229  function validateTokens(RequestInterface $request, &$conditions) {
230 
231  foreach ($conditions as $kk => $condition) {
232 
233  foreach ($condition['tokens'] as $ii => $token) {
234 
235  // Sync-tokens must always start with our designated prefix.
236  if (substr($token['token'], 0, strlen(self::SYNCTOKEN_PREFIX)) !== self::SYNCTOKEN_PREFIX) {
237  continue;
238  }
239 
240  // Checking if the token is a match.
241  $node = $this->server->tree->getNodeForPath($condition['uri']);
242 
243  if (
244  $node instanceof ISyncCollection &&
245  $node->getSyncToken() == substr($token['token'], strlen(self::SYNCTOKEN_PREFIX))
246  ) {
247  $conditions[$kk]['tokens'][$ii]['validToken'] = true;
248  }
249 
250  }
251 
252  }
253 
254  }
255 
267  function getPluginInfo() {
268 
269  return [
270  'name' => $this->getPluginName(),
271  'description' => 'Adds support for WebDAV Collection Sync (rfc6578)',
272  'link' => 'http://sabre.io/dav/sync/',
273  ];
274 
275  }
276 
277 }
The RequestInterface represents a HTTP request.
WebDAV MultiStatus parser.
Definition: MultiStatus.php:22
The baseclass for all server plugins.
foreach($paths as $path) $request
Definition: asyncclient.php:32
const SYNCTOKEN_PREFIX
Definition: Plugin.php:30
initialize(DAV\Server $server)
Initializes the plugin.
Definition: Plugin.php:54
This plugin all WebDAV-sync capabilities to the Server.
Definition: Plugin.php:21
getPluginInfo()
Returns a bunch of meta-data about the plugin.
Definition: Plugin.php:267
This class holds all the information about a PROPFIND request.
Definition: PropFind.php:11
propFind(DAV\PropFind $propFind, DAV\INode $node)
This method is triggered whenever properties are requested for a node.
Definition: Plugin.php:208
getSyncToken()
This method returns the current sync-token for this collection.
syncCollection($uri, SyncCollectionReport $report)
This method handles the {DAV:}sync-collection HTTP REPORT.
Definition: Plugin.php:107
getSupportedReportSet($uri)
Returns a list of reports this plugin supports.
Definition: Plugin.php:86
getPluginName()
Returns a plugin name.
Definition: Plugin.php:40
If a class extends ISyncCollection, it supports WebDAV-sync.
Main DAV server class.
Definition: Server.php:23
sendSyncCollectionResponse($syncToken, $collectionUrl, array $added, array $modified, array $deleted, array $properties)
Sends the response to a sync-collection request.
Definition: Plugin.php:160
The INode interface is the base interface, and the parent class of both ICollection and IFile...
Definition: INode.php:12
WebDAV {DAV:}response parser.
Definition: Response.php:20
validateTokens(RequestInterface $request, &$conditions)
The validateTokens event is triggered before every request.
Definition: Plugin.php:229