2015-12-09 22:19:23 +01:00
|
|
|
<?php
|
|
|
|
|
2016-08-19 00:51:35 +02:00
|
|
|
namespace SilverStripe\Assets\Storage;
|
|
|
|
|
|
|
|
use SilverStripe\Assets\File;
|
2016-09-09 08:43:05 +02:00
|
|
|
use SilverStripe\Control\HTTPRequest;
|
2016-08-19 00:51:35 +02:00
|
|
|
use SilverStripe\Control\Controller;
|
2016-09-09 08:43:05 +02:00
|
|
|
use SilverStripe\Control\HTTPResponse;
|
2015-12-09 22:19:23 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Provides routing for session-whitelisted protected files
|
|
|
|
*/
|
2016-08-19 00:51:35 +02:00
|
|
|
class ProtectedFileController extends Controller {
|
2015-12-09 22:19:23 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Designated router
|
|
|
|
*
|
|
|
|
* @var AssetStoreRouter
|
|
|
|
*/
|
|
|
|
protected $handler = null;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return AssetStoreRouter
|
|
|
|
*/
|
|
|
|
public function getRouteHandler() {
|
|
|
|
return $this->handler;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param AssetStoreRouter $handler
|
|
|
|
* @return $this
|
|
|
|
*/
|
|
|
|
public function setRouteHandler(AssetStoreRouter $handler) {
|
|
|
|
$this->handler = $handler;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
private static $url_handlers = array(
|
|
|
|
'$Filename' => "handleFile"
|
|
|
|
);
|
|
|
|
|
|
|
|
private static $allowed_actions = array(
|
|
|
|
'handleFile'
|
|
|
|
);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Provide a response for the given file request
|
|
|
|
*
|
2016-09-09 08:43:05 +02:00
|
|
|
* @param HTTPRequest $request
|
|
|
|
* @return HTTPResponse
|
2015-12-09 22:19:23 +01:00
|
|
|
*/
|
2016-09-09 08:43:05 +02:00
|
|
|
public function handleFile(HTTPRequest $request) {
|
2015-12-09 22:19:23 +01:00
|
|
|
$filename = $this->parseFilename($request);
|
|
|
|
|
|
|
|
// Deny requests to private file
|
|
|
|
if(!$this->isValidFilename($filename)) {
|
|
|
|
return $this->httpError(400, "Invalid request");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Pass through to backend
|
|
|
|
return $this->getRouteHandler()->getResponseFor($filename);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check if the given filename is safe to pass to the route handler.
|
|
|
|
* This should block direct requests to assets/.protected/ paths
|
|
|
|
*
|
|
|
|
* @param $filename
|
|
|
|
* @return bool True if the filename is allowed
|
|
|
|
*/
|
|
|
|
public function isValidFilename($filename) {
|
|
|
|
// Block hidden files
|
|
|
|
return !preg_match('#(^|[\\\\/])\\..*#', $filename);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the file component from the request
|
|
|
|
*
|
2016-09-09 08:43:05 +02:00
|
|
|
* @param HTTPRequest $request
|
2015-12-09 22:19:23 +01:00
|
|
|
* @return string
|
|
|
|
*/
|
2016-09-09 08:43:05 +02:00
|
|
|
protected function parseFilename(HTTPRequest $request) {
|
2015-12-09 22:19:23 +01:00
|
|
|
$filename = '';
|
|
|
|
$next = $request->param('Filename');
|
|
|
|
while($next) {
|
2016-08-19 00:51:35 +02:00
|
|
|
$filename = $filename ? File::join_paths($filename, $next) : $next;
|
2015-12-09 22:19:23 +01:00
|
|
|
$next = $request->shift();
|
|
|
|
}
|
|
|
|
if($extension = $request->getExtension()) {
|
|
|
|
$filename = $filename . "." . $extension;
|
|
|
|
}
|
|
|
|
return $filename;
|
|
|
|
}
|
|
|
|
}
|