summaryrefslogtreecommitdiffstats
path: root/krebs/5pkgs/simple/htgen-cyberlocker/src/htgen-cyberlocker
blob: d04b4b1f038247c9e21c20ccd00660693073f03c (plain)
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
emptyok_response() {(
  printf "HTTP/1.1 204 OK\r\n"
  printf 'Connection: close\r\n'
  printf 'Server: %s\r\n' "$Server"
  printf '\r\n'
)}

not_modifed_response() {(
  printf "HTTP/1.1 304 Not Modified\r\n"
  printf 'Connection: close\r\n'
  printf 'Server: %s\r\n' "$Server"
  printf '\r\n'
)}

delete_response() {
  jq -n -r \
  --arg server "$Server" \
  '
    [ "HTTP/1.1 204 OK\r"
    , "Connection: close\r"
    , "Server: \($server)\r"
    , "\r"
    ][]
  '
}

file_response() {(
  type=$(file -ib "$1")
  size=$(wc -c < "$1")
  jq -n -r \
  --arg type "$type" \
  --arg size "$size" \
  --arg server "$Server" \
  '
    [ "HTTP/1.1 200 OK\r"
    , "Connection: close\r"
    , "Content-Length: \($size)\r"
    , "Content-Type: \($type)\r"
    , "Server: \($server)\r"
    , "\r"
    ][]
  '
  cat "$1"
)}

read_uri() {
  jq -cn --arg uri "$1" '
    $uri |
    capture("^((?<scheme>[^:]*):)?(//(?<authority>[^/]*))?(?<path>[^?#]*)([?](?<query>[^#]*))?([#](?<fragment>.*))?$") |
    . + {
      query: (.query | if . != null then
        split("&") |
        map(split("=") | {key:.[0],value:.[1]}) |
        from_entries
      else . end)
    }
  '
}

uri=$(read_uri "$Request_URI")
path=$(jq -nr --argjson uri "$uri" '
  $uri.path |
  gsub("/+"; "/")
')

case "$Method $path" in
  'POST /'*|'PUT /'*)
    content=$(mktemp -t htgen.$$.content.XXXXXXXX)
    trap "rm $content >&2" EXIT

    head -c $req_content_length > $content

    item=$STATEDIR/items/$(echo "$path" | jq -rR @uri)

    mkdir -v -p $STATEDIR/items >&2
    cp -v $content $item >&2

    emptyok_response
    exit
  ;;
  'GET /'*)
    item=$STATEDIR/items/$(echo "$path" | jq -rR @uri)
    if [ -e "$item" ]; then
      if [ -z ${req_if_modified_since+x} ]; then
        file_response "$item"
        exit
      else
        age_file=$(date +%s -r "$item")
        age_header=$(date +%s --date="$req_if_modified_since")
        if [ "$age_file" -lt "$age_header" ]; then
          not_modifed_response
          exit
        else
          file_response "$item"
          exit
        fi
      fi
    fi
  ;;
  'DELETE /'*)
    item=$STATEDIR/items/$(echo "$path" | jq -rR @uri)
    if [ -e "$item" ]; then
      rm "$item"
      delete_response
      exit
    fi
esac