Commit 01cb0787 authored by Guillaume Perréal's avatar Guillaume Perréal
Browse files

UploadController: blinde la gestion des tokens CSRF.

Showing with 35 additions and 14 deletions
+35 -14
......@@ -28,7 +28,8 @@ use Symfony\Component\Routing\RouterInterface;
*/
class UploadController extends Controller
{
const CSRF_INTENTION = "file_upload";
const CSRF_READ_INTENTION = "uploaded_file_read";
const CSRF_WRITE_INTENTION = "uploaded_file_write_%s";
/**
*
......@@ -73,7 +74,7 @@ class UploadController extends Controller
isset($data['lastModified']) ? $data['lastModified'] : null
);
$token = $this->csrfProvider->generateCsrfToken(self::CSRF_INTENTION);
$token = $this->generateCsrfToken(self::CSRF_WRITE_INTENTION, $file);
$parameters = [
'id' => $file->getId(),
......@@ -104,17 +105,18 @@ class UploadController extends Controller
*/
public function putContentAction(Request $request, UploadedFile $file)
{
$this->validateToken($request);
$this->validateCsrfToken($request, self::CSRF_WRITE_INTENTION, $file);
if(null !== $range = $request->headers->get('Content-Range', null)) {
$matches = [];
if(!preg_match('@^bytes (\d+)-(\d+)/(\d+)$@', $range, $matches)) {
throw new BadRequestHttpException("Invalid Content-Range");
}
$start = intval($matches[1]);
$start = intval($matches[1]);
$end = intval($matches[2]);
$total = intval($matches[3]);
if($start < 0 || $start >= $end || $end >= $total) {
throw new HttpException(Response::HTTP_REQUESTED_RANGE_NOT_SATISFIABLE);
}
......@@ -124,13 +126,13 @@ class UploadController extends Controller
$complete = $end === ($total-1);
} else {
$offset = 0;
$maxlen = -1;
$maxlen = PHP_INT_MAX;
$complete = true;
}
// Demande un filehandle plutôt que charger le contenu en mémoire
$input = $request->getContent(true);
$copied = $file->copyFrom($input, $maxlen, $offset);
$file->copyFrom($input, $maxlen, $offset);
fclose($input);
if(!$complete) {
......@@ -171,7 +173,7 @@ class UploadController extends Controller
*/
public function getContentAction(Request $request, UploadedFile $file)
{
$this->validateToken($request);
$this->validateCsrfToken($request, self::CSRF_READ_INTENTION);
if(!$file->isValid()) {
throw new NotFoundHttpException();
......@@ -190,21 +192,40 @@ class UploadController extends Controller
*/
public function deleteAction(Request $request, UploadedFile $file)
{
$this->validateToken($request);
$this->validateCsrfToken($request, self::CSRF_WRITE_INTENTION, $file);
$this->fileManager->delete($file);
return $this->createResponse();
}
/**
*
* @param type $intention
* @param UploadedFile $file
* @return string
*/
protected function generateCsrfToken($intention, UploadedFile $file = null)
{
if(null !== $file) {
$intention = sprintf($intention, $file->getId());
}
return $this->csrfProvider->generateCsrfToken($intention);
}
/**
*
* @param Request $request
* @param type $intention
* @param UploadedFile $file
* @throws HttpException
*/
protected function validateToken(Request $request)
protected function validateCsrfToken(Request $request, $intention, UploadedFile $file = null)
{
if(!$this->csrfProvider->isCsrfTokenValid(self::CSRF_INTENTION, $request->query->get('token', null))) {
if(null !== $file) {
$intention = sprintf($intention, $file->getId());
}
if(!$this->csrfProvider->isCsrfTokenValid($intention, $request->query->get('token', null))) {
throw new HttpException(Response::HTTP_FORBIDDEN, 'Invalid CSRF token');
}
}
......
......@@ -35,9 +35,9 @@ class FileUploadType extends AbstractType
private $fileManager;
/**
* @var CsrfProviderInterface
* @var string
*/
private $csrfProvider;
private $csrfToken;
/**
* @var int
......@@ -53,7 +53,7 @@ class FileUploadType extends AbstractType
{
$this->router = $router;
$this->fileManager = $fileManager;
$this->csrfProvider = $csrfProvider;
$this->csrfToken = $csrfProvider->generateCsrfToken(UploadController::CSRF_READ_INTENTION);
$this->maxChunkSize = $maxChunkSize;
}
......@@ -74,7 +74,7 @@ class FileUploadType extends AbstractType
$this->buildWidgetView($view, $form, $options);
$view->vars['widget_attr']['data-create-url'] = $this->router->generate('file_upload_create');
$view->vars['csrfToken'] = $this->csrfProvider->generateCsrfToken(UploadController::CSRF_INTENTION);
$view->vars['csrfToken'] = $this->csrfToken;
$view->vars['multiple'] = $options['multiple'];
if($options['max_chunk_size'] > 0) {
$view->vars['widget_attr']['data-max-chunk-size'] = $options['max_chunk_size'];
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment