aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/sabre/dav/lib/DAV/TemporaryFileFilterPlugin.php
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/sabre/dav/lib/DAV/TemporaryFileFilterPlugin.php')
-rw-r--r--vendor/sabre/dav/lib/DAV/TemporaryFileFilterPlugin.php297
1 files changed, 297 insertions, 0 deletions
diff --git a/vendor/sabre/dav/lib/DAV/TemporaryFileFilterPlugin.php b/vendor/sabre/dav/lib/DAV/TemporaryFileFilterPlugin.php
new file mode 100644
index 000000000..c5b8aa1ca
--- /dev/null
+++ b/vendor/sabre/dav/lib/DAV/TemporaryFileFilterPlugin.php
@@ -0,0 +1,297 @@
+<?php
+
+namespace Sabre\DAV;
+
+use Sabre\HTTP\RequestInterface;
+use Sabre\HTTP\ResponseInterface;
+use Sabre\HTTP\URLUtil;
+
+/**
+ * Temporary File Filter Plugin
+ *
+ * The purpose of this filter is to intercept some of the garbage files
+ * operation systems and applications tend to generate when mounting
+ * a WebDAV share as a disk.
+ *
+ * It will intercept these files and place them in a separate directory.
+ * these files are not deleted automatically, so it is adviceable to
+ * delete these after they are not accessed for 24 hours.
+ *
+ * Currently it supports:
+ * * OS/X style resource forks and .DS_Store
+ * * desktop.ini and Thumbs.db (windows)
+ * * .*.swp (vim temporary files)
+ * * .dat.* (smultron temporary files)
+ *
+ * Additional patterns can be added, by adding on to the
+ * temporaryFilePatterns property.
+ *
+ * @copyright Copyright (C) fruux GmbH (https://fruux.com/)
+ * @author Evert Pot (http://evertpot.com/)
+ * @license http://sabre.io/license/ Modified BSD License
+ */
+class TemporaryFileFilterPlugin extends ServerPlugin {
+
+ /**
+ * This is the list of patterns we intercept.
+ * If new patterns are added, they must be valid patterns for preg_match.
+ *
+ * @var array
+ */
+ public $temporaryFilePatterns = [
+ '/^\._(.*)$/', // OS/X resource forks
+ '/^.DS_Store$/', // OS/X custom folder settings
+ '/^desktop.ini$/', // Windows custom folder settings
+ '/^Thumbs.db$/', // Windows thumbnail cache
+ '/^.(.*).swp$/', // ViM temporary files
+ '/^\.dat(.*)$/', // Smultron seems to create these
+ '/^~lock.(.*)#$/', // Windows 7 lockfiles
+ ];
+
+ /**
+ * A reference to the main Server class
+ *
+ * @var Sabre\DAV\Server
+ */
+ protected $server;
+
+ /**
+ * This is the directory where this plugin
+ * will store it's files.
+ *
+ * @var string
+ */
+ private $dataDir;
+
+ /**
+ * Creates the plugin.
+ *
+ * Make sure you specify a directory for your files. If you don't, we
+ * will use PHP's directory for session-storage instead, and you might
+ * not want that.
+ *
+ * @param string|null $dataDir
+ */
+ function __construct($dataDir = null) {
+
+ if (!$dataDir) $dataDir = ini_get('session.save_path') . '/sabredav/';
+ if (!is_dir($dataDir)) mkdir($dataDir);
+ $this->dataDir = $dataDir;
+
+ }
+
+ /**
+ * Initialize the plugin
+ *
+ * This is called automatically be the Server class after this plugin is
+ * added with Sabre\DAV\Server::addPlugin()
+ *
+ * @param Server $server
+ * @return void
+ */
+ function initialize(Server $server) {
+
+ $this->server = $server;
+ $server->on('beforeMethod', [$this, 'beforeMethod']);
+ $server->on('beforeCreateFile', [$this, 'beforeCreateFile']);
+
+ }
+
+ /**
+ * This method is called before any HTTP method handler
+ *
+ * This method intercepts any GET, DELETE, PUT and PROPFIND calls to
+ * filenames that are known to match the 'temporary file' regex.
+ *
+ * @param RequestInterface $request
+ * @param ResponseInterface $response
+ * @return bool
+ */
+ function beforeMethod(RequestInterface $request, ResponseInterface $response) {
+
+ if (!$tempLocation = $this->isTempFile($request->getPath()))
+ return;
+
+ switch ($request->getMethod()) {
+ case 'GET' :
+ return $this->httpGet($request, $response, $tempLocation);
+ case 'PUT' :
+ return $this->httpPut($request, $response, $tempLocation);
+ case 'PROPFIND' :
+ return $this->httpPropfind($request, $response, $tempLocation);
+ case 'DELETE' :
+ return $this->httpDelete($request, $response, $tempLocation);
+ }
+ return;
+
+ }
+
+ /**
+ * This method is invoked if some subsystem creates a new file.
+ *
+ * This is used to deal with HTTP LOCK requests which create a new
+ * file.
+ *
+ * @param string $uri
+ * @param resource $data
+ * @param DAV\ICollection $parentNode
+ * @param bool $modified Should be set to true, if this event handler
+ * changed &$data.
+ * @return bool
+ */
+ function beforeCreateFile($uri, $data, $parent, $modified) {
+
+ if ($tempPath = $this->isTempFile($uri)) {
+
+ $hR = $this->server->httpResponse;
+ $hR->setHeader('X-Sabre-Temp', 'true');
+ file_put_contents($tempPath, $data);
+ return false;
+ }
+ return;
+
+ }
+
+ /**
+ * This method will check if the url matches the temporary file pattern
+ * if it does, it will return an path based on $this->dataDir for the
+ * temporary file storage.
+ *
+ * @param string $path
+ * @return bool|string
+ */
+ protected function isTempFile($path) {
+
+ // We're only interested in the basename.
+ list(, $tempPath) = URLUtil::splitPath($path);
+
+ foreach ($this->temporaryFilePatterns as $tempFile) {
+
+ if (preg_match($tempFile, $tempPath)) {
+ return $this->getDataDir() . '/sabredav_' . md5($path) . '.tempfile';
+ }
+
+ }
+
+ return false;
+
+ }
+
+
+ /**
+ * This method handles the GET method for temporary files.
+ * If the file doesn't exist, it will return false which will kick in
+ * the regular system for the GET method.
+ *
+ * @param RequestInterface $request
+ * @param ResponseInterface $hR
+ * @param string $tempLocation
+ * @return bool
+ */
+ function httpGet(RequestInterface $request, ResponseInterface $hR, $tempLocation) {
+
+ if (!file_exists($tempLocation)) return;
+
+ $hR->setHeader('Content-Type', 'application/octet-stream');
+ $hR->setHeader('Content-Length', filesize($tempLocation));
+ $hR->setHeader('X-Sabre-Temp', 'true');
+ $hR->setStatus(200);
+ $hR->setBody(fopen($tempLocation, 'r'));
+ return false;
+
+ }
+
+ /**
+ * This method handles the PUT method.
+ *
+ * @param RequestInterface $request
+ * @param ResponseInterface $hR
+ * @param string $tempLocation
+ * @return bool
+ */
+ function httpPut(RequestInterface $request, ResponseInterface $hR, $tempLocation) {
+
+ $hR->setHeader('X-Sabre-Temp', 'true');
+
+ $newFile = !file_exists($tempLocation);
+
+ if (!$newFile && ($this->server->httpRequest->getHeader('If-None-Match'))) {
+ throw new Exception\PreconditionFailed('The resource already exists, and an If-None-Match header was supplied');
+ }
+
+ file_put_contents($tempLocation, $this->server->httpRequest->getBody());
+ $hR->setStatus($newFile ? 201 : 200);
+ return false;
+
+ }
+
+ /**
+ * This method handles the DELETE method.
+ *
+ * If the file didn't exist, it will return false, which will make the
+ * standard HTTP DELETE handler kick in.
+ *
+ * @param RequestInterface $request
+ * @param ResponseInterface $hR
+ * @param string $tempLocation
+ * @return bool
+ */
+ function httpDelete(RequestInterface $request, ResponseInterface $hR, $tempLocation) {
+
+ if (!file_exists($tempLocation)) return;
+
+ unlink($tempLocation);
+ $hR->setHeader('X-Sabre-Temp', 'true');
+ $hR->setStatus(204);
+ return false;
+
+ }
+
+ /**
+ * This method handles the PROPFIND method.
+ *
+ * It's a very lazy method, it won't bother checking the request body
+ * for which properties were requested, and just sends back a default
+ * set of properties.
+ *
+ * @param RequestInterface $request
+ * @param ResponseInterface $hR
+ * @param string $tempLocation
+ * @return bool
+ */
+ function httpPropfind(RequestInterface $request, ResponseInterface $hR, $tempLocation) {
+
+ if (!file_exists($tempLocation)) return;
+
+ $hR->setHeader('X-Sabre-Temp', 'true');
+ $hR->setStatus(207);
+ $hR->setHeader('Content-Type', 'application/xml; charset=utf-8');
+
+ $properties = [
+ 'href' => $request->getPath(),
+ 200 => [
+ '{DAV:}getlastmodified' => new Xml\Property\GetLastModified(filemtime($tempLocation)),
+ '{DAV:}getcontentlength' => filesize($tempLocation),
+ '{DAV:}resourcetype' => new Xml\Property\ResourceType(null),
+ '{' . Server::NS_SABREDAV . '}tempFile' => true,
+
+ ],
+ ];
+
+ $data = $this->server->generateMultiStatus([$properties]);
+ $hR->setBody($data);
+ return false;
+
+ }
+
+
+ /**
+ * This method returns the directory where the temporary files should be stored.
+ *
+ * @return string
+ */
+ protected function getDataDir()
+ {
+ return $this->dataDir;
+ }
+}