]> git.mxchange.org Git - friendica-addons.git/blob - dav/SabreDAV/lib/Sabre/DAV/TemporaryFileFilterPlugin.php
Update strings
[friendica-addons.git] / dav / SabreDAV / lib / Sabre / DAV / TemporaryFileFilterPlugin.php
1 <?php
2
3 /**
4  * Temporary File Filter Plugin
5  *
6  * The purpose of this filter is to intercept some of the garbage files
7  * operation systems and applications tend to generate when mounting
8  * a WebDAV share as a disk.
9  *
10  * It will intercept these files and place them in a separate directory.
11  * these files are not deleted automatically, so it is adviceable to
12  * delete these after they are not accessed for 24 hours.
13  *
14  * Currently it supports:
15  *   * OS/X style resource forks and .DS_Store
16  *   * desktop.ini and Thumbs.db (windows)
17  *   * .*.swp (vim temporary files)
18  *   * .dat.* (smultron temporary files)
19  *
20  * Additional patterns can be added, by adding on to the
21  * temporaryFilePatterns property.
22  *
23  * @package Sabre
24  * @subpackage DAV
25  * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
26  * @author Evert Pot (http://www.rooftopsolutions.nl/)
27  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
28  */
29 class Sabre_DAV_TemporaryFileFilterPlugin extends Sabre_DAV_ServerPlugin {
30
31     /**
32      * This is the list of patterns we intercept.
33      * If new patterns are added, they must be valid patterns for preg_match.
34      *
35      * @var array
36      */
37     public $temporaryFilePatterns = array(
38         '/^\._(.*)$/',     // OS/X resource forks
39         '/^.DS_Store$/',   // OS/X custom folder settings
40         '/^desktop.ini$/', // Windows custom folder settings
41         '/^Thumbs.db$/',   // Windows thumbnail cache
42         '/^.(.*).swp$/',   // ViM temporary files
43         '/^\.dat(.*)$/',   // Smultron seems to create these
44         '/^~lock.(.*)#$/', // Windows 7 lockfiles
45     );
46
47     /**
48      * This is the directory where this addon
49      * will store it's files.
50      *
51      * @var string
52      */
53     private $dataDir;
54
55     /**
56      * A reference to the main Server class
57      *
58      * @var Sabre_DAV_Server
59      */
60     private $server;
61
62     /**
63      * Creates the addon.
64      *
65      * Make sure you specify a directory for your files. If you don't, we
66      * will use PHP's directory for session-storage instead, and you might
67      * not want that.
68      *
69      * @param string|null $dataDir
70      */
71     public function __construct($dataDir = null) {
72
73         if (!$dataDir) $dataDir = ini_get('session.save_path').'/sabredav/';
74         if (!is_dir($dataDir)) mkdir($dataDir);
75         $this->dataDir = $dataDir;
76
77     }
78
79     /**
80      * Initialize the addon
81      *
82      * This is called automatically be the Server class after this addon is
83      * added with Sabre_DAV_Server::addPlugin()
84      *
85      * @param Sabre_DAV_Server $server
86      * @return void
87      */
88     public function initialize(Sabre_DAV_Server $server) {
89
90         $this->server = $server;
91         $server->subscribeEvent('beforeMethod',array($this,'beforeMethod'));
92         $server->subscribeEvent('beforeCreateFile',array($this,'beforeCreateFile'));
93
94     }
95
96     /**
97      * This method is called before any HTTP method handler
98      *
99      * This method intercepts any GET, DELETE, PUT and PROPFIND calls to
100      * filenames that are known to match the 'temporary file' regex.
101      *
102      * @param string $method
103      * @param string $uri
104      * @return bool
105      */
106     public function beforeMethod($method, $uri) {
107
108         if (!$tempLocation = $this->isTempFile($uri))
109             return true;
110
111         switch($method) {
112             case 'GET' :
113                 return $this->httpGet($tempLocation);
114             case 'PUT' :
115                 return $this->httpPut($tempLocation);
116             case 'PROPFIND' :
117                 return $this->httpPropfind($tempLocation, $uri);
118             case 'DELETE' :
119                 return $this->httpDelete($tempLocation);
120          }
121          return true;
122
123     }
124
125     /**
126      * This method is invoked if some subsystem creates a new file.
127      *
128      * This is used to deal with HTTP LOCK requests which create a new
129      * file.
130      *
131      * @param string $uri
132      * @param resource $data
133      * @return bool
134      */
135     public function beforeCreateFile($uri,$data) {
136
137         if ($tempPath = $this->isTempFile($uri)) {
138
139             $hR = $this->server->httpResponse;
140             $hR->setHeader('X-Sabre-Temp','true');
141             file_put_contents($tempPath,$data);
142             return false;
143         }
144         return true;
145
146     }
147
148     /**
149      * This method will check if the url matches the temporary file pattern
150      * if it does, it will return an path based on $this->dataDir for the
151      * temporary file storage.
152      *
153      * @param string $path
154      * @return boolean|string
155      */
156     protected function isTempFile($path) {
157
158         // We're only interested in the basename.
159         list(, $tempPath) = Sabre_DAV_URLUtil::splitPath($path);
160
161         foreach($this->temporaryFilePatterns as $tempFile) {
162
163             if (preg_match($tempFile,$tempPath)) {
164                 return $this->getDataDir() . '/sabredav_' . md5($path) . '.tempfile';
165             }
166
167         }
168
169         return false;
170
171     }
172
173
174     /**
175      * This method handles the GET method for temporary files.
176      * If the file doesn't exist, it will return false which will kick in
177      * the regular system for the GET method.
178      *
179      * @param string $tempLocation
180      * @return bool
181      */
182     public function httpGet($tempLocation) {
183
184         if (!file_exists($tempLocation)) return true;
185
186         $hR = $this->server->httpResponse;
187         $hR->setHeader('Content-Type','application/octet-stream');
188         $hR->setHeader('Content-Length',filesize($tempLocation));
189         $hR->setHeader('X-Sabre-Temp','true');
190         $hR->sendStatus(200);
191         $hR->sendBody(fopen($tempLocation,'r'));
192         return false;
193
194     }
195
196     /**
197      * This method handles the PUT method.
198      *
199      * @param string $tempLocation
200      * @return bool
201      */
202     public function httpPut($tempLocation) {
203
204         $hR = $this->server->httpResponse;
205         $hR->setHeader('X-Sabre-Temp','true');
206
207         $newFile = !file_exists($tempLocation);
208
209         if (!$newFile && ($this->server->httpRequest->getHeader('If-None-Match'))) {
210              throw new Sabre_DAV_Exception_PreconditionFailed('The resource already exists, and an If-None-Match header was supplied');
211         }
212
213         file_put_contents($tempLocation,$this->server->httpRequest->getBody());
214         $hR->sendStatus($newFile?201:200);
215         return false;
216
217     }
218
219     /**
220      * This method handles the DELETE method.
221      *
222      * If the file didn't exist, it will return false, which will make the
223      * standard HTTP DELETE handler kick in.
224      *
225      * @param string $tempLocation
226      * @return bool
227      */
228     public function httpDelete($tempLocation) {
229
230         if (!file_exists($tempLocation)) return true;
231
232         unlink($tempLocation);
233         $hR = $this->server->httpResponse;
234         $hR->setHeader('X-Sabre-Temp','true');
235         $hR->sendStatus(204);
236         return false;
237
238     }
239
240     /**
241      * This method handles the PROPFIND method.
242      *
243      * It's a very lazy method, it won't bother checking the request body
244      * for which properties were requested, and just sends back a default
245      * set of properties.
246      *
247      * @param string $tempLocation
248      * @param string $uri
249      * @return bool
250      */
251     public function httpPropfind($tempLocation, $uri) {
252
253         if (!file_exists($tempLocation)) return true;
254
255         $hR = $this->server->httpResponse;
256         $hR->setHeader('X-Sabre-Temp','true');
257         $hR->sendStatus(207);
258         $hR->setHeader('Content-Type','application/xml; charset=utf-8');
259
260         $this->server->parsePropFindRequest($this->server->httpRequest->getBody(true));
261
262         $properties = array(
263             'href' => $uri,
264             200 => array(
265                 '{DAV:}getlastmodified' => new Sabre_DAV_Property_GetLastModified(filemtime($tempLocation)),
266                 '{DAV:}getcontentlength' => filesize($tempLocation),
267                 '{DAV:}resourcetype' => new Sabre_DAV_Property_ResourceType(null),
268                 '{'.Sabre_DAV_Server::NS_SABREDAV.'}tempFile' => true,
269
270             ),
271          );
272
273         $data = $this->server->generateMultiStatus(array($properties));
274         $hR->sendBody($data);
275         return false;
276
277     }
278
279
280     /**
281      * This method returns the directory where the temporary files should be stored.
282      *
283      * @return string
284      */
285     protected function getDataDir()
286     {
287         return $this->dataDir;
288     }
289 }