#!/bin/sh
#
# A Hypertext Archie Gateway for the CGI interface of an httpd deamon
#
# Version 1.2 	21 Jan 94
#
# This script relies on the C-archie client from Brendan Kehoe
# Once installed, please set the correct path below.
# You can obtain the latest version from a comp.sources archive, or at
# file://ftp.uu.net/networking/info-service/archie/clients
#
# QUERIES 
#
# An accompanying HTML Form sets up the query and allows all the functionality
# of c-archie to be set explicitly. 
# 
# For clients without form support the script can be called without arguments,
# resulting in an ISINDEX page. Reasonable defaults are taken
# for each option. A pointer to the script without arguments is included in
# the form header.
#
# The accompanying Form relies heavilly on Martijn Koster's ArchiePlex Form.
# Infact it will probably work with that too.
#
# HYPERTEXT RESULTS
#
# The main point of providing this script is infact to format the Archie
# results into Hypertext. This is acheived with a bit of awk script.
# Hypertext links point to the files and directories listed by archie. 
# One click and you've got what was asked for !
# Mosaic's internal icons are used for file and directory pointers, a
# textual alternative is provided for browsers without. 
#
# INSTALLATION (very easy !)
#
# 1. Install C-archie (see above for suggested sources)
# 2. Edit the line in AA describing the location of C archie
# 3. Put AA in your servers cgi-bin. 
# 4. Put AA.html in your htdocs tree, and away you go...
#
# You might like to edit some of the defaults in AA, such as the server for
# non-forms based queries. See DEFAULT_SERVER and others below.
#
# PORTING NOTES
#
# This script should work on almost all systems with a bourne shell, awk and
# c-archie. Try the gnu utilities gawk and bash on non-unix machines 
# (NB I've not tried this). 
#
# I've used it sucessfully on Sillicon Graphics machines running IRIX 4 but..
#
#Ultrix
#
# set the first line to be #!/bin/sh5 otherwise the [ dosn't function correctly.
#
#
# Acknowledgements
#
# Thanks to Martijn Koster for his ArchiePlex interface. It was the
# inspiration for me to provide one for NCSA's httpd. I used his HTML form
# as the bsis for this script.
# Thanks also to Brendan Kehoe for his archie client, that was 
# quite straightforward to HyperTextualise (a new word ?)
#
# Thanks for the comments from the following people that brought version 1.1
# JQ Johnson, Simon Poole, Paul Harrington.
#
# Enjoy !
#
# Guy Brooker
# guy@jw.estec.esa.nl
#
# 21/01/94
#
# Modifications
# 
# Version 1.0
# 19/12/93	Guy Brooker
# 
# Version 1.1
# 07/01/94	Guy Brooker
#		o Dangerous Security Hole Removed. For a non-forms based query
#		  QUERY_STRING was assigned query=$*. This enabled malicious
#		  queries such as `cat</etc/passwd`. The QUERY_STRING passed
#		  by httpd is now used, as this escapes these 'special
#		  characters' i.e `ls` = %60ls%60. A hail of thanks go to
#		  JQ Johnson for pointing out the problem.
#
#		o The Swiss entry was removed due to site access resrictions.
#
#		o Horizontal rules are used to separate each Host.
#
# Version 1.2
# 21/01/94	Guy Brooker
#		o Improved variable expansion to check legality of identifiers
#		  and remove the possiblility of the shell interpreting any
#		  characters passed in QUERY_STRING.
#
#		o Report the name of the Archie server used
#
#		o Nice Level now works correctly
#
#		o Added DEFAULT_ variables
#
#

# **** **** **** ****    CONFIGURABLE VARIABLES     **** **** **** ****

ARCHIE=/sw/bin/archie

DEFAULT_SERVER=archie.funet.fi
DEFAULT_NICE=500
DEFAULT_HITS=95

# **** **** **** **** NO CONFIGURATION NEEDED BELOW **** **** **** ****

#
#.. Ensure that 'archie' is available on this machine
#
if [ -x $ARCHIE ]; then

#
#..	To support an ISINDEX type search, set query string if given
#	an argument on the command line
#
    if [ $# -gt 0 ]; then 
	PREFIX="query="
    fi
#
#..	Check that a query has been made
#
    if [ $QUERY_STRING ]; then

#
#..		Strip the variables out from the query string,
#		and assign them into the environment, prefixed by 'QS_'
#
#		 o sed removes any ' that would upset quoted assignment
#
#		 o awk ensures that 
#			- all variables passed have legal names
#			- special characters are not interpreted by sh
#
	eval `echo $PREFIX$QUERY_STRING | sed -e 's/'"'"'/%27/g' | \
	      awk 'BEGIN{RS="&";FS="="}
		$1~/^[a-zA-Z][a-zA-Z0-9_]*$/ {
			printf "QS_%s=%c%s%c\n",$1,39,$2,39}' `
#
#..		Set the search type
#
	case $QS_type in
		Case+Insensitive+Substring+Match)	OPT_search='-s' ;;
		Exact+Match)				OPT_search='-e' ;;
		Case+Sensitive+Substring+Match)		OPT_search='-c' ;;
		Regular+Expression+Match)		OPT_search='-r' ;;
		*)					OPT_search='-s' ;;
	esac
#
#..		Set the server address
#
	case $QS_server in
		United+Kingdom)		ArchieServer='archie.doc.ic.ac.uk' ;;
		ANS+archie+server)	ArchieServer='archie.ans.net' ;;
		Australia)		ArchieServer='archie.au' ;;
		Austria)		ArchieServer='archie.univie.ac.at' ;;
		Canada)			ArchieServer='archie.mcgill.ca' ;;
		Finland)		ArchieServer='archie.funet.fi' ;;
		Germany)		ArchieServer='archie.th-darmstadt.de' ;;
		Internic)		ArchieServer='archie.internic.net' ;;
		Israel)			ArchieServer='archie.ac.il' ;;
		Italy)			ArchieServer='archie.unipi.it' ;;
		Japan)			ArchieServer='archie.wide.ad.jp' ;;
		Korea)			ArchieServer='archie.kr' ;;
		New+Zealand)		ArchieServer='archie.nz' ;;
		Rutgers+University)	ArchieServer='archie.rutgers.edu' ;;
		Spain)			ArchieServer='archie.rediris.es' ;;
		SURAnet)		ArchieServer='archie.sura.net' ;;
		Sweden)			ArchieServer='archie.luth.se' ;;
		Taiwan)			ArchieServer='archie.ncu.edu.tw' ;;
		University+of+Nebraska) ArchieServer='archie.unl.edu';;
		
		*)			ArchieServer="$DEFAULT_SERVER" ;;
	esac
	OPT_server="-h $ArchieServer"
#
#..		Set the sort order
#
	case $QS_order in
		date)	OPT_order='-t' ;;
		host)	OPT_order='' ;;
		*)	OPT_order='' ;;
	esac
#
#..		Set the niceness level
#
	case $QS_nice in
		Not+Nice+At+All)OPT_nice="-N0" ;;
		Nice)		OPT_nice="-N500" ;;
		Nicer)		OPT_nice="-N1000" ;;
		Very+Nice)	OPT_nice="-N5000" ;;
		Extremely+Nice)	OPT_nice="-N10000" ;;
		Nicest)		OPT_nice="-N32765" ;;
		*)		OPT_nice="-N$DEFAULT_NICE" ;;
	esac
#
#..		 Set the maximum number of hits
#
	case $QS_hits in
		1[0123456789]|[0123456789][0123456789]) OPT_hits="-m$QS_hits" ;;
		[0123456789]|[0123456789][0123456789])  OPT_hits="-m$QS_hits" ;;
		*)				 OPT_hits="-m$DEFAULT_HITS" ;;
	esac

#
#..		Output header
#
	cat << EOM
Content-type: text/html

<HEAD>
<TITLE>Archie Results for $QS_query </TITLE>
</HEAD>
<BODY>
<H1>Archie search for $QS_query at $ArchieServer</H1>

EOM

#
#..		Call Archie, and filter the results into HTML
#
	$ARCHIE $OPT_hits $OPT_nice $OPT_search $OPT_order $OPT_server \
		"$QS_query" | awk '
BEGIN {
        HOST = ""
        DIR  = ""
        FILE = ""
}
    {
	if (NF == 0) {
        } else if ($1 == "Host") {
            if (HOST != "") print "</DL>"
            HOST = $2
	    if (!hostlist[HOST]) {
		hostlist[HOST]=1
		HC++
	    }
            printf "<HR><H2> Host <A HREF=\"file://%s/\">",HOST
            printf "%s</A></H2>\n",HOST
            print "\n"
        } else if ($1 == "Location:") {
            DIR = $2
	    DC++
            printf "<DT><A HREF=\"file://%s%s\">",HOST,DIR
            printf "<IMG SRC=\"internal-gopher-menu\" ALT=\"In \">"
	    printf " %s</A>\n",DIR
        } else if ($1 == "FILE") {
            FILE = $NF
	    FC++
            printf "<DD><A HREF=\"file://%s%s/%s\">",HOST,DIR,FILE
            printf "<IMG SRC=\"internal-gopher-binary\" ALT=\"File \">"
	    printf " %s</A>\n",FILE
	    printf " %dK (%d bytes) ",$3/1024,$3
            for (i=4 ; i<NF; i++) printf " %s",$i
            printf "\n"
        } else if ($1 == "DIRECTORY") {
            FILE = $NF
	    FC++
            printf "<DD><A HREF=\"file://%s%s/%s\">",HOST,DIR,FILE
            printf "<IMG SRC=\"internal-gopher-menu\" ALT=\"Directory \">"
	    printf " %s</A>\n",FILE
            for (i=4 ; i<NF; i++) printf " %s",$i
            printf "\n"
        } else if ($0 == "No matches.") {
	    print "<H2>No Matches</H2>"
	    print "No matches for the query could be found.<P>"
        } else {
                print "<P><CODE> * Unknown format..."
                print
                print " *</CODE>"
        }
    }
END {
        if (HOST != "") print "</DL>"
	print "</UL><HR>"
	printf "<H2>Summary for '%s'</H2>",QUERY
	printf "Archie at <CODE>%s</CODE>",SERVER
	printf " found %d files", FC
	printf " in %d directories", DC
	printf " on %d hosts",HC
	printf " for the query <CODE>%s</CODE>.<P>",QUERY

} ' QUERY="$QS_query" SERVER="$ArchieServer" -

	echo '</BODY>'

	else

#
#..		The script was called without a query. 
#		Provide an ISINDEX type response for browsers
#		without form support.
#
	cat << EOM
Content-type: text/html

<HEAD>
<TITLE>Archie Search</TITLE>
<ISINDEX>
</HEAD>
<BODY>
<H1>Archie Search</H1>

This is a simplified gateway to the archie database. Enter the string you wish
to search for.
<P>
<HR>
<H2>What is archie ?</H2>
<QUOTE>
 "Archie" is a database of anonymous ftp sites and their contents.
   The software for it was written by the "Archie Group" (Peter
   Deutsch, Alan Emtage, Bill Heelan, and Mike Parker) at McGill
   University in Montreal, Canada, and they maintain the database as
   well.
<P>

   "Archie" keeps track of the entire contents of a very large number
   of anonymous ftp sites, and allows you to search for files on those
   sites using various different kinds of filename searches.
</QUOTE>
</BODY>
EOM
    fi
else
#
# Brendan Kehoe's Archie Client was not found
# Report a useful message
#
	cat << EOM
Content-type: text/html

<HEAD>
<TITLE>Archie not found</TITLE>
</HEAD>
<BODY>
<H1>Archie not found</H1>

This gateway relies on <EM>Brendan Kehoe</EM>'s <CODE>archie</CODE>
client. If it is installed, please set the correct path in the script file.
Otherwise obtain the latest version from a comp.sources archive, or at
<A HREF="file://ftp.uu.net/networking/info-service/archie/clients">ftp.uu.net</A>
<P>
<ADDRESS>
Guy Brooker<BR>
guy@jw.estec.esa.nl
</ADDRESS>
</BODY>
EOM

fi

