#! /bin/sh
#
# simple web server - copyright 2005/09/09 by Brett Wynkoop - wynkoop@wynn.com
#
# serves out any type of file and generates directory indexes if desired
#
#
# 2005/12/07 - added serving out the entire directory as a gzipped tar file
# if the called path is http://some/dir/.tgz - wynkoop@wynn.com
#
#
PATH=/bin:/usr/bin:/sbin:/usr/sbin
export PATH
MYNAME=`basename $0`

export MYNAME

#
# some things we will need latter
#
STATOK="HTTP/1.0 200 OK"
STATFNF="HTTP/1.0 404 File Not Found"
CHTML="Content-Type: text/html"
CTXT="Content-Type: text/plain"
CTGZ="Content-Type: application/x-tar"
PRAND=`date  "+%S%M%d%s"`
PRAND=$PRAND$$

###############################
#
# config section
#
CONFIG=/usr/local/etc/$MYNAME.cfg

# The following can be over riden by seting them in 
# the config file.
#
# set this to yes for indexes
#
DOINDEX="yes"
RUNDIR=/usr/local/sws
DOCDIR=$RUNDIR/docs

#
# set this to yes to tar.gz entire directories
#
DOTAR="yes"

#
#  check for config file and source if present
# 
#  warning the config file should not be writable by anyone other than
#  the owner of the server of arbitrary code can be executed by the server!
#
if [ -f $CONFIG ]
then
     . $CONFIG
fi



###############################################
#
# mtime hack
#
# need this hack as Solaris has no way to get the full mtime out of the
# inode for the last-modified http header.  Since Solaris has perl
# this should work - wynkoop@wynn.com -2005-11-17
#
#MTIME=/tmp/mtime.$MYNAME.$PRAND
#PERL=`which perl`

#cat << EOF > $MTIME
#! $PERL
#
# mtime - show last modified time of file as needed for http headers

#\$fname = \$ARGV[0];
#
#open(FH,\$fname) || die("Can not open \$fname\n\r");

#(\$dev,\$ino,\$mode,\$nlink,\$uid,\$gid,\$rdev,\$size,
#       \$atime,\$mtime,\$ctime,\$blksize,\$blocks)
#           = stat(FH);

#\$time=gmtime(\$mtime);
#printf("%s GMT\n",\$time);


#EOF

#chmod 755 $MTIME

#
#
# end mtime hack
#
###########################################

###########################################
#
# change to a safe place to run 
#
cd $RUNDIR  2>/dev/null

read get docid
#
# get the name of the file we must surve figured out
#
TOSERVE=`echo $docid | cut -d " " -f1 `



#
# check to make sure we have not escaped the tree for directory indexes
#
if [ -d $DOCDIR$TOSERVE ]
then
       cd $DOCDIR$TOSERVE 
       if [ $? -ne 0 ]
       then
           cd ${DOCDIR} 2>/dev/null
       fi
       SERVDIR=`pwd`
       echo $SERVDIR | grep $DOCDIR 2>/dev/null >/dev/null
       if [ $? -ne 0 ]
       then
            TOSERVE=/file-not-allowed
       fi
       cd ${DOCDIR} 2>/dev/null
fi


echo $TOSERVE | grep "/$" 2>/dev/null >/dev/null
#
# if the requested file ended in / then append index.html to
# the request so we can show the index file instead of serving the 
# binary directory file or generate an index if $DOINDEX is yes.
#
if [ $? -eq 0 ]
then 
    CHKINDEX="${DOCDIR}${TOSERVE}index.html"
    if [ -r $CHKINDEX ]
    then 
        TOSERVE="${TOSERVE}index.html"
    else
        if [ x$DOINDEX = xyes -a -d ${DOCDIR}${TOSERVE} ]
        then
             cd ${DOCDIR}${TOSERVE} 2>/dev/null
             echo "$STATOK"
             echo "$CHTML"
             echo
             echo
             echo "<html><head><title>INDEX of ${TOSERVE}</title></head>"
             echo "<body><h1>INDEX of ${TOSERVE}</h1><hr>"
             echo "<ul>"
             echo "<li><a href=\"../\">Parent Directory</a>"
             for FILE in `ls`
             do
                  if [ -d $FILE ]
                  then
                      FILE=$FILE/
                  fi
                  echo "<li><a href=\"${TOSERVE}${FILE}\">$FILE</a>"
             done
             echo "</ul><hr><em>generated by <a href=\"/sws/COPYRIGHT\">sws</a> `date`</em></body></html>"
             exit 0
             sleep 2
        fi
      fi
fi

#
# set file for use in error message(s)
#
FILE=$TOSERVE

#
# set full path to the file we want
#
TOSERVE=$DOCDIR$TOSERVE


#
# check that the file we want is in the allowed tree!
#

REQDIR=`dirname $TOSERVE`
if [ -d $REQDIR ]
then
     cd $REQDIR 2>/dev/null
     if [ $? -ne 0 ]
     then
           $TOSERVE=${DOCDIR}/file-not-found
     fi
     CURDIR=`pwd`
     echo $CURDIR | grep $DOCDIR  2>/dev/null >/dev/null
     if  [ $? -ne 0 ]
       then
            TOSERVE=/file-not-allowed
       fi
       cd ${DOCDIR} 2>/dev/null

fi


#
#
# make sure no matter what we are back in DOCDIR
#


cd ${DOCDIR} 2>/dev/null
#
# send copyright info if asked
#
if [ x$TOSERVE = x${DOCDIR}/sws/COPYRIGHT ]
then
     cd $DOCDIR 2>/dev/null
     cat << EOF
$STATOK
$CTXT


Copyright 2005 by Brett Wynkoop - wynkoop@wynn.com

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

1. Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.

EOF

     exit 0
fi

#
# can we read the file?  Is it a regular file? 
# If so ship it out stdout and exit!
#
if [ -r $TOSERVE -a -f $TOSERVE ]
then
#     MOD=`ls -l ${TOSERVE} | tr -s " " | cut -d " " -f 6-8`
#     MOD=`$MTIME  ${TOSERVE} | sed -e "s/ /, /"`
     echo "$STATOK"
     echo "Last-Modified: ${MOD}"
#     echo
     echo
     cat $TOSERVE
     #echo
    # echo "Last-Modified: ${MOD}"
#    rm -f $MTIME
     exit 0
fi

#
# do we want to tar.gz the directory? 2005/12/07
#
if [ x$DOTAR = xyes ]
then
     TARIT=`basename ${TOSERVE}`
     if [ x${TARIT} = x.tgz ]
     then
           TARDIR=`dirname ${TOSERVE}`
           cd $TARDIR/..
           echo "$STATOK"
           echo  "$CTGZ"
           echo
           TOTAR=`basename ${TARDIR}`
           tar cpf -  ./${TOTAR} | gzip -c
           sleep 2
           exit 0
     fi
fi

      
#If we got here the file is not found, so send an error.

cat << EOF
$STATFNF
$CHTML


<html>
<head>
<title>
Error 404: File not found!
</title>
</head>
<body>
<center>
<h1>$FILE</h1>
<h1>Error 404: File not found!</h1>
<h1>File nicht gefunden!</h1>
<h1>Problema 404: El documento no se encuentra.</h1>
<hr>
</center>
 <a href=/sws/COPYRIGHT>sws</a> on `hostname` at `date`
</body>
</html>
EOF

#rm -f $MTIME

exit 0

