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
125
126
127
128
129
130
131
132
|
<?php
use GeminiFoundation\Client;
use GeminiFoundation\Gemtext;
require __DIR__ . '/vendor/autoload.php';
$geminiHost = $_ENV['GEMINI_HOST'];
$url = parse_url(
"//$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]"
);
$url['query'] ??= '';
$client = new Client($geminiHost);
$response = $client->request("$url[path]$url[query]");
$title = '';
if ($response->getStatusCode()->value == 20) {
ob_start();
$mime = explode(';', $response->getMeta())[0];
if (strpos($mime, 'text/gemini') === 0) {
$parser = new Gemtext($response->getBody());
$lines = $parser->parse();
$wasListItem = false;
$currentListItems = [];
foreach ($lines as $line) {
if ($wasListItem && $line['type'] !== 'listitem') {
echo "<ul>";
foreach ($currentListItems as $listItem) {
echo "<li>$listItem[text]</li>";
}
echo "</ul>";
$wasListItem = false;
$currentListItems = [];
}
if ($line['type'] === 'preformatted_on') {
echo "<div>$line[alt]</div><pre>";
}
else if ($line['type'] === 'preformatted') {
echo htmlentities($line['raw']);
}
else if ($line['type'] === 'preformatted_off') {
echo "</pre>";
}
else if ($line['type'] === 'heading') {
if (empty($title)) {
$title = $line['text'];
}
echo "<h$line[size]>$line[text]</h$line[size]>";
}
else if ($line['type'] === 'listitem') {
$currentListItems[] = $line;
$wasListItem = true;
}
else if ($line['type'] === 'quote') {
echo "<blockquote>$line[text]</blockquote>";
}
else if ($line['type'] === 'link') {
$line['link'] = str_replace(["gemini://$geminiHost", $geminiHost], "https://$geminiHost", $line['link']);
$line['text'] = $line['text'] ?: $line['link'];
echo "<a href=\"$line[link]\" style=\"display: block;\">$line[text]</a>";
}
else if ($line['type'] === 'text') {
if (! empty($line['text'])) {
echo "<p>$line[text]</p>";
}
}
}
}
else if (strpos($mime, 'text') === 0) {
echo $response->getBody();
}
else if (strpos($mime, 'image') === 0) {
$src = "data:{$mime};base64," . base64_encode($response->getBody());
?>
<img src="<?php echo $src; ?>">
<?php
}
else if (strpos($mime, 'video') === 0) {
$src = "data:{$mime};base64," . base64_encode($response->getBody());
?>
<video controls>
<source src="<?php echo $src; ?>" type="<?php echo $mime; ?>">
</video>
<?php
}
else if (strpos($mime, 'audio') === 0) {
$src = "data:{$mime};base64," . base64_encode($response->getBody());
?>
<audio controls>
<source src="<?php echo $src; ?>" type="<?php echo $mime; ?>">
</audio>
<?php
}
else {
echo "Unhandled MIME type: $mime";
}
} else {
$title = $response->getHeader();
echo $response->getHeader();
}
echo "<hr>";
echo "Original document at <a href=\"gemini://$geminiHost$url[path]$url[query]\">gemini://$geminiHost$url[path]$url[query]</a>";
$content = ob_get_clean();
?>
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title><?php echo $title; ?></title>
<meta name="color-scheme" content="light dark">
<?php if (! empty($_ENV['CSS'])): ?>
<style><?php echo $_ENV['CSS']; ?></style>
<?php endif; ?>
</head>
<body>
<?php echo $content; ?>
</body>
</html>
|