#!/bin/sh
#####################################################################
# tirph - Generate TIR gophermap from file system on SDF
#
# Copyright 2010 David Meyer. All rights reserved.  +JMJ
#
# 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 THE AUTHOR ``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 THE 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.
#
#####################################################################

# Identification ####################################################

PROGRAM='tirph'
VERSION=1.0
COPYRIGHT='Copyright 2010 David Meyer'
DESCRIPTION='Generate TIR gophermap from file system on SDF'
USAGE="Usage: $PROGRAM [-CPVh] [-n NUM] [-o OUTFILE] [-p PHLOGDIR] [DIR]"
CONTACT='David Meyer <[email protected]>'

# Initialize environment ############################################

IFS="
"
PATH=/bin:/usr/bin:/usr/pkg/bin

SERVER=sdf.org
PORT=70
NEXUSSEL=/users/$USER
NEXUSPATH=/ftp/pub/users/$USER

FORTUNE=/usr/games/fortune

# Arguments #########################################################

while getopts CPn:o:p:Vh option; do
   case $option in
       C ) NOCONTENTS=1 ;;
       P ) NOPHLOG=1 ;;
       n ) NUM=$OPTARG ;;
       o ) OUTFN=$OPTARG ;;
       p ) PHLOGDIR=$OPTARG ;;
       V ) echo "$PROGRAM $VERSION"
           echo $COPYRIGHT
           exit 0
           ;;
       h ) cat << ENDHELP
$USAGE

$DESCRIPTION.

DIR ...

Options are as follows:
-p PHLOGDIR
-n NUM
-o OUTFN
-C      Suppress output of directory contents section.
-P      Suppress output of phlog section.
-V      Display version number
-h      Display this help message

Files:
DIR/.title
DIR/.descripton
DIR/.gophhead
DIR/.gophfoot
DIR/.exits

Report bugs to $CONTACT.
ENDHELP
               exit 0
               ;;
       * )     echo $USAGE >&2
               exit 1
               ;;
       esac
done

shift $(( $OPTIND-1 ))

DIR=${1:-""}
: ${NUM:=10}
: ${OUTFN:=gophermap}
: ${PHLOGDIR:=""}

# Functions #########################################################

# ftitle() - Return title for file or subdirectory
ftitle() {
   bn=$(basename $1)
   if [ -d $1 ]; then
       if [ -f $1/.title ]; then
           ftitle=$(cat $1/.title)
       else
           ftitle=$bn
       fi
   else
       fn=${bn%.*}
       fext=${bn##*.}
       case $fext in
           txt | org | blink )
               ftitle=$(head -n 1 $1)
               ;;
           html | htm | shtml )
               ftitle=$(grep -i "\<h1\>" $1 | head -n 1 | sed -e "s;</*[hH]1>;;g")
               : ${ftitle:=$fn}
               ;;
           * )
               ftitle=$bn
               ;;
       esac
   fi
   echo $ftitle
}

# gtype() - Return Gopher item type
gtype() {
   if [ -d $1 ]; then
       gtype=1
   else
       fext=${1##*.}
       case $fext in
           txt | org )           gtype=0 ;;
           html | htm | shtml | blink )  gtype=h ;;
           jpg | jpeg | png )    gtype=I ;;
           gif )                 gtype=g ;;
           * )                   gtype=0 ;;
       esac
   fi
   echo $gtype
}

# blink_map() - Output gopher menu entry for blink file
blink_map() {
   bfile=$1
   btpre=${2:-""}
   btpost=${3:-""}
   btitle=""
   buri=""
   cat $bfile | while read bline; do
       if [ -z "$btitle" ]; then
           btitle=$bline
           if [ "$btpre" ]; then btitle="$btpre $btitle"; fi
           if [ "$btpost" ]; then btitle="$btitle $btpost"; fi
       elif [ -z "$buri" ]; then
           buri=$bline
           echo "h$btitle      URL:$buri" >>$OUTFILE
       else
           if [ "$buri" -a "$bline" ]; then
               echo $bline >>$OUTFILE
           fi
       fi
   done
}

# Main driver #######################################################

if [ "$DIR" ]; then
   DIRPATH=$NEXUSPATH/$DIR
   DIRSEL=$NEXUSSEL/$DIR
else
   DIRPATH=$NEXUSPATH
   DIRSEL=$NEXUSSEL
fi

OUTFILE=$DIRPATH/$OUTFN

# Backup output file ...
if [ -f $OUTFILE ]; then
   mv $OUTFILE $OUTFILE~
   touch $OUTFILE
   chmod 750 $OUTFILE
fi

# Directory title ...
if [ -f $DIRPATH/.title ]; then
   cat $DIRPATH/.title >>$OUTFILE
   echo "" >>$OUTFILE
fi

# Directory description ...
if [ -f $DIRPATH/.description ]; then
   cat $DIRPATH/.description >>$OUTFILE
   echo "" >>$OUTFILE
fi

# Link to nexus directory (top)  ...
if [ "$DIR" ]; then
   echo "1(to nexus)   $NEXUSSEL       $SERVER $PORT" >>$OUTFILE
   echo "" >>$OUTFILE
fi

# Gopher-specific header ...
if [ -f $DIRPATH/.gophhead ]; then
   cat $DIRPATH/.gophhead >>$OUTFILE
fi

# Phlog  ...
if [ -z "$NOPHLOG" ]; then
   if [ "$PHLOGDIR" ]; then
       PHLOGPATH=$NEXUSPATH/$PHLOGDIR
       PHLOGSEL=$NEXUSSEL/$PHLOGDIR
   else
       PHLOGPATH=$NEXUSPATH
       PHLOGSEL=$NEXUSSEL
   fi

   ls -lt $(find $PHLOGPATH -type f -name "[^\.]*") | grep -Ev "~$|#.*#$|gophermap$" | head -n $NUM | while read perm lc own gr sz t1 t2 t3 fn; do
       if [ -z "$phloginit" ]; then
           echo "" >>$OUTFILE
           echo "RECENT ACTIVITY:" >>$OUTFILE
           phloginit=1
       fi
       ft=$(ftitle $fn)
       loc=$(basename $(dirname $fn))
       case $fn in
           *.blink )
               blink_map $fn "$t1 $t2 $t3" "[$loc]" >>$OUTFILE
               ;;
           * )
               echo "0$t1 $t2 $t3 $ft [$loc]   $PHLOGSEL${fn#$PHLOGPATH}"  >>$OUTFILE
               ;;
       esac
   done
fi

# Directory contents  ...
if [ -z "$NOCONTENTS" ]; then
   ls $DIRPATH | grep -Ev "~$|^#.*#$|^gophermap$" | while read fn; do
       if [ -z "$continit" ]; then
           echo "" >>$OUTFILE
           echo "YOU SEE HERE:" >>$OUTFILE
           continit=1
       fi
       case $fn in
           *.blink )
               blink_map $DIRPATH/$fn
               ;;
           * )
               type=$(gtype $DIRPATH/$fn)
               title=$(ftitle $DIRPATH/$fn)
               echo "$type$title       $DIRSEL/$fn     $SERVER $PORT" >>$OUTFILE
               ;;
       esac
   done
fi

# Exits  ...
if [ -f $DIRPATH/.exits ]; then
   cat $DIRPATH/.exits | while read exit tag; do
       if [ -z "$exitinit" ]; then
           echo "" >>$OUTFILE
           echo "OBVIOUS EXITS:" >>$OUTFILE
           exitinit=1
       fi
       if [ "$exit" -a -d $NEXUSPATH/$exit ]; then
           title=$(ftitle $NEXUSPATH/$exit)
           if [ "$tag" ]; then
               title="($tag) "$title
           fi
           echo "1$title       $NEXUSSEL/$exit $SERVER $PORT" >>$OUTFILE
       fi
   done
fi

# Gopher-specific footer ...
if [ -f $DIRPATH/.gophfoot ]; then
   echo "" >>$OUTFILE
   cat $DIRPATH/.gophfoot >>$OUTFILE
fi

# Link to nexus directory (bottom)  ...
if [ "$DIR" ]; then
   echo "" >>$OUTFILE
   echo "1(to nexus)   $NEXUSSEL       $SERVER $PORT" >>$OUTFILE
fi

# Fortune cookie  ...
if [ "$FORTUNE" ]; then
   echo "" >>$OUTFILE
   $FORTUNE >>$OUTFILE
fi

exit 0