#!/usr/local/bin/perl ################################################################################ # # File name: search # Project: PEERS # Description: Search the PEERS directory # # # External documents: # # # Author: Peter Haworth # Date created: 1996 # # sccs version: 1.3 last changed: 04/27/99 # # Copyright Institute of Physics Publishing 1999 # ################################################################################ require 'IOPP/PEERS.pl'; require 'IOPP/hdbm.pl'; use TextSearch; use CGI; # These are the search types available %stypes=( string => q( Phrases. For example, "time and space" finds records containing the phrase "time and space" ), expr => q( Boolean Expressions. For example, "time and space" finds records containing the words "time" and "space" ), ); my $uri=$PEERS_admin ? "$PEERS_cgi/Admin" : $PEERS_cgi; $query=CGI->new; &escapeHTML_query($query); $query->import_names('query'); $query->autoEscape(undef); @args=split('/',$query->path_info); shift @args; while($arg=$args[0]){ if($arg=~/^_(\d+)_(\d+)$/){ ($seqn,$start)=($1,$2); shift @args; }elsif($arg=~/^__(\d+)$/){ $anticache=$1; shift @args; }elsif($PEERS_admin && $arg=~/^_(\d+)_dump$/){ $seqn=$1; $do_dump=1; shift @args; }else{ last; } } if($seqn){ # Read previously generated search results if(&hdbm_read(\%searchdb,$PEERS_searchdb)){ if(@searchrec=split(/\0/,$searchdb{$seqn})){ @hits=split(/\001/,$searchrec[$PEERS_search_results]); $nhits=@hits; }else{ push @errors,"No such search record: $seqn"; } }else{ push @errors,"The search database cannot be opened: $!"; } undef $do_dump if @errors; }elsif($query::submitting){ # Process a request, putting any errors in @errors @query::itype=grep($_ ne '.all',@query::itype); foreach(qw(sname dept inst itype ctry subj)){ my($terms,@values)=$_ eq 'itype' ? ($query::itype_other,@query::itype) : (${"query::$_"}) ; my $search=new TextSearch($query::stype,'or', "\$field=\$data->[\$PEERS_db_$_]",$terms,[@values],\&push_error); if($search){ $search{$_}=$search->{'code'}; } } if($code=join('','my $field;',values %search)){ my $sub=eval($code=join('','sub{my($data)=@_;',$code,"1}\n")) or push @errors,"$code$@"; my $sort1=${"PEERS_db_$query::sort1"}; $sort1=$PEERS_db_sname if $sort1 eq ''; my $sort2=$query::sort2=~/\w/ ? ${"PEERS_db_$query::sort2"} : $PEERS_db_sname; $sort2=$PEERS_db_sname if $sort2 eq ''; my $sortcode="sub{my(\$key,\@record)=\@_; lc \"\$record[$sort1]\\0\$record[$sort2]\\0\$record[$PEERS_db_fname]\\0\$key\"}\n"; my $sort=eval $sortcode or push @errors,"$sortcode$@"; if(!@errors){ if(&hdbm_read(\%emaildb,$PEERS_emaildb)){ while(($key,$record)=each %emaildb){ @record=split(/\0/,$record); if(&$sub(\@record)){ push @hits,&$sort($key,@record); if(++$nhits>$PEERS_search_m){ push @errors,"Your search matched more than $PEERS_search_m records. Please narrow your search terms."; last; } } } untie %emaildb; if($nhits){ $query::itype=join(' or ',grep($_,(map {$PEERS_itypes{$_}} @query::itype),$query::itype_other)); @hits=map {(split(/\0/))[-1]} sort @hits; if(&hdbm_write(\%searchdb,$PEERS_searchdb)){ $seqn=$searchdb{'_seqn_'}; ++$seqn; $searchdb{'_seqn_'}=$seqn; @searchrec=(); foreach(qw(sname dept inst itype ctry subj)){ $searchrec[${"PEERS_search_$_"}]=${"query::$_"}; } $searchrec[$PEERS_search_time]=time; $searchrec[$PEERS_search_results]=join("\001",@hits); $searchdb{$seqn}=join("\0",@searchrec); untie %searchdb; $PEERS_helpurl=~s|/$PEERS_script.*|/$PEERS_script/_${seqn}_0|; }else{ push @errors,"the search database cannot be opened: $!"; } }else{ push @errors,"Your search terms matched none of the records in the directory."; } }else{ push @errors,"The database cannot be opened: $!"; } } }else{ push @errors,"You must define your search terms."; } } if($nhits){ $title='Search Results'; $help='results'; $up="$uri/search"; }else{ $title='Search'; $help='search'; $up="$uri/main"; } if($do_dump){ print qq(Content-type: text/comma-separated-values; name="peers.csv"\n); print qq(Content-disposition: file; filename="peers.csv"\n); print "\n"; print "email,title,forename,surname,address,department,institute,inst_type,job_title,subject_interest,country,phone,url,iop_member\n"; }else{ &printHeader("$PEERS_name: $title",$title,{'up'=>$up},undef,[$help,($nhits?('main','search'):('main')),'add','update']); print "$IopStyle::TABLE\n"; } if($nhits && !@errors){ if(&hdbm_read(\%emaildb,$PEERS_emaildb)){ if($do_dump){ foreach(@hits){ my @record=split(/\0/,$emaildb{$_}) or next; my @data; foreach(qw( email title fname sname addr dept inst itype job subj ctry phone url iop )){ my $field=$record[${"PEERS_db_$_"}]; if($_ eq 'itype'){ $field=$PEERS_itypes{$field}; }elsif($_ eq 'iop'){ $field=$field ? 'Y' : 'N'; } $field=~s/"/""/g; $field=~s/[\n\r]+\s*/, /gs; push @data,"\"$field\""; }; print join(',',@data),"\n"; } }else{ $start=$start || 0; $start1=$start+1; $end=$start+$PEERS_search_n; if($end>$nhits){ $end=$nhits; } if($start || $end<$nhits){ if($start){ my $pstart=$start-$PEERS_search_n; $pntext=qq%[<< Previous Page]\n%; } if($end<$nhits){ my $nstart=$start+$PEERS_search_n; $pntext.=qq%[Next Page >>]\n%; } } print "

Your search matched $nhits records.\n"; print "Displaying hits $start1 to $end.\n$pntext" if $nhits>$PEERS_search_n; print qq(

Download results as CSV file\n) if $PEERS_admin; print "

"; print "Surname: $sname\n" if $sname=$searchrec[$PEERS_search_sname]; print "
Department: $dept\n" if $dept=$searchrec[$PEERS_search_dept]; print "
Institution/Company: $inst\n" if $inst=$searchrec[$PEERS_search_inst]; print "
Type of Institution: $itype\n" if $itype=$searchrec[$PEERS_search_itype]; print "
Country: $ctry\n" if $ctry=$searchrec[$PEERS_search_ctry]; print "
Subject: $subj\n" if $subj=$searchrec[$PEERS_search_subj]; print "

); } print "
\n"; foreach $number ($start..$end-1){ my $bg = ($number / 2.0 == int($number / 2)) ? '#ffffff' : '#bbdbbd'; my $key=$hits[$number]; @record=split(/\0/,&escapeHTML($emaildb{$key})); $key=&urlEncode($key); print qq(
[Details] $record[$PEERS_db_sname], $record[$PEERS_db_fname], $record[$PEERS_db_inst]
$record[$PEERS_db_email]

$IopStyle::TABLE\n"; untie %emaildb; print "

$pntext

" if $nhits>$PEERS_search_n; } }else{ push @errors,"the e-mail database cannot be opened: $!"; } } # Print any errors, then the search form if(@errors || !$query::submitting && !$nhits){ if(@errors){ print "

Sorry, your request could not be processed because of the following:

$IopStyle::HR

\n"; }else{ print qq%

Thank you for using this service. We hope that you will find it quick, easy and useful. Searches are performed by completing one or more of the fields below, then pressing one of the `Search' buttons. %; } if(!$anticache){ if(&hdbm_read(\%searchdb,$PEERS_searchdb)){ $anticache=$searchdb{'_seqn_'}; untie %searchdb; }else{ $anticache=time^$$; } } # print "\n"; print <<'!END!';

 
 
!END! print $query->startform('POST',"$uri/search/__$anticache"); print $query->hidden('submitting',1); print "
\n"; print "
",$query->submit('',' Search '),"\n"; print qq%Help is available.\n%; print "
Surname:
",$query->textfield('sname','',60),"\n"; print "
Department:
",$query->textfield('dept','',60),"\n"; print "
Name of Institution/Company:
",$query->textfield('inst','',60),"\n"; @itypes=sort grep($_ ne '.z.other',keys %PEERS_itypes); print "
Type of Institution:
",$query->checkbox_group( -name => 'itype', -values => ['.all',@itypes], -labels => {%PEERS_itypes, '.all' => ' All '}, ),"\n"; print "
or Other: ",$query->textfield('itype_other','',50),"\n"; print "
Country:
",$query->textfield('ctry','',60),"\n"; print "
Subject of interest:
",$query->textfield('subj','',60),"\n"; print "
Sort results by:
"; print $query->popup_menu('sort1',\@PEERS_search_by_order,'sname',\%PEERS_db_fnames),"\n"; print $query->popup_menu('sort2',['-',@PEERS_search_by_order],'-',{'-'=>'Secondary sort (optional)',%PEERS_db_fnames}),"\n"; print "
Search terms are:
"; $query->autoEscape(undef); print $query->radio_group('stype',['string','expr'],'string','true',\%stypes); $query->autoEscape('true'); print qq% Help is available for boolean search terms. %; print "

",$query->submit('',' Search '); print "
\n"; print $query->endform; print <<"!END2!";
 
 

!END2! # print "$IopStyle::TABLE\n"; } &printFooter($help,$nhits?('main','search'):('main'),'add','update','help') unless $do_dump; sub push_error{ my($type,$error)=@_; push @errors,$error if $type eq 'fatal'; }