#!/bin/sh

PATH=/usr/local/WebPortal:"$PATH"

# --- Helpers: ---

_htmlspecialchars() {
    echo -n "$1" | sed -r -e 's@&@\&amp;@g' -e 's@[""]@\&quot;@g' -e 's@<@\&lt;@g' -e 's@>@\&gt;@g' -e 's@ @\&nbsp;@g'
}

_urlencode() {
    echo -n "$1" | hexdump -v -e '/1 "%02x"' | sed -r -e 's@..@%&@g'
}

_parse() {
    local value
    value='&'"$2"'&'
    value="${value##*&$1=}"
    value="${value%%&*}"
    [ "$value" != "" ] && httpd -d "$value"
}

_get() {
    _parse "$1" "$QUERY_STRING"
}

_post() {
    _parse "$1" "$POST_STRING"
}

_header() {
    echo -n -e 'HTTP/1.0 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n'
    cat << 'EOF'
<html>
<head>
  <style type="text/css">
table {
    width: 100%;
    background-color: #fff5ee;
    border-width: 1px;
    border-spacing: 2px;
    border-style: solid;
    border-color: black;
    border-collapse: collapse;
}
th {
    border-width: 1px;
    padding: 1px;
    border-style: solid;
    border-color: black;
}
td {
    border-width: 0px 1px 0px 1px;
    padding: 1px;
    border-style: solid;
    border-color: black;
    white-space: nowrap;
}
tr.hdr {
    background-color: #eee5de;
}
tr.o {
    background-color: #ffffff;
}
tr.e {
    background-color: #eeeeee;
}
tr.foot {
    background-color: #eee5de;
}
th.cnt {
    text-align: left;
}
th.sz {
    text-align: right;
}
th.dt {
    text-align: right;
}
td.sz {
    text-align: right;
}
td.dt {
    text-align: right;
}
col.nm {
    width: 98%;
}
col.sz {
    width: 1%;
}
col.dt {
    width: 1%;
}
a.d {
   padding-left: 20px;
   background: url(data:image/gif;base64,R0lGODlhEgARAPUAAAAAAAcHBw8PDxcXFx8fHycnJy8vLzc3Nz8/P0dHR09PT1dXV19fX2dnZ29vb3d3d39/f4eHh4+Pj5eXl5+fn6enp6+vr7e3t7+/v8fHx8/Pz9fX19/f3+fn5+/v7/f39wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAACAALAAAAAASABEAAAanQNBgKBgOQMikEpQ4GJ6Hg2K5RBCNBAQ1eSAUBQGBuEAoFJ4JpEEcACQ+8LjcAPK2ARiPp8PvcP4eXhUTFIR/GxsaiRoZil5+GxyJjRkZGJYZFxkDARqXGBgXoRcWFhQUEoScoaWlgxISEbGxEwIApoUSELu8vRG2ExEPEMPFxMcPEW0OzM3Ozw4AAA0ODdbV2NbU1tIM3t/g4QsCQkZY5wQDBVvsSkEAOw==) transparent no-repeat center left;
}
a.f {
    padding-left: 20px;
    background: url(data:image/gif;base64,R0lGODlhDgASAOMJAPf39wAAAO/v7+fn57+/vw8PDy8vL19fX8/Pz////////////////////////////yH5BAEKAA8ALAAAAAAOABIAAAQ98MlJa7gY0yCA/8Q1cR9YGIFElgBRHOizlkN2dWyJ3Hkp8D1Pbdb7EXNDXNCo7CWDHiYU8IT+ZLZsZUuJAAA7) transparent no-repeat center left;
}
a.b {
    padding-left: 20px;
    background: url(data:image/gif;base64,R0lGODlhEgASAIQQAAcKBR8gHiYoJi4wLTo7OUlLSFhaV2xua3d5doeJhpKUkaWnpL7AvdDSzt/h3u3v7P///////////////////////////////////////////////////////////////yH5BAEKABAALAAAAAASABIAAAWeYCEWBmOeynEsyziWzdkgotIWBE6eJ5Ini5yOAGPEGAccEEdo5nimQxPoHDQLRpl0QB14vQQo0otYfL2CwQGxXhsMhYPBGxDY63e7AL/P1/99gH8BdQ4Ph4iJDweEhASHhpEPkgmEAAEDkw6bDZsOnQ8JlwEAmYqnCKQAlw8Nrq+wDgirqwGfsLgOB7SrDgsMv8HARrsAxgC/YjwFxiEAOw==) transparent no-repeat center left;
}
a.x {
    padding-left: 20px;
    background: url(data:image/gif;base64,R0lGODlhEgASAOMIAAoQEiUqLjk8PCxVilZYV3yAga6wrMPGwf///////////////////////////////yH5BAEKAAgALAAAAAASABIAAAR8EEkAJKIh2C2L0VNAFJwVeMQmkqYgEYZRSYEwWsThCkaKCzaXxHAoHAwsRK4AJMwCh+gxJYgSAgAbiCAQHasHH6A22wAGRB+tbDkPCgR1aTKoDwK9Od3+PibNfBoARnmAfCZESG18A2x4U3t1bBJVSEJukzhwQheZGzYSEQA7) transparent no-repeat center left;
}
a.epub {
    padding-left: 20px;
    background: url(data:image/gif;base64,R0lGODlhEgASAIABAIW5Fv///yH5BAEKAAEALAAAAAASABIAAAItjI+pCA2rnINHSnpDTlu3OFUfFxql5o2mmnbs1TFl3JLvKY50blHrDmL5PJACADs=) transparent no-repeat center left;
}
a.pdf {
    padding-left: 20px;
    background: url(data:image/gif;base64,R0lGODlhEgASAMIGAMINDeIXGMhIR85ycNihnt/d2P///////yH5BAEKAAcALAAAAAASABIAAANgeLG8UhASoBojhYw4gQ0ANoTR6DVbIQBApLLMA62sSwtpxu52LdG7VoSmAQZls6ByhyyYTEtAswMZLU6BZoE1wEwsWlh21tCuGCRBzKVrpB3srYXk0ao+rYmdUCk7tXwJADs=) transparent no-repeat center left;
}
  </style>
</head>
<body>
<h1>File Manager</h1>
EOF
}

_footer() {
    echo '<hr>'

    urltarget=$(_urlencode "$TARGET")

    # extra links
    while [ ${#@} -ge 2 ]
    do
        query="$1"
        text="$2"
        echo "<a href=\"?${urltarget}&${query}\">$text</a> | "
        shift 2 # busybox
    done

    echo '<a href="?">Back to File Manager</a>'
    echo '</body></html>'
    exit
}

_die() {
    echo "<p> $1 </p>"
    _footer
    exit
}

_yesno() {
    echo "<p> $1 </p>"
    _footer "$2" Yes "$3" No
    exit
}

# --- Views: ---

_view() {
    case $(_get action) in
        "")
            cd "$TARGET" && _view_index || _view_download
            ;;
        "tar")
            cd "$TARGET" && _view_tar || _die "Can not tar invalid target."
            ;;
        "upload")
            cd "$TARGET" && _view_upload || _die "Can not upload invalid target."
            ;;
    esac

    _header
    _die 'Invalid View'
}

_view_index() {
    _header

    htmltarget=$(_htmlspecialchars "$TARGET")

    echo "<h2>Index of ${htmltarget}</h2>"

    echo '<table>'
    echo '<col class="nm" /><col class="sz" /><col class="dt" />'
    echo '<tr class="hdr"><th class="cnt">Name</th><th class="sz">Size</th><th class="dt">Last modified</th></tr>'

    odd="o"
    even="e"
    oddeven="o"

    for item in .* *
    do
        realitem=$(realpath "$item") || continue
        urlitem=$(_urlencode "$realitem")
        htmlitem=$(_htmlspecialchars "$item")

        set -- $(stat -c "%A %s %y %F" "$item")
        pm=$1
        sz=$2
        dt="$3 $4"
        tp="$5$6$7"

        if [ "$tp" == "directory" ]
        then
            nm="<a class=\"d\" href=\"?${urlitem}\">${htmlitem}</a>"
        elif [ "$tp" == "regularfile" -o "$tp" == "regularemptyfile" ]
        then
            nm="<a class=\"f ${htmlitem##*.}\" href=\"?${urlitem}\">${htmlitem}</a>"
        elif [ "$tp" == "symboliclink" ]
        then
            link=$(readlink "$item")
            htmllink=$(_htmlspecialchars "$link")
            if [ -d "$link"/ ]
            then
                nm="&rarr; ${htmlitem} &rarr; <a href=\"?${urlitem}\">${htmllink}</a>"
            else
                nm="&rArr; ${htmlitem} &rArr; ${htmllink}"
            fi
        elif [ "$tp" == "blockspecialfile" ]
        then
            nm="<a class=\"b\" href=\"?${urlitem}\">${htmlitem}</a>"
        else
            nm="<a class=\"x\">${htmlitem}</a>"
        fi

        echo "<tr class=\"${odd}\"><td class=\"nm\">${nm}</td><td class=\"sz\">${sz}</td><td class=\"dt\">${dt:0:19}</td></tr>"

        oddeven=$odd
        odd=$even
        even=$oddeven
    done

    echo '</table>'

    _footer "action=upload" "&#8593; Upload" "action=tar" "&#8595; Download"
}

_view_download() {
    if [ ! -e "$TARGET" ]
    then
        _header
        _die "Not found: $TARGET"
    fi

    item=$(basename "$TARGET")
    urlitem=$(_urlencode "$item")

    echo -n -e 'HTTP/1.0 200 OK\r\n'
    echo -n -e 'Content-Type: application/octet-stream\r\n'
    echo -n -e "Content-Disposition: attachment; filename*=UTF-8''${urlitem}\r\n\r\n"
    sync
    cat "$TARGET"
    exit
}

_view_tar() {
    if [ ! -d "$TARGET"/ ]
    then
        _header
        _die "Not a directory: $TARGET"
    fi

    tarname=$(_urlencode FileManager-"$TARGET".tgz)

    echo -n -e 'HTTP/1.0 200 OK\r\n'
    echo -n -e 'Content-Type: application/octet-stream\r\n'
    echo -n -e "Content-Disposition: attachment; filename*=UTF-8''${tarname}\r\n\r\n"

    # FIXME: does not include empty directories
    find "$TARGET"/ -xdev -type f -o -type l | tar cz -T -
}

_view_upload() {
    _header

    if [ "$REQUEST_METHOD" == "POST" ]
    then
        _handle_upload
    fi

    if [ ! -d "$TARGET"/ ]
    then
        _die "Not a directory: $TARGET"
    fi

    htmltarget=$(_htmlspecialchars "$TARGET")

    echo "<h2>Upload to ${htmltarget}</h2>"

    echo '<form method="post" enctype="multipart/form-data">'
    echo '<p>Automatically handle TAR/TGZ files? '
    echo '<input type="radio" id="xa" name="untar" value="/"><label for="xa">Install (KoboRoot)</label> '
    echo '<input type="radio" id="xb" name="untar" value="."><label for="xb">Unpack here</label> '
    echo '<input type="radio" id="xc" name="untar" value="0" checked><label for="xc">No (leave as-is)</label> '
    echo '</p>'

    echo '<p>File(s) to upload: <input type="file" name="upload[]" multiple="multiple"></p>'
    echo '<p><input type="submit" value="Upload"><input type="reset"></p>'
    echo '</form>'

    _footer
}

_handle_upload() {
    boundary="${CONTENT_TYPE##*boundary=}"

    if [ "$boundary" == "" ]
    then
        _die "Error in the post data."
    fi

    filename="/dev/null"
    untar=0

    multipart_pipe --"$boundary" "/tmp/filemanagerXXXXXX" | while read key value
    do
        case "$key" in
            FIELD)
                if [ "$value" == "Content-Disposition" ]
                then
                    filename="/dev/null"
                fi
                ;;
            VALUE)
                case "$value" in
                    'form-data; name="untar"')
                        untar=1
                        ;;
                    'form-data; name="upload[]"; filename=""')
                        # special case: nothing uploaded
                        echo "No filename specified.<br>"
                        ;;
                    'form-data; name="upload[]"; filename="'*)
                        filename="${value##*filename=\"}"
                        filename="${filename%%\"}"
                        filename="$(basename "$filename")"
                        filename="$TARGET"/"$filename"
                        ;;
                esac
                ;;
            DATA)
                basename=$(basename "$filename")
                if [ "$filename" == "" ]
                then
                    continue
                elif [ "$untar" == 1 ]
                then
                    untar=$(cat "$value") # /, . or 0
                elif [ "$untar" != "0" -a "${filename##*.}" == "tgz" ]
                then
                    echo "Receiving and untarring $(_htmlspecialchars "\"$basename\"")...<br>"
                    tar zx -C "$untar" < "$value" &
                elif [ "$untar" != "0" -a "${filename##*.}" == "tar" ]
                then
                    echo "Receiving and untarring $(_htmlspecialchars "\"$basename\"")...<br>"
                    tar x -C "$untar" < "$value" &
                elif [ "$filename" == "/dev/null" ]
                then
                    cat < "$value" > /dev/null &
                else
                    echo "Receiving $(_htmlspecialchars "\"$basename\"")...<br>"
                    cat < "$value" > "$filename" &
                fi

                filename=""
                ;;
        esac
    done

    sync

    htmltarget=$(_htmlspecialchars $(basename "$TARGET"))
    urltarget=$(_urlencode "$TARGET")

    _footer "?$urltarget" "Back to $htmltarget"
}

# --- Main: ---

TARGET=$(httpd -d "${QUERY_STRING%%&*}")

if [ "${TARGET::1}" != "/" ]
then
    TARGET="/mnt/onboard"
fi

_view

# --- End of file. ---
