Diff for /loncom/interface/lonsearchcat.pm between versions 1.98 and 1.107

version 1.98, 2001/08/26 21:19:35 version 1.107, 2001/11/28 19:30:32
Line 3 Line 3
 # Search Catalog  # Search Catalog
 #  #
 # YEAR=2001  # YEAR=2001
 # 03/08/2001 Scott Harrison  # 3/8, 3/12, 3/13, 3/14, 3/15, 3/19 Scott Harrison
 # Scott Harrison: 03/12/2001, 03/13/2001, 03/14/2001, 03/15/2001, 03/19/2001  # 3/20, 3/21, 3/22, 3/26, 3/27, 4/2, 8/15, 8/24, 8/25 Scott Harrison
 # Scott Harrison: 03/20/2001, 03/21/2001, 03/22/2001, 03/26/2001, 03/27/2001  # 10/12,10/14,10/15,10/16,11/28 Scott Harrison
 # Scott Harrison: 04/02/2001, 08/15/2001, 08/24/2001, 08/25/2001  #
   # $Id$
   ###
   
 ###############################################################################  ###############################################################################
 ##                                                                           ##  ##                                                                           ##
 ## ORGANIZATION OF THIS PERL MODULE                                          ##  ## ORGANIZATION OF THIS PERL MODULE                                          ##
 ##                                                                           ##  ##                                                                           ##
 ## 1. Description of functions                                               ##  ## 1. Modules used by this module                                            ##
 ## 2. Modules used by this module                                            ##  ## 2. Choices for different output views (detailed, summary, xml, etc)       ##
 ## 3. Choices for different output views (detailed, summary, xml, etc)       ##  ## 3. BEGIN block (to be run once after compilation)                         ##
 ## 4. BEGIN block (to be run once after compilation)                         ##  ## 4. Handling routine called via Apache and mod_perl                        ##
 ## 5. Handling routine called via Apache and mod_perl                        ##  ## 5. Other subroutines                                                      ##
 ## 6. Other subroutines                                                      ##  
 ##                                                                           ##  ##                                                                           ##
 ###############################################################################  ###############################################################################
   
 # ---------------------------------------------------- Description of functions  
 #  
 #  
 # === WEB HANDLER FUNCTIONS  
 # BEGIN() : run once after compilation to initialize values  
 # handler(server reference) : interacts with the Apache server layer  
 #                             (for /adm/searchcat URLs)  
 # get_unprocessed_cgi() : reads in critical name/value pairs that may have not  
 #                         been processed and passed into %ENV by the web server  
 # make_persistent() : makes a set of hidden HTML fields to make  
 #                     SQL search interface information to be persistent  
 #  
 #  
 # === WEB INTERFACE COMPONENT FUNCTIONS  
 # simpletextfield(name,value) : returns HTML formatted string for simple text  
 #                               field  
 # simplecheckbox(name,value) : returns HTML formatted string for simple  
 #                              checkbox  
 # searchphrasefield(title,name,value) : returns HTML formatted string for  
 #                                       a search expression phrase field  
 # dateboxes(name, defaultmonth, defaultday, defaultyear) : returns HTML  
 #                                                          formatted string  
 #                                                          for a calendar date  
 # selectbox(title,name,value,%HASH=options) : returns HTML formatted string for  
 #                                             a selection box field  
 #  
 #  
 # === SEARCH FUNCTIONS  
 # advancedsearch(server reference, environment reference) : perform a complex  
 #                                  multi-field logical query  
 # basicsearch(server reference, environment reference) : perform a simple  
 #                               single-field logical query  
 # build_SQL_query(field name, logic) : builds a SQL query string from a  
 #                                      logical expression with AND/OR keywords  
 # build_custommetadata_query(field_name, logic_statement) : builds a perl  
 #                 regular expression from a logical expression with AND/OR  
 #                 keywords  
 # recursive_SQL_query_build(field name, reverse notation expression) :   
 #                 builds a SQL query string from a reverse notation expression  
 #                 logical expression with AND/OR keywords  
 # build_date_queries(cmonth1, cday1, cyear1, cmonth2, cday2, cyear2,  
 #                    lmonth1, lday1, lyear1, lmonth2, lday2, lyear2) :  
 #                 Builds a SQL logic query to check time/date entries.  
 #  
 #  
 # === OUTPUTTING RESULTS FUNCTION  
 # output_results(output mode,  
 #                server reference,   
 #                environment reference,  
 #                reply list reference) : outputs results from search  
 #  
 #  
 # === DIFFERENT WAYS TO VIEW METADATA RECORDS  
 # detailed_citation_view(ORDERED METADATA LIST FOR A RESULT OBJECT INSTANCE) :  
 #          see metadata viewing notes below   
 # summary_view(ORDERED METADATA LIST FOR A RESULT OBJECT INSTANCE) :  
 #          see metadata viewing notes below   
 # fielded_format_view(ORDERED METADATA LIST FOR A RESULT OBJECT INSTANCE) :  
 #          see metadata viewing notes below   
 # xml_sgml_view(ORDERED METADATA LIST FOR A RESULT OBJECT INSTANCE) :  
 #          see metadata viewing notes below   
 #  ___________________________________________________________________________  
 # | * Metadata viewing notes                                                  |  
 # | Output is a HTML-ified string.                                            |  
 # | Input arguments are title, author, subject, url, keywords, version, notes,|  
 # | short abstract, mime, language, creation date, last revision date, owner, |  
 # | copyright, hostname, httphost, and extra custom metadata to show.         |  
 #  ---------------------------------------------------------------------------  
 #  
 #  
 # === TEST CONDITIONAL FUNCTIONS  
 # filled(field) : determines whether a given field has been filled  
 #  
 #  
 # === ERROR FUNCTIONS  
 # output_blank_field_error(server reference) : outputs a message saying that  
 #                                              more fields need to be filled in  
 # output_date_error(server reference, error message) : outputs  
 #         an error message specific to bad date format.  
   
 package Apache::lonsearchcat;  package Apache::lonsearchcat;
   
 # ------------------------------------------------- modules used by this module  # ------------------------------------------------- modules used by this module
Line 110  use Apache::lonnet(); Line 31  use Apache::lonnet();
 use Apache::File();  use Apache::File();
 use CGI qw(:standard);  use CGI qw(:standard);
 use Text::Query;  use Text::Query;
   use GDBM_File;
   
 # ---------------------------------------- variables used throughout the module  # ---------------------------------------- variables used throughout the module
   
Line 127  my $importbutton; # button to take the s Line 49  my $importbutton; # button to take the s
   
 # -- miscellaneous variables  # -- miscellaneous variables
 my $scrout; # string that holds portions of the screen output  my $scrout; # string that holds portions of the screen output
 my $fnum; # search result counter  
 my $yourself; # allows for quickly limiting to oneself  my $yourself; # allows for quickly limiting to oneself
   my %hash;
   
 # ------------------------------------------ choices for different output views  # ------------------------------------------ choices for different output views
 # Detailed Citation View ---> sub detailed_citation_view  # Detailed Citation View ---> sub detailed_citation_view
Line 195  sub BEGIN { Line 117  sub BEGIN {
     }      }
 }  }
   
   my $diropendb = "";
   my $domain = "";
   
 # ----------------------------- Handling routine called via Apache and mod_perl  # ----------------------------- Handling routine called via Apache and mod_perl
 sub handler {  sub handler {
     my $r = shift;      my $r = shift;
       untie %hash;
     &get_unprocessed_cgi();      &get_unprocessed_cgi();
   
     $r->content_type('text/html');      $r->content_type('text/html');
     $r->send_http_header;      $r->send_http_header;
     return OK if $r->header_only;      return OK if $r->header_only;
   
       $domain  = $r->dir_config('lonDefDomain');
   
       $diropendb= "/home/httpd/perl/tmp/$domain\_$ENV{'user.name'}_searchcat.db";
   
       if ($ENV{'form.launch'} eq '1') {
    if (tie(%hash,'GDBM_File',$diropendb,&GDBM_WRCREAT,0640)) {
       &start_fresh_session();
       untie %hash;
    }
    else {
       $r->print('<html><head></head><body>Unable to tie hash to db '.
         'file</body></html>');
       return OK;
    }
       }
   
 # ----------------------------------- configure dynamic components of interface  # ----------------------------------- configure dynamic components of interface
     my $hidden='';      my $hidden='';
     if ($ENV{'form.catalogmode'} eq 'interactive') {      if ($ENV{'form.catalogmode'} eq 'interactive') {
Line 236  END Line 177  END
   
 # ----------------------------------- See if a search invocation should be done  # ----------------------------------- See if a search invocation should be done
     if ($ENV{'form.basicsubmit'} eq 'SEARCH') {      if ($ENV{'form.basicsubmit'} eq 'SEARCH') {
  return &basicsearch($r,\%ENV);   untie %hash; return &basicsearch($r,\%ENV);
     }      }
     elsif ($ENV{'form.advancedsubmit'} eq 'SEARCH') {      elsif ($ENV{'form.advancedsubmit'} eq 'SEARCH') {
  return &advancedsearch($r,\%ENV);   untie %hash; return &advancedsearch($r,\%ENV);
     }      }
   
 # ----------------------------- Else, begin building search interface to output  # ----------------------------- Else, begin building search interface to output
Line 335  LASTREVISIONDATEEND Line 276  LASTREVISIONDATEEND
 <font color="#800000" face="helvetica"><b>LIMIT BY SPECIAL METADATA FIELDS:</b>  <font color="#800000" face="helvetica"><b>LIMIT BY SPECIAL METADATA FIELDS:</b>
 </font>  </font>
 For resource-specific metadata, enter in an expression in the form of   For resource-specific metadata, enter in an expression in the form of 
 <i>key</i>=<i>value</i> separated by operators such as AND or OR.<br />  <i>key</i>=<i>value</i> separated by operators such as AND, OR or NOT.<br />
 <b>Example:</b> grandmother=75 OR grandfather=85  <b>Example:</b> grandmother=75 OR grandfather=85
 <br />  <br />
 CUSTOMMETADATA  CUSTOMMETADATA
Line 358  $scrout.=' <i>initial users of this syst Line 299  $scrout.=' <i>initial users of this syst
 <html>  <html>
 <head>  <head>
 <title>The LearningOnline Network with CAPA</title>  <title>The LearningOnline Network with CAPA</title>
   <script type="text/javascript">
       function openhelp(val) {
    openhelpwin=open('/adm/help/searchcat.html','helpscreen',
        'scrollbars=1,width=400,height=300');
    openhelpwin.focus();
       }
   </script>
 </head>  </head>
 <body bgcolor="#FFFFFF">  <body bgcolor="#FFFFFF">
 <img align='right' src='/adm/lonIcons/lonlogos.gif' />  <img align='right' src='/adm/lonIcons/lonlogos.gif' />
Line 368  $hidden Line 316  $hidden
 <h3>Basic Search</h3>  <h3>Basic Search</h3>
 <p>  <p>
 Enter terms or phrases separated by search operators  Enter terms or phrases separated by search operators
 such as AND or OR then press SEARCH below.  Terms should be specific  such as AND, OR, or NOT then press SEARCH below.  Terms should be specific
 to the title, author, subject, notes, or abstract information associated  to the title, author, subject, notes, or abstract information associated
 with a resource.  with a resource.
 <br />  <br />
Line 385  ENDDOCUMENT Line 333  ENDDOCUMENT
 <input type="reset" name="reset" value='RESET' />  <input type="reset" name="reset" value='RESET' />
 $closebutton  $closebutton
 $basicviewselect  $basicviewselect
   <input type="button" value="HELP" onClick="openhelp()" />
 </p>  </p>
 <hr />  <hr />
 <h3>Advanced Search</h3>  <h3>Advanced Search</h3>
Line 394  $scrout Line 343  $scrout
 <input type="reset" name="reset" value='RESET' />  <input type="reset" name="reset" value='RESET' />
 $closebutton  $closebutton
 $advancedviewselect  $advancedviewselect
   <input type="button" value="HELP" onClick="openhelp()" />
 </p>  </p>
 </form>  </form>
 </body>  </body>
Line 408  sub get_unprocessed_cgi { Line 358  sub get_unprocessed_cgi {
        my ($name, $value) = split(/=/,$_);         my ($name, $value) = split(/=/,$_);
        $value =~ tr/+/ /;         $value =~ tr/+/ /;
        $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg;         $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg;
        if ($name eq 'catalogmode') {         if ($name eq 'catalogmode' or $name eq 'launch' or $name eq 'acts') {
    $ENV{'form.'.$name}=$value;     $ENV{'form.'.$name}=$value;
        }         }
     } (split(/&/,$ENV{'QUERY_STRING'}));      } (split(/&/,$ENV{'QUERY_STRING'}));
Line 451  sub searchphrasefield { Line 401  sub searchphrasefield {
     my ($title,$name,$value)=@_;      my ($title,$name,$value)=@_;
     my $instruction=<<END;      my $instruction=<<END;
 Enter terms or phrases separated by search operators such  Enter terms or phrases separated by search operators such
 as AND or OR.  as AND, OR, or NOT.
 END  END
     my $uctitle=uc($title);      my $uctitle=uc($title);
     return "\n<p><font color=\"#800000\" face=\"helvetica\"><b>$uctitle:</b>".      return "\n<p><font color=\"#800000\" face=\"helvetica\"><b>$uctitle:</b>".
Line 632  sub advancedsearch { Line 582  sub advancedsearch {
    'lastrevisiondateend_day','lastrevisiondateend_year',     'lastrevisiondateend_day','lastrevisiondateend_year',
    'notes','abstract','mime','language','owner',     'notes','abstract','mime','language','owner',
    'custommetadata','customshow') {     'custommetadata','customshow') {
  $ENV{"form.$field"}=~s/[^\w\s\(\)\=\-\"\']//g;   $ENV{"form.$field"}=~s/[^\w\/\s\(\)\=\-\"\']//g;
     }      }
   
     # Check to see if enough information was filled in      # Check to see if enough information was filled in
Line 882  sub build_date_queries { Line 832  sub build_date_queries {
 # gives the status of the network search (time elapsed, number of machines  # gives the status of the network search (time elapsed, number of machines
 # contacted, etc.)  # contacted, etc.)
 sub output_results {  sub output_results {
       my $fnum; # search result counter
     my ($mode,$r,$envhash,$query,$replyref)=@_;      my ($mode,$r,$envhash,$query,$replyref)=@_;
     my %ENV=%{$envhash};      my %ENV=%{$envhash};
     my %rhash=%{$replyref};      my %rhash=%{$replyref};
     my $compiledresult='';      my $compiledresult='';
     my $timeremain=30;      my $timeremain=300;
     my $elapsetime=0;      my $elapsetime=0;
     my $resultflag=0;      my $resultflag=0;
     my $tflag=1;      my $tflag=1;
Line 904  BEGINNING Line 855  BEGINNING
     # conditional output of script functions dependent on the mode in      # conditional output of script functions dependent on the mode in
     # which the search was invoked      # which the search was invoked
         $r->print(<<SCRIPT) if $ENV{'form.catalogmode'} eq 'interactive';          $r->print(<<SCRIPT) if $ENV{'form.catalogmode'} eq 'interactive';
 <script>  <script type="text/javascript">
     function select_data(title,url) {      function select_data(title,url) {
  changeTitle(title);   changeTitle(title);
  changeURL(url);   changeURL(url);
Line 923  BEGINNING Line 874  BEGINNING
 </script>  </script>
 SCRIPT  SCRIPT
         $r->print(<<SCRIPT) if $ENV{'form.catalogmode'} eq 'groupsearch';          $r->print(<<SCRIPT) if $ENV{'form.catalogmode'} eq 'groupsearch';
 <script>  <script type="text/javascript">
     function select_data(title,url) {      function select_data(title,url) {
  alert('DEBUG: Should be storing '+title+' and '+url);  // alert('DEBUG: Should be storing '+title+' and '+url);
     }      }
     function queue(val) {      function queue(val) {
  if (eval("document.forms."+val+".filelink.checked")) {   if (eval("document.forms.results.returnvalues["+val+"].checked")) {
     document.forms.results.acts.value+='1a'+val+'b';      document.forms.results.acts.value+='1a'+val+'b';
  }   }
  else {   else {
Line 936  SCRIPT Line 887  SCRIPT
  }   }
     }      }
     function select_group() {      function select_group() {
  alert('DEBUG: Should be moving on to group sorting stage'+' acts');   window.location="/adm/groupsort?catalogmode=groupsearch&acts="+
       document.forms.results.acts.value;
     }      }
 </script>  </script>
 SCRIPT  SCRIPT
         $r->print(<<SCRIPT);                                            ;          $r->print(<<SCRIPT);
 <script>  <script type="text/javascript">
     function displayinfo(val) {      function displayinfo(val) {
  popwin.document.forms.popremain.sdetails.value=val;   popwin.document.forms.popremain.sdetails.value=val;
     }      }
       function openhelp(val) {
    openhelpwin=open('/adm/help/searchcat.html','helpscreen',
        'scrollbars=1,width=400,height=300');
    openhelpwin.focus();
       }
       function abortsearch(val) {
    openhelpwin=open('/adm/help/searchcat.html','helpscreen',
        'scrollbars=1,width=400,height=300');
    openhelpwin.focus();
       }
 </script>  </script>
 SCRIPT  SCRIPT
     $r->rflush();      $r->rflush();
Line 998  RESULTS Line 960  RESULTS
  $grid.="javascript:opener.displayinfo('+";   $grid.="javascript:opener.displayinfo('+";
  # "'"+'key   # "'"+'key
  $grid.="\"'\"+'";   $grid.="\"'\"+'";
  $grid.=$sk." domain=".$hostdomains{$sk};   $grid.=$sk;
  my $hc;   my $hc;
  if ($rhash{$sk} eq 'con_lost') {   if ($rhash{$sk} eq 'con_lost') {
     $hc="!!!BAD CONNECTION, CONTACT SYSTEM ADMINISTRATOR!!!";      $hc="!!!BAD CONNECTION, CONTACT SYSTEM ADMINISTRATOR!!!";
  }   }
  else {   else {
     $hc="'+\"'\"+\"+hc['$sk']+\"+\"'\"+'";      $hc="'+\"'\"+\"+hc['$sk']+\"+\"'\"+'";
     $hcinit.="hc[\"$sk\"]=0;";      $hcinit.="hc[\"$sk\"]=\"not yet connected...\";";
  }   }
  $grid.=" hitcount=".$hc;   $grid.=" hitcount=".$hc;
    $grid.=" domain=".$hostdomains{$sk};
  $grid.=" IP=".$hostips{$sk};   $grid.=" IP=".$hostips{$sk};
  # '+"'"+'">'+   # '+"'"+'">'+
  $grid.="'+\"'\"+')\">'+";   $grid.="'+\"'\"+')\">'+";
  $grid.="\n";   $grid.="\n";
  $grid.="'<img border=\"0\" name=\"img".$sn."\"".   $grid.="'<img border=\"0\" name=\"img".$sn."\"".
     " src=\"/adm/lonIcons/srvbad.gif\" alt=\"".$sk."\" /></a>'+\n";      " src=\"/adm/lonIcons/srvnull.gif\" alt=\"".$sk."\" /></a>'+\n";
  $grid.="'<br />'+\n" unless $sn%10;   $grid.="'<br />'+\n" unless $sn%10;
         $sn++;          $sn++;
     }      }
     $r->print(<<ENDPOP);      $r->print(<<ENDPOP);
 <script>  <script type="text/javascript">
     popwin=open('','popwin','scrollbars=1,width=400,height=200');      popwin=open('','popwin','scrollbars=1,width=400,height=200');
     popwin.focus();      popwin.focus();
     popwin.document.writeln('<'+'html>');      popwin.document.writeln('<'+'html>');
Line 1028  RESULTS Line 991  RESULTS
     popwin.document.writeln('<'+'/script>');      popwin.document.writeln('<'+'/script>');
     popwin.document.writeln('<'+'/head>'+      popwin.document.writeln('<'+'/head>'+
         '<'+'body bgcolor="#FFFFFF">'+          '<'+'body bgcolor="#FFFFFF">'+
    '<'+'image name="whirly" align="right" src="/adm/lonIcons/'+
    'lonanim.gif" '+
    'alt="animated logo" />'+
  '<'+'h3>Search Results Progress<'+'/h3>'+   '<'+'h3>Search Results Progress<'+'/h3>'+
         '<'+'form name="popremain">'+          '<'+'form name="popremain">'+
         '<'+'br />Server space <'+'input type=text size=25 name=space value="">'+  
         '<'+'br />Status <'+'input type=text size=25 name=status value="">'+  
         '<'+'br />Maximum remaining time <'+'input type=text size=25 name=timeout '+  
  'value="30">'+  
         '<'+'tt>'+          '<'+'tt>'+
  '<'+'image align="right" src="/adm/lonIcons/'+   '<'+'br clear="all"/><i>PLEASE BE PATIENT</i>'+
  'lonanim.gif" '+  
  'alt="animated logo" />'+  
  '<'+'br /><i>PLEASE BE PATIENT</i>'+  
  '<'+'br />SCANNING $servernum SERVERS'+   '<'+'br />SCANNING $servernum SERVERS'+
  '<'+'br clear="all" />Number of record hits found '+   '<'+'br clear="all" />Number of record hits found '+
  '<'+'input type="text" size="10" name="numhits"'+   '<'+'input type="text" size="10" name="numhits"'+
Line 1054  RESULTS Line 1013  RESULTS
  '<'+'input type="text" size="25" name="sdetails"'+   '<'+'input type="text" size="25" name="sdetails"'+
  ' value="" />'+   ' value="" />'+
  '<'+'br />'+   '<'+'br />'+
  '<'+'input type="button" name="button"'+  
  ' value="revise search" />'+  
  ' <'+'input type="button" name="button"'+   ' <'+'input type="button" name="button"'+
  ' value="view results" />'+   ' value="abort search and view current results" '+
    ' onClick="javascript:opener.abortsearch()" />'+
  ' <'+'input type="button" name="button"'+   ' <'+'input type="button" name="button"'+
  ' value="help" />'+   ' value="help" onClick="javascript:opener.openhelp()" />'+
  '<'+'/tt>'+   '<'+'/tt>'+
         '<'+'/form>'+          '<'+'/form>'+
         '<'+'/body><'+'/html>');          '<'+'/body><'+'/html>');
Line 1068  RESULTS Line 1026  RESULTS
 ENDPOP  ENDPOP
     $r->rflush();      $r->rflush();
   
     $r->print('<script>popwin.document.popremain.space.value="'.  
       $servernum.', 0%, count=0/'.$servernum.'";</script>');  
     $r->rflush();   
     my $servercount=0;      my $servercount=0;
     $sn=0;  
     my $hitcountsum=0;      my $hitcountsum=0;
     foreach my $rkey (sort keys %rhash) {      my $bloop=$servernum;
       my %orkey;
     BLOOP: while(1) {
         my $sn=0;
         last BLOOP unless $bloop;
         last BLOOP unless $timeremain;
       RLOOP: foreach my $rkey (sort keys %rhash) {
  $sn++;   $sn++;
    next RLOOP if $orkey{$rkey};
  $servercount++;   $servercount++;
  $tflag=1;   $tflag=1;
  $compiledresult='';   $compiledresult='';
  my $hostname=$rkey;   my $hostname=$rkey;
  $r->print('<script>popwin.document.popremain.status.value="'.  
   $rkey.', trying contact";</script>'."\n");  
  $r->rflush();  
  my $reply=$rhash{$rkey};   my $reply=$rhash{$rkey};
  my @results;   my @results;
   
  my $replyfile='';   my $replyfile='';
   
  if ($reply eq 'con_lost') {   if ($reply eq 'con_lost') {
     my $percent=sprintf('%3.0f',($servercount/$servernum*100));      $r->print('<script type="text/javascript">popwin.document.img'.
     $r->print('<script>popwin.document.popremain.space.value="'.        $sn.'.'.
       $servernum.', '.$percent.'%, count='.$servercount.        'src="/adm/lonIcons/srvbad.gif";</script>'.
       '/'.$servernum.'";</script>');        "\n");
       $r->rflush();
       $bloop--;
       $orkey{$rkey}=1;
  }   }
  else {   else {
     $reply=~/^([\.\w]+)$/; # must do since 'use strict' checks for tainting      $reply=~/^([\.\w]+)$/; # must do since 'use strict' checks for tainting
Line 1102  ENDPOP Line 1063  ENDPOP
  my $temp=0;   my $temp=0;
       WLOOP: while (1) {        WLOOP: while (1) {
   if (-e $replyfile && $tflag) {    if (-e $replyfile && $tflag) {
       $r->print('<script>popwin.document.popremain.status.'.        $r->print('<script type="text/javascript">'.
  'value="'.$rkey.', transmitting";</script>'.   'popwin.document.img'.$sn.'.'.
    'src="/adm/lonIcons/srvhalf.gif";</script>'.
  "\n");   "\n");
       $r->rflush();        $r->rflush();
       $r->print('<script>popwin.document.img'.$sn.'.'.        $r->print('<script type="text/javascript">'.
  'src="/adm/lonIcons/srvempty.gif";</script>'.   'popwin.hc["'.$rkey.'"]='.
    '"still transferring..."'.';</script>'.
  "\n");   "\n");
       $r->rflush();        $r->rflush();
       $tflag=0;        $tflag=0;
   }    }
   last WLOOP if $temp>5;  
   if (-e "$replyfile.end") {    if (-e "$replyfile.end") {
         $bloop--;
         $orkey{$rkey}=1;
       if (-s $replyfile) {        if (-s $replyfile) {
   $r->print('<script>popwin.document.img'.$sn.'.'.    $r->print('<script type="text/javascript">'.
  'src="/adm/lonIcons/srvgood.gif";</script>'.      'popwin.document.img'.$sn.'.'.
  "\n");      'src="/adm/lonIcons/srvgood.gif";'.
       '</script>'."\n");
   $r->rflush();    $r->rflush();
   my $fh=Apache::File->new($replyfile) or     my $fh=Apache::File->new($replyfile) or 
       ($r->print('ERROR: file '.        ($r->print('ERROR: file '.
Line 1125  ENDPOP Line 1090  ENDPOP
        return OK);         return OK);
   @results=<$fh> if $fh;    @results=<$fh> if $fh;
   $hitcount{$rkey}=@results+0;    $hitcount{$rkey}=@results+0;
   $r->print('<script>popwin.hc["'.$rkey.'"]='.    $r->print('<script type="text/javascript">'.
       'popwin.hc["'.$rkey.'"]='.
     $hitcount{$rkey}.';</script>'.      $hitcount{$rkey}.';</script>'.
     "\n");      "\n");
   $r->rflush();    $r->rflush();
   $hitcountsum+=$hitcount{$rkey};    $hitcountsum+=$hitcount{$rkey};
   $r->print('<script>popwin.document.forms.popremain.'.    $r->print('<script type="text/javascript">'.
       'popwin.document.forms.popremain.'.
     'numhits.value='.$hitcountsum.      'numhits.value='.$hitcountsum.
     ';</script>'.      ';</script>'.
     "\n");      "\n");
   $r->rflush();    $r->rflush();
       }        }
         else {
     $r->print('<script type="text/javascript">'.
       'popwin.document.img'.$sn.'.'.
       'src="/adm/lonIcons/srvempty.gif";'.
       '</script>'.
       "\n");
     $r->rflush();
     $r->print('<script type="text/javascript">'.
       'popwin.hc["'.$rkey.'"]=0'.
       ';</script>'.
       "\n");
     $r->rflush();
         }
         last WLOOP;
     }
     if ($temp>1) {
         sleep 1;
         $timeremain--;
         $elapsetime++;
       last WLOOP;        last WLOOP;
   }    }
   last WLOOP unless $timeremain;    last WLOOP unless $timeremain;
   sleep 1;    sleep 1;
   $timeremain--;    $timeremain--;
   $elapsetime++;    $elapsetime++;
   $r->print('<script>popwin.document.popremain.timeout.'.    $r->print('<script type="text/javascript">'.
     'value="'.$timeremain.'";</script>'."\n");      'popwin.document.popremain.elapsetime.'.
   $r->rflush();  
   $r->print('<script>popwin.document.popremain.elapsetime.'.  
     'value="'.$elapsetime.'";</script>'."\n");      'value="'.$elapsetime.'";</script>'."\n");
   $r->rflush();    $r->rflush();
   $temp++;    $temp++;
       }        }
     }      }
       $r->print('<script type="text/javascript">'.
         'popwin.document.whirly.'.
         'src="'.'/adm/lonIcons/lonanimend.gif'.
         '";</script>'."\n");
       $r->rflush();
  }   }
  my $customshow='';   my $customshow='';
  my $extrashow='';   my $extrashow='';
Line 1176  ENDPOP Line 1165  ENDPOP
  $customhash{$k}=$v;   $customhash{$k}=$v;
     }      }
  }   }
  foreach my $result (@results) {   if (keys %hash) {
     next if $result=~/^custom\=/;      untie %hash;
     chomp $result;   }
     next unless $result;   if (tie(%hash,'GDBM_File',$diropendb,&GDBM_WRCREAT,0640)) {
     my @fields=map      if ($ENV{'form.launch'} eq '1') {
     {&Apache::lonnet::unescape($_)}   &start_fresh_session();
     (split(/\,/,$result));      }
     my ($title,$author,$subject,$url,$keywords,$version,      foreach my $result (@results) {
  $notes,$abstract,$mime,$lang,   next if $result=~/^custom\=/;
  $creationdate,$lastrevisiondate,$owner,$copyright)=@fields;   chomp $result;
     my $shortabstract=$abstract;   next unless $result;
     $shortabstract=substr($abstract,0,200) if length($abstract)>200;   my @fields=map
     $fields[7]=$shortabstract;   {&Apache::lonnet::unescape($_)}
     my $extrashow2=$extrashow;   (split(/\,/,$result));
     if ($extrashow) {   my ($title,$author,$subject,$url,$keywords,$version,
  foreach my $field (@customfields) {      $notes,$abstract,$mime,$lang,
     my $value='';      $creationdate,$lastrevisiondate,$owner,$copyright)=@fields;
     if ($customhash{$url}=~/\<${field}[^\>]*\>(.*?)\<\/${field}[^\>]*\>/s) {  
         $value=$1;   unless ($ENV{'user.adv'}) {
     }      $keywords='<i>- not displayed -</i>';
             $extrashow2=~s/\<\!\-\- $field \-\-\>/ $value/g;      $fields[4]=$keywords;
         }      $notes='<i>- not displayed -</i>';
             }      $fields[6]=$notes;
       $abstract='<i>- not displayed -</i>';
       $fields[7]=$abstract;
       $subject='<i>- not displayed -</i>';
       $fields[2]=$subject;
    }
   
    my $shortabstract=$abstract;
    $shortabstract=substr($abstract,0,200).'...' if length($abstract)>200;
    $fields[7]=$shortabstract;
    my $shortkeywords=$keywords;
    $shortkeywords=substr($keywords,0,200).'...' if length($keywords)>200;
    $fields[4]=$shortkeywords;
   
    my $extrashow2=$extrashow;
    if ($extrashow) {
       foreach my $field (@customfields) {
    my $value='';
    if ($customhash{$url}=~/\<${field}[^\>]*\>(.*?)\<\/${field}[^\>]*\>/s) {
               $value=$1;
    }
           $extrashow2=~s/\<\!\-\- $field \-\-\>/ $value/g;
               }
                   }
   
             $compiledresult.=<<END if $compiledresult or $servercount!=$servernum;          $compiledresult.=<<END if $compiledresult or $servercount!=$servernum;
 <hr align='left' width='200' noshade />  <hr align='left' width='200' noshade />
 END  END
             $compiledresult.=<<END;                  $compiledresult.=<<END;
 <p>  <p>
 END  END
             $compiledresult.=<<END if $ENV{'form.catalogmode'} eq 'interactive';                  $compiledresult.=<<END if $ENV{'form.catalogmode'} eq 'interactive';
 <font size='-1'><INPUT TYPE="button" NAME="returnvalues" VALUE="SELECT"  <font size='-1'><INPUT TYPE="button" NAME="returnvalues" VALUE="SELECT"
 onClick="javascript:select_data('$title','$url')">  onClick="javascript:select_data('$title','$url')">
 </font>  </font>
 <br />  <br />
 END  END
             $compiledresult.=<<END if $ENV{'form.catalogmode'} eq 'groupsearch';                  if ($ENV{'form.catalogmode'} eq 'groupsearch') {
       $fnum+=0;
       $hash{"pre_${fnum}_link"}=$url;
       $hash{"pre_${fnum}_title"}=$title;
       $compiledresult.=<<END;
 <font size='-1'><input type="checkbox" name="returnvalues" value="SELECT"  <font size='-1'><input type="checkbox" name="returnvalues" value="SELECT"
 onClick="javascript:queue($fnum)" />  onClick="javascript:queue($fnum)" />
 </font>  </font>
 <input type="hidden" name="title$fnum" value="$title" />  
 <input type="hidden" name="url$fnum" value="$url" />  
 <br />  <br />
 END  END
             my $httphost=$ENV{'HTTP_HOST'};  # <input type="hidden" name="title$fnum" value="$title" />
   # <input type="hidden" name="url$fnum" value="$url" />
                       $fnum++;
    }
           my $httphost=$ENV{'HTTP_HOST'};
   
           my $viewselect;
           if ($mode eq 'Basic') {
       $viewselect=$ENV{'form.basicviewselect'};
    }
           elsif ($mode eq 'Advanced') {
       $viewselect=$ENV{'form.advancedviewselect'};
    }
   
             my $viewselect;          if ($viewselect eq 'Detailed Citation View') {
             if ($mode eq 'Basic') {      $compiledresult.=&detailed_citation_view(@fields,
  $viewselect=$ENV{'form.basicviewselect'};  
     }  
             elsif ($mode eq 'Advanced') {  
         $viewselect=$ENV{'form.advancedviewselect'};  
             }  
   
             if ($viewselect eq 'Detailed Citation View') {  
         $compiledresult.=&detailed_citation_view(@fields,  
  $hostname,$httphost,   $hostname,$httphost,
  $extrashow2);   $extrashow2);
     }   }
             elsif ($viewselect eq 'Summary View') {                  elsif ($viewselect eq 'Summary View') {
  $compiledresult.=&summary_view(@fields,$hostname,$httphost,      $compiledresult.=&summary_view(@fields,$hostname,$httphost,
        $extrashow2);         $extrashow2);
     }          }
             elsif ($viewselect eq 'Fielded Format') {                  elsif ($viewselect eq 'Fielded Format') {
  $compiledresult.=&fielded_format_view(@fields,$hostname,      $compiledresult.=&fielded_format_view(@fields,$hostname,
       $httphost,$extrashow2);        $httphost,$extrashow2);
     }          }
             elsif ($viewselect eq 'XML/SGML') {                  elsif ($viewselect eq 'XML/SGML') {
  $compiledresult.=&xml_sgml_view(@fields,$hostname,$httphost,      $compiledresult.=&xml_sgml_view(@fields,$hostname,$httphost,
  $extrashow2);   $extrashow2);
     }   }
           
         }              }
   
               untie %hash;
           }
           else {
       $r->print('<html><head></head><body>Unable to tie hash to db '.
     'file</body></html>');
    }
  if ($compiledresult) {   if ($compiledresult) {
     $resultflag=1;      $resultflag=1;
  }   }
Line 1258  END Line 1282  END
 $compiledresult  $compiledresult
 RESULTS  RESULTS
         my $percent=sprintf('%3.0f',($servercount/$servernum*100));          my $percent=sprintf('%3.0f',($servercount/$servernum*100));
  $r->print('<script>popwin.document.popremain.space.value="'.  
           $servernum.', '.$percent.'%, count='.$servercount.  
   '/'.$servernum.'";</script>'."\n");  
     }      }
     }
     unless ($resultflag) {      unless ($resultflag) {
         $r->print("\nThere were no results that matched your query\n");          $r->print("\nThere were no results that matched your query\n");
     }      }
 #    $r->print('<script>popwin.close()</script>'."\n"); $r->rflush();   #    $r->print('<script type="text/javascript">'.'popwin.close()</script>'."\n"); $r->rflush(); 
     $r->print(<<RESULTS);      $r->print(<<RESULTS);
 </body>  </body>
 </html>  </html>
Line 1459  $message Line 1481  $message
 RESULTS  RESULTS
 }  }
   
   # --------- settings whenever the user causes the search window to be launched
   sub start_fresh_session {
       delete $hash{'mode_catalog'};
       map {
           if ($_ =~ /^pre_/) {
               delete $hash{$_};
           }
           if ($_ =~ /^store/) {
       delete $hash{$_};
    }
       } keys %hash;
   }
   
 1;  1;
   
 __END__  __END__
   
   =head1 NAME
   
   Apache::lonsearchcat - mod_perl module for handling a searchable catalog
   
   =head1 SYNOPSIS
   
   Invoked by /etc/httpd/conf/srm.conf:
   
    <Location /adm/searchcat>
    PerlAccessHandler       Apache::lonacc
    SetHandler perl-script
    PerlHandler Apache::lonsearchcat
    ErrorDocument     403 /adm/login
    ErrorDocument  500 /adm/errorhandler
    </Location>
   
   =head1 INTRODUCTION
   
   This module enables searching for a distributed browseable catalog.
   
   This is part of the LearningOnline Network with CAPA project
   described at http://www.lon-capa.org.
   
   =head1 BEGIN SUBROUTINE
   
   This routine is only run once after compilation.
   
   =over 4
   
   =item *
   
   Initializes %language hash table.
   
   =item *
   
   Initializes %cprtag hash table (for copyright.tab).
   
   =item *
   
   Initializes %mimetag hash table (for filetypes.tab).
   
   =item *
   
   Initializes %hostdomains and hostips hash table (for hosts.tab).
   
   =back
   
   =head1 HANDLER SUBROUTINE
   
   This routine is called by Apache and mod_perl.
   
   =over 4
   
   =item *
   
   configure dynamic components of interface
   
   =item *
   
   determine current user
   
   =item *
   
   see if a search invocation should be done
   
   =item *
   
   else, begin building search interface to output
   
   =item *
   
   compute date selection boxes
   
   =item *
   
   compute customized metadata field
   
   =item *
   
   print screen
   
   =back
   
   =head1 OTHER SUBROUTINES
   
   =over 4
   
   =item *
   
   get_unprocessed_cgi() : reads in critical name/value pairs that may have not
   been processed and passed into %ENV by the web server
   
   =item *
   
   make_persistent() : makes a set of hidden HTML fields to make
   SQL search interface information to be persistent
   
   =back
   
   WEB INTERFACE COMPONENT FUNCTIONS
   
   =over 4
   
   =item *
   
   simpletextfield(name,value) : returns HTML formatted string for simple text
   field
   
   =item *
   
   simplecheckbox(name,value) : returns HTML formatted string for simple
   checkbox
   
   =item *
   
   searchphrasefield(title,name,value) : returns HTML formatted string for
   a search expression phrase field
   
   =item *
   
   dateboxes(name, defaultmonth, defaultday, defaultyear) : returns HTML
   formatted string for a calendar date
   
   =item *
   
   selectbox(title,name,value,%HASH=options) : returns HTML formatted string for
   a selection box field
   
   =back
   
   SEARCH FUNCTIONS
   
   =over 4
   
   =item *
   
   advancedsearch(server reference, environment reference) : perform a complex
   multi-field logical query
   
   =item *
   
   basicsearch(server reference, environment reference) : perform a simple
   single-field logical query
   
   =item *
   
   build_SQL_query(field name, logic) : builds a SQL query string from a
   logical expression with AND/OR keywords
   
   =item *
   
   build_custommetadata_query(field_name, logic_statement) : builds a perl
   regular expression from a logical expression with AND/OR keywords
   
   =item *
   
   recursive_SQL_query_build(field name, reverse notation expression) : 
   builds a SQL query string from a reverse notation expression
   logical expression with AND/OR keywords
   
   =item *
   
   build_date_queries(cmonth1, cday1, cyear1, cmonth2, cday2, cyear2,
   lmonth1, lday1, lyear1, lmonth2, lday2, lyear2) :
   Builds a SQL logic query to check time/date entries.
   
   =back
   
   OUTPUTTING RESULTS FUNCTION
   
   =over 4
   
   =item *
   
   output_results(output mode, server reference, environment reference,
   reply list reference) : outputs results from search
   
   =back
   
   DIFFERENT WAYS TO VIEW METADATA RECORDS
   
   =over 4
   
   =item *
   
   detailed_citation_view(ORDERED METADATA LIST FOR A RESULT OBJECT INSTANCE) :
   see metadata viewing notes below 
   
   =item *
   
   summary_view(ORDERED METADATA LIST FOR A RESULT OBJECT INSTANCE) :
   see metadata viewing notes below 
   
   =item *
   
   fielded_format_view(ORDERED METADATA LIST FOR A RESULT OBJECT INSTANCE) :
   see metadata viewing notes below 
   
   =item *
   
   xml_sgml_view(ORDERED METADATA LIST FOR A RESULT OBJECT INSTANCE) :
   see metadata viewing notes below 
   
   =back
   
     _____________________________________________________________________
    | * Metadata viewing notes                                            |
    | Output is a HTML-ified string.                                      |
    | Input arguments are title, author, subject, url, keywords, version, |
    | notes, short abstract, mime, language, creation date,               |
    | last revision date, owner, copyright, hostname, httphost, and       |
    | extra custom metadata to show.                                      |
     ---------------------------------------------------------------------
   
   TEST CONDITIONAL FUNCTIONS
   
   =over 4
   
   =item *
   
   filled(field) : determines whether a given field has been filled
   
   =back
   
   ERROR FUNCTIONS
   
   =over 4
   
   =item *
   
   output_blank_field_error(server reference) : outputs a message saying that
   more fields need to be filled in
   
   =item *
   
   output_date_error(server reference, error message) : outputs
   an error message specific to bad date format.
   
   =back
   
   =cut

Removed from v.1.98  
changed lines
  Added in v.1.107


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>