Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F1821408
TemporaryFileFilterPlugin.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Size
8 KB
Subscribers
None
TemporaryFileFilterPlugin.php
View Options
<?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) 2007-2015 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
* @return bool
*/
function
beforeCreateFile
(
$uri
,
$data
)
{
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
;
}
}
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Mon, Dec 23, 10:35 PM (1 d, 5 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
906808
Default Alt Text
TemporaryFileFilterPlugin.php (8 KB)
Attached To
rDAVCAL DokuWiki DAVCal PlugIn
Event Timeline
Log In to Comment