#!/bin/sh 
#******************************************************
# lnews   : a simple mail processor to make a local news
#           system for sites, not ready for or interrested
#           in running a local CNews/NNTP-server, but 
#           having a external NNTP-feed or using dnntpd 
#           locally.
#
#           lnews demands a Web-server and rights to write
#           it's files in a Web-directory. The files are
#           stored as .HTML-files, including directories.
#
#           Uses shell-functions
#
# Version : 1.0a
# Date    : 28.12.95
# Author  : Lars Magnusson (LMN)
#           TUPILAQ Arctica, Sweden
#           m8827@abc.se (address for bugreports)
#
# Changes :
# 19.03.96: v1.0a - some modifications to get runtime 
#           down. egrep instead of grep. New index page 
#           first written to a tmp-file.
# xx.xx.xx:
#******************************************************
# Basic security
#
trap 'rm $TMPDIR/*.$$; exit' 1 2 3 5 10 13
umask 022

#
# Site dependent.  
#
SITE=mysite.com
MBOX=lnews
LMAINT=listadmin@can_be.at_another.site
WEBPOS="http:/www.$SITE/webdir_for_lnews"
WEBDIR=/full_local_path_to_webdir
LOGDIR=/tmp
TMPDIR=/tmp

#
# System dependent (here Solaris)

# Queueing process
QUEUE=mailx    # using mailx or Mail

# Echo
ECHO=echo      # always using Sys5 echo
AWK=nawk

#
# Init values
#
PROC=$$
INFILE=$TMPDIR/lnewsin
OUTFILE=$TMPDIR/lnewso
SCRIPT=$TMPDIR/lnewssc
LOGFILE=$LOGDIR/lnews.log

#*********************************
# process the batch-queue#
get_posting() {

# If used as mail filter in aliases
        cat - > $INFILE.$PROC

# If used with cron, reading at fixed intervals
#       $ECHO "s 1 $INFILE.$PROC \n x \n" |\
#       $QUEUE -N -u $MBOX  > /dev/null 2>&1

# Test if any posting
        if test ! -f $INFILE.$PROC
        then
                exit
        fi
}

#*********************************
# Filter out needed info, due to 
# that the mail queuer wraps long 
# lines 
#
#
filter_post() {
        # Filter special char, nl and such to 
        # "readable chars" through a pipe
        # sed "" | awk "" | sed ""
        #

        sed '
             # split at true nl
             s/%0D%0A/\
/g
             s/&/\
/g' $INFILE.$PROC  |  $AWK '{
             # concatenate mailer induced nl
             if (index($0,"\\") != 0) {
                   oldlin=substr($0,1,length($0)-2)
                   getline newlin
                   print oldlin""newlin
                } else {
                   print $0
                }
        }' | sed '
        # map special chars
             s/\#\&//g
             s/%0D%0A/\
/g
             s/+/ /g
             s/%3E/\>/g
             s/%E5/\&aring;/g
             s/%C5/\&Aring;/g
             s/%E4/\&auml;/g
             s/%C4/\&Auml;/g
             s/%F6/\&ouml;/g
             s/%D6/\&Ouml;/g
             s/%E9/\&eacute;/g
             s/%C9/\&Eacute;/g
             s/%2C/,/g
             s/%3A/:/g
             s/%3B/;/g
             s/%3D/=/g
             s#%2F#/#g
             s/%3F/\?/g
             s/%21/\!/g
             s/%22/\"/g
             s/%23/\#/g
             s/%25/%/g
             s/%26/\&/g
             s/%27/\"/g
             s/%28/\(/g
             s/%29/\)/g
             s/%60/\`/g
             s/%7B/\{/g
             s/%7D/\}/g
             s/%5B/\[/g
             s/%5D/\]/g
             s/%7C/\|/g
             s/%3C/\</g
             s/%7E/\~/g
             s/%5E/\^/g
             s/TEXT=/TEXT=\
/' > $OUTFILE.$PROC

# Put filtered file back
#
        mv $OUTFILE.$PROC $INFILE.$PROC
}

#*********************************
# get some vars, store in shellvars 
#
get_env() {
        # Get needed variables
        
        FROM=`grep "^From: " $INFILE.$PROC | cut -c7-60`
        TITLE=`grep "^TITLE=" $INFILE.$PROC | cut -c7-60`
        POST=`grep "^MSG-ID=" $INFILE.$PROC | cut -c8-`
        START=`grep -n "^TEXT=" $INFILE.$PROC | cut -d":" -f1`
        STOP=`grep -n "^MSG-ID=" $INFILE.$PROC | cut -d":" -f1`
        GRP=`$ECHO $POST | cut -c1`
        PREV=`$ECHO $POST | cut -c2-20`

        # Build new msg-id
        
        mk_msg_id

        # OBSERVE: sed's handling of shell-var 
        # makes it necessary to generate a 
        # sed-script that cuts out mail headers 
        # in file

        START="`expr $START + 1`"
        STOP="`expr $STOP - 1`"
        $ECHO "$START,$STOP p" > $SCRIPT.$PROC

        # A kludge to fix a problem in MKS Toolkit 
        # Make a file header for $OUTFILE
        
        $ECHO "$LMAINT#$MBOX@$SITE#$FROM#$TITLE#$WEBPOS#$GRP#$MSG" > $OUTFILE.$PROC

        # get message filtered out from letter
        # with sed-script

        sed -n -f $SCRIPT.$PROC $INFILE.$PROC >> $OUTFILE.$PROC

        # which group that msg belongs to is not 
        # known until now. Define lockfile now.

        LOCK=$TMPDIR/lnews_$GRP.lck

}

#*********************************
# Make a msg-id (filename = msgid.html)
#
mk_msg_id() {
  # if a new thread, PREV is always = 0
  
  if [ "$PREV" != "0" ]
  then
        # Make subpost
        # First find last tread in level
        
        OMSG=`find $WEBDIR/$GRP \( -name "$POST.html" -o -name "$POST\_*.html" -a ! -name "$POST\_*_*.html" \) -print |\
               tail -1`
        OMSG=`basename $OMSG .html`

        # See if no reply before 
        # (first in thread)
        
        if [ "$OMSG" != "$GRP$PREV" ]
        then
             # if already replies in level count
             # up +1 and generate new msg-id
             
             MSG="`$ECHO $OMSG |\
                 $AWK 'BEGIN{ FS="_" }
                 { New=$NF+1
                   Nname=$1
                   for (i=2; i<=NF-1;i++)
                        Nname=sprintf("%s_%s",Nname,$i)
                   Nname=sprintf("%s_%s",Nname,New)
                 }
                 END { print Nname }'`"
        else
             # if no replies in level start a new
              
             MSG=$POST"_1"
        fi
 else
        # If new post, get highest msg-id and
        # add one.
        
        OMSG=`find $WEBDIR/$GRP \( -name "$GRP*.html" -a ! -name "$GRP*_*.html" -a ! -name "$GRP[A-Z,a-z]*" \) -print |\
               tail -1`
        OMSG=`basename $OMSG .html`
        GNR=`$ECHO $OMSG | cut -c2-`
        GNR=`expr $GNR + 1`
        MSG=$GRP$GNR
  fi
} 

#*********************************
# Build HTML-page from input
#
build_page() {
   $AWK 'BEGIN{ FS="#" }
        {
        # Problems reading shellvars within 
        # awk in MKS Toolkit
        # Use headers instead.

        Lmaint=$1
        To=$2
        From=$3
        Title=$4
        Webdir=$5
        Grp=$6
        Msgid=$7
        print "<HTML><HEAD><TITLE>"Title
        print "</TITLE></HEAD><BODY>"
        print "<PRE>"
        print "From: <A HREF=\"mailto:"From"\">"From"</A>" 
        print "Subject: "Title
        print "<HR>"
        while (getline) {
                print " "$0
        }
        print "<HR>"
        print "</PRE><P>"
        print "<A HREF=\""Webdir"/lnews_ix.html\"><IMG SRC=\""Webdir"/pic/lnews.jpg\" ALIGN=center BORDER=0></A>"
        print "<A HREF=\""Webdir"/lnews_"Grp".html\"><IMG SRC=\""Webdir"/pic/lgrp.jpg\" ALIGN=center BORDER=0></A>"
        print "<A HREF=\""Webdir"/new_"Grp".html\"><IMG SRC=\""Webdir"/pic/new.jpg\" ALIGN=center BORDER=0></A>"
        print "<A HREF=\""Webdir"/"Grp"/"Msgid".xhtml\"><IMG SRC=\""Webdir"/pic/followup.jpg\" ALIGN=center BORDER=0></A>"
        print "<A HREF=\"mailto:"From"\"><IMG SRC=\""Webdir"/pic/mail.jpg\" ALIGN=center BORDER=0></A>"
        print "<A HREF=\""Webdir"/lnews_"Grp".html\"><IMG SRC=\""Webdir"/pic/cancel.jpg\" ALIGN=center BORDER=0></A>"
        print "<HR>"
        print "<CENTER>Mail <A HREF=\"mailto:"Lmaint"\">Listmanager</A></CENTER>"
        print "</FORM></BODY></HTML>"
     }' $OUTFILE.$PROC > $WEBDIR/$GRP/$MSG.html
}

#*********************************
# Build answer html-page from input
#
build_apage() {
   $AWK 'BEGIN{ FS="#"}
        {
#       Problems reading shellvars within 
#       awk in MKS Toolkit
#       Use headers instead.
        Lmaint=$1
        To=$2
        From=$3
        Title=$4
        Webdir=$5
        Grp=$6
        Msgid=$7
        print "<HTML><HEAD><TITLE>"Title
        print "</TITLE></HEAD><BODY>"
        print "<FORM ENCTYPE=\"multipart/form-data\" ACTION=\"mailto:"To"\" METHOD=POST>"
        print "<PRE>"
        print "From: <A HREF=\"mailto:"From"\">"From"</A>" 
        print "Msg-id: "Msgid
        print "Subject: <INPUT NAME = \"TITLE\" size = 40 VALUE=\""Title"\">"
        print "<TEXTAREA NAME=\"TEXT\" rows=14 cols=72>"
        while (getline) {
                print ">"$0
        }
        print "</TEXTAREA></PRE>"
        print "<A HREF=\""Webdir"/lnews_ix.html\"><IMG SRC=\""Webdir"/pic/lnews.jpg\" ALIGN=center BORDER=0></A>"
        print "<A HREF=\""Webdir"/lnews_"Grp".html\"><IMG SRC=\""Webdir"/pic/lgrp.jpg\" ALIGN=center BORDER=0></A>"
        print "<A HREF=\""Webdir"/new_"Grp".html\"><IMG SRC=\""Webdir"/pic/new.jpg\" ALIGN=center BORDER=0></A>"
        print "<INPUT TYPE=\"submit\" VALUE=\"    Post    \">"
        print "<A HREF=\""Webdir"/lnews_"Grp".html\"><IMG SRC=\""Webdir"/pic/cancel.jpg\" ALIGN=center BORDER=0></A>"
        print "<HR>"
        print "<INPUT NAME=\"MSG-ID\" VALUE=\""Msgid"\" TYPE=\"HIDDEN\">"
        print "</FORM></BODY></HTML>"
     }' $OUTFILE.$PROC > $WEBDIR/$GRP/$MSG.xhtml
}


#**************************
# make threaded index side 
# for group - 4 subfunctions
#
#
#*****************************
# Make html-header for index side
#
mk_head_side() {
  TITLE=`grep TITLE $WEBDIR/lnews_$GRP.html | cut -d">" -f2 | cut -d"<" -f1`
  $ECHO "<HTML><HEAD>" > $TMPDIR/lnews_$GRP.$PROC
  $ECHO "<TITLE>$TITLE</TITLE>" >> $TMPDIR/lnews_$GRP.$PROC
  $ECHO "</HEAD><BODY><P><FONT SIZE=+1><B>$TITLE :</B></FONT>" >> $TMPDIR/lnews_$GRP.$PROC
  $ECHO "<P>" >> $TMPDIR/lnews_$GRP.$PROC
  $ECHO "<HR>" >> $TMPDIR/lnews_$GRP.$PROC
  $ECHO "<A HREF=\"$WEBPOS/lnews_ix.html\"><IMG SRC=\"$WEBPOS/pic/lnews.jpg\" ALIGN=center BORDER=0></A> " >> $TMPDIR/lnews_$GRP.$PROC
  $ECHO "<A HREF=\"$WEBPOS/new_$GRP.html\"><IMG SRC=\"$WEBPOS/pic/new.jpg\" ALIGN=center BORDER=0></A> " >> $TMPDIR/lnews_$GRP.$PROC
  $ECHO "<HR><PRE>" >> $TMPDIR/lnews_$GRP.$PROC
}

#*****************************
# Make html-footer for index side
#
mk_foot_side() {
  $ECHO "</PRE><HR>" >> $TMPDIR/lnews_$GRP.$PROC
  $ECHO "<A HREF=\"$WEBPOS/lnews_ix.html\"><IMG SRC=\"$WEBPOS/pic/lnews.jpg\" ALIGN=center BORDER=0></A> " >> $TMPDIR/lnews_$GRP.$PROC
  $ECHO "<A HREF=\"$WEBPOS/new_$GRP.html\"><IMG SRC=\"$WEBPOS/pic/new.jpg\" ALIGN=center BORDER=0></A> " >> $TMPDIR/lnews_$GRP.$PROC
  $ECHO "</BODY></HTML>" >> $TMPDIR/lnews_$GRP.$PROC
}


#*****************************
# Generate the threaded index part
# of the index side.
#
mk_the_index(){
  # Get the name of postings and sort 
  # in revers order for orignal posts
  # and natural order for sublevels.
  # Then extract needed info from postings - 
  # still a prototype (960127)
  
  find $WEBDIR/$GRP -type f -name "$GRP*.html" -print |\
  $AWK 'BEGIN{ FS="/" }{print substr($NF,2)}' |\
  sort +nr |\
  $AWK '{print "'$WEBDIR'/'$GRP'/'$GRP'"$0 }' |\
  xargs egrep "From: |Subject: " |\
  $AWK '{ while ($0 != "") {
             FS=":"
             fld=split($1,a,"/")
             grp=substr(a[fld],1,1)
             fname=substr(a[fld],2)
             split(fname,b,".")
             fname=b[1]
             split($4,a,">")
             split(a[2],b,"<")
             from=b[1]
             getline
             FS=":"
             subj=$3
             getline
             y=0
             fname2=""
             to=length(fname)
             for (x=0;x<=to;x++) {
                 if (substr(fname,x,1) == "_"){
                     y++
                     fname2=fname2"."
                 } else
                     fname2=fname2""substr(fname,x,1)
             }          
             fname2=substr(fname2,2)
             spacer=""
             for (x=1;x<=y;x++) {
                spacer=sprintf("%s&nbsp;&nbsp;&nbsp;&nbsp;",spacer)
             }
             printf "%s%s: \<A HREF=\"%s/%s%s.html\"\>\"%s\" %s\</A\>\n",spacer,fname2,grp,grp,fname,subj,from
        }
   }' >> $TMPDIR/lnews_$GRP.$PROC 
}

#*****************************
# Make a threaded html-page for group
# using previous 3 functions. 
# If two posts are processed concurrently
# one has to wait to be entered into index.

mk_side() {
  while test -f $LOCK
  do 
        sleep 10 # wait a bit
  done
  # Lock for concurrent responce
  echo "lnews.$PROC" > $LOCK
  
  # Make header
  mk_head_side

  # Make the threads
  mk_the_index

  # Make a footer
  mk_foot_side

  # Update index side
  cat $TMPDIR/lnews_$GRP.$PROC > $WEBDIR/lnews_$GRP.html


  # clean up tempfiles
  rm $LOCK #$TMPDIR/data.$PROC
}


#**************************
# Main 
#

get_posting
filter_post
get_env
build_page
build_apage
mk_side

rm $TMPDIR/*.$PROC

#
# End of script
#******************************************************

