Files
BookStack/app/Uploads/Controllers/DrawioImageController.php
T
Dan Brown fbe83a1895 Drawings: Validated drawing upload content as image data
Specifically check the mime type of Base64 drawing data to ensure
that it reads as image data rather than anything else which could be
potentially dangerous.

Thanks to Emanuele Cervelli (https://github.com/M4nu02) for reporting.
2026-08-19 16:53:47 +01:00

104 lines
3.3 KiB
PHP

<?php
namespace BookStack\Uploads\Controllers;
use BookStack\Entities\Queries\PageQueries;
use BookStack\Exceptions\ImageUploadException;
use BookStack\Http\Controller;
use BookStack\Permissions\Permission;
use BookStack\Uploads\Base64UriMimeRule;
use BookStack\Uploads\ImageRepo;
use BookStack\Uploads\ImageResizer;
use BookStack\Util\OutOfMemoryHandler;
use Exception;
use Illuminate\Http\Request;
class DrawioImageController extends Controller
{
public function __construct(
protected ImageRepo $imageRepo,
protected PageQueries $pageQueries,
) {
}
/**
* Get a list of gallery images, in a list.
* Can be paged and filtered by entity.
*/
public function list(Request $request, ImageResizer $resizer)
{
$page = $request->input('page', 1);
$searchTerm = $request->input('search', null);
$uploadedToFilter = $request->input('uploaded_to', null);
$parentTypeFilter = $request->input('filter_type', null);
$imgData = $this->imageRepo->getEntityFiltered('drawio', $parentTypeFilter, $page, 24, $uploadedToFilter, $searchTerm);
$viewData = [
'warning' => '',
'images' => $imgData['images'],
'hasMore' => $imgData['has_more'],
];
new OutOfMemoryHandler(function () use ($viewData) {
$viewData['warning'] = trans('errors.image_gallery_thumbnail_memory_limit');
return response()->view('pages.parts.image-manager-list', $viewData, 200);
});
$resizer->loadGalleryThumbnailsForMany($imgData['images']);
return view('pages.parts.image-manager-list', $viewData);
}
/**
* Store a new gallery image in the system.
*
* @throws Exception
*/
public function create(Request $request)
{
$this->checkPermission(Permission::ImageCreateAll);
$validated = $this->validate($request, [
'image' => ['required', 'string', new Base64UriMimeRule('image/png')],
'uploaded_to' => ['required', 'integer'],
]);
$imageBase64Data = $validated['image'];
$uploadedTo = $validated['uploaded_to'];
$targetPage = $this->pageQueries->findVisibleByIdOrFail($uploadedTo);
$this->checkOwnablePermission(Permission::PageUpdate, $targetPage);
try {
$image = $this->imageRepo->saveDrawing($imageBase64Data, $uploadedTo);
} catch (ImageUploadException $e) {
return response($e->getMessage(), 500);
}
return response()->json($image);
}
/**
* Get the content of an image based64 encoded.
*/
public function getAsBase64($id)
{
try {
$image = $this->imageRepo->getById($id);
} catch (Exception $exception) {
return $this->jsonError(trans('errors.drawing_data_not_found'), 404);
}
if ($image->type !== 'drawio' || !userCan(Permission::PageView, $image->getPage())) {
return $this->jsonError(trans('errors.drawing_data_not_found'), 404);
}
$imageData = $this->imageRepo->getImageData($image);
if (is_null($imageData)) {
return $this->jsonError(trans('errors.drawing_data_not_found'), 404);
}
return response()->json([
'content' => base64_encode($imageData),
]);
}
}