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
#******************************************************
|