Diff for /loncom/interface/lonsearchcat.pm between versions 1.121 and 1.134

version 1.121, 2002/06/18 21:36:38 version 1.134, 2002/07/03 19:11:09
Line 67  search (on a server basis) is displayed Line 67  search (on a server basis) is displayed
 ###############################################################################  ###############################################################################
 ###############################################################################  ###############################################################################
   
   ###############################################################################
 ##                                                                           ##  ##                                                                           ##
 ## ORGANIZATION OF THIS PERL MODULE                                          ##  ## ORGANIZATION OF THIS PERL MODULE                                          ##
 ##                                                                           ##  ##                                                                           ##
 ## 1. Modules used by this module                                            ##  ## 1. Modules used by this module                                            ##
 ## 2. Choices for different output views (detailed, summary, xml, etc)       ##  ## 2. Variables used throughout the module                                   ##
 ## 3. BEGIN block (to be run once after compilation)                         ##  ## 3. handler subroutine called via Apache and mod_perl                      ##
 ## 4. Handling routine called via Apache and mod_perl                        ##  ## 4. Other subroutines                                                      ##
 ## 5. Other subroutines                                                      ##  
 ##                                                                           ##  ##                                                                           ##
 ###############################################################################  ###############################################################################
   
Line 101  use Apache::loncommon(); Line 101  use Apache::loncommon();
   
 =over 4  =over 4
   
 =item %hostdomains  
   
 matches host name to host domain  
   
 =item %hostips  
   
 matches host name to host ip  
   
 =item %hitcount  
   
 stores number of hits per host  
   
 =item $closebutton  =item $closebutton
   
 button that closes the search window  button that closes the search window
   
 =item $importbutton  =item $importbutton
   
 button to take the selecte results and go to group sorting  button to take the select results and go to group sorting
   
 =item $hidden  
   
 holds 'hidden' html forms  
   
 =item $scrout  
   
 string that holds portions of the screen output  
   
 =item $yourself  
   
 allows for quickly limiting to oneself  
   
 =item %hash     =item %hash   
   
 The ubiquitous database hash  The ubiquitous database hash
   
 =item $basicviewselect and $advancedviewselect  
   
 View selection forms.  These are not actually global and will be   
 moved soon.  
   
 =item $diropendb   =item $diropendb 
   
 The full path to the (temporary) search database file.  This is set and  The full path to the (temporary) search database file.  This is set and
Line 154  used in &handler() and is also used in & Line 125  used in &handler() and is also used in &
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
   
 # -- information holders  
 my %hostdomains; # matches host name to host domain  
 my %hostips;     # matches host name to host ip  
 my %hitcount;    # stores number of hits per host  
   
 # -- dynamically rendered interface components  # -- dynamically rendered interface components
 my $closebutton;  # button that closes the search window  my $closebutton;  # button that closes the search window
 my $importbutton; # button to take the selected results and go to group sorting  my $importbutton; # button to take the selected results and go to group sorting
 my $hidden;       # Holds 'hidden' html forms  
   
 # -- miscellaneous variables  # -- miscellaneous variables
 my $scrout;   # string that holds portions of the screen output  
 my $yourself; # allows for quickly limiting to oneself  
 my %hash;     # database hash  my %hash;     # database hash
   my $diropendb = "";    # db file
   
 # ------------------------------------------ choices for different output views  ######################################################################
 # Detailed Citation View ---> sub detailed_citation_view  ######################################################################
 # Summary View ---> sub summary_view  
 # Fielded Format ---> sub fielded_format_view  
 # XML/SGML ---> sub xml_sgml_view  
 my $basicviewselect=<<END;  
 <select name='basicviewselect'>  
 <option value='Detailed Citation View' selected="true">  
 Detailed Citation View</option>  
 <option value='Summary View'>Summary View</option>  
 <option value='Fielded Format'>Fielded Format</option>  
 <option value='XML/SGML'>XML/SGML</option>  
 </select>  
 END  
 my $advancedviewselect=<<END;  
 <select name='advancedviewselect'>  
 <option value='Detailed Citation View' selected="true">  
 Detailed Citation View</option>  
 <option value='Summary View'>Summary View</option>  
 <option value='Fielded Format'>Fielded Format</option>  
 <option value='XML/SGML'>XML/SGML</option>  
 </select>  
 END  
   
 #------------------------------------------------------------- global variables  
 my $diropendb = "";  
 my $domain = "";  
   
 # ----------------------------------------------------------------------- BEGIN  =pod 
   
 =pod  =item &handler() - main handler invoked by httpd child
   
 =item BEGIN block  =item Variables
   
 Load %hostdomains and %hostips with data from lonnet.pm.  Only library  =over 4
 servers are considered.  
   
 =cut  =item $hidden
   
 BEGIN {  holds 'hidden' html forms
     foreach (keys (%Apache::lonnet::libserv)) {  
         $hostdomains{$_}=$Apache::lonnet::hostdom{$_};  
         $hostips{$_}=$Apache::lonnet::hostip{$_};  
     }  
 }  
   
 ######################################################################  =item $scrout
 ######################################################################  
   
 =pod   string that holds portions of the screen output
   
 =item &handler() - main handler invoked by httpd child  =back 
   
 =cut  =cut
   
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
 # ----------------------------- Handling routine called via Apache and mod_perl  
 sub handler {  sub handler {
     my $r = shift;      my $r = shift;
     untie %hash;      untie %hash;
Line 236  sub handler { Line 167  sub handler {
     return OK if $r->header_only;      return OK if $r->header_only;
   
     my $domain  = $r->dir_config('lonDefDomain');      my $domain  = $r->dir_config('lonDefDomain');
     $diropendb= "/home/httpd/perl/tmp/".&Apache::lonnet::unescape($domain).      $diropendb= "/home/httpd/perl/tmp/".&Apache::lonnet::escape($domain).
             "\_".&Apache::lonnet::unescape($ENV{'user.name'})."_searchcat.db";              "\_".&Apache::lonnet::escape($ENV{'user.name'})."_searchcat.db";
   
     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},      &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
              ['catalogmode','launch','acts','mode','form','element']);               ['catalogmode','launch','acts','mode','form','element',
                 'reqinterface']);
       ##
       ## Clear out old values from database
       ##
     if ($ENV{'form.launch'} eq '1') {      if ($ENV{'form.launch'} eq '1') {
  if (tie(%hash,'GDBM_File',$diropendb,&GDBM_WRCREAT,0640)) {   if (tie(%hash,'GDBM_File',$diropendb,&GDBM_WRCREAT,0640)) {
     &start_fresh_session();      &start_fresh_session();
     untie %hash;      untie %hash;
  }   } else {
  else {  
     $r->print('<html><head></head><body>Unable to tie hash to db '.      $r->print('<html><head></head><body>Unable to tie hash to db '.
       'file</body></html>');        'file</body></html>');
     return OK;      return OK;
  }   }
     }      }
       ##
 # --------------------------- Produce some output, so people know it is working      ## Produce some output, so people know it is working
       ##
     $r->print("\n");      $r->print("\n");
     $r->rflush;      $r->rflush;
       ##
 # ----------------------------------- configure dynamic components of interface      ## Configure dynamic components of interface
       ##
       my $hidden;       # Holds 'hidden' html forms
     if ($ENV{'form.catalogmode'} eq 'interactive') {      if ($ENV{'form.catalogmode'} eq 'interactive') {
  $hidden="<input type='hidden' name='catalogmode' value='interactive'>".   $hidden="<input type='hidden' name='catalogmode' value='interactive'>".
     "\n";      "\n";
         $closebutton="<input type='button' name='close' value='CLOSE' ".          $closebutton="<input type='button' name='close' value='CLOSE' ".
     "onClick='self.close()'>"."\n";      "onClick='self.close()'>"."\n";
     }      } elsif ($ENV{'form.catalogmode'} eq 'groupsearch') {
     elsif ($ENV{'form.catalogmode'} eq 'groupsearch') {  
  $hidden=<<END;   $hidden=<<END;
 <input type='hidden' name='catalogmode' value='groupsearch'>  <input type='hidden' name='catalogmode' value='groupsearch'>
 END  END
Line 279  END Line 212  END
 onClick='javascript:select_group()'>  onClick='javascript:select_group()'>
 END  END
     }      }
     $hidden .= <<END;      $hidden .= &make_persistent({ "form.mode"    => $ENV{'form.mode'},
 <input type='hidden' name='mode'    value='$ENV{'form.mode'}'>                                    "form.form"    => $ENV{'form.form'},
 <input type='hidden' name='form'    value='$ENV{'form.form'}'>                                    "form.element" => $ENV{'form.element'},
 <input type='hidden' name='element' value='$ENV{'form.element'}'>                                    "form.date"    => 2 });
 <input type='hidden' name='date' value='2'>      ##
 END      ##  What are we doing?
 # ------------------------------------------------------ Determine current user      ##
     $yourself=$ENV{'user.name'}.'@'.$ENV{'user.domain'};      my $searchtype;
       $searchtype = 'Basic'    if ($ENV{'form.basicsubmit'}    eq 'SEARCH');
       $searchtype = 'Advanced' if ($ENV{'form.advancedsubmit'} eq 'SEARCH');
       if ($searchtype) {
           my ($query,$customquery,$customshow,$libraries) = 
               (undef,undef,undef,undef);
           if ($searchtype eq 'Basic') {
               $query = &parse_basic_search($r);
           } elsif ($ENV{'form.advancedsubmit'} eq 'SEARCH') {
               ($query,$customquery,$customshow,$libraries) 
                   = &parse_advanced_search($r);
               return OK if (! defined($query));
           }
           # Send query statements over the network to be processed by 
           # either the SQL database or a recursive scheme of 'grep'-like 
           # actions (for custom metadata).
           $r->rflush();
           my $reply=&Apache::lonnet::metadata_query($query,$customquery,
                                                  $customshow,$libraries);
           &output_results($searchtype,$r,$reply,$hidden);
       } elsif ($ENV{'form.reqinterface'} eq 'advanced') {
           # Output the advanced interface
           $r->print(&advanced_search_form($closebutton,$hidden));
       } else { 
           # Output normal search interface
           $r->print(&basic_search_form($closebutton,$hidden));
       }
       return OK;
   } 
   
 # --- Now, depending on the interface actions, do one of three things here:  ######################################################################
 # --- 1. a basic search  ######################################################################
 # --- 2. an advanced search  
 # --- 3. output a search interface  
   
 # ----------------------------------- See if a search invocation should be done  =pod 
     if ($ENV{'form.basicsubmit'} eq 'SEARCH') {  
  untie %hash; return &basicsearch($r,\%ENV);  =item &basic_search_form() 
     }  
     elsif ($ENV{'form.advancedsubmit'} eq 'SEARCH') {  Returns a scalar which holds html for the basic search form.
  untie %hash; return &advancedsearch($r,\%ENV);  
   =cut
   
   ######################################################################
   ######################################################################
   
   sub basic_search_form{
       my ($closebutton,$hidden) = @_;
       my $scrout=<<"ENDDOCUMENT";
   <html>
   <head>
   <title>The LearningOnline Network with CAPA</title>
   <script type="text/javascript">
       function openhelp(val) {
    openhelpwin=open('/adm/help/searchcat.html','helpscreen',
        'scrollbars=1,width=600,height=300');
    openhelpwin.focus();
     }      }
   </script>
   </head>
   <body bgcolor="#FFFFFF">
   <img align='right' src='/adm/lonIcons/lonlogos.gif' />
   <h1>Search Catalog</h1>
   <form method="post" action="/adm/searchcat">
   $hidden
   <h3>Basic Search</h3>
   <p>
   Enter terms or phrases separated by AND, OR, or NOT 
   then press SEARCH below.
   </p>
   <p>
   <table>
   <tr><td>
   ENDDOCUMENT
       $scrout.='&nbsp;'.&simpletextfield('basicexp',$ENV{'form.basicexp'},40).
           '&nbsp;';
   #    $scrout.=&simplecheckbox('allversions',$ENV{'form.allversions'});
   #    $scrout.='<font color="#800000">Search historic archives</font>';
       $scrout.=<<ENDDOCUMENT;
   </td><td><a href="/adm/searchcat?reqinterface=advanced">Advanced Search</a></td></tr></table>
   </p>
   <p>
   &nbsp;<input type="submit" name="basicsubmit" value='SEARCH' />&nbsp;
   $closebutton
   <!-- view selection -->
   <select name="viewselect">
   <option value="Detailed Citation View" selected="true" >Detailed Citation View</option>
   <option value="Summary View"  >Summary View</option>
   <option value="Fielded Format">Fielded Format</option>
   <option value="XML/SGML"      >XML/SGML</option>
   </select>
   <!-- end of view selection -->
   <input type="button" value="HELP" onClick="openhelp()" />
   </p>
   </form>
   </body>
   </html>
   ENDDOCUMENT
       return $scrout;
   }
   ######################################################################
   ######################################################################
   
 # ----------------------------- Else, begin building search interface to output  =pod 
     $scrout=''; # building a part of screen output  
     $scrout.=&searchphrasefield('Limit by title','title',  
  $ENV{'form.title'});  
   
     $scrout.=&searchphrasefield('Limit by author','author',  =item &advanced_search_form() 
  $ENV{'form.author'});  
   
     $scrout.=&searchphrasefield('Limit by subject','subject',  Returns a scalar which holds html for the advanced search form.
  $ENV{'form.subject'});  
   
     $scrout.=&searchphrasefield('Limit by keywords','keywords',  =cut
  $ENV{'form.keywords'});  
   
     $scrout.=&searchphrasefield('Limit by URL','url',  ######################################################################
  $ENV{'form.url'});  ######################################################################
   
   sub advanced_search_form{
       my ($closebutton,$hidden) = @_;
       my $advanced_buttons = <<"END";
   <p>
   <input type="submit" name="advancedsubmit" value='SEARCH' />
   <input type="reset" name="reset" value='RESET' />
   $closebutton
   <input type="button" value="HELP" onClick="openhelp()" />
   </p>
   END
       my $scrout=<<"ENDHEADER";
   <html>
   <head>
   <title>The LearningOnline Network with CAPA</title>
   <script type="text/javascript">
       function openhelp(val) {
    openhelpwin=open('/adm/help/searchcat.html','helpscreen',
        'scrollbars=1,width=600,height=300');
    openhelpwin.focus();
       }
   </script>
   </head>
   <body bgcolor="#FFFFFF">
   <img align='right' src='/adm/lonIcons/lonlogos.gif' />
   <h1>Advanced Catalog Search</h1>
   <hr />
   Enter terms or phrases separated by search operators 
   such as AND, OR, or NOT.<br />
   <form method="post" action="/adm/searchcat">
   $advanced_buttons
   $hidden
   <table>
   <tr><td><font color="#800000" face="helvetica"><b>VIEW:</b></font></td>
   <td>
   <!-- view selection -->
   <select name="viewselect" size ="1">
       <option value="Detailed Citation View" selected="true">Detailed Citation View</option>
       <option value="Summary View">Summary View</option>
       <option value="Fielded Format">Fielded Format</option>
       <option value="XML/SGML">XML/SGML</option>
   </select>
   <!-- end of view selection -->
   </td></tr>
   ENDHEADER
       $scrout.=&searchphrasefield('title','title',
    $ENV{'form.title'});
       $scrout.=&searchphrasefield('author','author',
    $ENV{'form.author'});
       $scrout.=&searchphrasefield('subject','subject',
    $ENV{'form.subject'});
       $scrout.=&searchphrasefield('keywords','keywords',
    $ENV{'form.keywords'});
       $scrout.=&searchphrasefield('URL','url',
    $ENV{'form.url'});
 #    $scrout.=&searchphrasefield('Limit by version','version',  #    $scrout.=&searchphrasefield('Limit by version','version',
 # $ENV{'form.version'});  # $ENV{'form.version'});
       $scrout.=&searchphrasefield('notes','notes',
     $scrout.=&searchphrasefield('Limit by notes','notes',  
  $ENV{'form.notes'});   $ENV{'form.notes'});
       $scrout.=&searchphrasefield('abstract','abstract',
     $scrout.=&searchphrasefield('Limit by abstract','abstract',  
  $ENV{'form.abstract'});   $ENV{'form.abstract'});
       # Hack - an empty table row.
     $ENV{'form.mime'}='any' unless length($ENV{'form.mime'});      $scrout.="<tr><td>&nbsp;</td><td>&nbsp;</td></tr>\n";
     $scrout.=&selectbox('Limit by MIME type','mime',      $scrout.=&searchphrasefield('file<br />extension','mime',
  $ENV{'form.mime'},                          $ENV{'form.mime'});
  'any','Any type',      $scrout.="<tr><td>&nbsp;</td><td>&nbsp;</td></tr>\n";
  \&{Apache::loncommon::filedescriptionex},      $scrout.=&searchphrasefield('publisher<br />owner','owner',
  (&Apache::loncommon::fileextensions));   $ENV{'form.owner'});
       $scrout.="</table>\n";
       $ENV{'form.category'}='any' unless length($ENV{'form.category'});
       $scrout.=&selectbox('File Category','category',
    $ENV{'form.category'},
    'any','Any category',
    undef,
    (&Apache::loncommon::filecategories()));
     $ENV{'form.language'}='any' unless length($ENV{'form.language'});      $ENV{'form.language'}='any' unless length($ENV{'form.language'});
       #----------------------------------------------------------------
       # Allow restriction to multiple domains.
       #   I make the crazy assumption that there will never be a domain 'any'.
       #
       $ENV{'form.domains'} = 'any' if (! exists($ENV{'form.domains'}));
       my @allowed_domains = (ref($ENV{'form.domains'}) ? @{$ENV{'form.domains'}} 
                              :  ($ENV{'form.domains'}) );
       my %domain_hash = ();
       foreach (@allowed_domains) {
           $domain_hash{$_}++;
       }
       my @domains =&Apache::loncommon::get_domains();
       # adjust the size of the select box
       my $size = 4;
       my $size = (scalar @domains < ($size - 1) ? scalar @domains + 1 : $size);
       # standalone machines do not get to choose a domain to search.
       if ((scalar @domains) == 1) {
           $scrout .='<input type="hidden" name="domains" value="any" />'."\n";
       } else {
           $scrout.="\n".'<font color="#800000" face="helvetica"><b>'.
               'DOMAINS</b></font><br />'.
                   '<select name="domains" size="'.$size.'" multiple>'."\n".
                       '<option name="any" value="any" '.
                           ($domain_hash{'any'}? 'selected ' :'').
                           '>all domains</option>'."\n";
           foreach my $dom (sort @domains) {
               $scrout.="<option name=\"$dom\" ".
                   ($domain_hash{$dom} ? 'selected ' :'').">$dom</option>\n";
           }
           $scrout.="</select>\n";
       }
       #----------------------------------------------------------------
       # 
       #
     $scrout.=&selectbox('Limit by language','language',      $scrout.=&selectbox('Limit by language','language',
  $ENV{'form.language'},'any','Any Language',   $ENV{'form.language'},'any','Any Language',
  \&{Apache::loncommon::languagedescription},   \&{Apache::loncommon::languagedescription},
  (&Apache::loncommon::languageids),   (&Apache::loncommon::languageids),
  );   );
   
 # ------------------------------------------------ Compute date selection boxes  # ------------------------------------------------ Compute date selection boxes
     $scrout.=<<CREATIONDATESTART;      $scrout.=<<CREATIONDATESTART;
 <p>  <p>
Line 355  CREATIONDATESTART Line 458  CREATIONDATESTART
  $ENV{'form.creationdatestart_day'},   $ENV{'form.creationdatestart_day'},
  $ENV{'form.creationdatestart_year'},   $ENV{'form.creationdatestart_year'},
  );   );
     $scrout.=<<CREATIONDATEEND;      $scrout.="and:\n";
 and:  
 CREATIONDATEEND  
     $scrout.=&dateboxes('creationdateend',12,31,2051,      $scrout.=&dateboxes('creationdateend',12,31,2051,
  $ENV{'form.creationdateend_month'},   $ENV{'form.creationdateend_month'},
  $ENV{'form.creationdateend_day'},   $ENV{'form.creationdateend_day'},
  $ENV{'form.creationdateend_year'},   $ENV{'form.creationdateend_year'},
  );   );
     $scrout.="</p>";      $scrout.="</p>";
   
     $scrout.=<<LASTREVISIONDATESTART;      $scrout.=<<LASTREVISIONDATESTART;
 <p>  <p>
 <font color="#800000" face="helvetica"><b>LIMIT BY LAST REVISION DATE RANGE:  <font color="#800000" face="helvetica"><b>LIMIT BY LAST REVISION DATE RANGE:
Line 385  LASTREVISIONDATEEND Line 485  LASTREVISIONDATEEND
  $ENV{'form.lastrevisiondateend_year'},   $ENV{'form.lastrevisiondateend_year'},
  );   );
     $scrout.='</p>';      $scrout.='</p>';
   
     $scrout.=&searchphrasefield('Limit by publisher/owner','owner',  
  $ENV{'form.owner'});  
   
     $ENV{'form.copyright'}='any' unless length($ENV{'form.copyright'});      $ENV{'form.copyright'}='any' unless length($ENV{'form.copyright'});
     $scrout.=&selectbox('Limit by copyright/distribution','copyright',      $scrout.=&selectbox('Limit by copyright/distribution','copyright',
  $ENV{'form.copyright'},   $ENV{'form.copyright'},
Line 396  LASTREVISIONDATEEND Line 492  LASTREVISIONDATEEND
  \&{Apache::loncommon::copyrightdescription},   \&{Apache::loncommon::copyrightdescription},
  (&Apache::loncommon::copyrightids),   (&Apache::loncommon::copyrightids),
  );   );
   
 # ------------------------------------------- Compute customized metadata field  # ------------------------------------------- Compute customized metadata field
     $scrout.=<<CUSTOMMETADATA;      $scrout.=<<CUSTOMMETADATA;
 <p>  <p>
Line 407  For resource-specific metadata, enter in Line 502  For resource-specific metadata, enter in
 <b>Example:</b> grandmother=75 OR grandfather=85  <b>Example:</b> grandmother=75 OR grandfather=85
 <br />  <br />
 CUSTOMMETADATA  CUSTOMMETADATA
 $scrout.=&simpletextfield('custommetadata',$ENV{'form.custommetadata'});      $scrout.=&simpletextfield('custommetadata',$ENV{'form.custommetadata'});
 $scrout.=' <i>initial users of this system do not need to worry about this option</i>';  
   
     $scrout.=<<CUSTOMSHOW;      $scrout.=<<CUSTOMSHOW;
 <p>  <p>
 <font color="#800000" face="helvetica"><b>SHOW SPECIAL METADATA FIELDS:</b>  <font color="#800000" face="helvetica"><b>SHOW SPECIAL METADATA FIELDS:</b>
Line 418  Enter in a space-separated list of speci Line 511  Enter in a space-separated list of speci
 in a fielded listing for each record result.  in a fielded listing for each record result.
 <br />  <br />
 CUSTOMSHOW  CUSTOMSHOW
 $scrout.=&simpletextfield('customshow',$ENV{'form.customshow'});      $scrout.=&simpletextfield('customshow',$ENV{'form.customshow'});
 $scrout.=' <i>initial users of this system do not need to worry about this option</i>';      $scrout.=<<ENDDOCUMENT;
   $advanced_buttons
 # ---------------------------------------------------------------- Print screen  
     $r->print(<<ENDDOCUMENT);  
 <html>  
 <head>  
 <title>The LearningOnline Network with CAPA</title>  
 <script type="text/javascript">  
     function openhelp(val) {  
  openhelpwin=open('/adm/help/searchcat.html','helpscreen',  
      'scrollbars=1,width=600,height=300');  
  openhelpwin.focus();  
     }  
 </script>  
 </head>  
 <body bgcolor="#FFFFFF">  
 <img align='right' src='/adm/lonIcons/lonlogos.gif' />  
 <h1>Search Catalog</h1>  
 <form method="post" action="/adm/searchcat">  
 $hidden  
 <hr />  
 <h3>Basic Search</h3>  
 <p>  
 Enter terms or phrases separated by search operators  
 such as AND, OR, or NOT then press SEARCH below.  Terms should be specific  
 to the title, author, subject, notes, or abstract information associated  
 with a resource.  
 <br />  
 ENDDOCUMENT  
     $r->print(&simpletextfield('basicexp',$ENV{'form.basicexp'}));  
     $r->print(' ');  
     $r->print(&simplecheckbox('titleonly',$ENV{'form.titleonly'}));  
     $r->print('<font color="#800000">Title only</font> ');  
 #    $r->print(&simplecheckbox('allversions',$ENV{'form.allversions'}));  
 # <font color="#800000">Search historic archives</font>  
     $r->print(<<ENDDOCUMENT);  
 <br />  
 <input type="submit" name="basicsubmit" value='SEARCH' />  
 <input type="reset" name="reset" value='RESET' />  
 $closebutton  
 $basicviewselect  
 <input type="button" value="HELP" onClick="openhelp()" />  
 </p>  
 <hr />  
 <h3>Advanced Search</h3>  
 $scrout  
 <p>  
 <input type="submit" name="advancedsubmit" value='SEARCH' />  
 <input type="reset" name="reset" value='RESET' />  
 $closebutton  
 $advancedviewselect  
 <input type="button" value="HELP" onClick="openhelp()" />  
 </p>  
 </form>  </form>
 </body>  </body>
 </html>  </html>
 ENDDOCUMENT  ENDDOCUMENT
     return OK;      return $scrout;
 }   }
   
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
Line 487  ENDDOCUMENT Line 529  ENDDOCUMENT
 =item &make_persistent()   =item &make_persistent() 
   
 Returns a scalar which holds the current ENV{'form.*'} values in  Returns a scalar which holds the current ENV{'form.*'} values in
 a 'hidden' html input tag.    a 'hidden' html input tag.  This allows search interface information
   to be somewhat persistent.
   
 =cut  =cut
   
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
   
 # ------------------------------------------------------------- make persistent  
   
 sub make_persistent {  sub make_persistent {
       my %save = %{shift()};
     my $persistent='';      my $persistent='';
           foreach (keys %save) {
     foreach (keys %ENV) {  
  if (/^form\./ && !/submit/) {   if (/^form\./ && !/submit/) {
     my $name=$_;      my $name=$_;
     my $key=$name;              my @values = (ref($save{$name}) ? @{$save{$name}} : ($save{$name}));
     $ENV{$key}=~s/\'//g; # do not mess with html field syntax  
     $name=~s/^form\.//;      $name=~s/^form\.//;
     $persistent.=<<END;              foreach (@values) {
 <input type='hidden' name='$name' value='$ENV{$key}' />                  s/\"/\'/g; # do not mess with html field syntax
                   $persistent.=<<END;
   <input type="hidden" name="$name" value="$_" />
 END  END
               }
         }          }
     }      }
     return $persistent;      return $persistent;
 }  }
   
 # --------------------------------------------------------- Various form fields  
   ######################################################################
   ######################################################################
   
   =pod 
   
   =item HTML form building functions
   
   =over 4
   
   =item &simpletextfield() 
   
   Inputs: $name,$value,$size
   
   Returns a text input field with the given name, value, and size.  
   If size is not specified, a value of 20 is used.
   
   =item &simplecheckbox()
   
   Inputs: $name,$value
   
   Returns a simple check box with the given $name.
   If $value eq 'on' the box is checked.
   
   =item &searchphrasefield()
   
   Inputs: $title,$name,$value
   
   Returns html for a title line and an input field for entering search terms.
   the instructions "Enter terms or phrases separated by search operators such 
   as AND, OR, or NOT." are given following the title.  The entry field (which
   is where the $name and $value are used) is an 80 column simpletextfield.
   
   =item &dateboxes()
   
   Returns html selection form elements for the specification of 
   the day, month, and year.
   
   =item &selectbox()
   
   Returns a scalar containing an html <select> form.  
   
   Inputs: 
   
   =over 4
   
   =item $title 
   
   Printed above the select box, in uppercase.
   
   =item $name 
   
   The name element of the <select> tag.
   
   =item $default 
   
   The default value of the form.  Can be $anyvalue or in @idlist.
   
   =item $anyvalue 
   
   The <option value="..."> used to indicate a default of 
   none of the values.
   
   =item $anytag 
   
   The text associate with $anyvalue above.
   
   =item $functionref 
   
   Each element in @idlist will be passed as a parameter 
   to the function referenced here.  The return value of the function should
   be a scalar description of the items.  If this value is undefined the 
   description of each item in @idlist will be the item name.
   
   =item @idlist 
   
   The items to be selected from.  One of these or $anyvalue will be the 
   value returned by the form element, $ENV{form.$name}.
   
   =back
   
   =back 
   
   =cut
   
   ######################################################################
   ######################################################################
   
 sub simpletextfield {  sub simpletextfield {
     my ($name,$value)=@_;      my ($name,$value,$size)=@_;
     return '<input type=text name=\''.$name.      $size = 20 if (! defined($size));
    '\' size=20 value=\''.$value.'\' />';      return '<input type="text" name="'.$name.
           '" size="'.$size.'" value="'.$value.'" />';
 }  }
   
 sub simplecheckbox {  sub simplecheckbox {
     my ($name,$value)=@_;      my ($name,$value)=@_;
     my $checked='';      my $checked='';
     $checked="CHECKED" if $value eq 'on';      $checked="checked" if $value eq 'on';
     return '<input type=checkbox name=\''.$name.'\' '. $checked . '>';      return '<input type="checkbox" name="'.$name.'" '. $checked . ' />';
 }  }
   
 sub searchphrasefield {  sub searchphrasefield {
     my ($title,$name,$value)=@_;      my ($title,$name,$value)=@_;
     my $instruction=<<END;  
 Enter terms or phrases separated by search operators such  
 as AND, OR, or NOT.  
 END  
     my $uctitle=uc($title);      my $uctitle=uc($title);
     return "\n<p><font color=\"#800000\" face=\"helvetica\"><b>$uctitle:</b>".      return '<tr><td><font color="#800000" face="helvetica">'.
    "</FONT> $instruction<br />".          '<b>'.$uctitle.':&nbsp;</b></font></td><td>'.
            '<input type=text name="'.$name.'" size=80 value=\''.$value.'\'>';                  &simpletextfield($name,$value,50)."</td></tr>\n";
 }  }
   
 sub dateboxes {  sub dateboxes {
Line 584  END Line 711  END
 }  }
   
 sub selectbox {  sub selectbox {
     my ($title,$name,$value,$anyvalue,$anytag,$functionref,@idlist)=@_;      my ($title,$name,$default,$anyvalue,$anytag,$functionref,@idlist)=@_;
       if (! defined($functionref)) { $functionref = sub { $_[0]}; }
     my $uctitle=uc($title);      my $uctitle=uc($title);
     my $selout="\n<p><font color=\"#800000\" face=\"helvetica\"><b>$uctitle:".      my $selout="\n".'<p><font color="#800000" face="helvetica">'.
  "</b></font><br />".'<select name="'.$name.'">';          '<b>'.$uctitle.': </b></font><select name="'.$name.'">';
     foreach ($anyvalue,@idlist) {      foreach ($anyvalue,@idlist) {
         $selout.='<option value=\''.$_.'\'';          $selout.='<option value="'.$_.'"';
         if ($_ eq $value and !/^any$/) {          if ($_ eq $default and !/^any$/) {
     $selout.=' selected>'.&{$functionref}($_).'</option>';      $selout.=' selected >'.&{$functionref}($_).'</option>';
  }   }
  elsif ($_ eq $value and /^$anyvalue$/) {   elsif ($_ eq $default and /^$anyvalue$/) {
     $selout.=' selected>'.$anytag.'</option>';      $selout.=' selected >'.$anytag.'</option>';
  }   }
         else {$selout.='>'.&{$functionref}($_).'</option>';}          else {$selout.='>'.&{$functionref}($_).'</option>';}
     }      }
     return $selout.'</select>';      return $selout.'</select></p>';
 }  }
   
 # ----------------------------------------------- Performing an advanced search  ######################################################################
 sub advancedsearch {  ######################################################################
     my ($r,$envhash)=@_;  
     my %ENV=%{$envhash};  =pod 
   
   =item &parse_advanced_search()
   
   Parse advanced search form and return the following:
   
   =over 4
   
   =item $query Scalar containing an SQL query.
   
   =item $customquery Scalar containing a custom query.
   
   =item $customshow Scalar containing commands to show custom metadata.
   
   =item $libraries_to_query Reference to array of domains to search.
   
   =back
   
   =cut
   
   ######################################################################
   ######################################################################
   sub parse_advanced_search {
       my ($r)=@_;
     my $fillflag=0;      my $fillflag=0;
     # Clean up fields for safety      # Clean up fields for safety
     for my $field ('title','author','subject','keywords','url','version',      for my $field ('title','author','subject','keywords','url','version',
Line 616  sub advancedsearch { Line 766  sub advancedsearch {
    'lastrevisiondatestart_year','lastrevisiondateend_month',     'lastrevisiondatestart_year','lastrevisiondateend_month',
    'lastrevisiondateend_day','lastrevisiondateend_year',     'lastrevisiondateend_day','lastrevisiondateend_year',
    'notes','abstract','mime','language','owner',     'notes','abstract','mime','language','owner',
    'custommetadata','customshow') {     'custommetadata','customshow','category') {
  $ENV{"form.$field"}=~s/[^\w\/\s\(\)\=\-\"\']//g;   $ENV{"form.$field"}=~s/[^\w\/\s\(\)\=\-\"\']//g;
     }      }
     foreach ('mode','form','element') {      foreach ('mode','form','element') {
Line 625  sub advancedsearch { Line 775  sub advancedsearch {
  $ENV{"form.$_"}=&Apache::lonnet::unescape($ENV{"form.$_"});   $ENV{"form.$_"}=&Apache::lonnet::unescape($ENV{"form.$_"});
  $ENV{"form.$_"}=~s/[^\w\/\s\(\)\=\-\"\']//g;   $ENV{"form.$_"}=~s/[^\w\/\s\(\)\=\-\"\']//g;
     }      }
       # Preprocess the category form element.
       if ($ENV{'form.category'} ne 'any') {
           my @extensions = &Apache::loncommon::filecategorytypes
               ($ENV{'form.category'});
           $ENV{'form.mime'} = join ' OR ',@extensions;
       }
     # Check to see if enough information was filled in      # Check to see if enough information was filled in
     for my $field ('title','author','subject','keywords','url','version',      for my $field ('title','author','subject','keywords','url','version',
    'notes','abstract','mime','language','owner',     'notes','abstract','mime','language','owner',
Line 635  sub advancedsearch { Line 791  sub advancedsearch {
     }      }
     unless ($fillflag) {      unless ($fillflag) {
  &output_blank_field_error($r);   &output_blank_field_error($r);
  return OK;   return ;
     }      }
   
   
     # Turn the form input into a SQL-based query      # Turn the form input into a SQL-based query
     my $query='';      my $query='';
   
     my @queries;      my @queries;
     # Evaluate logical expression AND/OR/NOT phrase fields.      # Evaluate logical expression AND/OR/NOT phrase fields.
     foreach my $field ('title','author','subject','notes','abstract','url',      foreach my $field ('title','author','subject','notes','abstract','url',
        'keywords','version','owner') {         'keywords','version','owner','mime') {
  if ($ENV{'form.'.$field}) {   if ($ENV{'form.'.$field}) {
     push @queries,&build_SQL_query($field,$ENV{'form.'.$field});      push @queries,&build_SQL_query($field,$ENV{'form.'.$field});
  }          }
     }      }
     # Evaluate option lists      # Evaluate option lists
     if ($ENV{'form.language'} and $ENV{'form.language'} ne 'any') {      if ($ENV{'form.language'} and $ENV{'form.language'} ne 'any') {
  push @queries,"(language like \"$ENV{'form.language'}\")";   push @queries,"(language like \"$ENV{'form.language'}\")";
     }      }
     if ($ENV{'form.mime'} and $ENV{'form.mime'} ne 'any') {  
  push @queries,"(mime like \"$ENV{'form.mime'}\")";  
     }  
     if ($ENV{'form.copyright'} and $ENV{'form.copyright'} ne 'any') {      if ($ENV{'form.copyright'} and $ENV{'form.copyright'} ne 'any') {
  push @queries,"(copyright like \"$ENV{'form.copyright'}\")";   push @queries,"(copyright like \"$ENV{'form.copyright'}\")";
     }      }
Line 678  sub advancedsearch { Line 828  sub advancedsearch {
     # Test to see if date windows are legitimate      # Test to see if date windows are legitimate
     if ($datequery=~/^Incorrect/) {      if ($datequery=~/^Incorrect/) {
  &output_date_error($r,$datequery);   &output_date_error($r,$datequery);
  return OK;   return ;
     }      }
     elsif ($datequery) {      elsif ($datequery) {
  push @queries,$datequery;   push @queries,$datequery;
     }      }
   
     # Process form information for custom metadata querying      # Process form information for custom metadata querying
     my $customquery='';      my $customquery=undef;
     if ($ENV{'form.custommetadata'}) {      if ($ENV{'form.custommetadata'}) {
  $customquery=&build_custommetadata_query('custommetadata',   $customquery=&build_custommetadata_query('custommetadata',
       $ENV{'form.custommetadata'});        $ENV{'form.custommetadata'});
     }      }
     my $customshow='';      my $customshow=undef;
     if ($ENV{'form.customshow'}) {      if ($ENV{'form.customshow'}) {
  $customshow=$ENV{'form.customshow'};   $customshow=$ENV{'form.customshow'};
  $customshow=~s/[^\w\s]//g;   $customshow=~s/[^\w\s]//g;
  my @fields=split(/\s+/,$customshow);   my @fields=split(/\s+/,$customshow);
  $customshow=join(" ",@fields);   $customshow=join(" ",@fields);
     }      }
     # Send query statements over the network to be processed by either the SQL      ## ---------------------------------------------------------------
     # database or a recursive scheme of 'grep'-like actions (for custom      ## Deal with restrictions to given domains
     # metadata).      ## 
       my $libraries_to_query = undef;
       # $ENV{'form.domains'} can be either a scalar or an array reference.
       # We need an array.
       my @allowed_domains = (ref($ENV{'form.domains'}) ? @{$ENV{'form.domains'}} 
                              :  ($ENV{'form.domains'}) );
       my %domain_hash = ();
       foreach (@allowed_domains) {
           $domain_hash{$_}++;
       }
       foreach (keys(%Apache::lonnet::libserv)) {
           if ($_ eq 'any') {
               $libraries_to_query = undef;
               last;
           }
           if (exists($domain_hash{$Apache::lonnet::hostdom{$_}})) {
               push @$libraries_to_query,$_;
           }
       }
       #
     if (@queries) {      if (@queries) {
  $query=join(" AND ",@queries);   $query=join(" AND ",@queries);
  $query="select * from metadata where $query";   $query="select * from metadata where $query";
  my $reply; # reply hash reference      } elsif ($customquery) {
  unless ($customquery or $customshow) {          $query = '';
     $reply=&Apache::lonnet::metadata_query($query);  
  }  
  else {  
     $reply=&Apache::lonnet::metadata_query($query,  
    $customquery,$customshow);  
  }  
  &output_results('Advanced',$r,$envhash,$customquery,$reply);  
     }      }
     elsif ($customquery) {      return ($query,$customquery,$customshow,$libraries_to_query);
  my $reply; # reply hash reference  }
  $reply=&Apache::lonnet::metadata_query('',  
        $customquery,$customshow);  ######################################################################
  &output_results('Advanced',$r,$envhash,$customquery,$reply);  ######################################################################
     }  
     # should not get to this point  =pod 
     return 'Error.  Should not have gone to this point.';  
 }  =item &parse_basic_search() 
   
 # --------------------------------------------------- Performing a basic search  Parse the basic search form and return a scalar containing an sql query.
 sub basicsearch {  
     my ($r,$envhash)=@_;  =cut
     my %ENV=%{$envhash};  
   ######################################################################
   ######################################################################
   sub parse_basic_search {
       my ($r)=@_;
     # Clean up fields for safety      # Clean up fields for safety
     for my $field ('basicexp') {      for my $field ('basicexp') {
  $ENV{"form.$field"}=~s/[^\w\s\(\)\-]//g;   $ENV{"form.$field"}=~s/[^\w\s\(\)\-]//g;
Line 747  sub basicsearch { Line 912  sub basicsearch {
     # Build SQL query string based on form page      # Build SQL query string based on form page
     my $query='';      my $query='';
     my $concatarg=join(',"    ",',      my $concatarg=join(',"    ",',
        ('title', 'author', 'subject', 'notes', 'abstract'));         ('title', 'author', 'subject', 'notes', 'abstract',
                           'keywords'));
     $concatarg='title' if $ENV{'form.titleonly'};      $concatarg='title' if $ENV{'form.titleonly'};
   
     $query=&build_SQL_query('concat('.$concatarg.')',$ENV{'form.'.'basicexp'});      $query=&build_SQL_query('concat('.$concatarg.')',$ENV{'form.'.'basicexp'});
       return 'select * from metadata where '.$query;
   }
   
     # Get reply (either a hash reference to filehandles or bad connection)  
     my $reply=&Apache::lonnet::metadata_query('select * from metadata where '.$query);  
   
     # Output search results  ######################################################################
   ######################################################################
   
     &output_results('Basic',$r,$envhash,$query,$reply);  =pod 
   
     return OK;  =item &build_SQL_query() 
 }  
   Builds a SQL query string from a logical expression with AND/OR keywords
   using Text::Query and &recursive_SQL_query_builder()
   
   =cut
   
 # ------------------------------------------------------------- build_SQL_query  ######################################################################
   ######################################################################
 sub build_SQL_query {  sub build_SQL_query {
     my ($field_name,$logic_statement)=@_;      my ($field_name,$logic_statement)=@_;
     my $q=new Text::Query('abc',      my $q=new Text::Query('abc',
Line 774  sub build_SQL_query { Line 946  sub build_SQL_query {
     return $sql_query;      return $sql_query;
 }  }
   
 # ------------------------------------------------- build custom metadata query  ######################################################################
   ######################################################################
   
   =pod 
   
   =item &build_custommetadata_query() 
   
   Constructs a custom metadata query using a rather heinous regular
   expression.
   
   =cut
   
   ######################################################################
   ######################################################################
 sub build_custommetadata_query {  sub build_custommetadata_query {
     my ($field_name,$logic_statement)=@_;      my ($field_name,$logic_statement)=@_;
     my $q=new Text::Query('abc',      my $q=new Text::Query('abc',
Line 784  sub build_custommetadata_query { Line 969  sub build_custommetadata_query {
     my $matchexp=${$q}{'-parse'}{'-build'}{'matchstring'};      my $matchexp=${$q}{'-parse'}{'-build'}{'matchstring'};
     # quick fix to change literal into xml tag-matching      # quick fix to change literal into xml tag-matching
     # will eventually have to write a separate builder module      # will eventually have to write a separate builder module
     my $oldmatchexp=$matchexp;      # wordone=wordtwo becomes\<wordone\>[^\<] *wordtwo[^\<]*\<\/wordone\>
     $matchexp=~s/(\w+)\\=([\w\\\+]+)/\\<$1\\>\[\^\\<\]\*$2\[\^\\<\]\*\\<\\\/$1\\>/g;      $matchexp =~ s/(\w+)\\=([\w\\\+]+)?# wordone=wordtwo is changed to 
                    /\\<$1\\>?#           \<wordone\>
                      \[\^\\<\]?#        [^\<]         
                      \*$2\[\^\\<\]?#           *wordtwo[^\<]
                      \*\\<\\\/$1\\>?#                        *\<\/wordone\>
                      /g;
     return $matchexp;      return $matchexp;
 }  }
   
 # - Recursively parse a reverse notation expression into a SQL query expression  ######################################################################
   ######################################################################
   
   =pod 
   
   =item &recursive_SQL_query_build() 
   
   Recursively constructs an SQL query.  Takes as input $dkey and $pattern.
   
   =cut
   
   ######################################################################
   ######################################################################
 sub recursive_SQL_query_build {  sub recursive_SQL_query_build {
     my ($dkey,$pattern)=@_;      my ($dkey,$pattern)=@_;
     my @matches=($pattern=~/(\[[^\]|\[]*\])/g);      my @matches=($pattern=~/(\[[^\]|\[]*\])/g);
Line 823  sub recursive_SQL_query_build { Line 1025  sub recursive_SQL_query_build {
     &recursive_SQL_query_build($dkey,$pattern);      &recursive_SQL_query_build($dkey,$pattern);
 }  }
   
 # ------------------------------------------------------------ Build date query  ######################################################################
   ######################################################################
   
   =pod 
   
   =item &build_date_queries() 
   
   Builds a SQL logic query to check time/date entries.
   Also reports errors (check for /^Incorrect/).
   
   =cut
   
   ######################################################################
   ######################################################################
 sub build_date_queries {  sub build_date_queries {
     my ($cmonth1,$cday1,$cyear1,$cmonth2,$cday2,$cyear2,      my ($cmonth1,$cday1,$cyear1,$cmonth2,$cday2,$cyear2,
  $lmonth1,$lday1,$lyear1,$lmonth2,$lday2,$lyear2)=@_;   $lmonth1,$lday1,$lyear1,$lmonth2,$lday2,$lyear2)=@_;
Line 872  sub build_date_queries { Line 1087  sub build_date_queries {
     return '';      return '';
 }  }
   
 # ----------------------------- format and output results based on a reply list  ######################################################################
 # There are two windows that this function writes to.  The main search  ######################################################################
 # window ("srch") has a listing of the results.  A secondary window ("popwin")  
 # gives the status of the network search (time elapsed, number of machines  =pod 
 # contacted, etc.)  
   =item &output_results() 
   
   Format and output results based on a reply list.
   There are two windows that this function writes to.  The main search
   window ("srch") has a listing of the results.  A secondary window ("popwin")
   gives the status of the network search (time elapsed, number of machines
   contacted, etc.)
   
   =cut
   
   ######################################################################
   ######################################################################
 sub output_results {  sub output_results {
   #    &Apache::lonnet::logthis("output_results:".time);
     my $fnum; # search result counter      my $fnum; # search result counter
     my ($mode,$r,$envhash,$query,$replyref)=@_;      my ($mode,$r,$replyref,$hidden)=@_;
     my %ENV=%{$envhash};  
     my %rhash=%{$replyref};      my %rhash=%{$replyref};
     my $compiledresult='';      my $compiledresult='';
     my $timeremain=300;      my $timeremain=300; # (seconds)
     my $elapsetime=0;      my $elapsetime=0;
     my $resultflag=0;      my $resultflag=0;
     my $tflag=1;      my $tflag=1;
       my $viewselect=$ENV{'form.viewselect'};
       #
     # make query information persistent to allow for subsequent revision      # make query information persistent to allow for subsequent revision
     my $persistent=&make_persistent();      my $persistent=&make_persistent(\%ENV);
       # spit out the results header
       $r->print(&search_results_header($mode));
       $r->rflush();
       # begin showing the cataloged results
       my $action = "/adm/searchcat";
       if ($mode eq 'Basic') { 
           $action .= "?reqinterface=basic";
       } elsif ($mode eq 'Advanced') {
           $action .= "?reqinterface=advanced";
       }
       $r->print(<<CATALOGCONTROLS);
   <form name='results' method="post" action="$action">
   $hidden
   <input type='hidden' name='acts' value='' />
   <input type='button' value='Revise search request'
   onClick='this.form.submit();' />
   $importbutton
   $closebutton
   $persistent
   <hr />
   CATALOGCONTROLS
       #
       # make the pop-up window for status
       #
       $r->print(&make_popwin(%rhash));
       $r->rflush();
       ##
       ## Prepare for the main loop below
       ##
       my $servercount=0;
       my $hitcountsum=0;
       my $servernum=(keys %rhash);
       my $serversleft=$servernum;
       ##
       ## Run until we run out of time or we run out of servers
       ##
       while($serversleft && $timeremain) {
         ##
         ## %rhash has servers deleted from it as results come in 
         ## (within the foreach loop below).
         ##
         foreach my $rkey (sort keys %rhash) {
   #        &Apache::lonnet::logthis("Server $rkey:".time);
    $servercount++;
    $compiledresult='';
    my $reply=$rhash{$rkey};
    my @results;
    if ($reply eq 'con_lost') {
       &popwin_imgupdate($r,$rkey,"srvbad.gif");
       $serversleft--;
               delete $rhash{$rkey};
    } else {
               # must do since 'use strict' checks for tainting
       $reply=~/^([\.\w]+)$/; 
       my $replyfile=$r->dir_config('lonDaemons').'/tmp/'.$1;
       $reply=~/(.*?)\_/;
               for (my $counter=0;$counter<2;$counter++) {
                   if (-e $replyfile && ! -e "$replyfile.end") {
                       &popwin_imgupdate($r,$rkey,"srvhalf.gif");
                       &popwin_js($r,'popwin.hc["'.$rkey.'"]='.
                                  '"still transferring..."'.';');
                   }
                   # Are we finished transferring data?
                   if (-e "$replyfile.end") {
                       $serversleft--;
                       delete $rhash{$rkey};
                       if (-s $replyfile) {
                           &popwin_imgupdate($r,$rkey,"srvgood.gif");
                           my $fh;
                           unless ($fh=Apache::File->new($replyfile)){ 
                               # Is it really appropriate to die on this error?
                               $r->print('ERROR: file '.
                                         $replyfile.' cannot be opened');
                               return OK;
                           }
                           @results=<$fh> if $fh;
                           my $hits =@results;
                           &popwin_js($r,'popwin.hc["'.$rkey.'"]='.
                                      $hits.';');
                           $hitcountsum+=$hits;
                           &popwin_js($r,'popwin.document.forms.popremain.'.
                                      'numhits.value='.$hitcountsum.';');
                       } else {
                           &popwin_imgupdate($r,$rkey,"srvempty.gif");
                           &popwin_js($r,'popwin.hc["'.$rkey.'"]=0;');
                       }
                       last;
                   } # end of if ( -e "$replyfile.end")
                   last unless $timeremain;
                   sleep 1;    # wait for daemons to write files?
                   $timeremain--;
                   $elapsetime++;
                   &popwin_js($r,"popwin.document.popremain.".
                              "elapsetime.value=$elapsetime;");
       }
       &popwin_js($r,'popwin.document.whirly.'.
          'src="/adm/lonIcons/lonanimend.gif";');
    } # end of if ($reply eq 'con_lost') else statement
           my %Fields = undef;     # Holds the data to be sent to the various 
                                   # *_view routines.
           my ($extrashow,$customfields,$customhash) = &handle_custom_fields(\@results);
           my @customfields = @$customfields;
           my %customhash   = %$customhash;
    untie %hash if (keys %hash);
           #
    if (! tie(%hash,'GDBM_File',$diropendb,&GDBM_WRCREAT,0640)) {
       $r->print('<html><head></head><body>Unable to tie hash to db '.
                         'file</body></html>');
           } else {
       if ($ENV{'form.launch'} eq '1') {
    &start_fresh_session();
       }
       foreach my $result (@results) {
    next if $result=~/^custom\=/;
    chomp $result;
    next unless $result;
                   %Fields = &parse_raw_result($result,$rkey);
    $Fields{'extrashow'}=$extrashow;
    if ($extrashow) {
       foreach my $field (@customfields) {
    my $value='';
    $value = $1 if ($customhash{$Fields{'url'}}=~/\<{$field}[^\>]*\>(.*?)\<\/{$field}[^\>]*\>/s);
                           $Fields{'extrashow'}=~s/\<\!\-\- $field \-\-\>/ $value/g;
                       }
                   }
                   $compiledresult.="\n<p>\n";
                   if ($ENV{'form.catalogmode'} eq 'interactive') {
                       my $titleesc=$Fields{'title'};
                       $titleesc=~s/\'/\\'/; # '
                       $compiledresult.=<<END if ($ENV{'form.catalogmode'} eq 'interactive');
   <font size='-1'><INPUT TYPE="button" NAME="returnvalues" VALUE="SELECT"
   onClick="javascript:select_data('$titleesc','$Fields{'url'}')">
   </font>
   <br />
   END
                   }
                   if ($ENV{'form.catalogmode'} eq 'groupsearch') {
       $fnum+=0;
       $hash{"pre_${fnum}_link"}=$Fields{'url'};
       $hash{"pre_${fnum}_title"}=$Fields{'title'};
       $compiledresult.=<<END;
   <font size='-1'>
   <input type="checkbox" name="returnvalues" value="SELECT"
   onClick="javascript:queue($fnum)" />
   </font>
   <br />
   END
   # <input type="hidden" name="title$fnum" value="$title" />
   # <input type="hidden" name="url$fnum" value="$url" />
                       $fnum++;
    }
           if ($viewselect eq 'Detailed Citation View') {
       $compiledresult.=&detailed_citation_view
                           (%Fields, hostname => $rkey );
    }
                   elsif ($viewselect eq 'Summary View') {
       $compiledresult.=&summary_view
                           (%Fields, hostname => $rkey );
           }
                   elsif ($viewselect eq 'Fielded Format') {
       $compiledresult.=&fielded_format_view
                           (%Fields, hostname => $rkey );
           }
                   elsif ($viewselect eq 'XML/SGML') {
       $compiledresult.=&xml_sgml_view
                           (%Fields, hostname => $rkey );
    }
                   if ($compiledresult or $servercount!=$servernum) {
                       $compiledresult.="<hr align='left' width='200' noshade />";
                   }
               }
               untie %hash;
           }
    if ($compiledresult) {
       $resultflag=1;
               $r->print($compiledresult);
    }
           my $percent=sprintf('%3.0f',($servercount/$servernum*100));
         } # End of foreach loop over servers remaining
       }   # End of big loop - while($serversleft && $timeremain)
       unless ($resultflag) {
           $r->print("\nThere were no results that matched your query\n");
       }
   #    $r->print('<script type="text/javascript">'.'popwin.close()</script>'."\n"); $r->rflush(); 
       $r->print("</body>\n</html>\n");
       return;
   }
   
   ###########################################################
   ###########################################################
   
   =pod
   
   =item &parse_raw_result()
   
   Takes a line from the file of results and parse it.  Returns a hash 
   with keys for the following fields:
   'title', 'author', 'subject', 'url', 'keywords', 'version', 'notes', 
   'abstract', 'mime', 'lang', 'owner', 'copyright', 'creationdate', 
   'lastrevisiondate'.
   
   In addition, the following tags are set by calling the appropriate 
   lonnet function: 'language', 'cprtag', 'mimetag'.
   
   The 'title' field is set to "Untitled" if the title field is blank.
   
   'abstract' and 'keywords' are truncated to 200 characters.
   
   =cut
   
   ###########################################################
   ###########################################################
   sub parse_raw_result {
       my ($result,$hostname) = @_;
       # Check for a comma - if it is there then we do not need to unescape the
       # string.  There seems to be some kind of problem with some items in
       # the database - the entire string gets sent out unescaped...?
       unless ($result =~ /,/) {
           $result = &Apache::lonnet::unescape($result);
       }
       my @fields=map {
           &Apache::lonnet::unescape($_);
       } (split(/\,/,$result));
       my ($title,$author,$subject,$url,$keywords,$version,
           $notes,$abstract,$mime,$lang,
           $creationdate,$lastrevisiondate,$owner,$copyright)=@fields;
       my %Fields = 
           ( title     => &Apache::lonnet::unescape($title),
             author    => &Apache::lonnet::unescape($author),
             subject   => &Apache::lonnet::unescape($subject),
             url       => &Apache::lonnet::unescape($url),
             keywords  => &Apache::lonnet::unescape($keywords),
             version   => &Apache::lonnet::unescape($version),
             notes     => &Apache::lonnet::unescape($notes),
             abstract  => &Apache::lonnet::unescape($abstract),
             mime      => &Apache::lonnet::unescape($mime),
             lang      => &Apache::lonnet::unescape($lang),
             owner     => &Apache::lonnet::unescape($owner),
             copyright => &Apache::lonnet::unescape($copyright),
             creationdate     => &Apache::lonnet::unescape($creationdate),
             lastrevisiondate => &Apache::lonnet::unescape($lastrevisiondate)
           );
       $Fields{'language'} = 
           &Apache::loncommon::languagedescription($Fields{'lang'});
       $Fields{'copyrighttag'} =
           &Apache::loncommon::copyrightdescription($Fields{'copyright'});
       $Fields{'mimetag'} =
           &Apache::loncommon::filedescription($Fields{'mime'});
       if ($Fields{'author'}=~/^(\s*|error)$/) {
           $Fields{'author'}="Unknown Author";
       }
       # Put spaces in the keyword list, if needed.
       $Fields{'keywords'}=~ s/,([A-z])/, $1/g; 
       if ($Fields{'title'}=~ /^\s*$/ ) { 
           $Fields{'title'}='Untitled'; 
       }
       unless ($ENV{'user.adv'}) {
           $Fields{'keywords'} = '- not displayed -';
           $Fields{'notes'}    = '- not displayed -';
           $Fields{'abstract'} = '- not displayed -';
           $Fields{'subject'}  = '- not displayed -';
       }
       if (length($Fields{'abstract'})>200) {
           $Fields{'abstract'} = 
               substr($Fields{'abstract'},0,200).'...';
       }
       if (length($Fields{'keywords'})>200) {
           $Fields{'keywords'} =
               substr($Fields{'keywords'},0,200).'...';
       }
       return %Fields;
   }
   
   ###########################################################
   ###########################################################
   
   =pod
   
   =item &handle_custom_fields()
   
   =cut
   
   ###########################################################
   ###########################################################
   sub handle_custom_fields {
       my @results = @{shift()};
       my $customshow='';
       my $extrashow='';
       my @customfields;
       if ($ENV{'form.customshow'}) {
           $customshow=$ENV{'form.customshow'};
           $customshow=~s/[^\w\s]//g;
           my @fields=map {
               "<font color=\"#008000\">$_:</font><!-- $_ -->";
           } split(/\s+/,$customshow);
           @customfields=split(/\s+/,$customshow);
           if ($customshow) {
               $extrashow="<ul><li>".join("</li><li>",@fields)."</li></ul>\n";
           }
       }
       my $customdata='';
       my %customhash;
       foreach my $result (@results) {
           if ($result=~/^(custom\=.*)$/) { # grab all custom metadata
               my $tmp=$result;
               $tmp=~s/^custom\=//;
               my ($k,$v)=map {&Apache::lonnet::unescape($_);
                           } split(/\,/,$tmp);
               $customhash{$k}=$v;
           }
       }
       return ($extrashow,\@customfields,\%customhash);
   }
   
   ######################################################################
   ######################################################################
   
   =pod
   
   =item &search_results_header
   
   Output the proper html headers and javascript code to deal with different 
   calling modes.
   
   Takes most inputs directly from %ENV, except $mode.  
   
   =over 4
   
   =item $mode is either (at this writing) 'Basic' or 'Advanced'
   
   =back
   
   The following environment variables are checked:
   
   =over 4
   
   =item 'form.catalogmode' 
   
   Checked for 'interactive' and 'groupsearch'.
   
   =item 'form.mode'
   
   Checked for existance & 'edit' mode.
   
   =item 'form.form'
   
   =item 'form.element'
   
   =back
   
   =cut
   
   ######################################################################
   ######################################################################
   sub search_results_header {
       my ($mode) = @_;
       $mode = lc($mode);
       my $title;
       if ($mode eq 'advanced') {
           $title = "Advanced Search Results";
       } elsif ($mode eq 'basic') {
           $title = "Basic Search Results";
       }
       my $result = '';
     # output beginning of search page      # output beginning of search page
  $r->print(<<BEGINNING);      $result.=<<BEGINNING;
 <html>  <html>
 <head>  <head>
 <title>The LearningOnline Network with CAPA</title>  <title>$title</title>
 BEGINNING  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
     if ($ENV{'form.catalogmode'} eq 'interactive'){      if ($ENV{'form.catalogmode'} eq 'interactive'){
  if (! exists($ENV{'form.mode'}) || $ENV{'form.mode'} ne 'edit') {   if (! exists($ENV{'form.mode'}) || $ENV{'form.mode'} ne 'edit') {
             $r->print(<<SCRIPT)               $result.=<<SCRIPT;
 <script type="text/javascript">  <script type="text/javascript">
     function select_data(title,url) {      function select_data(title,url) {
  changeTitle(title);   changeTitle(title);
Line 924  SCRIPT Line 1514  SCRIPT
         } elsif ($ENV{'form.mode'} eq 'edit') {          } elsif ($ENV{'form.mode'} eq 'edit') {
             my $form = $ENV{'form.form'};              my $form = $ENV{'form.form'};
             my $element = $ENV{'form.element'};              my $element = $ENV{'form.element'};
             $r->print(<<SCRIPT)               $result.=<<SCRIPT;
 <script type="text/javascript">  <script type="text/javascript">
 function select_data(title,url) {  function select_data(title,url) {
     changeURL(url);      changeURL(url);
Line 944  function changeURL(val) { Line 1534  function changeURL(val) {
 SCRIPT  SCRIPT
         }          }
     }      }
     $r->print(<<SCRIPT) if $ENV{'form.catalogmode'} eq 'groupsearch';      $result.=<<SCRIPT if $ENV{'form.catalogmode'} eq 'groupsearch';
 <script type="text/javascript">  <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);
Line 964  SCRIPT Line 1554  SCRIPT
     }      }
 </script>  </script>
 SCRIPT  SCRIPT
     $r->print(<<SCRIPT);      $result.=<<SCRIPT;
 <script type="text/javascript">  <script type="text/javascript">
     function displayinfo(val) {      function displayinfo(val) {
  popwin.document.forms.popremain.sdetails.value=val;   popwin.document.forms.popremain.sdetails.value=val;
Line 979  SCRIPT Line 1569  SCRIPT
     }      }
 </script>  </script>
 SCRIPT  SCRIPT
     $r->rflush();      $result.=<<END;
   
     # begin showing the cataloged results  
     $r->print(<<CATALOGBEGIN);  
 </head>  </head>
 <body bgcolor="#ffffff">  <body bgcolor="#ffffff">
 <img align=right src=/adm/lonIcons/lonlogos.gif>  <img align=right src=/adm/lonIcons/lonlogos.gif>
 <h1>Search Catalog</h1>  <h1>$title</h1>
 CATALOGBEGIN  END
         $r->print(<<CATALOGCONTROLS);      return $result;
 <form name='results' method="post" action="/adm/searchcat">  }
 $hidden  
 <input type='hidden' name='acts' value='' />  ######################################################################
 <input type='button' value='Revise search request'  ######################################################################
 onClick='this.form.submit();' />  
 $importbutton  =pod
 $closebutton  
 $persistent  =item &make_popwin()
 <hr />  
 <h3>Search Query</h3>  Returns html with javascript in it to open up the status window.
 CATALOGCONTROLS  
     if ($mode eq 'Basic') {  
  $r->print(<<RESULTS);  
 <p>  
 <b>Basic search:</b> $ENV{'form.basicexp'}  
 </p>  
 RESULTS  
     }  
     elsif ($mode eq 'Advanced') {  
  $r->print(<<RESULTS);  
 <p>  
 <b>Advanced search</b>  
 $query  
 </p>  
 RESULTS  
     }  
     $r->print('<h3>Search Results</h3>');  
     $r->rflush();  
     my $servernum=(keys %rhash)+0;  
   
     # define server grid (shows status of multiple machines)  =cut
   
   ######################################################################
   ######################################################################
   sub make_popwin {
       my %rhash = @_;
       my $servernum=(keys %rhash);
     my $hcinit;      my $hcinit;
     my $grid="'<br />'+";      my $grid="'<br />'+\n";
     $grid.="\n";      # $sn is the server number, used ONLY to make sure we have
       # rows of 10 each.  No longer used to index images.
     my $sn=1;      my $sn=1;
     for my $sk (sort keys %rhash) {      foreach my $sk (sort keys %rhash) {
  # '<a href="   # '<a href="
  $grid.="'<a href=\"";   $grid.="'<a href=\"";
  # javascript:displayinfo('+   # javascript:displayinfo('+
Line 1041  RESULTS Line 1616  RESULTS
     $hcinit.="hc[\"$sk\"]=\"not yet connected...\";";      $hcinit.="hc[\"$sk\"]=\"not yet connected...\";";
  }   }
  $grid.=" hitcount=".$hc;   $grid.=" hitcount=".$hc;
  $grid.=" domain=".$hostdomains{$sk};   $grid.=" domain=".$Apache::lonnet::hostdom{$sk};
  $grid.=" IP=".$hostips{$sk};   $grid.=" IP=".$Apache::lonnet::hostip{$sk};
  # '+"'"+'">'+   # '+"'"+'">'+
  $grid.="'+\"'\"+')\">'+";   $grid.="'+\"'\"+')\">'+";
  $grid.="\n";   $grid.="\n";
  $grid.="'<img border=\"0\" name=\"img".$sn."\"".   $grid.="'<img border=\"0\" name=\"img_".$Apache::lonnet::hostdom{$sk}.
     " src=\"/adm/lonIcons/srvnull.gif\" alt=\"".$sk."\" /></a>'+\n";              '_'.$sk."\" 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);      my $result.=<<ENDPOP;
 <script type="text/javascript">  <script type="text/javascript">
     popwin=open('','popwin','scrollbars=1,width=400,height=220');      popwin=open('','popwin','scrollbars=1,width=400,height=220');
     popwin.focus();      popwin.focus();
Line 1095  RESULTS Line 1671  RESULTS
     popwin.document.close();      popwin.document.close();
 </script>  </script>
 ENDPOP  ENDPOP
     $r->rflush();      return $result;
   }
   
     my $servercount=0;  ######################################################################
     my $hitcountsum=0;  ######################################################################
     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++;  
  next RLOOP if $orkey{$rkey};  
  $servercount++;  
  $tflag=1;  
  $compiledresult='';  
  my $hostname=$rkey;  
  my $reply=$rhash{$rkey};  
  my @results;  
   
  my $replyfile='';  
   
  if ($reply eq 'con_lost') {  =pod 
     &popwin_imgupdate($r,$sn,"srvbad.gif");  
     $bloop--;  
     $orkey{$rkey}=1;  
  }  
  else {  
     $reply=~/^([\.\w]+)$/; # must do since 'use strict' checks for tainting  
     $replyfile=$r->dir_config('lonDaemons').'/tmp/'.$1;  
     $reply=~/(.*?)\_/;  
     {  
  my $temp=0;  
       WLOOP: while (1) {  
   if (-e $replyfile && $tflag) {  
       &popwin_imgupdate($r,$sn,"srvhalf.gif");  
       &popwin_js($r,'popwin.hc["'.$rkey.'"]='.  
  '"still transferring..."'.';');  
       $tflag=0;  
   }  
   if (-e "$replyfile.end") {  
       $bloop--;  
       $orkey{$rkey}=1;  
       if (-s $replyfile) {  
   &popwin_imgupdate($r,$sn,"srvgood.gif");  
   my $fh=Apache::File->new($replyfile) or   
       ($r->print('ERROR: file '.  
  $replyfile.' cannot be opened') and  
        return OK);  
   @results=<$fh> if $fh;  
   $hitcount{$rkey}=@results+0;  
   &popwin_js($r,'popwin.hc["'.$rkey.'"]='.  
     $hitcount{$rkey}.';');  
   $hitcountsum+=$hitcount{$rkey};  
   &popwin_js($r,'popwin.document.forms.popremain.'.  
     'numhits.value='.$hitcountsum.';');  
       }  
       else {  
   &popwin_imgupdate($r,$sn,"srvempty.gif");  
   &popwin_js($r,'popwin.hc["'.$rkey.'"]=0;');  
       }  
       last WLOOP;  
   }  
   if ($temp>1) {  
       sleep 1;  
       $timeremain--;  
       $elapsetime++;  
       last WLOOP;  
   }  
   last WLOOP unless $timeremain;  
   sleep 1;  
   $timeremain--;  
   $elapsetime++;  
   &popwin_js($r,"popwin.document.popremain.".  
        "elapsetime.value=$elapsetime;");  
   $temp++;  
       }  
     }  
     &popwin_js($r,'popwin.document.whirly.'.  
        'src="/adm/lonIcons/lonanimend.gif";');  
  }  
  my $customshow='';  
  my $extrashow='';  
  my @customfields;  
  if ($ENV{'form.customshow'}) {  
     $customshow=$ENV{'form.customshow'};  
     $customshow=~s/[^\w\s]//g;  
     my @fields=map {"<font color=\"#008000\">$_:</font><!-- $_ -->"}   
     split(/\s+/,$customshow);  
     @customfields=split(/\s+/,$customshow);  
     if ($customshow) {  
  $extrashow="<ul><li>".join("</li><li>",@fields)."</li></ul>\n";  
     }  
  }  
  my $customdata='';  
  my %customhash;  
  foreach my $result (@results) {  
     if ($result=~/^(custom\=.*)$/) { # grab all custom metadata  
  my $tmp=$result;  
  $tmp=~s/^custom\=//;  
  my ($k,$v)=map {&Apache::lonnet::unescape($_);  
     } split(/\,/,$tmp);  
  $customhash{$k}=$v;  
     }  
  }  
  if (keys %hash) {  
     untie %hash;  
  }  
  if (tie(%hash,'GDBM_File',$diropendb,&GDBM_WRCREAT,0640)) {  
     if ($ENV{'form.launch'} eq '1') {  
  &start_fresh_session();  
     }  
     foreach my $result (@results) {  
  next if $result=~/^custom\=/;  
  chomp $result;  
  next unless $result;  
  my @fields=map  
  {&Apache::lonnet::unescape($_)}  
  (split(/\,/,$result));  
  my ($title,$author,$subject,$url,$keywords,$version,  
     $notes,$abstract,$mime,$lang,  
     $creationdate,$lastrevisiondate,$owner,$copyright)=@fields;  
   
                 unless ($title) { $title='<i>Untitled</i>'; }  
  unless ($ENV{'user.adv'}) {  
     $keywords='<i>- not displayed -</i>';  
     $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;  =item Metadata Viewing Functions
  $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;  Output is a HTML-ified string.
  if ($extrashow) {  Input arguments are title, author, subject, url, keywords, version,
     foreach my $field (@customfields) {  notes, short abstract, mime, language, creation date,
  my $value='';  last revision date, owner, copyright, hostname, and
  if ($customhash{$url}=~/\<${field}[^\>]*\>(.*?)\<\/${field}[^\>]*\>/s) {  extra custom metadata to show.
             $value=$1;  
  }  
         $extrashow2=~s/\<\!\-\- $field \-\-\>/ $value/g;  
             }  
                 }  
   
         $compiledresult.=<<END if $compiledresult or $servercount!=$servernum;  
 <hr align='left' width='200' noshade />  
 END  
                 $compiledresult.=<<END;  
 <p>  
 END  
                if ($ENV{'form.catalogmode'} eq 'interactive') {  
    my $titleesc=$title;  
    $titleesc=~s/\'/\\'/; # '  
   
                    $compiledresult.=<<END if ($ENV{'form.catalogmode'} eq 'interactive');  =over 4
 <font size='-1'><INPUT TYPE="button" NAME="returnvalues" VALUE="SELECT"  
 onClick="javascript:select_data('$titleesc','$url')">  
 </font>  
 <br />  
 END  
                 }  
                 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"  
 onClick="javascript:queue($fnum)" />  
 </font>  
 <br />  
 END  
 # <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'};  
  }  
   
         if ($viewselect eq 'Detailed Citation View') {  
     $compiledresult.=&detailed_citation_view(@fields,  
  $hostname,$httphost,  
  $extrashow2);  
  }  
                 elsif ($viewselect eq 'Summary View') {  
     $compiledresult.=&summary_view(@fields,$hostname,$httphost,  
        $extrashow2);  
         }  
                 elsif ($viewselect eq 'Fielded Format') {  
     $compiledresult.=&fielded_format_view(@fields,$hostname,  
       $httphost,$extrashow2);  
         }  
                 elsif ($viewselect eq 'XML/SGML') {  
     $compiledresult.=&xml_sgml_view(@fields,$hostname,$httphost,  
  $extrashow2);  
  }  
       
             }  
   
             untie %hash;  =item &detailed_citation_view() 
         }  
         else {  
     $r->print('<html><head></head><body>Unable to tie hash to db '.  
   'file</body></html>');  
  }  
  if ($compiledresult) {  
     $resultflag=1;  
  }  
   
  $r->print(<<RESULTS);  =cut
 $compiledresult  
 RESULTS  
         my $percent=sprintf('%3.0f',($servercount/$servernum*100));  
     }  
   }  
     unless ($resultflag) {  
         $r->print("\nThere were no results that matched your query\n");  
     }  
 #    $r->print('<script type="text/javascript">'.'popwin.close()</script>'."\n"); $r->rflush();   
     $r->print(<<RESULTS);  
 </body>  
 </html>  
 RESULTS  
 }  
   
 # ------------------------------------------------------ Detailed Citation View  ######################################################################
   ######################################################################
 sub detailed_citation_view {  sub detailed_citation_view {
     my ($title,$author,$subject,$url,$keywords,$version,      my %values = @_;
  $notes,$shortabstract,$mime,$lang,  
  $creationdate,$lastrevisiondate,$owner,$copyright,  
  $hostname,$httphost,$extrashow)=@_;  
     my $result=<<END;      my $result=<<END;
 <i>$owner</i>, last revised $lastrevisiondate  <h3><a href="http://$ENV{'HTTP_HOST'}$values{'url'}" 
 <h3><A HREF="http://$httphost$url" TARGET='search_preview'>$title</A></h3>      target='search_preview'>$values{'title'}</a></h3>
 <h3>$author</h3>  
 </p>  
 <p>  <p>
 <b>Subject:</b> $subject<br />  <b>$values{'author'}</b>, <i>$values{'owner'}</i><br />
 <b>Keyword(s):</b> $keywords<br />  
 <b>Notes:</b> $notes<br />  <b>Subject:       </b> $values{'subject'}<br />
 <b>MIME Type:</b>  <b>Keyword(s):    </b> $values{'keywords'}<br />
 END  <b>Notes:         </b> $values{'notes'}<br />
     $result.=&Apache::loncommon::filedescription($mime);  <b>MIME Type:     </b> $values{'mimetag'}<br />
     $result.=<<END;  <b>Language:      </b> $values{'language'}<br />
 <br />  <b>Copyright/Distribution:</b> $values{'cprtag'}<br />
 <b>Language:</b>   
 END  
     $result.=&Apache::loncommon::languagedescription($lang);  
     $result.=<<END;  
 <br />  
 <b>Copyright/Distribution:</b>   
 END  
     $result.=&Apache::loncommon::copyrightdescription($copyright);  
     $result.=<<END;  
 <br />  
 </p>  </p>
 $extrashow  $values{'extrashow'}
 <p>  <p>
 $shortabstract  $values{'shortabstract'}
 </p>  </p>
 END  END
     return $result;      return $result;
 }  }
   
 # ---------------------------------------------------------------- Summary View  ######################################################################
   ######################################################################
   
   =pod 
   
   =item &summary_view() 
   
   =cut
   
   ######################################################################
   ######################################################################
 sub summary_view {  sub summary_view {
     my ($title,$author,$subject,$url,$keywords,$version,      my %values = @_;
  $notes,$shortabstract,$mime,$lang,  
  $creationdate,$lastrevisiondate,$owner,$copyright,  
  $hostname,$httphost,$extrashow)=@_;  
     my $cprtag=&Apache::loncommon::copyrightdescription($copyright);  
     my $result=<<END;      my $result=<<END;
 <a href="http://$httphost$url" TARGET='search_preview'>$author</a><br />  <a href="http://$ENV{'HTTP_HOST'}$values{'url'}" 
 $title<br />     target='search_preview'>$values{'author'}</a><br />
 $owner -- $lastrevisiondate<br />  $values{'title'}<br />
 $cprtag<br />  $values{'owner'} -- $values{'lastrevisiondate'}<br />
 $extrashow  $values{'copyrighttag'}<br />
   $values{'extrashow'}
 </p>  </p>
 END  END
     return $result;      return $result;
 }  }
   
 # -------------------------------------------------------------- Fielded Format  ######################################################################
   ######################################################################
   
   =pod 
   
   =item &fielded_format_view() 
   
   =cut
   
   ######################################################################
   ######################################################################
 sub fielded_format_view {  sub fielded_format_view {
     my ($title,$author,$subject,$url,$keywords,$version,      my %values = @_;
  $notes,$shortabstract,$mime,$lang,  
  $creationdate,$lastrevisiondate,$owner,$copyright,  
  $hostname,$httphost,$extrashow)=@_;  
     my $mimetag=&Apache::loncommon::filedescription($mime);  
     my $language=&Apache::loncommon::languagedescription($lang);  
     my $cprtag=&Apache::loncommon::copyrightdescription($copyright);  
     my $result=<<END;      my $result=<<END;
 <b>URL: </b> <A HREF="http://$httphost$url" TARGET='search_preview'>$url</A>  <b>URL: </b> <a href="http://$ENV{'HTTP_HOST'}$values{'url'}" 
                 target='search_preview'>$values{'url'}</a>
 <br />  <br />
 <b>Title:</b> $title<br />  <b>Title:</b> $values{'title'}<br />
 <b>Author(s):</b> $author<br />  <b>Author(s):</b> $values{'author'}<br />
 <b>Subject:</b> $subject<br />  <b>Subject:</b> $values{'subject'}<br />
 <b>Keyword(s):</b> $keywords<br />  <b>Keyword(s):</b> $values{'keywords'}<br />
 <b>Notes:</b> $notes<br />  <b>Notes:</b> $values{'notes'}<br />
 <b>MIME Type:</b> $mimetag<br />  <b>MIME Type:</b> $values{'mimetag'}<br />
 <b>Language:</b> $language<br />  <b>Language:</b> $values{'language'}<br />
 <b>Creation Date:</b> $creationdate<br />  <b>Creation Date:</b> $values{'creationdate'}<br />
 <b>Last Revision Date:</b> $lastrevisiondate<br />  <b>Last Revision Date:</b> $values{'lastrevisiondate'}<br />
 <b>Publisher/Owner:</b> $owner<br />  <b>Publisher/Owner:</b> $values{'owner'}<br />
 <b>Copyright/Distribution:</b> $cprtag<br />  <b>Copyright/Distribution:</b> $values{'copyrighttag'}<br />
 <b>Repository Location:</b> $hostname<br />  <b>Repository Location:</b> $values{'hostname'}<br />
 <b>Abstract:</b> $shortabstract<br />  <b>Abstract:</b> $values{'shortabstract'}<br />
 $extrashow  $values{'extrashow'}
 </p>  </p>
 END  END
     return $result;      return $result;
 }  }
   
 # -------------------------------------------------------------------- XML/SGML  ######################################################################
   ######################################################################
   
   =pod 
   
   =item &xml_sgml_view() 
   
   =back 
   
   =cut
   
   ######################################################################
   ######################################################################
 sub xml_sgml_view {  sub xml_sgml_view {
     my ($title,$author,$subject,$url,$keywords,$version,      my %values = @_;
  $notes,$shortabstract,$mime,$lang,  
  $creationdate,$lastrevisiondate,$owner,$copyright,  
  $hostname,$httphost,$extrashow)=@_;  
     my $cprtag=&Apache::loncommon::copyrightdescription($copyright);  
     my $mimetag=&Apache::loncommon::filedescription($mime);  
     my $language=&Apache::loncommon::languagedescription($lang);  
     my $result=<<END;      my $result=<<END;
 <pre>  <pre>
 &lt;LonCapaResource&gt;  &lt;LonCapaResource&gt;
 &lt;url&gt;$url&lt;/url&gt;  &lt;url&gt;$values{'url'}&lt;/url&gt;
 &lt;title&gt;$title&lt;/title&gt;  &lt;title&gt;$values{'title'}&lt;/title&gt;
 &lt;author&gt;$author&lt;/author&gt;  &lt;author&gt;$values{'author'}&lt;/author&gt;
 &lt;subject&gt;$subject&lt;/subject&gt;  &lt;subject&gt;$values{'subject'}&lt;/subject&gt;
 &lt;keywords&gt;$keywords&lt;/keywords&gt;  &lt;keywords&gt;$values{'keywords'}&lt;/keywords&gt;
 &lt;notes&gt;$notes&lt;/notes&gt;  &lt;notes&gt;$values{'notes'}&lt;/notes&gt;
 &lt;mimeInfo&gt;  &lt;mimeInfo&gt;
 &lt;mime&gt;$mime&lt;/mime&gt;  &lt;mime&gt;$values{'mime'}&lt;/mime&gt;
 &lt;mimetag&gt;$mimetag&lt;/mimetag&gt;  &lt;mimetag&gt;$values{'mimetag'}&lt;/mimetag&gt;
 &lt;/mimeInfo&gt;  &lt;/mimeInfo&gt;
 &lt;languageInfo&gt;  &lt;languageInfo&gt;
 &lt;language&gt;$lang&lt;/language&gt;  &lt;language&gt;$values{'lang'}&lt;/language&gt;
 &lt;languagetag&gt;$language&lt;/languagetag&gt;  &lt;languagetag&gt;$values{'language'}&lt;/languagetag&gt;
 &lt;/languageInfo&gt;  &lt;/languageInfo&gt;
 &lt;creationdate&gt;$creationdate&lt;/creationdate&gt;  &lt;creationdate&gt;$values{'creationdate'}&lt;/creationdate&gt;
 &lt;lastrevisiondate&gt;$lastrevisiondate&lt;/lastrevisiondate&gt;  &lt;lastrevisiondate&gt;$values{'lastrevisiondate'}&lt;/lastrevisiondate&gt;
 &lt;owner&gt;$owner&lt;/owner&gt;  &lt;owner&gt;$values{'owner'}&lt;/owner&gt;
 &lt;copyrightInfo&gt;  &lt;copyrightInfo&gt;
 &lt;copyright&gt;$copyright&lt;/copyright&gt;  &lt;copyright&gt;$values{'copyright'}&lt;/copyright&gt;
 &lt;copyrighttag&gt;$cprtag&lt;/copyrighttag&gt;  &lt;copyrighttag&gt;$values{'copyrighttag'}&lt;/copyrighttag&gt;
 &lt;/copyrightInfo&gt;  &lt;/copyrightInfo&gt;
 &lt;repositoryLocation&gt;$hostname&lt;/repositoryLocation&gt;  &lt;repositoryLocation&gt;$values{'hostname'}&lt;/repositoryLocation&gt;
 &lt;shortabstract&gt;$shortabstract&lt;/shortabstract&gt;  &lt;shortabstract&gt;$values{'shortabstract'}&lt;/shortabstract&gt;
 &lt;/LonCapaResource&gt;  &lt;/LonCapaResource&gt;
 </pre>  </pre>
 $extrashow  $values{'extrashow'}
 END  END
     return $result;      return $result;
 }  }
   
 # ---------------------------------------------------- see if a field is filled  ######################################################################
   ######################################################################
   
   =pod 
   
   =item &filled() see if field is filled.
   
   =cut
   
   ######################################################################
   ######################################################################
 sub filled {  sub filled {
     my ($field)=@_;      my ($field)=@_;
     if ($field=~/\S/ && $field ne 'any') {      if ($field=~/\S/ && $field ne 'any') {
Line 1477  sub filled { Line 1848  sub filled {
     }      }
 }  }
   
 # ---------------- Message to output when there are not enough fields filled in  ######################################################################
   ######################################################################
   
   =pod 
   
   =item &output_blank_field_error()
   
   =cut
   
   ######################################################################
   ######################################################################
 sub output_blank_field_error {  sub output_blank_field_error {
     my ($r)=@_;      my ($r)=@_;
     # make query information persistent to allow for subsequent revision      # make query information persistent to allow for subsequent revision
     my $persistent=&make_persistent();      my $persistent=&make_persistent(\%ENV);
   
     $r->print(<<BEGINNING);      $r->print(<<BEGINNING);
 <html>  <html>
Line 1511  processed. Line 1892  processed.
 RESULTS  RESULTS
 }  }
   
 # ----------------------------------------------------------- Output date error  ######################################################################
   ######################################################################
   
   =pod 
   
   =item &output_date_error()
   
   Output a full html page with an error message.
   
   =cut
   
   ######################################################################
   ######################################################################
 sub output_date_error {  sub output_date_error {
     my ($r,$message)=@_;      my ($r,$message)=@_;
     # make query information persistent to allow for subsequent revision      # make query information persistent to allow for subsequent revision
     my $persistent=&make_persistent();      my $persistent=&make_persistent(\%ENV);
   
     $r->print(<<BEGINNING);      $r->print(<<RESULTS);
 <html>  <html>
 <head>  <head>
 <title>The LearningOnline Network with CAPA</title>  <title>The LearningOnline Network with CAPA</title>
 BEGINNING  
     $r->print(<<RESULTS);  
 </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 1542  $message Line 1933  $message
 RESULTS  RESULTS
 }  }
   
 # --------- settings whenever the user causes the search window to be launched  ######################################################################
   ######################################################################
   
   =pod 
   
   =item &start_fresh_session()
   
   Cleans the global %hash by removing all fields which begin with
   'pre_' or 'store'.
   
   =cut
   
   ######################################################################
   ######################################################################
 sub start_fresh_session {  sub start_fresh_session {
     delete $hash{'mode_catalog'};      delete $hash{'mode_catalog'};
     foreach (keys %hash) {      foreach (keys %hash) {
Line 1555  sub start_fresh_session { Line 1959  sub start_fresh_session {
     }      }
 }  }
   
 # ----------------------------------------------- send javascript to popwin  ######################################################################
   ######################################################################
   
   =pod 
   
   =item &popwin_js() send javascript to popwin
   
   =cut
   
   ######################################################################
   ######################################################################
 sub popwin_js {  sub popwin_js {
     # Print javascript out to popwin, but make sure we dont generate      # Print javascript out to popwin, but make sure we dont generate
     # any javascript errors in doing so.      # any javascript errors in doing so.
Line 1570  END Line 1984  END
     $r->rflush();      $r->rflush();
 }  }
   
   ######################################################################
   ######################################################################
   
   =pod 
   
   =item &popwin_imgupdate()
   
   Send a given image (and its location) out to the browser.  Takes as 
   input $r, loncapa server id, and an icon URL.
   
   =cut
   
   ######################################################################
   ######################################################################
 sub popwin_imgupdate {  sub popwin_imgupdate {
     my ($r,$imgnum,$icon) = @_;      my ($r,$server,$icon) = @_;
     &popwin_js($r,'popwin.document.img'.$imgnum.'.'.      &popwin_js($r,'popwin.document.img_'.$Apache::lonnet::hostdom{$server}.
        'src="/adm/lonIcons/'.$icon.'";');                 '_'.$server.'.'.'src="/adm/lonIcons/'.$icon.'";');
 }      }    
   
 1;  1;
Line 1584  __END__ Line 2012  __END__
   
 =back   =back 
   
 =over 4  
   
 =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  =cut

Removed from v.1.121  
changed lines
  Added in v.1.134


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