#!/bin/bash

function fetch() {
    dd of=/dev/null bs=1 count=$2 2>/dev/null

    if ! [ -f "$1" -a -f "$1.ct" ]; then
        echo -e "HTTP/1.1 404 Not Found\r"
        echo -e "Content-Length: 0\r"
        echo -e "\r"
        return 0
    fi

    echo -e "HTTP/1.1 200 OK\r"
    echo -e "Content-Type: `cat $1.ct`\r"
    echo -e "Content-Length: `stat -c%s $1`\r"
    echo -e "\r"
    cat $1
}

function store() {
    if [ -z "$3" ]; then
        dd of=/dev/null bs=1 count=$2 2>/dev/null
        echo -e "HTTP/1.1 400 Bad Request\r"
        echo -e "Content-Length: 0\r"
        echo -e "\r"
    fi

    dd of=$1 bs=1 count=$2 2>/dev/null
    echo "$3" > $1.ct

    echo -e "HTTP/1.1 200 OK\r"
    echo -e "Content-Length: 0\r"
    echo -e "\r"
}

function methd() {
    dd of=/dev/null bs=1 count=$2 2>/dev/null

    echo -e "HTTP/1.1 405 Method Not Allowed\r"
    echo -e "Content-Length: 0\r"
    echo -e "\r"
}

if [ $# -ne 1 ]; then
    echo "Usage: `basename $0` STATEDIR" >&2
    exit 1
fi

shopt -s nocasematch

while true; do
    read meth path vers

    [ -z "$meth" -a -z "$path" -a -z "$vers" ] && exit 0
    [[ "$vers" =~ ^HTTP/1\.[01]$'\r'?$ ]] || exit 1

    cl=0
    while read h && [ "$h" != $'\r' ]; do
        [[ "$h" =~ ^Content-Length:[[:blank:]]*([[:digit:]]+)[[:space:]]*$ ]] \
            && cl=${BASH_REMATCH[1]}
        [[ "$h" =~ ^Content-Type:[[:blank:]]*(.+)[[:blank:]]*$ ]] \
            && ct=${BASH_REMATCH[1]}
    done

    echo "$meth $path" >&2

    read path discard < <(echo "$path" | sha224sum)
    case "$meth" in
    GET)  fetch "$1/$path" "$cl";;
    PUT)  store "$1/$path" "$cl" "$ct";;
    POST) store "$1/$path" "$cl" "$ct";;
    *)    methd "$1/$path" "$cl";;
    esac
done
