Diff for /loncom/interface/lonsearchcat.pm between versions 1.122 and 1.139

version 1.122, 2002/06/19 19:40:38 version 1.139, 2002/07/08 20:35:36
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
 used in &handler() and is also used in &output_results().  used in &handler() and is also used in &output_results().
   
   =item %Views
   
   Hash which associates an output view description with the function
   that produces it.  Adding a new view type should be as easy as
   adding a line to the definition of this hash and making sure the function
   takes the proper parameters.
   
 =back   =back 
   
 =cut  =cut
Line 154  used in &handler() and is also used in & Line 132  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  #             View Description           Function Pointer
 # Detailed Citation View ---> sub detailed_citation_view  my %Views = ("Detailed Citation View" => \&detailed_citation_view,
 # Summary View ---> sub summary_view               "Summary View"           => \&summary_view,
 # Fielded Format ---> sub fielded_format_view               "Fielded Format"         => \&fielded_format_view,
 # XML/SGML ---> sub xml_sgml_view               "XML/SGML"               => \&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 240  sub handler { Line 184  sub handler {
             "\_".&Apache::lonnet::escape($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();
Line 252  sub handler { Line 199  sub handler {
     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 278  END Line 225  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) {
           # We are running a search
           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);
       } else {
           #
           # We need to get information to search on
           #
           # Set the default view if it is not already set.
           if (!defined($ENV{'form.viewselect'})) {
               $ENV{'form.viewselect'} ="Detailed Citation View";
           }
           # Output the advanced interface
           if ($ENV{'form.reqinterface'} eq 'advanced') {
               $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:  =pod 
 # --- 1. a basic search  
 # --- 2. an advanced search  
 # --- 3. output a search interface  
   
 # ----------------------------------- See if a search invocation should be done  =item &basic_search_form() 
     if ($ENV{'form.basicsubmit'} eq 'SEARCH') {  
  untie %hash; return &basicsearch($r,\%ENV);  
     }  
     elsif ($ENV{'form.advancedsubmit'} eq 'SEARCH') {  
  untie %hash; return &advancedsearch($r,\%ENV);  
     }  
   
 # ----------------------------- Else, begin building search interface to output  Returns a scalar which holds html for the basic search form.
     $scrout=''; # building a part of screen output  
     $scrout.=&searchphrasefield('Limit by title','title',  
  $ENV{'form.title'});  
   
     $scrout.=&searchphrasefield('Limit by author','author',  =cut
  $ENV{'form.author'});  
   
     $scrout.=&searchphrasefield('Limit by subject','subject',  ######################################################################
  $ENV{'form.subject'});  ######################################################################
   
     $scrout.=&searchphrasefield('Limit by keywords','keywords',  sub basic_search_form{
  $ENV{'form.keywords'});      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.=<<END;
   </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
   END
       $scrout.=&selectbox(undef,'viewselect',
    $ENV{'form.viewselect'},
    undef,undef,undef,
    sort(keys(%Views)));
       $scrout.=<<ENDDOCUMENT;
   <input type="button" value="HELP" onClick="openhelp()" />
   </p>
   </form>
   </body>
   </html>
   ENDDOCUMENT
       return $scrout;
   }
   ######################################################################
   ######################################################################
   
     $scrout.=&searchphrasefield('Limit by URL','url',  =pod 
  $ENV{'form.url'});  
   
 #    $scrout.=&searchphrasefield('Limit by version','version',  =item &advanced_search_form() 
 # $ENV{'form.version'});  
   
     $scrout.=&searchphrasefield('Limit by notes','notes',  Returns a scalar which holds html for the advanced search form.
  $ENV{'form.notes'});  
   
     $scrout.=&searchphrasefield('Limit by abstract','abstract',  =cut
  $ENV{'form.abstract'});  
   
     $ENV{'form.mime'}='any' unless length($ENV{'form.mime'});  ######################################################################
     $scrout.=&selectbox('Limit by MIME type','mime',  ######################################################################
  $ENV{'form.mime'},  
  'any','Any type',  
  \&{Apache::loncommon::filedescriptionex},  
  (&Apache::loncommon::fileextensions));  
   
   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
       if (!defined($ENV{'form.viewselect'})) {
           $ENV{'form.viewselect'} ="Detailed Citation View";
       }
       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>
   ENDHEADER
       $scrout.=&selectbox(undef,'viewselect',
    $ENV{'form.viewselect'},
    undef,undef,undef,
    sort(keys(%Views)));
       $scrout.="</td></tr>\n";
       $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('notes',   'notes'   ,$ENV{'form.notes'});
       $scrout.=&searchphrasefield('abstract','abstract',$ENV{'form.abstract'});
       # Hack - an empty table row.
       $scrout.="<tr><td>&nbsp;</td><td>&nbsp;</td></tr>\n";
       $scrout.=&searchphrasefield('file<br />extension','mime',
                           $ENV{'form.mime'});
       $scrout.="<tr><td>&nbsp;</td><td>&nbsp;</td></tr>\n";
       $scrout.=&searchphrasefield('publisher<br />owner','owner',
    $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 354  CREATIONDATESTART Line 467  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 384  LASTREVISIONDATEEND Line 494  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 395  LASTREVISIONDATEEND Line 501  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 406  For resource-specific metadata, enter in Line 511  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 417  Enter in a space-separated list of speci Line 520  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 486  ENDDOCUMENT Line 538  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
   
Line 494  a 'hidden' html input tag. Line 547  a 'hidden' html input tag.
 ######################################################################  ######################################################################
   
 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;
Line 545  is where the $name and $value are used) Line 600  is where the $name and $value are used)
   
 =item &dateboxes()  =item &dateboxes()
   
   Returns html selection form elements for the specification of 
   the day, month, and year.
   
 =item &selectbox()  =item &selectbox()
   
   Returns a scalar containing an html <select> form.  
   
   Inputs: 
   
   =over 4
   
   =item $title 
   
   Printed above the select box, in uppercase.  If undefined, only a select
   box will be returned, with no additional html.
   
   =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.  Can be undef.
   
   =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   =back 
   
 =cut  =cut
Line 564  sub simpletextfield { Line 664  sub simpletextfield {
 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".      return '<tr><td><font color="#800000" face="helvetica">'.
         '<p><font color="#800000" face="helvetica"><b>'.$uctitle.':</b>'.          '<b>'.$uctitle.':&nbsp;</b></font></td><td>'.
         "</FONT> $instruction<br />".&simpletextfield($name,$value,80);                  &simpletextfield($name,$value,50)."</td></tr>\n";
 }  }
   
 sub dateboxes {  sub dateboxes {
Line 624  END Line 721  END
 }  }
   
 sub selectbox {  sub selectbox {
     my ($title,$name,$value,$anyvalue,$anytag,$functionref,@idlist)=@_;      my ($title,$name,$default,$anyvalue,$anytag,$functionref,@idlist)=@_;
     my $uctitle=uc($title);      if (! defined($functionref)) { $functionref = sub { $_[0]}; }
     my $selout="\n".'<p><font color="#800000" face="helvetica">'.      my $selout='';
         '<b>'.$uctitle.':</b></font><br /><select name="'.$name.'">';      if (defined($title)) {
     foreach ($anyvalue,@idlist) {          my $uctitle=uc($title);
           $selout="\n".'<p><font color="#800000" face="helvetica">'.
               '<b>'.$uctitle.': </b></font>';
       }
       $selout .= '<select name="'.$name.'">';
       unshift @idlist,$anyvalue if (defined($anyvalue));
       foreach (@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>'.(defined($title)?'</p>':' ');
 }  }
   
 ######################################################################  ######################################################################
Line 646  sub selectbox { Line 749  sub selectbox {
   
 =pod   =pod 
   
 =item &advancedsearch()   =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  =cut
   
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
 sub advancedsearch {  sub parse_advanced_search {
     my ($r,$envhash)=@_;      my ($r)=@_;
     my %ENV=%{$envhash};  
     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 665  sub advancedsearch { Line 781  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 674  sub advancedsearch { Line 790  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 684  sub advancedsearch { Line 806  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});
  }          }
       }
       # I dislike the hack below.
       if ($ENV{'form.category'}) {
           $ENV{'form.mime'}='';
     }      }
     # 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 724  sub advancedsearch { Line 847  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  
     return 'Error.  Should not have gone to this point.';  
 }  }
   
 ######################################################################  ######################################################################
Line 773  sub advancedsearch { Line 901  sub advancedsearch {
   
 =pod   =pod 
   
 =item &basicsearch()   =item &parse_basic_search() 
   
   Parse the basic search form and return a scalar containing an sql query.
   
 =cut  =cut
   
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
 sub basicsearch {  sub parse_basic_search {
     my ($r,$envhash)=@_;      my ($r)=@_;
     my %ENV=%{$envhash};  
     # 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 802  sub basicsearch { Line 931  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);  
   
     return OK;  
 }  }
   
   
Line 825  sub basicsearch { Line 947  sub basicsearch {
   
 =item &build_SQL_query()   =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  =cut
   
 ######################################################################  ######################################################################
Line 847  sub build_SQL_query { Line 972  sub build_SQL_query {
   
 =item &build_custommetadata_query()   =item &build_custommetadata_query() 
   
   Constructs a custom metadata query using a rather heinous regular
   expression.
   
 =cut  =cut
   
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
 sub build_custommetadata_query {  sub build_custommetadata_query {
     my ($field_name,$logic_statement)=@_;      my ($field_name,$logic_statement)=@_;
     &Apache::lonnet::logthis("Entered build_custommetadata_query:".  
                              $field_name.':'.$logic_statement);  
     my $q=new Text::Query('abc',      my $q=new Text::Query('abc',
   -parse => 'Text::Query::ParseAdvanced',    -parse => 'Text::Query::ParseAdvanced',
   -build => 'Text::Query::BuildAdvancedString');    -build => 'Text::Query::BuildAdvancedString');
Line 869  sub build_custommetadata_query { Line 995  sub build_custommetadata_query {
                    \*$2\[\^\\<\]?#           *wordtwo[^\<]                     \*$2\[\^\\<\]?#           *wordtwo[^\<]
                    \*\\<\\\/$1\\>?#                        *\<\/wordone\>                     \*\\<\\\/$1\\>?#                        *\<\/wordone\>
                    /g;                     /g;
     &Apache::lonnet::logthis("match expression: ".$matchexp);  
     return $matchexp;      return $matchexp;
 }  }
   
Line 880  sub build_custommetadata_query { Line 1005  sub build_custommetadata_query {
   
 =item &recursive_SQL_query_build()   =item &recursive_SQL_query_build() 
   
   Recursively constructs an SQL query.  Takes as input $dkey and $pattern.
   
 =cut  =cut
   
 ######################################################################  ######################################################################
Line 924  sub recursive_SQL_query_build { Line 1051  sub recursive_SQL_query_build {
   
 =item &build_date_queries()   =item &build_date_queries() 
   
   Builds a SQL logic query to check time/date entries.
   Also reports errors (check for /^Incorrect/).
   
 =cut  =cut
   
 ######################################################################  ######################################################################
Line 994  contacted, etc.) Line 1124  contacted, etc.)
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
 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;
       ##
       ## Set viewing function
       ##
       my $viewfunction = $Views{$ENV{'form.viewselect'}};
       if (!defined($viewfunction)) {
           $r->print("Internal Error - Bad view selected.\n");
           $r->rflush();
           return;
       }
       #
     # 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);
       #
       # Begin producing output
       $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);
                   #
                   # Check copyright tags and skip results the user cannot use
                   my (undef,undef,$resdom,$resname) = split('/',$Fields{'url'});
                   # Check for priv
                   if (($Fields{'copyright'} eq 'priv') && 
                       (($ENV{'user.name'} ne $resname) &&
                        ($ENV{'user.domain'} ne $resdom))) {
                       next;
                   }
                   # Check for domain
                   if (($Fields{'copyright'} eq 'domain') &&
                       ($ENV{'user.domain'} ne $resdom)) {
                       next;
                   }
                   #
    $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++;
    }
                   # Render the result into html
                   $compiledresult.= &$viewfunction(%Fields, hostname => $rkey );
                   if ($compiledresult or $servercount!=$servernum) {
                       $compiledresult.="<hr align='left' width='200' noshade />";
                   }
               }
               untie %hash;
           }
    if ($compiledresult) {
       $resultflag=1;
               $r->print($compiledresult);
    }
         } # 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->print("</body>\n</html>\n");
       $r->rflush(); 
       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 1040  SCRIPT Line 1545  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 1060  function changeURL(val) { Line 1565  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 1080  SCRIPT Line 1585  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 1095  SCRIPT Line 1600  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  
 $closebutton  
 $persistent  
 <hr />  
 <h3>Search Query</h3>  
 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)  ######################################################################
   ######################################################################
   
   =pod
   
   =item &make_popwin()
   
   Returns html with javascript in it to open up the status window.
   
   =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="  
  $grid.="'<a href=\"";   $grid.="'<a href=\"";
  # javascript:displayinfo('+  
  $grid.="javascript:opener.displayinfo('+";   $grid.="javascript:opener.displayinfo('+";
  # "'"+'key  
  $grid.="\"'\"+'";   $grid.="\"'\"+'";
  $grid.=$sk;   $grid.=$sk;
  my $hc;   my $hc;
  if ($rhash{$sk} eq 'con_lost') {   if ($rhash{$sk} eq 'con_lost') {
     $hc="BAD CONNECTION, CONTACT SYSTEM ADMINISTRATOR ";      $hc="BAD CONNECTION ";
  }   }
  else {   else {
     $hc="'+\"'\"+\"+hc['$sk']+\"+\"'\"+'";      $hc="'+\"'\"+\"+hc['$sk']+\"+\"'\"+'";
     $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 1211  RESULTS Line 1699  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') {  
     &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;  
  $shortabstract=substr($abstract,0,200).'...' if length($abstract)>200;  
  $fields[7]=$shortabstract;  
  my $shortkeywords=$keywords;  
  $shortkeywords=substr($keywords,0,200).'...' if length($keywords)>200;  
  $fields[4]=$shortkeywords;  
   
  my $extrashow2=$extrashow;  
  if ($extrashow) {  
     foreach my $field (@customfields) {  
  my $value='';  
  if ($customhash{$url}=~/\<${field}[^\>]*\>(.*?)\<\/${field}[^\>]*\>/s) {  
             $value=$1;  
  }  
         $extrashow2=~s/\<\!\-\- $field \-\-\>/ $value/g;  
             }  
                 }  
   
         $compiledresult.=<<END if $compiledresult or $servercount!=$servernum;  
 <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');  
 <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;  
         }  
         else {  
     $r->print('<html><head></head><body>Unable to tie hash to db '.  
   'file</body></html>');  
  }  
  if ($compiledresult) {  
     $resultflag=1;  
  }  
   
  $r->print(<<RESULTS);  
 $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  
 }  }
   
 ######################################################################  ######################################################################
Line 1462  RESULTS Line 1712  RESULTS
 Output is a HTML-ified string.  Output is a HTML-ified string.
 Input arguments are title, author, subject, url, keywords, version,  Input arguments are title, author, subject, url, keywords, version,
 notes, short abstract, mime, language, creation date,  notes, short abstract, mime, language, creation date,
 last revision date, owner, copyright, hostname, httphost, and  last revision date, owner, copyright, hostname, and
 extra custom metadata to show.  extra custom metadata to show.
   
 =over 4  =over 4
Line 1474  extra custom metadata to show. Line 1724  extra custom metadata to show.
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
 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;
Line 1523  END Line 1758  END
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
 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;
Line 1551  END Line 1783  END
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
 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;
Line 1594  END Line 1821  END
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
 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;
 }  }
Line 1669  sub filled { Line 1890  sub filled {
 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 1715  Output a full html page with an error me Line 1936  Output a full html page with an error me
 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(<<RESULTS);      $r->print(<<RESULTS);
 <html>  <html>
Line 1798  END Line 2019  END
   
 =item &popwin_imgupdate()  =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  =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 1816  __END__ Line 2040  __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) :   
   
   
 =back  
   
 =cut  =cut

Removed from v.1.122  
changed lines
  Added in v.1.139


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