Skip to content

Commit b2ef223

Browse files
committed
Preserve information whether attachments are executable.
This is relevant for testing tools which are often uploaded as attachments for interactive problems. When we download the samples (via the web interface or API), we should mark these files as executable iff they were executable when uploading.
1 parent f30e6d3 commit b2ef223

File tree

3 files changed

+38
-1
lines changed

3 files changed

+38
-1
lines changed

webapp/src/Entity/ProblemAttachmentContent.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ class ProblemAttachmentContent
2525
#[ORM\Column(type: 'blobtext', options: ['comment' => 'Attachment content'])]
2626
private string $content;
2727

28+
#[ORM\Column(options: ['comment' => 'Whether this file gets an executable bit.', 'default' => 0])]
29+
#[Serializer\Exclude]
30+
private bool $isExecutable = false;
31+
2832
public function getAttachment(): ProblemAttachment
2933
{
3034
return $this->attachment;
@@ -48,4 +52,15 @@ public function setContent(string $content): self
4852

4953
return $this;
5054
}
55+
56+
public function setIsExecutable(bool $isExecutable): ProblemAttachmentContent
57+
{
58+
$this->isExecutable = $isExecutable;
59+
return $this;
60+
}
61+
62+
public function isExecutable(): bool
63+
{
64+
return $this->isExecutable;
65+
}
5166
}

webapp/src/Service/DOMJudgeService.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -892,6 +892,14 @@ public function getSamplesZipForContest(Contest $contest): StreamedResponse
892892
foreach ($problem->getProblem()->getAttachments() as $attachment) {
893893
$filename = sprintf('%s/attachments/%s', $problem->getShortname(), $attachment->getName());
894894
$zip->addFromString($filename, $attachment->getContent()->getContent());
895+
if ($attachment->getContent()->isExecutable()) {
896+
// 100755 = regular file, executable
897+
$zip->setExternalAttributesName(
898+
$filename,
899+
ZipArchive::OPSYS_UNIX,
900+
octdec('100755') << 16
901+
);
902+
}
895903
}
896904
}
897905

webapp/src/Service/ImportProblemService.php

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,14 @@ public function importZippedProblem(
539539
continue;
540540
}
541541

542+
// In doubt make files executable, but try to read it from the zip file.
543+
$executableBit = true;
544+
if ($zip->getExternalAttributesIndex($j, $opsys, $attr)
545+
&& $opsys==ZipArchive::OPSYS_UNIX
546+
&& (($attr >> 16) & 0100) === 0) {
547+
$executableBit = false;
548+
}
549+
542550
$name = basename($filename);
543551

544552
$fileParts = explode('.', $name);
@@ -558,6 +566,10 @@ public function importZippedProblem(
558566
$messages['info'][] = sprintf("Updated attachment '%s'", $name);
559567
$numAttachments++;
560568
}
569+
if ($executableBit !== $attachmentContent->isExecutable()) {
570+
$attachmentContent->setIsExecutable($executableBit);
571+
$messages['info'][] = sprintf("Updated executable bit of attachment '%s'", $name);
572+
}
561573
} else {
562574
$attachment = new ProblemAttachment();
563575
$attachmentContent = new ProblemAttachmentContent();
@@ -567,7 +579,9 @@ public function importZippedProblem(
567579
->setType($type)
568580
->setContent($attachmentContent);
569581

570-
$attachmentContent->setContent($content);
582+
$attachmentContent
583+
->setContent($content)
584+
->setIsExecutable($executableBit);
571585

572586
$this->em->persist($attachment);
573587

0 commit comments

Comments
 (0)