home *** CD-ROM | disk | FTP | other *** search
Wrap
#!/bin/sh perl=/usr/local/etc/architext/perl eval "exec $perl -x $0 $*" #!perl ## Copyright Architext Software, 1994 (c) ## ## This CGI script allows users to configure Architext databases ## through a WWW interface. Naturally, there are plenty of security ## concerns associated with this scheme. ## ## This script appears as several different web pages, depending on ## its invocation. If invoked with a 'db=<database>' argument, the ## script prints out the configuration information for a particular ## database and then allows the user to change it. If invoked with ## 'new=<database>', the user is allowed to create a new database. If ## invoked with 'Update=Update' and 'dbname=<database>', it updates an ## existing database configuration file. Without any of these ## arguments, it displays a list of currently existing database.conf ## files, and also allows the user to create a new database.conf file. $root = "/usr/local/etc/architext"; die "Invalid root directory '$root'\n" unless -d $root; unshift(@INC, "$root/perllib"); require 'architext.pl'; require 'architextConf.pl'; %form = &Architext'readFormArgs; %attr = &ArchitextConf'readConfig("$root/Architext.conf", $form{'db'}); if (&Architext'remoteMode($root)) { $helppath = &Architext'helpPath(); } else { $helppath = $attr{'ArchitextURL'}; } $scriptname = "AT-config.cgi"; ## check for password, if one is specified in Architext.conf ## if it doesn't appear as a form arg, present password page &Architext'password($attr{'ArchitextURL'}, $scriptname, $attr{'Password'}, $form{'password'}); $attr{'Password'} =~ tr/a-zA-Z/n-za-mN-ZA-M/; $postpass = "<INPUT TYPE=\"hidden\" NAME=\"password\" VALUE=\"$attr{'Password'}\">" if ($attr{'Password'}); $getpass = "?password=$attr{'Password'}" if $postpass; if ($form{'Update'}) { ## Assuming all the relevant configuration options are specified ## as form arguments, this mode actually writes the db.conf file. ## will notify user if required information is missing from ## the form by passing a message to the next page ## Header again if (! ($error_str = &createDbConf())) { &Architext'printHeader($attr{'ArchitextURL'}, "Collection Configuration"); if (!$form{'dbname'}) { &Architext'exitError($attr{'ArchitextURL'}, "Configure specified with no dbname."); } ## Let the user know the update was a success. print "<H2>Configuration successful</H2>\n"; print "<p><hr>\n"; if ($getpass) { $getpass .= "&"; } else { $getpass = "?"; } $getpass .= "db=$form{'dbname'}"; print <<EOF; <b>Next steps:</b> <p> <FORM ACTION="AT-index.cgi" METHOD=POST> <INPUT TYPE="submit" NAME="Indexing" VALUE="Index"> Create an index for this collection. <INPUT TYPE="hidden" NAME="db" VALUE="$form{'dbname'}"> $postpass </FORM> <p> <FORM ACTION="AT-generate.cgi" METHOD=POST> <INPUT TYPE="submit" NAME="Generation" VALUE="Generate"> Generate search pages for this collection. <INPUT TYPE="hidden" NAME="db" VALUE="$form{'dbname'}"> $postpass </FORM> <p> <FORM ACTION="AT-admin.cgi" METHOD=POST> <INPUT TYPE="hidden" NAME="db" VALUE="$form{'dbname'}"> <INPUT TYPE="submit" NAME="Admin" VALUE="Admin"> Go back to the main admin page for this collection. $postpass </FORM> EOF ; &Architext'Copyright($attr{'ArchitextURL'}); exit(0); } else { ## required elements were not passed in... $message = $error_str; $form{'db'} = $form{'dbname'}; } } if ($form{'new'}) { ## Print out a form to allow the user to create a new database. $form{'new'} =~ s/\W+/_/g; ## check to see if user has entered name of existing db opendir(CONF, "$root/collections"); @dbconf = grep(/\.conf$/, readdir(CONF)); for (@dbconf) { s|\.conf$||; $preexist = 1 if ($form{'new'} eq $_); last if $preexist; } if (! $preexist) { ## Our standard header &Architext'printHeader($attr{'ArchitextURL'}, "Configure New Collection: $form{'new'}"); print "<p><b>ATTENTION: $message Try again.</b>" if $message; ## Read the default configuration information. ##%attr = &ArchitextConf'readConfig("$root/Architext.conf"); ## Print the form. &printForm($form{'new'}, $form{'new'}); &Architext'Copyright($attr{'ArchitextURL'}); exit(0); } else { $form{'db'} = $form{'new'}; $message = "<b>You chose a name for the new collection that was already in use by an existing collection.</b> Go back if you want to create a new collection, otherwise, you can now configure the collection whose name you specified."; %attr = &ArchitextConf'readConfig("$root/Architext.conf", $form{'db'}); } } if ($form{'db'}) { ## Print out configuration options for an already-existing ## database, and allow the user to update the options. ## Dump our standard header &Architext'printHeader($attr{'ArchitextURL'}, "Collection Configuration: $form{'db'}"); ## print a message from the Update mode if something was missing print "<b>ATTENTION: $message</b>" if $message; ## Check for the desired database.conf file. $dbconfig = $root . "/collections/" . $form{'db'} . ".conf"; if (! -r $dbconfig) { &Architext'exitFileError($dbconfig, "does not exist"); } ## Read all the configuration information. ##%attr = &ArchitextConf'readConfig("$root/Architext.conf", $form{'db'}); ## Print the form. &printForm($form{'db'}); &Architext'Copyright($attr{'ArchitextURL'}); } else { ## Print out the top-level screen: scan the root directory for ## db.conf files, and allow the user to initialize a new db.conf file. opendir(CONF, "$root/collections"); @dbconf = grep(/\.conf$/, readdir(CONF)); &Architext'printHeader($attr{'ArchitextURL'}, "Collection Configuration"); print <<EOF; <FORM ACTION="http:AT-config.cgi" METHOD=POST> Choose a document collection to configure, or enter a new collection:<P> <DL> <DT> Existing <a href="${helppath}AT-helpdoc.html#Document Collections"> document collections:</a> <DD> EOF ; if ($#dbconf > -1) { print "<SELECT NAME=\"db\" SIZE=5>"; for (@dbconf) { s|\.conf$||; next if $_ eq 'Architext'; print "<OPTION> $_\n"; } print "</SELECT><P>\n"; } else { print "<p>(No document collections found)<p>\n"; } print <<EOF; <DT> If you wish to configure a <a href="${helppath}AT-helpdoc.html#New Collection"> new collection</a> please supply a name for it here. <DD> <INPUT NAME="new"> </DL> <INPUT TYPE="submit" NAME="Configure" VALUE="Configure"> $postpass </FORM> EOF ; &Architext'Copyright($attr{'ArchitextURL'}); } ## Prints an input line for a form. sub printInputLine { local($name, $text, $db) = @_; local($val); local($size); $text = $name unless $text; $val = eval "\$attr{$name}"; $val = "$attr{'ArchitextRoot'}/collections/" if $db; $size=40; $size = (length($val) +10) unless ((length($val) +10) < 40); print <<EOF; <a href="${helppath}AT-helpdoc.html#$text">$text:</a> <INPUT NAME="$name" VALUE="$val" SIZE=$size><P> EOF ; } ## Prints out the Architext form. Uses dynamic scoping to ensure that ## the values in the %attr array are properly set. sub printForm { local($db, $new) = @_; local($files, $rules); local($fileval, $ruleval, $filter_html, $filter_both); print "<p>Please use absolute pathnames for filenames.\n"; print qq(<FORM ACTION="http:AT-config.cgi" METHOD=POST>\n); &printHiddenLine('IndexExecutable'); &printHiddenLine('SearchExecutable'); &printHiddenLine('StemTable'); &printHiddenLine('StopTable'); &printHiddenLine('CollectionInfo', 'CollectionInfo', "$db.cf"); if ($new) { print qq(<INPUT TYPE="hidden" NAME="new" VALUE="$new">); } print "Designate the directory where the index files will be stored.<br>"; &printInputLine('CollectionIndex', 'CollectionIndex', $db); if ($attr{'IndexFilter'} =~ /^Text/) { $filter_both = "CHECKED"; } else { $filter_html = "CHECKED"; } $files = "CHECKED" if ($attr{'CollectionContents'} =~ /^\+/); $rules = "CHECKED" if (! ($attr{'CollectionContents'} =~ /^\+/)); if ($files) { $fileval = $attr{'CollectionContents'}; $fileval =~ s/^\+//; } $ruleval = join("\n", split(/[:,;\s]+/, $attr{'CollectionContents'})) if $rules; print <<EOF; <p> Describe the <a href="${helppath}AT-helpdoc.html#CollectionContents"> CollectionContents</a> (the files you wish to index): <br> Only HTML and ASCII files are recognized by the indexer.<hr> <INPUT TYPE="radio" NAME="FileSource" VALUE="FileList" $files> <b> Index Using Explicit List </b><ul> Index files listed in the following file: <INPUT NAME="FileList" VALUE="$fileval" SIZE=30><br> Filenames must be listed using absolute pathnames, with one filename per line. </ul> <hr> <INPUT TYPE="radio" NAME="FileSource" VALUE="Files" $rules> <b> Index Using Rules </b><ul> Using the options below, index the files and directories listed here: <br> <TEXTAREA NAME="Files" ROWS=4 COLS=60>$ruleval</TEXTAREA> <p>Select the types of files to include in the index.<br> <a href="${helppath}AT-helpdoc.html#IndexFilter">IndexFilter:</a> <INPUT TYPE="radio" NAME="IndexFilter" VALUE="HTML Files Only" $filter_html> HTML Files Only <INPUT TYPE="radio" NAME="IndexFilter" VALUE="Text And HTML Files" $filter_both> Text And Html Files (non-binary files) <p> EOF ; print "Optionally designate a file that contains regular expressions which match filenames that you wish to exclude from the index.<br>"; &printInputLine('ExclusionRules'); print "</ul>"; print "<hr>"; print "<p>If you would like to receive email notification when the indexing process completes, provide an address here.<br>"; &printInputLine('AdminMail'); print <<EOF; <p><INPUT TYPE="submit" NAME="Set" VALUE="Save"> Save the configuration characteristics for this collection. <INPUT TYPE="hidden" NAME="Update" VALUE="Update"> <INPUT TYPE="hidden" NAME="dbname" VALUE="$db"> <INPUT TYPE="hidden" NAME="db" VALUE="$db"> $postpass </FORM> EOF ; if (-e "$root/collections/$db.conf") { $dbline = "<INPUT TYPE=\"hidden\" NAME=\"db\" VALUE=\"$db\">"; } print <<EOF; <p> <FORM ACTION="AT-admin.cgi" METHOD=POST> $dbline <INPUT TYPE="submit" NAME="Admin" VALUE="Admin"> Don't save, go back to the admin page. $postpass </FORM> EOF ; } ## pass around all the parameters that user doesn't need to see sub printHiddenLine { local($name, $value, $dummy) = @_; if (!&Architext'debugMode()) { $val = eval "\$attr{$name}"; $val = "$attr{'ArchitextRoot'}/collections/$dummy" if $dummy; print qq(<INPUT TYPE="hidden" NAME="$name" VALUE="$val">); } else { &printInputLine($name, $value, $dummy); } } ## writes a db conf file to disk and does some error checking ## to make sure that the user has entered sensible values. ## also adds the AdminMail field to Architext.conf if it is ## not already there, so that it will be defaulted in the ## future sub createDbConf { local($dbconfig, $message, $collection_root, $exit, @index); if (!$form{'CollectionIndex'}) { return "You cannot leave the 'CollectionIndex' field blank."; } if ($form{'FileSource'} eq 'FileList') { return "You must supply a filename for the file list." unless $form{'FileList'}; } if ($form{'FileSource'} eq 'Files') { return "You must supply filenames for the files you wish to index." unless $form{'Files'}; ##return "You can't specify a file list if you are using the 'Index Using Rules' option." if $form{'FileList'}; } ## add rootnmame to collection index path $dbconfig = $root . "/collections/" . $form{'dbname'} . ".conf"; $form{'CollectionIndex'} .= "/" unless $form{'CollectionIndex'} =~ /\/$/; $collection_root = "$form{'CollectionIndex'}$form{'dbname'}"; ## Can we write to the db.conf file? if (-e $dbconfig && ! -w $dbconfig) { &Architext'exitFileError($attr{'ArchitextURL'}, $dbconfig, "is not writable."); } ## test user's entries to make sure they are valid ## makes sense and will not be likely to kill the indexing ## process. return "The index binary '$form{'IndexExecutable'}' does not exist." if (! -e $form{'IndexExecutable'}); return "The index binary '$form{'IndexExecutable'}' is not executable." if (! -x $form{'IndexExecutable'}); return "The search binary '$form{'SearchExecutable'}' does not exist." if (! -e $form{'SearchExecutable'}); return "The search binary '$form{'SearchExecutable'}' is not executable." if (! -x $form{'SearchExecutable'}); return "The stem table '$form{'StemTable'}' is not readable." if (! -r $form{'StemTable'}); return "The stop table '$form{'StopTable'}.key' is not readable." if (! -r "$form{'StopTable'}.key"); return "The stop table '$form{'StopTable'}.ptr' is not readable." if (! -r "$form{'StopTable'}.ptr"); return "The CollectionIndex directory you specified ($form{'CollectionIndex'}) does not exist." if (! -e $form{'CollectionIndex'}); return "The CollectionIndex directory you specified ($form{'CollectionIndex'}) is not a directory." if (! -d $form{'CollectionIndex'}); return "The CollectionIndex directory you specified ($form{'CollectionIndex'}) is not writeable." if (! -w $form{'CollectionIndex'}); if ($form{'ExclusionRules'}) { return "The ExclusionRules file you specified ($form{'ExclusionRules'}) does not exist." if (! -e $form{'ExclusionRules'}); return "The ExclusionRules file you specified ($form{'ExclusionRules'}) is not readable." if (! -r $form{'ExclusionRules'}); } if ($form{'FileSource'} eq 'FileList') { $form{'FileList'} =~ s/^\s+//; $form{'FileList'} =~ s/\s+$//; return "Please specify only one file list file." if ($form{'FileList'} =~ /\S\s\S/); $form{'CollectionContents'} = "+$form{'FileList'}"; } else { $form{'CollectionContents'} = join(" ", split(/[:,;\s]+/, $form{'Files'})); } @index = split(/[:,;\s]+/, $form{'CollectionContents'}); for (@index) { if (/^\+/) { if ($form{'FileSource'} eq 'Files') { return "Bad filename given. ($_) Please use absolute pathnames."; } s/^\+//; return "Could not find file list '$_'. Please re-enter the file list filename." if (! -e $_); return "Could not read from file list '$_'. Please re-enter the file list filename." if (! -r $_); ## check to to enforce files in file list appear under html root open(FLIST, "$_"); while (<FLIST>) { if (! &underHtmlRoot($attr{'HtmlRoot'}, $_)) { close(FLIST); return "The file '$_' specified in the file list does not appear under your html root. Please specify files that appear under your html root, or your Web server will not have access to them."; } } close(FLIST); } else { ## check here to enforce that files appear under html root return "Specified file or directory '$_' does not appear under your html root. Please specify files that appear under your html root, or your Web server will not have access to them." unless &underHtmlRoot($attr{'HtmlRoot'}, $_); return "Specified file or directory '$_' does not exist. Please re-enter the list of files to index." if (! -e $_); return "Could not read from the specified file or directory '$_'. Please re-enter the list of files to index." if (! -r $_); } } if (! open(DBCONF, ">$dbconfig")) { &Architext'exitFileError($attr{'ArchitextURL'}, $dbconfig, "could not be opened for writing."); } ## now that everything has been tested for accuracy, write to disk print DBCONF "<Collection $form{'dbname'}>\n"; for ('IndexExecutable', 'SearchExecutable', 'StemTable', 'StopTable', 'CollectionContents', 'CollectionIndex', 'CollectionInfo', 'IndexFilter') { print DBCONF "$_ $form{$_}\n"; } print DBCONF "CollectionRoot $collection_root\n"; print DBCONF "AdminMail $form{'AdminMail'}\n"; print DBCONF "ExclusionRules $form{'ExclusionRules'}\n" if $form{'ExclusionRules'}; print DBCONF "</Collection>\n"; close(DBCONF); ## put AdminMail in Architext.conf if it is not already there if ($form{'AdminMail'} && (! $attr{'AdminMail'})) { $command = "echo AdminMail $form{'AdminMail'} >> $root/Architext.conf"; $exit = system($command); &Architext'exitError($attr{'ArchitextURL'}, "Error updating Architext.conf with AdminMail - $!") if $exit; } return($message); } sub underHtmlRoot { local($root, $file) = @_; local($prefix); $root =~ s|\/$|| if ($root =~ /\/$/); $prefix = substr($file, 0, length($root)); return 1 if ($prefix eq $root); return 0; }