~cadence/bliz

ref: 4537e402d71cd77817da3448e4a73b5497470fdc bliz/src/cgi.fish -rw-r--r-- 2.6 KiB
4537e402Cadence Ember First version 1 year, 21 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
#!/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

# 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

# directory listing
if test -d "$file_path"
    if string match -q -- '*/' $req_path
        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
    else
        gem_header 31 $req_path/
        exit
    end
end

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