-
Notifications
You must be signed in to change notification settings - Fork 4
/
cacheable.php
124 lines (114 loc) · 4.76 KB
/
cacheable.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
<?php
// cacheable.php -- HotCRP cacheability helper
// HotCRP and Peteramati are Copyright (c) 2006-2024 Eddie Kohler and others
// See LICENSE for open-source distribution terms
class Cacheable_Page {
static function cacheable_headers() {
header("Cache-Control: max-age=315576000, public");
header("Expires: " . gmdate("D, d M Y H:i:s", time() + 315576000) . " GMT");
}
static function skip_content_length_header() {
// see also Downloader::skip_content_length_header
return function_exists("zlib_get_coding_type") && zlib_get_coding_type() !== false;
}
/** @param string $status
* @param string $text
* @param bool $cacheable */
static function fail($status, $text, $cacheable) {
header("HTTP/1.0 {$status}");
header("Content-Type: text/plain; charset=utf-8");
if (!self::skip_content_length_header()) {
header("Content-Length: " . (strlen($text) + 2));
}
if ($cacheable) {
self::cacheable_headers();
}
echo $text, "\r\n";
}
/** @param NavigationState $nav */
static function go_nav($nav) {
session_cache_limiter("");
// read file
$file = $_GET["file"] ?? null;
if ($file === null && $nav->path !== "" && $nav->path[0] === "/") {
$file = substr($nav->path, 1);
}
if ($file === null || $file === "") {
self::fail("400 Bad Request", "File missing", true);
return;
}
// analyze file
$prefix = "";
if (preg_match('/\A(?:images|scripts|stylesheets)(?:\/[^.\/][^\/]+)+\z/', $file)
&& ($dot = strrpos($file, ".")) !== false
&& ctype_alnum(($ext = substr($file, $dot + 1)))) {
if ($ext === "js") {
header("Content-Type: text/javascript; charset=utf-8");
if (isset($_GET["strictjs"]) && $_GET["strictjs"]) {
$prefix = "\"use strict\";\n";
}
} else if ($ext === "map" || $ext === "json") {
header("Content-Type: application/json; charset=utf-8");
} else if ($ext === "css") {
header("Content-Type: text/css; charset=utf-8");
} else if ($ext === "gif") {
header("Content-Type: image/gif");
} else if ($ext === "jpg") {
header("Content-Type: image/jpeg");
} else if ($ext === "png") {
header("Content-Type: image/png");
} else if ($ext === "svg") {
header("Content-Type: image/svg+xml");
} else if ($ext === "mp3") {
header("Content-Type: audio/mpeg");
} else if ($ext === "woff") {
header("Content-Type: application/font-woff");
} else if ($ext === "woff2") {
header("Content-Type: application/font-woff2");
} else if ($ext === "ttf") {
header("Content-Type: application/x-font-ttf");
} else if ($ext === "otf") {
header("Content-Type: font/opentype");
} else if ($ext === "eot") {
header("Content-Type: application/vnd.ms-fontobject");
} else {
self::fail("403 Forbidden", "File cannot be served", true);
return;
}
header("Access-Control-Allow-Origin: *");
} else {
self::fail("403 Forbidden", "File cannot be served", true);
return;
}
$mtime = @filemtime($file);
if ($mtime === false) {
self::fail("404 Not Found", "File not found", false);
return;
}
$last_modified = gmdate("D, d M Y H:i:s", $mtime) . " GMT";
$etag = '"' . md5("{$file} {$last_modified}") . '"';
header("Last-Modified: {$last_modified}");
header("ETag: {$etag}");
$skip_length = self::skip_content_length_header();
// check for a conditional request
$if_modified_since = $_SERVER["HTTP_IF_MODIFIED_SINCE"] ?? null;
$if_none_match = $_SERVER["HTTP_IF_NONE_MATCH"] ?? null;
if (($if_modified_since || $if_none_match)
&& (!$if_modified_since || $if_modified_since === $last_modified)
&& (!$if_none_match || $if_none_match === $etag)) {
header("HTTP/1.0 304 Not Modified");
} else if (function_exists("ob_gzhandler") && !$skip_length) {
ob_start("ob_gzhandler");
echo $prefix;
readfile($file);
ob_end_flush();
} else {
if (!$skip_length) {
header("Content-Length: " . (filesize($file) + strlen($prefix)));
}
echo $prefix;
readfile($file);
}
}
}
Cacheable_Page::go_nav(Navigation::get());