~cadence/bliz

ref: d7a1829f359ca24577655514d03977697f6575bf bliz/src/cgi.fish -rw-r--r-- 3.1 KiB
d7a1829fCadence Ember Add directory index preference 1 year, 25 days ago
                                                                                
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
#!/usr/bin/env fish

source src/config.fish
source src/includes.fish

read req_url # gemini requests are just a url

# remove special like trailing \r
set req_url (string match -r -- '\S*' $req_url)

# parse url
set req_protocol gemini://
set req_host
set req_path
begin
    set -l req_no_protocol $req_url
    if string match -q -- '*://*' $req_url
        set req_protocol (string match -r -- '^.*://' $req_url)
        set req_no_protocol (string sub -s (math (string length -- $req_protocol) + 1) -- $req_url)
    end
    set req_host (string match -r -- '^(?:.*?://)?[^/]+' $req_no_protocol; or echo default)
    set -l prefix_length (string match -r -- '^[^/]*' $req_no_protocol | string length)
    set req_path (string sub -s (math "$prefix_length + 1") $req_no_protocol)
    string length -q -- $req_path; or set req_path /
end

# quit on non-gemini protocol
if test "$req_protocol" != gemini://
    gem_header 59 "Bliz server: Unknown protocol $req_protocol. Allowed protocols: gemini://"
    exit
end

server_echo "Incoming request for: $req_path"

# revise path to be relative to root
set file_path (echo "$serve_root$req_path")
server_echo "Rewrite to: $file_path"

# future host handling code here?
# ...

# verify that path starts with /
if not string match -q -- '/*' $req_path
    gem_header 59 "Bliz server: Request path must start with /"
    exit
end

# verify that path does not include /../ to protect from directory traversal attacks
if contains .. (string split -- / $req_path)
    gem_header 59 "Bliz server: Request path must not include /../"
    exit
end

# directory listing
if test -d "$file_path"
    # ensure directory has trailing /
    if string match -q -- '*/' $req_path
        set -l default_index true
        for index in $serve_index
            if test -f "$file_path$index"
                set default_index false
                set req_path $req_path$index
                set file_path $file_path$index
                server_echo "Used index to rewrite to: $req_path"
            end
        end
        if $default_index
            gem_header 20 text/gemini
            echo "# Directory listing for $req_path"
            echo
            pushd $file_path
            if test $req_path != /
                echo '=> ..'
            end
            for file in (ls -pB)
                # ignore dotfiles, tildefiles, etc
                if string match -q -- '.*' $file; or string match -q -- '*~' $file
                    continue
                end
                echo "=> $file"
            end
            popd
            exit
        end
    else
        # add trailing / to directory
        gem_header 31 $req_path/
        exit
    end
end

# route request to file
if test -f "$file_path"
    if string match -q -- '*.bliz' $file_path
        # process bliz script
        fish src/process-bliz.fish $file_path
        exit
    end
    set -l mime
    if string match -q -- '*.gmi' $file_path
        set mime text/gemini
    else
        set mime (file -i $file_path)
    end
    gem_header 20 $mime
    cat $file_path
    exit
end

# not found
gem_header 50 "Bliz server: Not found: $req_path"
exit