Cover V05, I10
Article
Listing 1

oct96.tar


Listing 1: lnews.sh

#!/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/\å/g
s/%C5/\Å/g
s/%E4/\ä/g
s/%C4/\Ä/g
s/%F6/\ö/g
s/%D6/\Ö/g
s/%E9/\é/g
s/%C9/\É/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/\ $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    ",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
#******************************************************