| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273 |
- <?php
- /**
- * Sends the flag for the logged-in student's open flags question.
- *
- * The question page shows <img src="flag.php?r=...">. Linking the file
- * directly (resources/flags/AUS.svg) would put the answer's ISO code in the
- * page for anyone who looks at the image address. This looks the flag up
- * from the question stored for the student (TkAnswerStore / tkPendingAnswer)
- * and sends it without saying which file it was.
- *
- * Only a logged-in user gets anything, and only the flag of their own open
- * question: the file name comes from the stored question, never from the URL,
- * and has to match a strict pattern and exist in resources/flags.
- *
- * SVGs are cleaned of comments and <title>/<desc>/<script> before they are
- * sent (a title can name the country), and are sent with a content security
- * policy that stops scripts if someone opens the address directly.
- */
- if (!defined('e107_INIT')) {
- require_once('../../class2.php');
- }
- if (!e107::isInstalled('timekeeper') || !USER) {
- http_response_code(403);
- exit;
- }
- $db = e107::getDb();
- $row = $db->retrieve('tkPendingAnswer', 'payload', "username = '" . $db->escape(e107::getUser()->getLoginName()) . "'");
- if (is_array($row)) {
- $row = isset($row['payload']) ? $row['payload'] : reset($row);
- }
- $payload = is_string($row) ? json_decode($row, true) : null;
- $file = (is_array($payload) && isset($payload['flag'])) ? (string) $payload['flag'] : '';
- if (!preg_match('/^[A-Za-z]{3}\.(svg|png)$/', $file)) {
- http_response_code(404);
- exit;
- }
- $path = __DIR__ . '/resources/flags/' . $file;
- if (!is_file($path)) {
- http_response_code(404);
- exit;
- }
- while (ob_get_level() > 0) {
- ob_end_clean();
- }
- header('Cache-Control: private, no-store');
- header('X-Content-Type-Options: nosniff');
- if (substr($file, -4) === '.svg') {
- $svg = (string) file_get_contents($path);
- foreach (['#<!--.*?-->#s', '#<title\b.*?</title>#is', '#<desc\b.*?</desc>#is', '#<script\b.*?</script>#is'] as $pattern) {
- $clean = preg_replace($pattern, '', $svg);
- if ($clean !== null) {
- $svg = $clean;
- }
- }
- header('Content-Type: image/svg+xml');
- header("Content-Security-Policy: default-src 'none'; style-src 'unsafe-inline'; sandbox");
- header('Content-Length: ' . strlen($svg));
- echo $svg;
- } else {
- header('Content-Type: image/png');
- header('Content-Length: ' . filesize($path));
- readfile($path);
- }
- exit;
|