#!/usr/bin/perl
# CGI script to facilitate advanced retrieval search for the Textpresso system.
#
# copyright (c) Hans-Michael Muller & Juancarlos Chan, Pasadena, California, 2002-2004
#
use strict;
use CGI;
use POSIX;
### INITIALIZE GLOBALS ###
### globals
#
# handle to this CGI and own address
my $query = new CGI;
my $absmyself = $query->url(absolute=>1);
# directories of importance
my $databaseroot = "/var/www/html/text/tdb/";
my $indexattspec = $databaseroot . "ind/attspec";
my $indexkey = $databaseroot . "ind/key/";
# cookies
my %generalsettings = $query->cookie('generalsettings'); # general settings
my %displayoptions; # display options
if ($query->cookie('displayoptions')) { # if options in cookie
%displayoptions = $query->cookie('displayoptions');
} else { # else use default
$displayoptions{'Source Type'} = 1;
$displayoptions{Title} = 1;
$displayoptions{Abstract} = 1;
$displayoptions{Author} = 1;
$displayoptions{Journal} = 1;
$displayoptions{Year} = 1;
$displayoptions{Citation} = 1;
$displayoptions{'Number of matches'} = 1;
$displayoptions{Select} = 1;
} # else # if ($query->cookie('displayoptions'))
my %displayvalues; # display values
if ($query->cookie('displayvalues')) { # if values in cookie
%displayvalues = $query->cookie('displayvalues');
} else { # else use default
$displayvalues{ResultsPerPage} = 10;
$displayvalues{SentencesPerMatch} = 10;
} # else # if ($query->cookie('displayvalues'))
my %advretoptions; # query options
if ($query->cookie('advretoptions')) { # if values in cookie
%advretoptions = $query->cookie('advretoptions');
} else { # else use default
$advretoptions{NumberOfCategories} = 3;
$advretoptions{NumberOfKeywords} = 3;
} # else # if ($query->cookie('advretoptions'))
my %lastadvancedquery = $query->cookie('lastadvancedquery'); # last query
# other globals of interest
my %targetdirectories = (Title => 'tit/', Abstract => 'abs/', Paper => 'art/');
my %searchtargets = (Title => 0, Abstract => 0, Paper => 0); # This hash defines the search targets
my %labels = ReadElements("/var/www/html/text/textpresso.dtd"); # read in elements that can be searched for.
my @elementkeys = sort keys % labels; # list of elements, abbreviated.
my @attributes = ReadAttributes("/var/www/html/text/textpresso.dtd");
my %attnmecde = ();
for (my $j = 0; $j <@attributes; $j++) { # separate code from label
(my $cde, my $value) = split(/-/,$attributes[$j]);
my $label = "";
if ($value =~ /(\w+)\s+\((.+)\)/) { $label = $2 . ": " . $1; }
$attnmecde { $label } = $cde;
$attributes[$j] = $label;
} # for (my $j = 0; $j <@attributes; $j++)
# format of result: $searchresult{ searchtarget }{ file }{ sentence } = no. of occ.;
my %searchresults = ();
my $lastsearchfilename = $query->param('lsfilename');
my $displaypage = 1;
my @displayedkeys = $query->param('dispkeys');
my @expandedabs = $query->param('expandedabs');
my $totalpages = $query->param('totalpages');
my $execcommand = "";
my $catrows;
if (defined($query->param('catrows'))) { $catrows = $query->param('catrows'); }
else { $catrows = $advretoptions{NumberOfCategories}; }
my $keyrows;
if (defined($query->param('keyrows'))) { $keyrows = $query->param('keyrows'); }
else { $keyrows = $advretoptions{NumberOfKeywords}; }
my $firstpage = 1; # default is firstpage unless already displayed via &display();
my $clearquery = 0; # flag to $query->delete_all();
my @specchoices = ( 'named', 'unnamed', 'all' ); # possible specialization choices
#
### end globals;
### INITIALIZE GLOBALS ###
### PROCESS ###
### process form
#
my $abstractkeyhit = 0;
foreach my $key (@displayedkeys) {
if ($query->param("expanded$key")) {
push @expandedabs, $key;
$abstractkeyhit = 1;
}
if ($query->param("collapse$key")) {
for (my $i = 0; $i < @expandedabs; $i++) { delete $expandedabs[$i] if ($expandedabs[$i] eq $key) }
$abstractkeyhit = 1;
}
} # foreach my $key (@displayedkeys)
if ($query->param('querytable')) {
$catrows = $query->param('catrows'); $keyrows = $query->param('keyrows');
&display();
} # if ($query->param('querytable'))
if ($query->param('lastquery')) {
&processLastquery();
my $lsqcookie = &setlsqCookie();
&PrintHeader($query, $lsqcookie);
&displayMainForm();
&overrideCatAttCookies(); # get cookie values to override catatt selections
&displayOutput();
&passHidden();
&closeForm();
$firstpage = 0;
} # if ($query->param('lastquery'))
if ($query->param('clearquery')) {
$query->delete_all(); $clearquery = 1;
&display();
}
if ($query->param('search')) {
my $lsqcookie = &setlsqCookie();
&PrintHeader($query, $lsqcookie);
&displayMainForm();
&processSearch();
# &overrideCatAttCookies(); # get cookie values to override catatt selections
# foreach my $key (sort keys %lastadvancedquery) { print STDERR "SEARCH $key\t$lastadvancedquery{$key}\n"; }
print "\n";
&displayOutput();
&passHidden();
&closeForm();
$firstpage = 0;
} # if ($query->param('search'))
if (($query->param('lastsearch')) || ($query->param('emailresults'))
|| ($query->param('previouspage')) || ($query->param('nextpage'))
|| $abstractkeyhit) {
&processVarious();
&display();
}
if ($firstpage) { &display(); } # if firstpage, display it
if ($query->param('emailresults')) { # deal with emailing stuff
if ($query->param('recipient') ne "") {
my $subject = "Your request from Texpresso - Advanced Query ";
my $recipient = $query->param('recipient');
my $matchsentences = -1; # negative number indicates no sentences incl.
if ($query->param('emailmatches')) {
$matchsentences = $displayvalues{SentencesPerMatch};
}
my $options = "";
foreach my $key (keys % displayoptions) {
$options .= "\"" . $key . "\" " if ($displayoptions{$key});
}
my $comment = "Y O U R Q U E R Y \n";
$comment .= "------------------- \n";
$comment .= "CATEGORIES:\n" if ($catrows > 0);
for (my $i = 0; $i < $catrows; $i++) {
my $catvarname = "catcat" . $i;
my $category = $query->param($catvarname);
my $boolvarname = "catbool" . $i;
my $bool = $query->param($boolvarname);
my $attvarname = "catatt" . $i;
my @att = $query->param($attvarname);
my $specvarname = "catspec" . $i;
my $specification = $query->param($specvarname);
my $compvarname = "catcomp" . $i;
my $comparison = $query->param($compvarname);
my $numvarname = "catnum" . $i;
my $number = $query->param($numvarname);
if ($category ne "") {
$comment .= $labels{$category} . "( - ";
$comment .= "Boolean operation: " . $bool . " - " if (defined($bool));
if (@att) {
$comment .= "Attributes: ";
my $attstring = "";
foreach my $attribute (@att) {
$attribute =~ s/\,/ /g;
$attstring .= $attribute . " & ";
}
chop ($attstring); chop ($attstring); chop ($attstring);
$comment .= $attstring . " - ";
}
$comment .= "Specification: " . $specification . " - " if (defined($specification));
$comment .= "Comparison: " . $comparison . " - " if (defined($comparison));
$comment .= "Number of matches: " . $number . " - " if (defined($number));
$comment .= ")\n";
}
}
$comment .= "KEYWORDS:\n" if ($keyrows > 0);
for (my $i = 0; $i < $keyrows; $i++) {
my $keyvarname = "keykey" . $i;
my $keyword = $query->param($keyvarname);
my $exactvarname = "keyexact" . $i;
my $boolvarname = "keybool" . $i;
my $bool = $query->param($boolvarname);
my $compvarname = "keycomp" . $i;
my $comparison = $query->param($compvarname);
my $numvarname = "keynum" . $i;
my $number = $query->param($numvarname);
if (($keyword ne "") && (!$query->param($exactvarname))) {
$keyword .= "*";
}
if ($keyword ne "") {
$comment .= $keyword ."( - ";
$comment .= "Boolean operation: " . $bool . " - " if (defined($bool));
$comment .= "Comparison: " . $comparison . " - " if (defined($comparison));
$comment .= "Number of matches: ". $number . " - " if (defined($number));
$comment .=")\n";
}
}
$execcommand = "echo \'nice $databaseroot/scr/mailresults.pl $recipient \"$subject\" \"$comment\" $lastsearchfilename $matchsentences $options\' \| at now";
}
} # if ($query->param('emailresults'))
### exec system command 'offline'
#
system($execcommand); # mail results if so chosen
#
###
### SUBROUTINES ###
sub processLastquery {
$catrows = $lastadvancedquery{catrows};
$keyrows = $lastadvancedquery{keyrows};
for (my $i = 0; $i < $catrows; $i++) {
my $varname = "catbool" . $i;
$query->param(-name => $varname, -value => $lastadvancedquery{$varname});
$varname = "catcat" . $i;
$query->param(-name => $varname, -value => $lastadvancedquery{$varname});
$varname = "catspec" . $i;
$query->param(-name => $varname, -value => $lastadvancedquery{$varname});
$varname = "catcomp" . $i;
$query->param(-name => $varname, -value => $lastadvancedquery{$varname});
$varname = "catnum" . $i;
$query->param(-name => $varname, -value => $lastadvancedquery{$varname});
}
for (my $i = 0; $i < $keyrows; $i++) {
my $varname = "keybool" . $i;
$query->param(-name => $varname, -value => $lastadvancedquery{$varname});
$varname = "keykey" . $i;
$query->param(-name => $varname, -value => $lastadvancedquery{$varname});
$varname = "keyexact" . $i;
$query->param(-name => $varname, -value => $lastadvancedquery{$varname});
$varname = "keycomp" . $i;
$query->param(-name => $varname, -value => $lastadvancedquery{$varname});
$varname = "keynum" . $i;
$query->param(-name => $varname, -value => $lastadvancedquery{$varname});
}
} # sub processLastquery
sub processSearch {
print $query->hr;
print $query->b($query->font({-face => 'verdana, helvetica', -size => '2', -color => 'green'}, 'Searching..'));
%searchresults = ();
my $mode = $query->param('searchmode');
if ($query->param('searchtargets')) {
foreach my $key (keys % searchtargets) { $searchtargets{$key} = 0}
foreach my $key ($query->param('searchtargets')) {
$searchtargets{$key} = 1;
}
} # if ($query->param('searchtargets'))
if ($searchtargets{Paper} || $searchtargets{Abstract} || $searchtargets{Title}) {
for (my $i = 0; $i < $catrows; $i++) {
my $catvarname = "catcat" . $i;
my $category = $query->param($catvarname);
if ($category ne "") {
my $attvarname = "catatt" . $i;
my @attributes = $query->param($attvarname);
my $specvarname = "catspec" . $i;
my $specification = $query->param($specvarname);
my $numcompvarname = "catcomp" . $i;
my $comparison = $query->param($numcompvarname);
my $nummatchvarname = "catnum" . $i;
my $numberofmatches = $query->param($nummatchvarname);
if ($i > 0) {
my %auxlist = GetListFromCategories($indexattspec, $databaseroot,
\%targetdirectories, $category,
\%searchtargets, \%attnmecde, \@attributes,
$specification, $comparison, $numberofmatches);
my $boolvarname = "catbool" . $i;
my $bool = $query->param($boolvarname);
if ($bool eq "and") {
%searchresults = AndLists(\%searchresults, \%auxlist, $mode);
} elsif ($bool eq "or") {
%searchresults = OrLists(\%searchresults, \%auxlist);
} elsif ($bool eq "not") {
%searchresults = ListAAndNotListB(\%searchresults, \%auxlist, $mode);
}
} else {
%searchresults = GetListFromCategories($indexattspec, $databaseroot,
\%targetdirectories, $category,
\%searchtargets, \%attnmecde, \@attributes,
$specification, $comparison, $numberofmatches);
}
}
}
}
for (my $i = 0; $i < $keyrows; $i++) {
my $keyvarname = "keykey" . $i;
my $keyword = $query->param($keyvarname);
if ($keyword ne "") {
my $exactvarname = "keyexact" . $i;
my $numcompvarname = "keycomp" . $i;
my $comparison = $query->param($numcompvarname);
my $nummatchvarname = "keynum" . $i;
my $numberofmatches = $query->param($nummatchvarname);
if (($keyword ne "") && (!$query->param($exactvarname))) {
$keyword .= "*";
}
unless(($catrows < 1) && ($i < 1)) {
my %auxlist = GetListFromKeyword($indexkey, \%targetdirectories,
$keyword, \%searchtargets,
$comparison, $numberofmatches);
my $boolvarname = "keybool" . $i;
my $bool = $query->param($boolvarname);
if ($bool eq "and") {
%searchresults = AndLists(\%searchresults, \%auxlist, $mode);
} elsif ($bool eq "or") {
%searchresults = OrLists(\%searchresults, \%auxlist);
} elsif ($bool eq "not") {
%searchresults = ListAAndNotListB(\%searchresults, \%auxlist, $mode);
}
} else {
%searchresults = GetListFromKeyword($indexkey, \%targetdirectories,
$keyword, \%searchtargets,
$comparison, $numberofmatches);
}
}
}
my $tmp1filename;
do { $tmp1filename = tmpnam() } until (!-e "$databaseroot/$tmp1filename");
open (OUT1,">$databaseroot/$tmp1filename");
for (my $i = 0; $i < $catrows; $i++) {
my $catvarname = "catcat" . $i;
my $category = $query->param($catvarname);
my $boolvarname = "catbool" . $i;
my $bool = $query->param($boolvarname);
my $attvarname = "catatt" . $i;
my @att = $query->param($attvarname);
my $specvarname = "catspec" . $i;
my $specification = $query->param($specvarname);
my $compvarname = "catcomp" . $i;
my $comparison = $query->param($compvarname);
my $numvarname = "catnum" . $i;
my $number = $query->param($numvarname);
if ($category ne "") {
print OUT1 $category;
print OUT1 "# - "; # when category is specified, comment is always required
print OUT1 "Boolean operation: ", $bool, " - " if (defined($bool));
if (@att) {
print OUT1 "Attributes: ";
my $attstring = "";
foreach my $attribute (@att) {
$attribute =~ s/\,/ /g;
$attstring .= $attribute . " & ";
}
chop ($attstring); chop ($attstring); chop ($attstring);
print OUT1 $attstring, " - ";
}
print OUT1 "Specification: ", $specification, " - " if (defined($specification));
print OUT1 "Comparison: ", $comparison, " - " if (defined($comparison));
print OUT1 "Number of matches: ", $number, " - " if (defined($number));
print OUT1 ",";
}
}
print OUT1 "\n";
for (my $i = 0; $i < $keyrows; $i++) {
my $keyvarname = "keykey" . $i;
my $keyword = $query->param($keyvarname);
my $exactvarname = "keyexact" . $i;
my $boolvarname = "keybool" . $i;
my $bool = $query->param($boolvarname);
my $compvarname = "keycomp" . $i;
my $comparison = $query->param($compvarname);
my $numvarname = "keynum" . $i;
my $number = $query->param($numvarname);
if (($keyword ne "") && (!$query->param($exactvarname))) {
$keyword .= "*";
}
if ($keyword ne "") {
print OUT1 $keyword;
print OUT1 "# - "; # when keyword is specified, comment is always required
print OUT1 "Boolean operation: ", $bool, " - " if (defined($bool));
print OUT1 "Comparison: ", $comparison, " - " if (defined($comparison));
print OUT1 "Number of matches: ", $number, " - " if (defined($number));
print OUT1 ",";
}
}
print OUT1 "\n";
foreach my $target (keys % searchresults) {
foreach my $key (keys %{ $searchresults{$target} }) {
print OUT1 $target . "," . $key . ",";
foreach my $sentence (keys % { $searchresults{$target}{$key} }) {
print OUT1 $sentence . ",";
}
print OUT1 "\n";
}
}
close (OUT1);
$lastsearchfilename = $tmp1filename;
$query->param(-name => 'lsfilename', -value => $lastsearchfilename);
$query->param(-name => 'page', -value => 1);
print $query->b($query->font({-face => 'verdana, helvetica', -size => '2', -color => 'green'}, '..done.'));
} # sub processSearch
sub processVarious {
%searchresults = ();
if ($lastsearchfilename) {
open (IN, "$databaseroot/$lastsearchfilename");
my $junk = ;
$junk = ; # first two lines (query) are of no interest here.
while (my $line = ) {
chomp ($line);
my @items = split (/\,/, $line);
my $target = shift(@items);
my $key = shift(@items);
while (my $sentence = shift(@items)) {
$searchresults{$target}{$key}{$sentence} = 1;
}
}
close (IN);
}
if ($query->param('previouspage')) {
if ($query->param('page') == 1) {
$displaypage = 1;
$query->param(-name => 'page', -value => 1);
} else {
$displaypage = $query->param('page') - 1;
$query->param(-name => 'page', -value => $displaypage);
}
} elsif ($query->param('nextpage')) {
$displaypage = $query->param('page') + 1;
$displaypage = ($displaypage > $totalpages) ? $totalpages : $displaypage;
$query->param(-name => 'page', -value => $displaypage);
} else {
$displaypage = $query->param('page');
}
} # sub processVarious
#
### PROCESS ###
### DISPLAY ###
sub display {
my $lsqcookie = &setlsqCookie();
&PrintHeader($query, $lsqcookie);
&displayMainForm();
&displayOutput();
&passHidden();
&closeForm();
$firstpage = 0;
} # sub display
### Set cookie (last advanced query) to current query, if current query is not empty
sub setlsqCookie { # if search and data, save query in cookie
my $realquery = 0;
for (my $i = 0; $i < $catrows; $i++) {
my $varname = "catcat" . $i;
if ($query->param($varname) ne "") { $realquery = 1 };
}
for (my $i = 0; $i < $keyrows; $i++) {
my $varname = "keykey" . $i;
if ($query->param($varname)) { $realquery = 1 };
}
my $lsqcookie; # initialize the cookie
if ($realquery) {
%lastadvancedquery = ();
$lastadvancedquery{catrows} = $catrows;
$lastadvancedquery{keyrows} = $keyrows;
for (my $i = 0; $i < $catrows; $i++) {
my $varname = "catbool" . $i;
$lastadvancedquery{$varname} = $query->param($varname);
$varname = "catcat" . $i;
$lastadvancedquery{$varname} = $query->param($varname);
$varname = "catatt" . $i;
my @catatt = $query->param($varname); # get the catatt values
my $catattlen = $varname . 'len'; # set length variable
$lastadvancedquery{$catattlen} = scalar(@catatt); # pass length to hash
for (my $j = 0; $j < scalar(@catatt); $j++) { # for each value
my $attattarrval = $varname . 'val' . $j; # set variable name
$lastadvancedquery{$attattarrval} = $catatt[$j]; # pass value to hash
}
$varname = "catspec" . $i;
$lastadvancedquery{$varname} = $query->param($varname);
$varname = "catcomp" . $i;
$lastadvancedquery{$varname} = $query->param($varname);
$varname = "catnum" . $i;
$lastadvancedquery{$varname} = $query->param($varname);
}
for (my $i = 0; $i < $keyrows; $i++) {
my $varname = "keybool" . $i;
$lastadvancedquery{$varname} = $query->param($varname);
$varname = "keykey" . $i;
$lastadvancedquery{$varname} = $query->param($varname);
$varname = "keyexact" . $i;
$lastadvancedquery{$varname} = $query->param($varname);
$varname = "keycomp" . $i;
$lastadvancedquery{$varname} = $query->param($varname);
$varname = "keynum" . $i;
}
if ($query->param('search')) { # if search, set cookie
$lsqcookie = $query->cookie(-name => 'lastadvancedquery',
-value => \%lastadvancedquery,
-path => '/cgi-bin/',
-expires => '+730d');
} # if ($query->param('search')
} # if ($realquery)
return $lsqcookie;
} # setlsqCookie
### FORM ###
### start form
#
sub displayMainForm {
print $query->start_form(-method => 'POST', -name => 'form1', -action => $absmyself);
print $query->font({-face => 'verdana, helvetica', -size => '2'},
'In the advanced retrieval, searches of categories or keywords ');
print $query->font({-face => 'verdana, helvetica', -size => '2'},
'at any level of sophistication can be undertaken. ');
print $query->font({-face => 'verdana, helvetica', -size => '2'},
'Specify boolean operators, attributes, number of occurrences, etc.. In a keyword row, specify only one keyword per row. ');
print $query->start_b;
print $query->font({-face => 'verdana, helvetica', -size => '2', -color => 'darkred'},
'This interface requires javascript. It does not work well with Netscape 4.79 or earlier versions.');
print $query->end_b;
print $query->p;
my @tablecontent = ();
my @columns = ();
push @columns, "boolean
operation";
push @columns, "category
or keyword";
push @columns, "category or
match attributes";
push @columns, "specification" if ($catrows > 0);
push @columns, "numerical
comparison
of matches";
push @columns, "number
of matches";
push @tablecontent , $query->th([@columns]);
for (my $i = 0; $i < $catrows; $i++) {
@columns = ();
my $varname = "catbool" . $i;
if ($i > 0) {
push @columns, $query->popup_menu(-name => $varname,
-values =>["and", "or", "not"]);
} else {
push @columns, $query->font({-color => 'darkred'}, 'required
field');
}
$varname = "catcat" . $i;
push @columns, $query->popup_menu(-name => $varname,
-values => [@elementkeys],
-onChange => 'javascript:checkifselected()',
-labels => \%labels);
$varname = "catatt" . $i;
push @columns, $query->scrolling_list(-name => $varname,
-values => [ 'Please select a category or keyword.' ],
-size => 5, -multiple=> 'true');
$varname = "catspec". $i;
push @columns, $query->popup_menu(-name => $varname,
-values => [ 'n/a' ],
-size => 3);
$varname = "catcomp" . $i;
push @columns, $query->popup_menu(-name => $varname,
-values => ['less than', 'greater than',
'equal to'],
-default => 'greater than');
$varname = "catnum" . $i;
push @columns, $query->popup_menu(-name => $varname,
-values => [0,1,2,3,4,5,6,7,8,9,10],
-default => 0);
push @tablecontent, $query->td([@columns]);
} # for (my $i = 0; $i < $catrows; $i++)
for (my $i = 0; $i < $keyrows; $i++ ) {
@columns = ();
my $varname = "keybool" . $i;
unless(($catrows < 1) && ($i < 1)) {
push @columns, $query->popup_menu(-name => $varname,
-values =>["and", "or", "not"]);
} else {
push @columns, $query->font({-color => 'darkred'}, 'required
field');
}
$varname = "keykey" . $i;
push @columns, $query->textfield(-name => $varname,
-size => 20,
-maxlength => 255);
$varname = "keyexact" . $i;
push @columns, $query->checkbox(-name => $varname,
-label => 'Exact match');
push @columns, "" if ($catrows > 0); # specification doesn't make sense for keywords
$varname = "keycomp" . $i;
push @columns, $query->popup_menu(-name => $varname,
-values => ['less than', 'greater than',
'equal to'],
-default => 'greater than');
$varname = "keynum" . $i;
push @columns, $query->popup_menu(-name => $varname,
-values => [0,1,2,3,4,5,6,7,8,9,10],
-default => 0);
push @tablecontent, $query->td([@columns]);
} # for (my $i = 0; $i < $keyrows; $i++ )
print $query->table({-border => '1', -cellpadding => '4',
-cellspacing => '1'},
$query->caption($query->b("Q U E R Y")),
$query->Tr([@tablecontent]));
print $query->p;
print $query->font({-face => 'verdana, helvetica', -size => '2'},
'These criteria should be met in a ');
my %locallabel;
$locallabel{sentence} = " sentence";
$locallabel{publication} = " publication";
print $query->radio_group(-name => 'searchmode',
-linebreak => 0,
-value => ['sentence', 'publication'],
-default => 'sentence',
-labels => \%locallabel);
print $query->br;
print $query->font({-face => 'verdana, helvetica', -size => '2'},
' and searched in ');
my @defaults = ("Abstract", "Paper");
foreach my $key (sort keys % searchtargets) {
if ($searchtargets{$key}) { push @defaults, $key}
}
my %locallabel2;
foreach my $key (keys % searchtargets) {
if ($key eq "Paper") {
$locallabel2{$key} = " Full Text";
} else {
$locallabel2{$key} = " " . $key;
}
}
print $query->checkbox_group(-name=>'searchtargets',
-value => [sort keys % searchtargets],
-defaults => [sort @defaults],
-linebreak => 'false',
-rows => 1,
-labels => \%locallabel2);
print $query->p;
print $query->submit(-name => 'search', -value => 'Search!');
print $query->font(" ");
print $query->submit(-name => 'lastquery', -value => 'Load last query!');
print $query->font(" ");
print $query->submit(-name => 'clearquery', -value => 'Clear last query!');
print $query->font(" ");
print $query->button(-value => 'Undo current changes!', -onClick => 'javascript:load_catcat_and_catatt()');
print $query->p;
print $query->submit(-name => 'querytable', -value => 'Reproduce query table');
print $query->font({-face => 'verdana, helvetica', -size => '2'},
' with ');
print $query->popup_menu(-name => 'catrows',
-values => [0,1,2,3,4,5,6,7,8,9,10],
-default => $catrows);
print $query->font({-face => 'verdana, helvetica', -size => '2'},
' category row(s) and ');
print $query->popup_menu(-name => 'keyrows',
-values => [0,1,2,3,4,5,6,7,8,9,10],
-default => $keyrows);
print $query->font({-face => 'verdana, helvetica', -size => '2'},
' keyword row(s).');
my ($menu, %menuhash) = &readDtd(); # read dtd into menu variable to pass to javascript
# and menu hash to deal with searched values
my $menu_catrow_forjavascript = 'var catrowmenu = new Array();'. "\n";
my $menu_catatt_forjavascript = 'var catattmenu = new Array();'. "\n";
my $menu_catspec_forjavascript = 'var catspecmenu = new Array();'. "\n";
if ($catrows > 0) {
for (my $i = 0; $i < $catrows; $i++) { # for each of the catrows
my $catname = 'none'; # init name of catcat
my $catindex = 0; # init index of catcat
my @catatt = (); # init array of attributes
my @catspec = (); # init array of specifications
my @selected_att_index = (); # array or selected catatt indices
my @selected_spec_index = (); # array or selected catspec indices
my @catrow = ();
my ($oop, $catcat) = &getHtmlVar($query, "catcat$i");
if ($catcat) { # if there was a value
@catatt = $query->param("catatt$i"); # get the catatt values
if ($menuhash{$catcat}{name}) { # if catcat has a name
$catname = $menuhash{$catcat}{name}; # pass the name
}
if ($menuhash{$catcat}{index}) { # if catcat has an index
$catindex = $menuhash{$catcat}{index}; # pass the index
}
foreach my $catatt (@catatt) { # for each of the catatt values from form
for (my $j = 0; $j < scalar(@{ $menuhash{$catcat}{vals} }); $j++) {
# for each possible value from menuhash
if ($catatt eq $menuhash{$catcat}{vals}[$j]) { # if they match
push @selected_att_index, $j; # add index to array for javascript
}
} # for (my $j = 0; $j < scalar(@{ $menuhash{$catcat}{vals} }); $j++)
} # foreach my $catatt (@catatt)
@catspec = $query->param("catspec$i"); # get the catspec values
foreach my $catspec (@catspec) { # for each of the catspec values from form
for (my $j = 0; $j < scalar(@specchoices); $j++) {
# for each possible value from menuhash
if ($catspec eq $specchoices[$j]) { # if they match
push @selected_spec_index, $j; # add index to array for javascript
}
} # for (my $j = 0; $j < scalar(@specchoices); $j++)
} # foreach my $catspec (@catspec)
} # if ($catcat)
push @catrow, $catindex;
push @catrow, $catname;
push @catrow, $catcat;
my $catrow = join"', '", @catrow;
$menu_catrow_forjavascript .= 'var menu' . $i . ' = new Array(\'' . $catrow . '\');' . "\n";
$menu_catrow_forjavascript .= 'catrowmenu[' . $i . '] = menu' . $i . ";\n";
# compose array of catatt selected indices to pass to javascript from search results
my $selected_att_index = join"', '", @selected_att_index;
$menu_catatt_forjavascript .= 'var attmenu' . $i . ' = new Array(\'' . $selected_att_index . '\');' . "\n";
$menu_catatt_forjavascript .= 'catattmenu[' . $i . '] = attmenu' . $i . ";\n";
my $selected_spec_index = join"', '", @selected_spec_index;
$menu_catspec_forjavascript .= 'var specmenu' . $i . ' = new Array(\'' . $selected_spec_index . '\');' . "\n";
$menu_catspec_forjavascript .= 'catspecmenu[' . $i . '] = specmenu' . $i . ";\n";
} # for (my $i = 0; $i < $catrows; $i++)
print <<"EndOfText";
EndOfText
} # if ($catrows > 0)
print <<"EndOfText";
EndOfText
} # sub displayMainForm
#
### FORM ###
### OUTPUT ###
### output goes here
#
sub displayOutput {
if (%searchresults) {
my $total = 0;
my $occurrence = 0;
my %keychecker = ();
foreach my $target (keys % searchresults) {
foreach my $key (keys %{ $searchresults{$target} }) {
if ((%{$searchresults{$target}{$key}}) && (!$keychecker{$key})) {$total++}
$keychecker{$key} = 1;
foreach my $sentence (keys % { $searchresults{$target}{$key} }) {
$occurrence ++;
}
}
}
print $query->hr;
print $query->start_b;
print $query->font({-face => 'verdana, helvetica', -size => '2'},
$occurrence, ' matches ', ' in ', $total, ' publication(s) found.');
print $query->end_b;
print $query->p;
print $query->submit(-name => 'lastsearch', -value => 'Display');
print $query->font({-face => 'verdana, helvetica', -size => '2'},
' page ');
my @choices;
$totalpages = int($total/($displayvalues{ResultsPerPage} || 10) + 1);
$query->param(-name => 'totalpages', -value => $totalpages);
for (my $j = 0; $j < $totalpages; $j++) {
push @choices, $j + 1;
}
print $query->popup_menu(-name =>'page',
-default => $displaypage,
-values => \@choices);
print $query->font({-face => 'verdana, helvetica', -size => '2'},
', or ');
print $query->submit(-name =>'previouspage', -value => 'previous');
print $query->font({-face => 'verdana, helvetica', -size => '2'},
' or ');
print $query->submit(-name =>'nextpage', -value => 'next');
print $query->font({-face => 'verdana, helvetica', -size => '2'},
' page.');
print $query->p;
print $query->submit(-name => 'emailresults', -value => 'E-mail');
print $query->font({-face => 'verdana, helvetica', -size => '2'},
' results to ');
print $query->textfield(-name => 'recipient',
-size => 35,
-maxlength => 255,
-default => $generalsettings{'Email'});
print $query->font({-face => 'verdana, helvetica', -size => '2'},
', ');
print $query->checkbox(-name => 'emailmatches',
-checked => 'checked',
-value => 'ON',
-label => 'including matches.');
(my $selectid = $lastsearchfilename) =~ s/\/tmp\/file//g;
my @giftable = ();
push @giftable, $query->a({-href => "introducepdf.cgi?id=$selectid",
-target => '_blank'},
$query->img({-src => "/text/gif/resultsinpdf.gif",
-border => 0, -alt => 'results in PDF'}))
.
$query->a({-href => "exportendnote.cgi?mode=aen&id=$selectid"},
$query->img({-src => "/text/gif/allend.jpg",
-border => 0, -alt => 'export endnote (all)'}))
.
$query->br
.
$query->a({-href => "showmatches.cgi?id=$selectid",
-target => '_blank'},
$query->img({-src => "/text/gif/viewallmatches.gif",
-border => 0, -alt => 'view all matches'}))
.
$query->a({-href => "exportendnote.cgi?mode=aea&id=$selectid"},
$query->img({-src => "/text/gif/alleab.jpg",
-border => 0, -alt => 'export endnote (all) with abstract'}));
my @minitable = ();
push @minitable, $query->td({-align => 'center', -valign => 'center'},
[
$query->img({-src => "/text/gif/vm.jpg", -width => "100%",
-border => 0, -align => 'center'}),
$query->font({-size => 1}, "view matches for respective reference"),
$query->img({-src => "/text/gif/ot.jpg", -width => "100%",
-border => 0, -align => 'center'}),
$query->font({-size => 1}, "journal's online text"),
$query->img({-src => "/text/gif/ra.jpg", -width => "100%",
-border => 0, -align => 'center'}),
$query->font({-size => 1}, "related articles (PubMed)")
]);
push @minitable, $query->td({-align => 'center', -valign => 'center'},
[
$query->img({-src => "/text/gif/en.jpg", -width => "100%",
-border => 0, -align => 'center'}),
$query->font({-size => 1}, "export bibliography for Endnote"),
$query->img({-src => "/text/gif/ea.jpg", -width => "100%",
-border => 0, -align => 'center'}),
$query->font({-size => 1}, "export bibliography including abstracts for Endnote"),
$query->img({-src => "/text/gif/pf.jpg", -width => "100%",
-border => 0, -align => 'center'}),
$query->font({-size => 1}, "download PDF of article ", $query->b("(Caltech only)"))
]);
push @giftable, $query->table({-border => '1', -cellpadding => '0',
-cellspacing => '0', -width => '80%'},
$query->caption("Abbreviation Index"),
$query->Tr([@minitable]));
print $query->p;
print $query->table({-border => '0', -cellpadding => '4',
-cellspacing => '1', -width => '100%'},
$query->Tr([$query->td({-align => 'left', -valign => 'center'},[@giftable])]));
@displayedkeys = DisplayAsHTML($query, $displaypage, \@expandedabs,
\%searchresults, $databaseroot, $lastsearchfilename,
\%displayoptions, \%displayvalues);
$query->param(-name => 'dispkeys', -value => [@displayedkeys]);
$query->param(-name => 'expandedabs', -value => [@expandedabs]);
print $query->p;
print $query->font({-face => 'verdana, helvetica', -size => '2'},
'Go to ');
print $query->submit(-name =>'previouspage', -value => 'previous');
print $query->font({-face => 'verdana, helvetica', -size => '2'},
' or ');
print $query->submit(-name =>'nextpage', -value => 'next');
print $query->font({-face => 'verdana, helvetica', -size => '2'},
' page.');
print $query->p;
} elsif (($lastsearchfilename ne "") && (!$query->param('querytable')) && (!$clearquery) && (!$query->param('lastquery'))) {
print $query->hr;
print $query->start_b;
print $query->font({-face => 'verdana, helvetica', -size => '2', -color => 'red'},
'No matches found.');
print $query->end_b;
} # if (%searchresults)
} # sub displayOutput
#
### OUTPUT ###
### end form here
#
# pass last search result file name to next round
sub passHidden {
print $query->hidden(-name => 'lsfilename', -default => $lastsearchfilename);
print $query->hidden(-name => 'dispkeys', -default => [@displayedkeys]);
print $query->hidden(-name => 'expandedabs', -default => [@expandedabs]);
print $query->hidden(-name => 'totalpages', -default => $totalpages);
} # sub passHidden
sub closeForm {
print $query->end_form;
print $query->end_html;
} # sub closeForm
#
###
### DISPLAY ###
### AUXILIARY SUBS ###
sub overrideCatAttCookies { # get cookie values to override catatt selections
my %lastadvancedquery = $query->cookie('lastadvancedquery'); # get last query cookie values
# foreach my $key (sort keys %lastadvancedquery) { print STDERR "$key\t$lastadvancedquery{$key}\n"; }
my ($menu, %menuhash) = &readDtd(); # need menu hash to deal with searched values
my $catrows = $lastadvancedquery{catrows};
for (my $i = 0; $i < $catrows; $i++) {
my $varname = "catcat" . $i; # get catcat to compare versus menuhash
my $catcat = $lastadvancedquery{$varname};
if ($catcat) { # if there's a value
$varname = "catatt" . $i;
my $catattlen = $varname . 'len'; # set length variable
my $length = $lastadvancedquery{$catattlen}; # pass variable
if ($length > 0) { # if there were values in cookie
for (my $j = 0; $j < $length; $j++) { # for each of those values
my $attattarrval = $varname . 'val' . $j; # set to get it
my $catatt = $lastadvancedquery{$attattarrval}; # pass it to $catatt
for (my $k = 0; $k < scalar(@{ $menuhash{$catcat}{vals} }); $k++) {
# for each possible value from menuhash
if ($catatt eq $menuhash{$catcat}{vals}[$k]) { # if they match
print "\n";
}
} # for (my $k = 0; $k < scalar(@{ $menuhash{$catcat}{vals} }); $k++)
} # for (my $j = 0; $j < $length; $j++)
} # if ($length > 0)
$varname = 'catspec' . $i; # get spec value
for (my $k = 0; $k < scalar(@specchoices); $k++) { # for each of the spec choices
if ($lastadvancedquery{$varname} eq $specchoices[$k]) { # if they match
print "\n";
}
}
} # if ($catcat)
} # for (my $i = 0; $i < $catrows; $i++)
} # sub overrideCatAttCookies
sub PrintHeader { # begin PrintHeader
my $query = shift;
my @cookies = ();
while (@_) { push @cookies, shift(@_)}
$|=1;
print $query->header(-cookie=>[@cookies]);
print $query->start_html(-title=>'Advanced Retrieval', -author=>'Hans-Michael Muller',
-bgcolor=>'#e6e6f6',
-text=>'#000000', -link=>'#662222', -vlink=>'#993333');
print $query->br;
print $query->font({-face => 'verdana, arial, helvetica', -size => '5'}, 'Advanced Retrieval');
print $query->p;
} # end PrintHeader
sub ReadElements {
my $dtdfile = shift;
my %labels = ();
$labels { "" } = "none"; # include empty tag for search
open (DTDFILE, "$dtdfile") or die "Can't open DTD file $dtdfile.";
while (my $line = ) {
chomp ($line);
if ($line =~ / <\!--\s((\w|\s)+)\s-->/) {
my $key = $1;
my $label = $2;
# print STDERR "ReadElements\t$key\t$label\n";
if (($key ne "sentence") && ($key ne "article")){ #because pattern above is more specific, this isn't really necessary
$labels { substr($key, 0, 2) } = $label;
}
}
}
close (DTDFILE);
return %labels;
}
sub ReadAttributes {
my $dtdfile = shift;
my @names_codes_and_attributes = ();
open (DTDFILE, "$dtdfile") or die "Can't open DTD file $dtdfile.";
while (my $line = ) {
chomp ($line);
if ($line =~ / /) {
my $official_attribute_name = $2;
my $label = $7;
my @values = split(/\s\|\s/, $5);
foreach my $value (@values) {
my $key = $official_attribute_name . " " . $value . " (" . $label . ")";
push @names_codes_and_attributes, $key;
}
}
}
close (DTDFILE);
return (@names_codes_and_attributes);
}
sub DisplayAsHTML {
my $query = shift;
my $page = shift;
my $pExpandedabs = shift;
my $pSearchresults = shift;
my $databaseroot = shift;
my $selectfilename = shift;
my $pDisplayoptions = shift;
my $pDisplayvalues = shift;
my %sortscorelist = SortedList($pSearchresults);
my @tablecontent = ();
my @displayedkeys = ();
# make headline
my @columns = DefineColumns($pDisplayoptions);
push @tablecontent, $query->th([@columns]);
# fill table
my $counter = 0;
foreach my $score (sort numerically keys % sortscorelist) {
foreach my $key (sort keys %{$sortscorelist{$score}}) {
$counter++;
next unless ($counter > $displayvalues{ResultsPerPage}*($page-1));
next unless ($counter <= $displayvalues{ResultsPerPage}*$page);
my $expanded = 0;
foreach my $element (@$pExpandedabs) { next unless ($element eq $key); $expanded = 1;}
my @columns = FillColumns($query, $databaseroot, $selectfilename, $pDisplayoptions,
$pSearchresults, $key, $score, $expanded);
push @tablecontent, $query->td([@columns]);
push @displayedkeys, $key;
}
}
print $query->table({-border => '1', -cellpadding => '4',
-cellspacing => '1', -width => '100%'},
$query->caption($query->b("Search Results")),
$query->Tr([@tablecontent]));
return @displayedkeys;
} # sub DisplayAsHTML
sub SortedList { # for DisplayAsHtml
my $pSearchresults = shift;
my %scorelist = ();
foreach my $target (keys % {$pSearchresults}) {
foreach my $key (keys % { $$pSearchresults{$target} }) {
foreach my $sentence (keys % { $$pSearchresults{$target}{$key} }) {
$scorelist{$key} += $searchresults{$target}{$key}{$sentence};
}
}
}
my %sortscorelist = ();
foreach my $key (keys % scorelist) {
$sortscorelist{$scorelist{$key}}{$key} = 1;
}
return %sortscorelist;
} # sub SortedList
sub numerically { $b <=> $a }
sub DefineColumns { # for DisplayAsHtml
my $pDisplayoptions = shift;
my @columns = ();
if ($$pDisplayoptions{'Source Type'}) { push @columns, 'Publication type' }
if ($$pDisplayoptions{Title}) { push @columns, 'Title' }
if ($$pDisplayoptions{Abstract}) { push @columns, 'Abstract' }
if ($$pDisplayoptions{Author}) { push @columns, 'Author' }
if ($$pDisplayoptions{Journal}) { push @columns, 'Journal' }
if ($$pDisplayoptions{Year}) { push @columns, 'Year' }
if ($$pDisplayoptions{Citation}) { push @columns, 'Citation' }
if ($$pDisplayoptions{'Number of matches'}) { push @columns, 'Number of matches' }
if ($$pDisplayoptions{Select}) { push @columns, 'Select' }
return @columns;
}
sub FillColumns { # for DisplayAsHtml
my $query = shift;
my $databaseroot = shift;
my $selectfilename = shift;
my $pDisplayoptions = shift;
my $pSearchresults = shift;
my $key = shift;
my $score = shift;
my $expanded = shift;
my @columns = ();
if ($$pDisplayoptions{'Source Type'}) {
my $content = join ("\n", GetContents("$databaseroot/typ/$key"));
$content =~ s/\_/ /g;
push @columns, "\L$content\E";
}
if ($$pDisplayoptions{Title}) {
my @aux = GetContents("$databaseroot/tit/xml/$key");
my $content = join ("\n", WormBaseLinks ("$databaseroot/ind/wbl/tit/$key",
"$databaseroot/wbl/", $query, @aux));
push @columns, $content;
}
if ($$pDisplayoptions{Abstract}) {
my @aux = GetContents("$databaseroot/abs/xml/$key");
my @neat = WormBaseLinks ("$databaseroot/ind/wbl/abs/$key",
"$databaseroot/wbl/", $query, @aux);
my $content;
if ($expanded) {
$content = join ("\n", @neat);
if ($content) {
$content .= $query->submit(-name => "collapse$key",
-value => 'Collapse abstract');
}
} else {
$content = $neat[3] . $neat[4];
if ($content) {
$content .= $query->submit(-name => "expanded$key",
-value => 'Expand abstract');
}
}
push @columns, $content;
}
if ($$pDisplayoptions{Author}) {
my $content = join ("\n", GetContents("$databaseroot/aut/$key"));
$content =~ s/\n/
/g;
push @columns, $content;
}
if ($$pDisplayoptions{Journal}) {
my $content = join ("\n", GetContents("$databaseroot/jou/$key"));
push @columns, $content;
}
if ($$pDisplayoptions{Year}) {
my $content = join ("\n", GetContents("$databaseroot/yea/$key"));
push @columns, $content;
}
if ($$pDisplayoptions{Citation}) {
my $content = join ("\n", GetContents("$databaseroot/cit/$key"));
$content =~ s/P\:\s+(\d+)\s+(\d+)/Pages $1-$2/g;
$content =~ s/V\:/
Vol\./g;
push @columns, $content;
}
if ($$pDisplayoptions{'Number of matches'}) {
push @columns, $score;
}
if ($$pDisplayoptions{Select}) {
my $content = $query->start_center;
$content .= "$key";
$content .= $query->end_center;
if (!-e "$databaseroot/$selectfilename\.$key") {
open (IN, "$databaseroot/$selectfilename");
my $firstline = ;
my $secondline = ;
close (IN);
open (OUT, ">$databaseroot/$selectfilename\.$key");
print OUT $firstline;
print OUT $secondline; # make sure queries are saved.
foreach my $target (keys %{ $pSearchresults}) {
print OUT $target . "," . $key . ",";
foreach my $sentence (keys % { $$pSearchresults{$target}{$key} }) {
print OUT $sentence . ",";
}
print OUT "\n";
}
close (OUT);
}
(my $selectid = "$selectfilename\.$key") =~ s/\/tmp\/file//g;
$content .= $query->start_center;
$content .= $query->a({-href => "showmatches.cgi?id=$selectid", -target => '_blank'},
$query->img({-src => "/text/gif/vm.jpg",
-border => 0, -alt => 'view matches'}));
if (-e "$databaseroot/pdf/$key.pdf") {
if ($query->remote_host() =~ /(131\.215\.|\.caltech\.edu)/) {
$content .= $query->a({href => "/text/tdb/pdf/$key.pdf", target => "_blank"},
$query->img({-src => "/text/gif/pf.jpg", -border => 0, -alt => 'PDF'}));
}
}
if (-e "$databaseroot/url/$key") {
open (URL, "$databaseroot/url/$key");
my $url = ;
chomp ($url);
$content .= $query->a({href => "$url", target => "_blank"},
$query->img({-src => "/text/gif/ot.jpg", -border => 0, -alt => 'article text from journal'}));
close(URL);
}
if (-e "$databaseroot/rel/$key") {
open (URL, "$databaseroot/rel/$key");
my $url = ;
chomp ($url);
$content .= $query->a({href => "$url", target => "_blank"},
$query->img({-src => "/text/gif/ra.jpg", -border => 0, -alt => 'related articles'}));
close(URL);
}
if (-e "$databaseroot/end/$key") {
$content .= $query->a({href => "exportendnote.cgi?mode=sen&id=$key"},
$query->img({-src => "/text/gif/en.jpg", -border => 0, -alt => 'Endnote'}));
}
if (-e "$databaseroot/eab/$key") {
$content .= $query->a({href => "exportendnote.cgi?mode=sea&id=$key"},
$query->img({-src => "/text/gif/ea.jpg", -border => 0, -alt => 'Endnote (w/ abstract)'}));
}
$content .= $query->end_center;
push @columns, $content;
}
return @columns;
}
sub GetContents { # for FillColumns # for DisplayAsHtml
my $filename = shift;
my @return = ();
open (IN,"$filename");
while (my $line = ) {
chomp ($line);
push @return, $line;
}
close (IN);
return @return;
}
sub WormBaseLinks {
my $indexfile = shift;
my $linkdir = shift;
my $query = shift;
my @lines = ();
while (@_) {push @lines, shift;}
if (-e "$indexfile") {
my %indexcontent = ();
open (INDEX, $indexfile);
while (my $line = ) {
chomp $line;
my @words = split(/\t/, $line);
my $id = shift(@words);
while (@words) { push @{ $indexcontent{$id} }, shift(@words)};
}
close (INDEX);
for (my $i = 0; $i < @lines; $i++) {
if ($lines[$i] =~ ///g; # remove xml brackets
$lines[$i] =~ s/<\/.+?>//g;
if ($indexcontent{$id}) {
while (@{$indexcontent{$id}}) {
my $term = shift (@{$indexcontent{$id}});
(my $lookup = $term) =~ s/\s//g;
my $lcflookup = lcfirst($lookup);
open (URL, "$linkdir/$lookup") or open(URL, "$linkdir/$lcflookup");
my $url = ;
close (URL);
if ($url) {
chomp($url);
my $replacement = " " . $query->a({-href => $url, -target => '_blank'}, "$term") . " ";
$lines[$i] =~ s/(^|\s)$term($|\s)/$replacement/g;
}
}
}
} else {
$lines[$i] =~ s/<.+?>//g; # remove xml brackets
$lines[$i] =~ s/<\/.+?>//g;
}
}
}
return @lines;
}
sub GetListFromKeyword { # %searchresult or %auxlist for if ($query->param('search'))
my $indexkey = shift;
my $pTargetdirectories = shift;
my $keyword = shift;
my $pSearchtargets = shift;
my $numcomp = shift;
my $numofmatches = shift;
my %result = ();
foreach my $target (keys % $pSearchtargets) {
if ($$pSearchtargets{$target}) {
my $keydir = $indexkey . $$pTargetdirectories{$target};
my $lowered = "\L$keyword\E";
my @keywordfiles = <$keydir/$lowered>;
foreach my $file (@keywordfiles) {
open (INKEY, "$file");
print $query->b($query->font({-face => 'verdana, helvetica', -size => '2', color => 'green'}, '.'));
while (my $line = ) {
chomp ($line);
my @entry = split(/\,/, $line);
my $key = shift (@entry);
foreach my $sentence (@entry) {
$result{$target}{$key}{$sentence}++;
}
}
close (INKEY);
foreach my $key (keys %{$result{$target}}) {
if ($numcomp eq 'equal to') {
foreach my $sentence (keys %{$result{$target}{$key}}) {
if ($result{$target}{$key}{$sentence} != $numofmatches) {
delete $result{$target}{$key}{$sentence};
}
}
} elsif ($numcomp eq 'greater than') {
foreach my $sentence (keys %{$result{$target}{$key}}) {
if ($result{$target}{$key}{$sentence} <= $numofmatches) {
delete $result{$target}{$key}{$sentence};
}
}
} elsif ($numcomp eq 'less than') {
foreach my $sentence (keys %{$result{$target}{$key}}) {
if ($result{$target}{$key}{$sentence} >= $numofmatches) {
delete $result{$target}{$key}{$sentence};
}
}
}
}
}
}
}
# delete all $result{$target}{$key} if empty
foreach my $target (keys % result) {
foreach my $key (keys %{$result{$target}}) {
my @aux = keys %{$result{$target}{$key}};
delete $result{$target}{$key} if (@aux < 1);
}
}
return %result;
} # sub GetListFromKeyword
sub GetListFromCategories { # %searchresult or %auxlist for if ($query->param('search'))
my $indexattspec = shift;
my $databaseroot = shift;
my $pTargetdirectories = shift;
my $category = shift;
my $pSearchtargets = shift;
my $pAttnmecde = shift;
my $pAttributes = shift;
my $specification = shift;
my $numcomp = shift;
my $numofmatches = shift;
my %result = ();
foreach my $target (keys % $pSearchtargets) {
if ($$pSearchtargets{$target}) {
my %checklist = ();
my $total = 1;
my $filename = $indexattspec . "/" . $$pTargetdirectories{$target} . "/" . $category . "/" ."cat" . $category;
open (INCAT, "$filename");
print $query->b($query->font({-face => 'verdana, helvetica', -size => '2', -color => 'green'}, '.'));
while (my $line = ) {
chomp ($line);
my @entry = split (/\,/, $line);
my $key = shift (@entry);
foreach my $id (@entry) {
(my $sentence, my $token) = split(/-/, $id);
$checklist{$key}{$sentence}{$token}++;
}
}
close (INCAT);
if (@$pAttributes > 0) {
my @locallist = ();
foreach my $key (@$pAttributes) { push @locallist, $$pAttnmecde{$key}}
$total += @locallist;
foreach my $entry (sort @locallist) {
(my $localname, my $localcde) = split(/ /, $entry);
my $filename = $indexattspec . "/" .$$pTargetdirectories{$target} . "/" . $category . "/" . $localcde;
open (ATT, "$filename");
while (my $line = ) {
chomp ($line);
my @entry = split (/\,/, $line);
my $key = shift (@entry);
foreach my $id (@entry) {
(my $sentence, my $token) = split(/-/, $id);
$checklist{$key}{$sentence}{$token}++;
}
}
close (ATT);
}
}
if (($specification eq 'named') || ($specification eq 'unnamed')) {
$total += 1;
my $spec = ($specification eq 'named') ? 'd' : 'i';
my $filename = $indexattspec . "/" . $$pTargetdirectories{$target} . "/" . $category . "/" ."spec" . $spec;
open (SPEC, "$filename");
while (my $line = ) {
chomp($line);
my @entry = split (/\,/, $line);
my $key = shift (@entry);
foreach my $id (@entry) {
(my $sentence, my $token) = split(/-/, $id);
$checklist{$key}{$sentence}{$token}++;
}
}
close (SPEC);
}
foreach my $key (keys % checklist) {
foreach my $sentence (keys %{$checklist{$key}}) {
foreach my $token (keys %{$checklist{$key}{$sentence}}) {
if ($checklist{$key}{$sentence}{$token} == $total) {
$result{$target}{$key}{$sentence}++;
}
}
}
}
# compare to numofmatches here
foreach my $key (keys %{$result{$target}}) {
if ($numcomp eq 'equal to') {
foreach my $sentence (keys %{$result{$target}{$key}}) {
if ($result{$target}{$key}{$sentence} != $numofmatches) {
delete $result{$target}{$key}{$sentence};
}
}
} elsif ($numcomp eq 'greater than') {
foreach my $sentence (keys %{$result{$target}{$key}}) {
if ($result{$target}{$key}{$sentence} <= $numofmatches) {
delete $result{$target}{$key}{$sentence};
}
}
} elsif ($numcomp eq 'less than') {
foreach my $sentence (keys %{$result{$target}{$key}}) {
if ($result{$target}{$key}{$sentence} >= $numofmatches) {
delete $result{$target}{$key}{$sentence};
}
}
}
}
}
}
# delete all $result{$target}{$key} if empty
foreach my $target (keys % result) {
foreach my $key (keys %{$result{$target}}) {
my @aux = keys %{$result{$target}{$key}};
delete $result{$target}{$key} if (@aux < 1);
}
}
return %result;
} # sub GetListFromCategories
sub OrLists { # %searchresult for if ($query->param('search'))
my $pListA = shift;
my $pListB = shift;
my %result = ();
foreach my $target (keys % $pListA) {
foreach my $key (keys %{$$pListA{$target}}) {
foreach my $sentence (keys %{$$pListA{$target}{$key}}) {
$result{$target}{$key}{$sentence} = 1;
}
}
}
foreach my $target (keys % $pListB) {
foreach my $key (keys %{$$pListB{$target}}) {
foreach my $sentence (keys %{$$pListB{$target}{$key}}) {
$result{$target}{$key}{$sentence} = 1;
}
}
}
return %result;
}
sub AndLists { # %searchresult for if ($query->param('search'))
my $pListA = shift;
my $pListB = shift;
my $mode = shift;
my %result = ();
foreach my $target (keys % $pListA) {
foreach my $key (keys %{$$pListA{$target}}) {
foreach my $sentenceA (keys %{$$pListA{$target}{$key}}) {
if ($mode eq 'sentence') {
if ($$pListB{$target}{$key}{$sentenceA}) {
$result{$target}{$key}{$sentenceA} = 1;
}
} elsif ($mode eq 'publication') {
foreach my $sentenceB (keys %{$$pListB{$target}{$key}}) {
$result{$target}{$key}{$sentenceA} = 1;
$result{$target}{$key}{$sentenceB} = 1;
}
}
}
}
}
return %result;
}
sub ListAAndNotListB { # %searchresult for if ($query->param('search'))
my $pListA = shift;
my $pListB = shift;
my $mode = shift;
my %result = ();
foreach my $target (keys % $pListA) {
foreach my $key (keys %{$$pListA{$target}}) {
foreach my $sentenceA (keys %{$$pListA{$target}{$key}}) {
if ($mode eq 'sentence') {
if (!$$pListB{$target}{$key}{$sentenceA}) {
$result{$target}{$key}{$sentenceA} = 1;
}
} elsif ($mode eq 'publication') {
$result{$target}{$key}{$sentenceA} = 1 if (keys %{$$pListB{$target}{$key}} < 1);
}
}
}
}
return %result;
}
sub readDtd {
my $dtdfile = '/var/www/html/text/textpresso.dtd';
$/ = ''; # set <> to paragraph mode
open (DTD, "$dtdfile") or die "Can't open DTD file $dtdfile.";
my %menuhash; # hash of menu stuff key is catcatvalue
# name is catcatname vals are catattvalues
my $menu1 = ''; # parts of array
my %readElementsCompatibility; # sub ReadElements outputs a hash that is sorted
# this hash is just to sort these values
my %readElementsSpecCompatibility; # like above
my $menu2 = 'var menu = new Array();' . "\n"; # full array of arrays
my $menuspec1 = ''; # parts of array for specification
my $menuspec2 = 'var menuspec = new Array();' . "\n"; # full array of arrays for specification
my @orig_menu_name = ('none'); # want original value to be empty so don't pass values where not selected
my @orig_menu_val = (' '); # init menu
my %orig_menu_name; # hash to filter (sort) values by key value
my $count1 = 1; # count of first submenu
while (my $entry = ) { # while there are paragraphs in dtd
next unless ($entry =~ m/ELEMENT.*!--/); # skip non-data lines
my @lines = split /\n/, $entry; # break paragraphs into lines
my ($main_val, $main_name) = $lines[0] =~ m/ELEMENT\s+(\w\w)\w*? .*!-- (.*?) --/;
$orig_menu_name{$main_val} = $main_name;
$menuhash{$main_val}{name} = $main_name;
$menuhash{$main_val}{index} = $count1;
my @groupN2_vals = qw(); # array of values for menu$count1
my @groupSpec_vals = qw(); # array of values for menuspec$count1
foreach my $line (@lines) { # check each line for implied attributes for second column
if ($line =~ / /) {
my $label = $7;
my @values = split(/\s\|\s/, $5);
foreach my $value (@values) {
$value =~ s/^\w+\-//g; # take out the first 2 letters and hyphen
$value = $label . ": " . $value;
push @groupN2_vals, $value;
push @{ $menuhash{$main_val}{vals} }, $value;
} # foreach my $value (@values)
} # if ..
if ($line =~ m/ 0 ) { push @groupSpec_vals, 'all'; }
} # if ($line =~ m/)
close (DTD);
$/ = "\n"; # reset <> to line at a time
my $count2 = 1; # count of first submenu
foreach (sort keys %readElementsCompatibility) {
$menu1 .= 'var menu' . $count2 . $readElementsCompatibility{$_};
$menu2 .= 'menu[' . $count2 . '] = menu' . $count2 . ";\n";
$menuspec1 .= 'var menuspec' . $count2 . $readElementsSpecCompatibility{$_};
$menuspec2 .= 'menuspec[' . $count2 . '] = menuspec' . $count2 . ";\n";
$count2++;
} # foreach (sort keys %readElementsCompatibility)
foreach (sort keys %orig_menu_name) { push @orig_menu_val, $_; push @orig_menu_name, $orig_menu_name{$_}; }
# get the hash values sorted into the arrays
my $orig_menu_name = join"', '", @orig_menu_name;
my $orig_menu_val = join"', '", @orig_menu_val;
my $menu3 = 'var orig_menu_name = new Array(\'' . $orig_menu_name . '\');' . "\n";
my $menu4 = 'var orig_menu_val = new Array(\'' . $orig_menu_val . '\');' . "\n";
my $menu = $menu1 . $menu2 . $menuspec1 . $menuspec2 . $menu3 . $menu4;
return ($menu, %menuhash);
} # sub readDtd
sub getHtmlVar { # get variables from html form and untaint them
no strict 'refs'; # need to disable refs to get the values
# possibly a better way than this
my ($query, $var, $err) = @_; # get the CGI query val,
# get the name of the variable to query->param,
# get whether to display and error if no such
# variable found
unless ($query->param("$var")) { # if no such variable found
if ($err) { # if we want error displayed, display error
print "ERROR : No such variable : $var
\n";
} # if ($err)
} else { # unless ($query->param("$var")) # if we got a value
my $oop = $query->param("$var"); # get the value
$$var = &untaint($oop); # untaint and put value under ref
return ($var, $$var); # return the variable and value
} # else # unless ($query->param("$var"))
} # sub getHtmlVar
sub untaint {
my $tainted = shift;
my $untainted;
if ($tainted eq "") {
$untainted = "";
} else { # if ($tainted eq "")
$tainted =~ s/[^\w\-.,;:?\/\\@#\$\%\^&*(){}[\]+=!~|' \t\n\r\f]//g;
if ($tainted =~ m/^([\w\-.,;:?\/\\@#\$\%&\^*(){}[\]+=!~|' \t\n\r\f]+)$/) {
$untainted = $1;
} else {
die "Bad data in $tainted";
}
} # else # if ($tainted eq "")
return $untainted;
} # sub untaint
### AUXILIARY SUBS ###