#!/bin/sh
-# Copyright 2016 - 2019 Paul Hänsch
-#
-# This file is part of cgilite.
+# Copyright 2016 - 2023 Paul Hänsch
#
-# cgilite is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
#
-# cgilite is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with cgilite. If not, see <http://www.gnu.org/licenses/>.
+# THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+# IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
[ -n "$include_fileserve" ] && return 0
include_fileserve="$0"
file_type(){
case ${1##*.} in
- html|html) printf 'text/html';;
css) printf 'text/css';;
- js) printf 'text/javascript';;
- txt) printf 'text/plain';;
- sh) printf 'text/shellscript';;
+ gif) printf 'image/gif';;
+ html|html) printf 'text/html';;
jpg|jpeg) printf 'image/jpeg';;
+ js) printf 'text/javascript';;
+ m3u8) printf 'application/x-mpegURL';;
+ m4a) printf 'audio/mp4';;
+ m4s) printf 'video/iso.segment';;
+ m4v|mp4) printf 'video/mp4';;
+ mpd) printf 'application/dash+xml';;
+ ogg) printf 'audio/ogg';;
+ pdf) printf 'application/pdf';;
png) printf 'image/png';;
+ sh) printf 'text/x-shellscript';;
svg) printf 'image/svg+xml';;
- gif) printf 'image/gif';;
+ tex) printf 'text/x-tex';;
+ txt) printf 'text/plain';;
+ short) printf 'text/prs.shorthand';;
+ ts) printf 'video/MP2T';;
webm) printf 'video/webm';;
- mp4) printf 'video/mp4';;
- ogg) printf 'audio/ogg';;
xml) printf 'application/xml';;
*) printf 'application/octet-stream';;
esac
}
FILE(){
- local file file_size file_date http_date cachedate range mime
- file="$1" mime="$2"
+ local file="$1" mime="$2"
+ local file_size file_date http_date cachedate range
if ! [ -f "$file" ]; then
printf 'Content-Length: 0\r\nStatus: 404 Not Found\r\n\r\n'
- exit 0
+ return 0
elif ! [ -r "$file" ]; then
printf 'Content-Length: 0\r\nStatus: 403 Forbidden\r\n\r\n'
- exit 0
+ return 0
fi
- file_size="$(stat -Lc %s "$file")"
- file_date="$(stat -Lc %Y "$file")"
- http_date="$(date -uRd @$file_date)"
- http_date="${http_date%+0000}GMT"
+ read file_size file_date <<-EOF
+ $(stat -Lc "%s %Y" "$file")
+ EOF
+ http_date="$(date -ud "@$file_date" +"%a, %d %b %Y %T GMT")"
+
+ [ ! "$HTTP_IF_MODIFIED_SINCE" -a "$cgilite_headers" ] \
+ && HTTP_IF_MODIFIED_SINCE="$(HEADER If-Modified-Since)"
+ [ ! "$HTTP_RANGE" -a "$cgilite_headers" ] \
+ && HTTP_RANGE="$(HEADER Range)"
+
cachedate="$(
# Parse the allowable date formats from Section 3.3.1 of
# https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html
- HEADER If-Modified-Since \
+ # HEADER If-Modified-Since \
+ printf %s "$HTTP_IF_MODIFIED_SINCE" \
| sed -E 's;^[^ ]+, ([0-9]{2}) (...) ([0-9]{4}) (..:..:..) GMT$;\3-\2-\1 \4;;
s;^[^ ]+, ([0-9]{2})-(...)-([789][0-9]) (..:..:..) GMT$;19\3-\2-\1 \4;;
s;^[^ ]+, ([0-9]{2})-(...)-([0-6][0-9]) (..:..:..) GMT$;20\3-\2-\1 \4;;
| xargs -r0 date +%s -ud 2>&-
)"
- range="$(HEADER Range |sed -nE 's;^bytes=([0-9]+-[0-9]*|-[0-9]+)$;\1;p;q;')"
+ range="${HTTP_RANGE#bytes=}"
case "$range" in
- *-) range="${range}$((file_size - 1))";;
- -*) [ ${range#-} -le $file_size ] \
- && range="$((file_size - ${range#-}))-$((file_size - 1))" \
- || range="0-$((file_size - 1))";;
- *-*) [ ${range#*-} -ge $file_size ] \
- && range="${range%-*}-$((file_size - 1))";;
+ *[^0-9]*-*|*-*[^0-9]*)
+ range=""
+ ;;
+ *-)
+ range="${range}$((file_size - 1))"
+ ;;
+ -*)
+ [ ${range#-} -le $file_size ] \
+ && range="$((file_size - ${range#-}))-$((file_size - 1))" \
+ || range="0-$((file_size - 1))"
+ ;;
+ *-*)
+ [ ${range#*-} -ge $file_size ] \
+ && range="${range%-*}-$((file_size - 1))"
+ ;;
+ *) range=""
+ ;;
esac
if [ "$file_date" -lt "$cachedate" ] 2>&-; then