silverstripe-framework/Assets/Storage/ProtectedFileController.php

95 lines
2.0 KiB
PHP
Raw Normal View History

<?php
namespace SilverStripe\Assets\Storage;
use SilverStripe\Assets\File;
2016-09-09 08:43:05 +02:00
use SilverStripe\Control\HTTPRequest;
use SilverStripe\Control\Controller;
2016-09-09 08:43:05 +02:00
use SilverStripe\Control\HTTPResponse;
/**
* Provides routing for session-whitelisted protected files
*/
class ProtectedFileController extends Controller {
/**
* 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
*/
2016-09-09 08:43:05 +02:00
public function handleFile(HTTPRequest $request) {
$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
* @return string
*/
2016-09-09 08:43:05 +02:00
protected function parseFilename(HTTPRequest $request) {
$filename = '';
$next = $request->param('Filename');
while($next) {
$filename = $filename ? File::join_paths($filename, $next) : $next;
$next = $request->shift();
}
if($extension = $request->getExtension()) {
$filename = $filename . "." . $extension;
}
return $filename;
}
}