ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
Plugin.php
Go to the documentation of this file.
1 <?php
2 
4 
5 use Sabre\DAV;
8 
23 class Plugin extends DAV\ServerPlugin {
24 
25  const RANGE_APPEND = 1;
26  const RANGE_START = 2;
27  const RANGE_END = 3;
28 
34  protected $server;
35 
44  function initialize(DAV\Server $server) {
45 
46  $this->server = $server;
47  $server->on('method:PATCH', [$this, 'httpPatch']);
48 
49  }
50 
59  function getPluginName() {
60 
61  return 'partialupdate';
62 
63  }
64 
79  function getHTTPMethods($uri) {
80 
81  $tree = $this->server->tree;
82 
83  if ($tree->nodeExists($uri)) {
84  $node = $tree->getNodeForPath($uri);
85  if ($node instanceof IPatchSupport) {
86  return ['PATCH'];
87  }
88  }
89  return [];
90 
91  }
92 
98  function getFeatures() {
99 
100  return ['sabredav-partialupdate'];
101 
102  }
103 
116 
117  $path = $request->getPath();
118 
119  // Get the node. Will throw a 404 if not found
120  $node = $this->server->tree->getNodeForPath($path);
121  if (!$node instanceof IPatchSupport) {
122  throw new DAV\Exception\MethodNotAllowed('The target resource does not support the PATCH method.');
123  }
124 
125  $range = $this->getHTTPUpdateRange($request);
126 
127  if (!$range) {
128  throw new DAV\Exception\BadRequest('No valid "X-Update-Range" found in the headers');
129  }
130 
131  $contentType = strtolower(
132  $request->getHeader('Content-Type')
133  );
134 
135  if ($contentType != 'application/x-sabredav-partialupdate') {
136  throw new DAV\Exception\UnsupportedMediaType('Unknown Content-Type header "' . $contentType . '"');
137  }
138 
139  $len = $this->server->httpRequest->getHeader('Content-Length');
140  if (!$len) throw new DAV\Exception\LengthRequired('A Content-Length header is required');
141 
142  switch ($range[0]) {
143  case self::RANGE_START :
144  // Calculate the end-range if it doesn't exist.
145  if (!$range[2]) {
146  $range[2] = $range[1] + $len - 1;
147  } else {
148  if ($range[2] < $range[1]) {
149  throw new DAV\Exception\RequestedRangeNotSatisfiable('The end offset (' . $range[2] . ') is lower than the start offset (' . $range[1] . ')');
150  }
151  if ($range[2] - $range[1] + 1 != $len) {
152  throw new DAV\Exception\RequestedRangeNotSatisfiable('Actual data length (' . $len . ') is not consistent with begin (' . $range[1] . ') and end (' . $range[2] . ') offsets');
153  }
154  }
155  break;
156  }
157 
158  if (!$this->server->emit('beforeWriteContent', [$path, $node, null]))
159  return;
160 
161  $body = $this->server->httpRequest->getBody();
162 
163 
164  $etag = $node->patch($body, $range[0], isset($range[1]) ? $range[1] : null);
165 
166  $this->server->emit('afterWriteContent', [$path, $node]);
167 
168  $response->setHeader('Content-Length', '0');
169  if ($etag) $response->setHeader('ETag', $etag);
170  $response->setStatus(204);
171 
172  // Breaks the event chain
173  return false;
174 
175  }
176 
198 
199  $range = $request->getHeader('X-Update-Range');
200  if (is_null($range)) return null;
201 
202  // Matching "Range: bytes=1234-5678: both numbers are optional
203 
204  if (!preg_match('/^(append)|(?:bytes=([0-9]+)-([0-9]*))|(?:bytes=(-[0-9]+))$/i', $range, $matches)) return null;
205 
206  if ($matches[1] === 'append') {
207  return [self::RANGE_APPEND];
208  } elseif (strlen($matches[2]) > 0) {
209  return [self::RANGE_START, $matches[2], $matches[3] ?: null];
210  } else {
211  return [self::RANGE_END, $matches[4]];
212  }
213 
214  }
215 }
This interface represents a HTTP response.
The RequestInterface represents a HTTP request.
$path
Definition: aliased.php:25
This interface provides a way to modify only part of a target resource It may be used to update a fil...
The baseclass for all server plugins.
getFeatures()
Returns a list of features for the HTTP OPTIONS Dav: header.
Definition: Plugin.php:98
httpPatch(RequestInterface $request, ResponseInterface $response)
Patch an uri.
Definition: Plugin.php:115
foreach($paths as $path) $request
Definition: asyncclient.php:32
initialize(DAV\Server $server)
Initializes the plugin.
Definition: Plugin.php:44
Partial update plugin (Patch method)
Definition: Plugin.php:23
getHTTPMethods($uri)
Use this method to tell the server this plugin defines additional HTTP methods.
Definition: Plugin.php:79
setStatus($status)
Sets the HTTP status code.
Main DAV server class.
Definition: Server.php:23
getHeader($name)
Returns a specific HTTP header, based on it&#39;s name.
getPath()
Returns the relative path.
if($path[strlen($path) - 1]==='/') if(is_dir($path)) if(!file_exists($path)) if(preg_match('#\.php$#D', mb_strtolower($path, 'UTF-8'))) $contentType
Definition: module.php:144
getPluginName()
Returns a plugin name.
Definition: Plugin.php:59
$response
getHTTPUpdateRange(RequestInterface $request)
Returns the HTTP custom range update header.
Definition: Plugin.php:197
setHeader($name, $value)
Updates a HTTP header.