Skip to content

Commit f3a1e3e

Browse files
committed
Allow SVG in jury test case visualization
1 parent 027965b commit f3a1e3e

File tree

5 files changed

+42
-11
lines changed

5 files changed

+42
-11
lines changed

webapp/src/Controller/Jury/ProblemController.php

+20-10
Original file line numberDiff line numberDiff line change
@@ -605,16 +605,26 @@ public function testcasesAction(Request $request, int $probId): Response
605605
}
606606
$content = file_get_contents($file->getRealPath());
607607
if ($type === 'image') {
608-
$imageType = Utils::getImageType($content, $error);
609-
if ($imageType === false) {
610-
$this->addFlash('danger', sprintf('image: %s', $error));
611-
return $this->redirectToRoute('jury_problem_testcases', ['probId' => $probId]);
612-
}
613-
$thumb = Utils::getImageThumb($content, $thumbnailSize,
614-
$this->dj->getDomjudgeTmpDir(), $error);
615-
if ($thumb === false) {
616-
$this->addFlash('danger', sprintf('image: %s', $error));
617-
return $this->redirectToRoute('jury_problem_testcases', ['probId' => $probId]);
608+
if (mime_content_type($file->getRealPath()) === 'image/svg+xml') {
609+
$content = Utils::sanitizeSvg($content);
610+
if ($content === false) {
611+
$this->addFlash('danger', sprintf('image: %s', $error));
612+
return $this->redirectToRoute('jury_problem_testcases', ['probId' => $probId]);
613+
}
614+
$thumb = $content;
615+
$imageType = 'svg';
616+
} else {
617+
$imageType = Utils::getImageType($content, $error);
618+
if ($imageType === false) {
619+
$this->addFlash('danger', sprintf('image: %s', $error));
620+
return $this->redirectToRoute('jury_problem_testcases', ['probId' => $probId]);
621+
}
622+
$thumb = Utils::getImageThumb($content, $thumbnailSize,
623+
$this->dj->getDomjudgeTmpDir(), $error);
624+
if ($thumb === false) {
625+
$this->addFlash('danger', sprintf('image: %s', $error));
626+
return $this->redirectToRoute('jury_problem_testcases', ['probId' => $probId]);
627+
}
618628
}
619629

620630
$testcase->setImageType($imageType);

webapp/src/Service/DOMJudgeService.php

+6
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,12 @@ class DOMJudgeService
8585
'image/svg+xml' => 'svg',
8686
];
8787

88+
final public const EXTENSION_TO_MIMETYPE = [
89+
'png' => 'image/png',
90+
'jpg' => 'image/jpeg',
91+
'svg' => 'image/svg+xml',
92+
];
93+
8894
public function __construct(
8995
protected readonly EntityManagerInterface $em,
9096
protected readonly LoggerInterface $logger,

webapp/src/Service/ImportProblemService.php

+9
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,15 @@ public function importZippedProblem(
427427
break;
428428
}
429429
}
430+
// Handle SVG differently, as a lot of the above concepts do not make sense in this context.
431+
$imageFileName = $baseFileName . '.svg';
432+
if (($imageFile = $zip->getFromName($imageFileName)) !== false) {
433+
if (($imageFile = Utils::sanitizeSvg($imageFile)) === false) {
434+
$messages['warning'][] = sprintf("Contents of '%s' is not safe.", $imageFileName);
435+
}
436+
$imageType = 'svg';
437+
$imageThumb = $imageFile;
438+
}
430439

431440
if (str_contains($testInput, "\r")) {
432441
$messages['warning'][] = "Testcase file '$baseFileName.in' contains Windows newlines.";

webapp/src/Twig/TwigExtension.php

+6
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ public function getFilters(): array
117117
new TwigFilter('entityIdBadge', $this->entityIdBadge(...), ['is_safe' => ['html']]),
118118
new TwigFilter('medalType', $this->awards->medalType(...)),
119119
new TwigFilter('numTableActions', $this->numTableActions(...)),
120+
new TwigFilter('extensionToMime', $this->extensionToMime(...)),
120121
];
121122
}
122123

@@ -1346,4 +1347,9 @@ protected function numTableActions(array $tableData): int
13461347
}
13471348
return $maxNumActions;
13481349
}
1350+
1351+
public function extensionToMime(string $extension): string
1352+
{
1353+
return DOMJudgeService::EXTENSION_TO_MIMETYPE[$extension];
1354+
}
13491355
}

webapp/templates/jury/submission.html.twig

+1-1
Original file line numberDiff line numberDiff line change
@@ -742,7 +742,7 @@
742742
<span style="float:right; border: 3px solid #438ec3; margin: 5px; padding: 5px;">
743743
{% set imgUrl = path('jury_problem_testcase_fetch', {'probId': submission.problem.probid, 'rank': run.rank, 'type': 'image'}) %}
744744
<a href="{{ imgUrl }}">
745-
<img src="data:image/{{ run.imageType }};base64,{{ runsOutput[runIdx].image_thumb | base64 }}"/>
745+
<img src="data:{{ run.imageType | extensionToMime }};base64,{{ runsOutput[runIdx].image_thumb | base64 }}"/>
746746
</a>
747747
</span>
748748
{% endif %}

0 commit comments

Comments
 (0)