page: move getoutput() to render method
[minimedit.git] / page.php
1 <?php
2 error_reporting(E_ALL);
3 ini_set('display_errors', TRUE);
4
5 function abort($body, $status = NULL) {
6         if ($status) header("HTTP/1.1 $status");
7         print "$body\n";
8         exit;
9 }
10
11 # custom error handling
12
13 define('DOCROOT', getcwd());
14 set_include_path(implode(PATH_SEPARATOR, [ DOCROOT, __DIR__ ]));
15
16 function fail($error)
17 {
18         global $User, $Page;
19         http_response_code(500);
20         if (!isset($Page)) {
21                 require_once('article.inc.php');
22                 $Page = new ArchiveArticle(NULL);
23                 $Page->title = 'Fout';
24         }
25         include_once 'page.inc.php';
26         ob_start();
27         require '500.inc.html';
28         print $Page->render(['debug' => htmlspecialchars($error)]);
29 }
30
31 set_exception_handler('fail');
32
33 define('E_FATAL', E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR);
34
35 set_error_handler(function ($level, $error, $file, $line) {
36         if ($level & E_FATAL) {
37                 fail($error);
38                 return;
39         }
40         return FALSE;
41 });
42
43 register_shutdown_function(function () {
44         # display failure page for fatal exceptions
45         $error = error_get_last();
46         if (!($error['type'] & E_FATAL)) return;
47         fail("Fatal: $error[message] in $error[file]:$error[line]");
48 });
49
50 error_reporting(error_reporting() & ~E_FATAL);
51
52 # user login and control
53
54 include_once 'auth.inc.php'; // sets global $User
55 $Edit = isset($_GET['edit']);
56
57 # setup requested page
58
59 $request = preg_replace('/\?.*/', '', @$_SERVER['PATH_INFO'] ?: $_SERVER['REQUEST_URI']);
60 $request = urldecode(trim($request, '/')) ?: 'index';
61
62 $staticpage = "$request.html";
63 if (file_exists($staticpage)) {
64         if (is_link($staticpage)) {
65                 $target = preg_replace('/\.html$/', '', readlink($staticpage));
66                 header("HTTP/1.1 302 Shorthand");
67                 header("Location: $target");
68                 exit;
69         }
70 }
71 elseif (file_exists("$request/index.html")) {
72         $staticpage = "$request/index.html";
73 }
74
75 require_once('article.inc.php');
76 $Page = new ArchiveArticle($staticpage);
77
78 if ($Page->restricted) {
79         # access restriction
80         if (!$User->login) {
81                 http_response_code(303);
82                 $target = urlencode($Page->link);
83                 header("Location: /login?goto=$target");
84                 exit;
85         }
86 }
87
88 # prepare page contents
89
90 header(sprintf('Content-Security-Policy: %s', implode('; ', [
91         "default-src 'self' 'unsafe-inline' http://cdn.ckeditor.com", # some overrides remain
92         "img-src 'self' data: http://cdn.ckeditor.com", # inline svg (in css)
93         "base-uri 'self'", # only local pages
94         "frame-ancestors 'none'", # prevent malicious embedding
95 ])));
96
97 ob_start(); # page body
98 $Place = [
99         'user'  => $User->login ?: '',
100         'url'   => htmlspecialchars($_SERVER['REQUEST_URI']),
101 ];
102
103 if (!isset($Page->raw) and $User->admin("edit {$Page->link}")) {
104         # open bottom template as initial contents
105         $template = 'template.inc.html';
106         if ($Page->handler and file_exists("{$Page->handler}/$template")) {
107                 $template = "{$Page->handler}/$template";
108         }
109         $Page->raw($template);
110         $Page->meta['article:published_time'] = date('Y-m-d h:i:s O');
111         $Page->meta['article:author'] = '/' . $User->dir;
112 }
113
114 if (isset($Page->raw)) {
115         if ($User->admin("edit {$Page->link}")) {
116                 # restore meta tags in static contents for editing
117                 foreach (array_reverse($Page->meta) as $metaprop => $val) {
118                         $Page->raw = sprintf(
119                                 '<meta property="%s" content="%s">'."\n",
120                                 $metaprop, $val
121                         ) . $Page->raw;
122                 }
123         }
124         $Page->raw = '<div class="static">'."\n\n".$Page->raw."</div>\n\n";
125 }
126
127 # output dynamic and/or static html
128
129 if (!$Page->handler or require("./{$Page->handler}/index.php")) {
130         # static contents
131         if (isset($Page->raw)) {
132                 print $Page->raw;
133         }
134         else {
135                 # no resulting output
136                 http_response_code(404);
137                 @require '404.inc.html';
138         }
139 }
140
141 include_once 'page.inc.php';
142