#!/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 ###