diff --git a/Controller/UploadController.php b/Controller/UploadController.php index fddd3c8be642c7bd9d6f40464c4d862a640bdc44..804dc7704a52f39c6e4b25e6939d5d2a885442c0 100644 --- a/Controller/UploadController.php +++ b/Controller/UploadController.php @@ -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'); } } diff --git a/Form/Type/FileUploadType.php b/Form/Type/FileUploadType.php index 21243424a606fd5adc52dedaf7c59c99f06bd976..e570f5ade87d4f36479db549418f0a5d6ed59ff1 100644 --- a/Form/Type/FileUploadType.php +++ b/Form/Type/FileUploadType.php @@ -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'];