Diff for /loncom/interface/lonsearchcat.pm between versions 1.125 and 1.142

version 1.125, 2002/06/20 19:43:50 version 1.142, 2002/07/12 21:02:27
Line 40 Line 40
   
 =head1 NAME  =head1 NAME
   
 lonsearchcat  lonsearchcat - LONCAPA Search Interface
   
 =head1 SYNOPSIS  =head1 SYNOPSIS
   
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 %hash     =item %groupsearch_db   
   
 The ubiquitous database hash  Database hash used to save values for the groupsearch RAT interface.
   
 =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 137  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
   
 # -- miscellaneous variables  # -- miscellaneous variables
 my $yourself; # allows for quickly limiting to oneself  my %groupsearch_db;     # 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  
   
 #------------------------------------------------------------- global variables  
 my $diropendb = "";  
 my $domain = "";  
   
 # ----------------------------------------------------------------------- BEGIN  
   
 =pod  
   
 =item BEGIN block  #             View Description           Function Pointer
   my %Views = ("Detailed Citation View" => \&detailed_citation_view,
 Load %hostdomains and %hostips with data from lonnet.pm.  Only library               "Summary View"           => \&summary_view,
 servers are considered.               "Fielded Format"         => \&fielded_format_view,
                "XML/SGML"               => \&xml_sgml_view );
 =cut  
   
 BEGIN {  
     foreach (keys (%Apache::lonnet::libserv)) {  
         $hostdomains{$_}=$Apache::lonnet::hostdom{$_};  
         $hostips{$_}=$Apache::lonnet::hostip{$_};  
     }  
 }  
   
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
Line 205  string that holds portions of the screen Line 173  string that holds portions of the screen
 ######################################################################  ######################################################################
 sub handler {  sub handler {
     my $r = shift;      my $r = shift;
     untie %hash;      untie %groupsearch_db;
   
     $r->content_type('text/html');      $r->content_type('text/html');
     $r->send_http_header;      $r->send_http_header;
Line 222  sub handler { Line 190  sub handler {
     ## Clear out old values from database      ## 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(%groupsearch_db,'GDBM_File',$diropendb,&GDBM_WRCREAT,0640)) {
     &start_fresh_session();      &start_fresh_session();
     untie %hash;      untie %groupsearch_db;
  } 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>');
Line 257  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?      ##  What are we doing?
     ##      ##
     if ($ENV{'form.basicsubmit'} eq 'SEARCH') {      my $searchtype;
         # Perform basic search and give results      $searchtype = 'Basic'    if ($ENV{'form.basicsubmit'}    eq 'SEARCH');
  return &basicsearch($r,\%ENV,$hidden);      $searchtype = 'Advanced' if ($ENV{'form.advancedsubmit'} eq 'SEARCH');
     } elsif ($ENV{'form.advancedsubmit'} eq 'SEARCH') {      if ($searchtype) {
         # Perform advanced search and give results          # We are running a search
  return &advancedsearch($r,\%ENV,$hidden);          my ($query,$customquery,$customshow,$libraries) = 
     } elsif ($ENV{'form.reqinterface'} eq 'advanced') {              (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));
           }
           # Output some information to the user.
           $r->print(&search_results_header($searchtype));
           $r->print("Sending search request to LON-CAPA servers.<br />\n");
           $r->rflush();
           # 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).
           my $reply=&Apache::lonnet::metadata_query($query,$customquery,
                                                  $customshow,$libraries);
           $r->rflush();
           &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          # Output the advanced interface
         $r->print(&advanced_search_form($closebutton,$hidden));          if ($ENV{'form.reqinterface'} eq 'advanced') {
         return OK;              $r->print(&advanced_search_form($closebutton,$hidden));
     } else {           } else { 
         # Output normal search interface              # Output normal search interface
         $r->print(&basic_search_form($closebutton,$hidden));              $r->print(&basic_search_form($closebutton,$hidden));
           }
     }      }
     return OK;      return OK;
 }   } 
Line 318  sub basic_search_form{ Line 311  sub basic_search_form{
 $hidden  $hidden
 <h3>Basic Search</h3>  <h3>Basic Search</h3>
 <p>  <p>
 Enter terms or phrases separated by AND, OR, or NOT then press SEARCH below.  Enter terms or phrases separated by AND, OR, or NOT 
   then press SEARCH below.
 </p>  </p>
 <p>  <p>
 <table>  <table>
Line 328  ENDDOCUMENT Line 322  ENDDOCUMENT
         '&nbsp;';          '&nbsp;';
 #    $scrout.=&simplecheckbox('allversions',$ENV{'form.allversions'});  #    $scrout.=&simplecheckbox('allversions',$ENV{'form.allversions'});
 #    $scrout.='<font color="#800000">Search historic archives</font>';  #    $scrout.='<font color="#800000">Search historic archives</font>';
     $scrout.=<<ENDDOCUMENT;      my $checkbox = &simplecheckbox('related',$ENV{'form.related'});
 </td><td><a href="/adm/searchcat?reqinterface=advanced">Advanced Search</a></td></tr></table>      $scrout.=<<END;
   </td><td><a href="/adm/searchcat?reqinterface=advanced">Advanced Search</a></td></tr>
   <tr><td>$checkbox use related words</td><td></td></tr>
   </table>
 </p>  </p>
 <p>  <p>
 &nbsp;<input type="submit" name="basicsubmit" value='SEARCH' />&nbsp;  &nbsp;<input type="submit" name="basicsubmit" value='SEARCH' />&nbsp;
 $closebutton  $closebutton
 <!-- basic view selection -->  END
 <select name='basicviewselect'>      $scrout.=&selectbox(undef,'viewselect',
 <option value='Detailed Citation View' selected="true">   $ENV{'form.viewselect'},
 Detailed Citation View</option>   undef,undef,undef,
 <option value='Summary View'>Summary View</option>   sort(keys(%Views)));
 <option value='Fielded Format'>Fielded Format</option>      $scrout.=<<ENDDOCUMENT;
 <option value='XML/SGML'>XML/SGML</option>  
 </select>  
 <!-- end of basic view selection -->  
 <input type="button" value="HELP" onClick="openhelp()" />  <input type="button" value="HELP" onClick="openhelp()" />
 </p>  </p>
 </form>  </form>
Line 367  Returns a scalar which holds html for th Line 361  Returns a scalar which holds html for th
   
 sub advanced_search_form{  sub advanced_search_form{
     my ($closebutton,$hidden) = @_;      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";      my $scrout=<<"ENDHEADER";
 <html>  <html>
 <head>  <head>
Line 381  sub advanced_search_form{ Line 386  sub advanced_search_form{
 </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>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">  <form method="post" action="/adm/searchcat">
   $advanced_buttons
 $hidden  $hidden
 <hr />  <table>
 <h3>Advanced Search</h3>  <tr><td><font color="#800000" face="helvetica"><b>VIEW:</b></font></td>
   <td>
 ENDHEADER  ENDHEADER
     $scrout.=&searchphrasefield('Limit by title','title',      $scrout.=&selectbox(undef,'viewselect',
  $ENV{'form.title'});   $ENV{'form.viewselect'},
     $scrout.=&searchphrasefield('Limit by author','author',   undef,undef,undef,
  $ENV{'form.author'});   sort(keys(%Views)));
     $scrout.=&searchphrasefield('Limit by subject','subject',      $scrout.="</td><td>Related<br />Words</td></tr>\n";
  $ENV{'form.subject'});      $scrout.=&searchphrasefield_with_related('title',   'title'   ,
     $scrout.=&searchphrasefield('Limit by keywords','keywords',                                               $ENV{'form.title'});
  $ENV{'form.keywords'});      $scrout.=&searchphrasefield('author',  'author'  ,$ENV{'form.author'});
     $scrout.=&searchphrasefield('Limit by URL','url',      $scrout.=&searchphrasefield_with_related('subject', 'subject' ,
  $ENV{'form.url'});                                               $ENV{'form.subject'});
 #    $scrout.=&searchphrasefield('Limit by version','version',      $scrout.=&searchphrasefield_with_related('keywords','keywords',
 # $ENV{'form.version'});                                               $ENV{'form.keywords'});
     $scrout.=&searchphrasefield('Limit by notes','notes',      $scrout.=&searchphrasefield('URL',     'url'     ,$ENV{'form.url'});
  $ENV{'form.notes'});      $scrout.=&searchphrasefield_with_related('notes',   'notes'   ,
     $scrout.=&searchphrasefield('Limit by abstract','abstract',                                               $ENV{'form.notes'});
  $ENV{'form.abstract'});      $scrout.=&searchphrasefield_with_related('abstract','abstract',
     $ENV{'form.mime'}='any' unless length($ENV{'form.mime'});                                               $ENV{'form.abstract'});
     $scrout.=&selectbox('Limit by MIME type','mime',      # Hack - an empty table row.
  $ENV{'form.mime'},      $scrout.="<tr><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr>\n";
  'any','Any type',      $scrout.=&searchphrasefield('file<br />extension','mime',
  \&{Apache::loncommon::filedescriptionex},                          $ENV{'form.mime'});
  (&Apache::loncommon::fileextensions));      $scrout.="<tr><td>&nbsp;</td><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},
Line 455  LASTREVISIONDATEEND Line 506  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 485  in a fielded listing for each record res Line 534  in a fielded listing for each record res
 CUSTOMSHOW  CUSTOMSHOW
     $scrout.=&simpletextfield('customshow',$ENV{'form.customshow'});      $scrout.=&simpletextfield('customshow',$ENV{'form.customshow'});
     $scrout.=<<ENDDOCUMENT;      $scrout.=<<ENDDOCUMENT;
 <p>  $advanced_buttons
 <input type="submit" name="advancedsubmit" value='SEARCH' />  
 <input type="reset" name="reset" value='RESET' />  
 $closebutton  
 <!-- advance view select -->  
 <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 of advanced view select -->  
 <input type="button" value="HELP" onClick="openhelp()" />  
 </p>  
 </form>  </form>
 </body>  </body>
 </html>  </html>
Line 515  ENDDOCUMENT Line 550  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 523  a 'hidden' html input tag. Line 559  a 'hidden' html input tag.
 ######################################################################  ######################################################################
   
 sub make_persistent {  sub make_persistent {
       my %save = %{shift()};
     my $persistent='';      my $persistent='';
     foreach (keys %ENV) {      foreach (keys %save) {
  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;
 }  }
   
   
 ######################################################################  ######################################################################
   #                HTML form building functions                        #  
 ######################################################################  ######################################################################
   
 =pod   =pod 
Line 548  END Line 587  END
   
 =over 4  =over 4
   
   =cut
   
   ###############################################
   ###############################################
   
   =pod
   
 =item &simpletextfield()   =item &simpletextfield() 
   
 Inputs: $name,$value,$size  Inputs: $name,$value,$size
Line 555  Inputs: $name,$value,$size Line 601  Inputs: $name,$value,$size
 Returns a text input field with the given name, value, and size.    Returns a text input field with the given name, value, and size.  
 If size is not specified, a value of 20 is used.  If size is not specified, a value of 20 is used.
   
   =cut
   
   ###############################################
   ###############################################
   
   sub simpletextfield {
       my ($name,$value,$size)=@_;
       $size = 20 if (! defined($size));
       return '<input type="text" name="'.$name.
           '" size="'.$size.'" value="'.$value.'" />';
   }
   
   ###############################################
   ###############################################
   
   =pod
   
 =item &simplecheckbox()  =item &simplecheckbox()
   
 Inputs: $name,$value  Inputs: $name,$value
Line 562  Inputs: $name,$value Line 625  Inputs: $name,$value
 Returns a simple check box with the given $name.  Returns a simple check box with the given $name.
 If $value eq 'on' the box is checked.  If $value eq 'on' the box is checked.
   
 =item &searchphrasefield()  =cut
   
 Inputs: $title,$name,$value  ###############################################
   ###############################################
   
 Returns html for a title line and an input field for entering search terms.  sub simplecheckbox {
 the instructions "Enter terms or phrases separated by search operators such       my ($name,$value)=@_;
 as AND, OR, or NOT." are given following the title.  The entry field (which      my $checked='';
 is where the $name and $value are used) is an 80 column simpletextfield.      $checked="checked" if $value eq 'on';
       return '<input type="checkbox" name="'.$name.'" '. $checked . ' />';
   }
   
 =item &dateboxes()  ###############################################
   ###############################################
   
 =item &selectbox()  =pod
   
 =back   =item &fieldtitle()
   
   Input: $title
   
   Returns a scalar with html which will display $title as a search
   field heading.
   
 =cut  =cut
   
 ######################################################################  ###############################################
 ######################################################################  ###############################################
   
 sub simpletextfield {  sub fieldtitle {
     my ($name,$value,$size)=@_;      my $title = uc(shift());
     $size = 20 if (! defined($size));      return '<font color="#800000" face="helvetica"><b>'.$title.
     return '<input type="text" name="'.$name.          ':&nbsp;</b></font>';
         '" size="'.$size.'" value="'.$value.'" />';  
 }  }
   
 sub simplecheckbox {  ###############################################
     my ($name,$value)=@_;  ###############################################
     my $checked='';  
     $checked="CHECKED" if $value eq 'on';  =pod
     return '<input type="checkbox" name="'.$name.'" '. $checked . ' />';  
 }  =item &searchphrasefield()
   
   Inputs: $title,$name,$value
   
   Returns html for a title line and an input field for entering search terms.
   The entry field (which is where the $name and $value are used) is a 50 column 
   simpletextfield.  The html returned is for a row in a three column table.
   
   =cut
   
   ###############################################
   ###############################################
       
 sub searchphrasefield {  sub searchphrasefield {
     my ($title,$name,$value)=@_;      my ($title,$name,$value)=@_;
     my $instruction=<<END;      return '<tr><td>'.&fieldtitle($title).'</td><td>'.
 Enter terms or phrases separated by search operators such as AND, OR, or NOT.          &simpletextfield($name,$value,50)."</td><td>&nbsp;</td></tr>\n";
 END  
     my $uctitle=uc($title);  
     return "\n".  
         '<p><font color="#800000" face="helvetica"><b>'.$uctitle.':</b>'.  
         "</FONT> $instruction<br />".&simpletextfield($name,$value,80);  
 }  }
   
   ###############################################
   ###############################################
   
   =pod
   
   =item &searchphrasefield_with_related()
   
   Inputs: $title,$name,$value
   
   Returns html for a title line and an input field for entering search terms
   and a check box for 'related words'.  The entry field (which is where the 
   $name and $value are used) is a 50 column simpletextfield.  The name of
   the related words checkbox is "$name_related".
   
   =cut
   
   ###############################################
   ###############################################
       
   sub searchphrasefield_with_related {
       my ($title,$name,$value)=@_;
       return '<tr><td>'.&fieldtitle($title).'</td><td>'.
           &simpletextfield($name,$value,50).'</td><td align="center">&nbsp;'.
               &simplecheckbox($name.'_related',$ENV{'form.'.$name.'_related'}).
                   "&nbsp;</td></tr>\n";
   }
   
   ###############################################
   ###############################################
   
   =pod
   
   =item &dateboxes()
   
   Returns html selection form elements for the specification of 
   the day, month, and year.
   
   =cut
   
   ###############################################
   ###############################################
   
 sub dateboxes {  sub dateboxes {
     my ($name,$defaultmonth,$defaultday,$defaultyear,      my ($name,$defaultmonth,$defaultday,$defaultyear,
  $currentmonth,$currentday,$currentyear)=@_;   $currentmonth,$currentday,$currentyear)=@_;
Line 651  END Line 770  END
     return "$month$day$year";      return "$month$day$year";
 }  }
   
   ###############################################
   ###############################################
   
   =pod
   
   =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
   
   =cut
   
   ###############################################
   
 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>':' ');
 }  }
   
 ######################################################################  ######################################################################
   #                End of HTML form building functions                 #  
   ######################################################################
   
   =pod
   
   =back 
   
   =cut
   
   
   ######################################################################
 ######################################################################  ######################################################################
   
 =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,$hidden)=@_;      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 693  sub advancedsearch { Line 895  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 702  sub advancedsearch { Line 904  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 712  sub advancedsearch { Line 920  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});              my $searchphrase = $ENV{'form.'.$field};
  }              if ($ENV{'form.'.$field.'_related'}) {
                   $searchphrase = &related_version($searchphrase);
                   $ENV{'form.'.$field} = $searchphrase;
                   $ENV{'form.'.$field.'_related'} = undef;
               }
       push @queries,&build_SQL_query($field,$searchphrase);
           }
       }
       # 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 752  sub advancedsearch { Line 967  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,$hidden);  
     }      }
     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,$hidden);  
     }  
     # should not get to this point  
     return 'Error.  Should not have gone to this point.';  
 }  }
   
 ######################################################################  ######################################################################
Line 801  sub advancedsearch { Line 1021  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,$hidden)=@_;      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 826  sub basicsearch { Line 1047  sub basicsearch {
  &output_blank_field_error($r);   &output_blank_field_error($r);
  return OK;   return OK;
     }      }
       my $search_string = $ENV{'form.basicexp'};
       if ($ENV{'form.related'}) {
           $search_string = &related_version($ENV{'form.basicexp'});
       }
     # 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'));                          'keywords'));
     $concatarg='title' if $ENV{'form.titleonly'};      $concatarg='title' if $ENV{'form.titleonly'};
       $query=&build_SQL_query('concat('.$concatarg.')',$search_string);
       return 'select * from metadata where '.$query;
   }
   
     $query=&build_SQL_query('concat('.$concatarg.')',$ENV{'form.'.'basicexp'});  
   
     # 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  =pod 
   
     &output_results('Basic',$r,$envhash,$query,$reply,$hidden);  =item &related_version
   
     return OK;  Modifies an input string to include related words.  Words in the string
 }  are replaced with parenthesized lists of 'OR'd words.  For example
   "torque" is replaced with "(torque OR word1 OR word2 OR ...)".  
   
   Note: Using this twice on a string is probably silly.
   
   =cut
   
   ######################################################################
   ######################################################################
   sub related_version {
       my $search_string = shift;
       my $result = $search_string;
       while ($search_string =~ /(\w+)/cg) {
           my $word = $1;
           next if (lc($word) =~ /\b(or|and|not)\b/);
           my @Words = &Apache::loncommon::get_related_words($word);
           my $replacement = join " OR ", ($word,
                                           ($#Words>4? @Words[0..4] : @Words)
                                           );
           $result =~ s/(\b)$word(\b)/$1($replacement)$2/g;
       }
       return $result;
   }
   
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
Line 854  sub basicsearch { Line 1101  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 876  sub build_SQL_query { Line 1126  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 898  sub build_custommetadata_query { Line 1149  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 909  sub build_custommetadata_query { Line 1159  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 953  sub recursive_SQL_query_build { Line 1205  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 1023  contacted, etc.) Line 1278  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,$hidden)=@_;      my ($mode,$r,$replyref,$hidden)=@_;
     my %ENV=%{$envhash};  
     my %rhash=%{$replyref};      my %rhash=%{$replyref};
     my $compiledresult='';      my $compiledresult='';
     my $timeremain=300; # (seconds)      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);
     # spit out the generic header      #
     $r->print(&search_results_header());      # Begin producing output
     $r->rflush();      $r->rflush();
       #
     # begin showing the cataloged results      # begin showing the cataloged results
     $r->print(<<CATALOGBEGIN);      my $action = "/adm/searchcat";
 </head>      if ($mode eq 'Basic') { 
 <body bgcolor="#ffffff">          $action .= "?reqinterface=basic";
 <img align=right src=/adm/lonIcons/lonlogos.gif>      } elsif ($mode eq 'Advanced') {
 <h1>Search Catalog</h1>          $action .= "?reqinterface=advanced";
 CATALOGBEGIN      }
         $r->print(<<CATALOGCONTROLS);      $r->print(<<CATALOGCONTROLS);
 <form name='results' method="post" action="/adm/searchcat">  <form name='results' method="post" action="$action">
 $hidden  $hidden
 <input type='hidden' name='acts' value='' />  <input type='hidden' name='acts' value='' />
 <input type='button' value='Revise search request'  <input type='button' value='Revise search request'
Line 1055  $importbutton Line 1320  $importbutton
 $closebutton  $closebutton
 $persistent  $persistent
 <hr />  <hr />
 <h3>Search Query</h3>  
 CATALOGCONTROLS  CATALOGCONTROLS
     #      #
     # Remind them what they searched for  
     #  
     if ($mode eq 'Basic') {  
  $r->print('<p><b>Basic search:</b> '.$ENV{'form.basicexp'}.'</p>');  
     } elsif ($mode eq 'Advanced') {  
  $r->print('<p><b>Advanced search</b> '.$query.'</p>');  
     }  
     $r->print('<h3>Search Results</h3>');  
     $r->rflush();  
     #  
     # make the pop-up window for status      # make the pop-up window for status
     #  
     $r->print(&make_popwin(%rhash));      $r->print(&make_popwin(%rhash));
     $r->rflush();      $r->rflush();
     ##      ##
Line 1088  CATALOGCONTROLS Line 1341  CATALOGCONTROLS
       ## (within the foreach loop below).        ## (within the foreach loop below).
       ##        ##
       foreach my $rkey (sort keys %rhash) {        foreach my $rkey (sort keys %rhash) {
   #        &Apache::lonnet::logthis("Server $rkey:".time);
  $servercount++;   $servercount++;
  $tflag=1;  
  $compiledresult='';   $compiledresult='';
  my $hostname=$rkey;  
  my $reply=$rhash{$rkey};   my $reply=$rhash{$rkey};
  my @results;   my @results;
  if ($reply eq 'con_lost') {   if ($reply eq 'con_lost') {
Line 1103  CATALOGCONTROLS Line 1355  CATALOGCONTROLS
     $reply=~/^([\.\w]+)$/;       $reply=~/^([\.\w]+)$/; 
     my $replyfile=$r->dir_config('lonDaemons').'/tmp/'.$1;      my $replyfile=$r->dir_config('lonDaemons').'/tmp/'.$1;
     $reply=~/(.*?)\_/;      $reply=~/(.*?)\_/;
     {              for (my $counter=0;$counter<2;$counter++) {
  my $temp=0;                  if (-e $replyfile && ! -e "$replyfile.end") {
       WLOOP: while (1) {                      &popwin_imgupdate($r,$rkey,"srvhalf.gif");
   if (-e $replyfile && $tflag) {                      &popwin_js($r,'popwin.hc["'.$rkey.'"]='.
       &popwin_imgupdate($r,$rkey,"srvhalf.gif");                                 '"still transferring..."'.';');
       &popwin_js($r,'popwin.hc["'.$rkey.'"]='.                  }
  '"still transferring..."'.';');                  # Are we finished transferring data?
       $tflag=0;                  if (-e "$replyfile.end") {
   }                      $serversleft--;
   if (-e "$replyfile.end") {                      delete $rhash{$rkey};
       $serversleft--;                      if (-s $replyfile) {
                       delete $rhash{$rkey};                          &popwin_imgupdate($r,$rkey,"srvgood.gif");
       if (-s $replyfile) {                          my $fh;
   &popwin_imgupdate($r,$rkey,"srvgood.gif");                          unless ($fh=Apache::File->new($replyfile)){ 
   my $fh=Apache::File->new($replyfile) or                               # Is it really appropriate to die on this error?
       ($r->print('ERROR: file '.                              $r->print('ERROR: file '.
  $replyfile.' cannot be opened') and                                        $replyfile.' cannot be opened');
        return OK);                              return OK;
   @results=<$fh> if $fh;                          }
   $hitcount{$rkey}=@results+0;                          @results=<$fh> if $fh;
   &popwin_js($r,'popwin.hc["'.$rkey.'"]='.                          my $hits =@results;
     $hitcount{$rkey}.';');                          &popwin_js($r,'popwin.hc["'.$rkey.'"]='.
   $hitcountsum+=$hitcount{$rkey};                                     $hits.';');
   &popwin_js($r,'popwin.document.forms.popremain.'.                          $hitcountsum+=$hits;
     'numhits.value='.$hitcountsum.';');                          &popwin_js($r,'popwin.document.forms.popremain.'.
       }                                     'numhits.value='.$hitcountsum.';');
       else {                      } else {
   &popwin_imgupdate($r,$rkey,"srvempty.gif");                          &popwin_imgupdate($r,$rkey,"srvempty.gif");
   &popwin_js($r,'popwin.hc["'.$rkey.'"]=0;');                          &popwin_js($r,'popwin.hc["'.$rkey.'"]=0;');
       }                      }
       last WLOOP;                      last;
   } # end of if ( -e "$replyfile.end")                  } # end of if ( -e "$replyfile.end")
   last WLOOP unless $timeremain;                  last unless $timeremain;
   sleep 1;    # wait for daemons to write files?                  sleep 1;    # wait for daemons to write files?
   $timeremain--;                  $timeremain--;
   $elapsetime++;                  $elapsetime++;
   last WLOOP if ($temp>1);                  &popwin_js($r,"popwin.document.popremain.".
   &popwin_js($r,"popwin.document.popremain.".                             "elapsetime.value=$elapsetime;");
        "elapsetime.value=$elapsetime;");  
   $temp++;  
       }  
     }      }
     &popwin_js($r,'popwin.document.whirly.'.      &popwin_js($r,'popwin.document.whirly.'.
        'src="/adm/lonIcons/lonanimend.gif";');         'src="/adm/lonIcons/lonanimend.gif";');
  } # end of if ($reply eq 'con_lost') else statement   } # end of if ($reply eq 'con_lost') else statement
  my $customshow='';          my %Fields = undef;     # Holds the data to be sent to the various 
  my $extrashow='';                                  # *_view routines.
  my @customfields;          my ($extrashow,$customfields,$customhash) = 
  if ($ENV{'form.customshow'}) {                                      &handle_custom_fields(\@results);
     $customshow=$ENV{'form.customshow'};          my @customfields = @$customfields;
     $customshow=~s/[^\w\s]//g;          my %customhash   = %$customhash;
     my @fields=map {"<font color=\"#008000\">$_:</font><!-- $_ -->"}    untie %groupsearch_db if (tied %groupsearch_db);
     split(/\s+/,$customshow);          #
     @customfields=split(/\s+/,$customshow);   if (! tie(%groupsearch_db,'GDBM_File',$diropendb,&GDBM_WRCREAT,0640)) {
     if ($customshow) {      $r->print('<html><head></head><body>Unable to tie hash to db '.
  $extrashow="<ul><li>".join("</li><li>",@fields)."</li></ul>\n";                        'file</body></html>');
     }          } else {
  }  
  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') {      if ($ENV{'form.launch'} eq '1') {
  &start_fresh_session();   &start_fresh_session();
     }      }
Line 1183  CATALOGCONTROLS Line 1416  CATALOGCONTROLS
  next if $result=~/^custom\=/;   next if $result=~/^custom\=/;
  chomp $result;   chomp $result;
  next unless $result;   next unless $result;
  my @fields=map                  %Fields = &parse_raw_result($result,$rkey);
  {&Apache::lonnet::unescape($_)}                  #
  (split(/\,/,$result));                  # Check copyright tags and skip results the user cannot use
  my ($title,$author,$subject,$url,$keywords,$version,                  my (undef,undef,$resdom,$resname) = split('/',$Fields{'url'});
     $notes,$abstract,$mime,$lang,                  # Check for priv
     $creationdate,$lastrevisiondate,$owner,$copyright)=@fields;                  if (($Fields{'copyright'} eq 'priv') && 
                 unless ($title =~ /^\s*$/ ) { $title='<i>Untitled</i>'; }                      (($ENV{'user.name'} ne $resname) &&
  unless ($ENV{'user.adv'}) {                       ($ENV{'user.domain'} ne $resdom))) {
     $keywords='<i>- not displayed -</i>';                      next;
     $fields[4]=$keywords;                  }
     $notes='<i>- not displayed -</i>';                  # Check for domain
     $fields[6]=$notes;                  if (($Fields{'copyright'} eq 'domain') &&
     $abstract='<i>- not displayed -</i>';                      ($ENV{'user.domain'} ne $resdom)) {
     $fields[7]=$abstract;                      next;
     $subject='<i>- not displayed -</i>';                  }
     $fields[2]=$subject;                  #
  }   $Fields{'extrashow'}=$extrashow;
   
  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) {   if ($extrashow) {
     foreach my $field (@customfields) {      foreach my $field (@customfields) {
  my $value='';   my $value='';
  if ($customhash{$url}=~/\<${field}[^\>]*\>(.*?)\<\/${field}[^\>]*\>/s) {   $value = $1 if ($customhash{$Fields{'url'}}=~/\<{$field}[^\>]*\>(.*?)\<\/{$field}[^\>]*\>/s);
             $value=$1;                          $Fields{'extrashow'}=~s/\<\!\-\- $field \-\-\>/ $value/g;
  }                      }
         $extrashow2=~s/\<\!\-\- $field \-\-\>/ $value/g;  
             }  
                 }                  }
                   $compiledresult.="\n<p>\n";
         $compiledresult.=<<END if $compiledresult or $servercount!=$servernum;                  if ($ENV{'form.catalogmode'} eq 'interactive') {
 <hr align='left' width='200' noshade />                      my $titleesc=$Fields{'title'};
 END                      $titleesc=~s/\'/\\'/; # '
                 $compiledresult.=<<END;                      $compiledresult.=<<END if ($ENV{'form.catalogmode'} eq 'interactive');
 <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"  <font size='-1'><INPUT TYPE="button" NAME="returnvalues" VALUE="SELECT"
 onClick="javascript:select_data('$titleesc','$url')">  onClick="javascript:select_data('$titleesc','$Fields{'url'}')">
 </font>  </font>
 <br />  <br />
 END  END
                 }                  }
                 if ($ENV{'form.catalogmode'} eq 'groupsearch') {                  if ($ENV{'form.catalogmode'} eq 'groupsearch') {
     $fnum+=0;      $fnum+=0;
     $hash{"pre_${fnum}_link"}=$url;      $groupsearch_db{"pre_${fnum}_link"}=$Fields{'url'};
     $hash{"pre_${fnum}_title"}=$title;      $groupsearch_db{"pre_${fnum}_title"}=$Fields{'title'};
     $compiledresult.=<<END;      $compiledresult.=<<END;
 <font size='-1'>  <font size='-1'>
 <input type="checkbox" name="returnvalues" value="SELECT"  <input type="checkbox" name="returnvalues" value="SELECT"
Line 1251  END Line 1466  END
 # <input type="hidden" name="url$fnum" value="$url" />  # <input type="hidden" name="url$fnum" value="$url" />
                     $fnum++;                      $fnum++;
  }   }
         my $httphost=$ENV{'HTTP_HOST'};                  # Render the result into html
                   $compiledresult.= &$viewfunction(%Fields, hostname => $rkey );
         my $viewselect;                  if ($compiledresult or $servercount!=$servernum) {
         if ($mode eq 'Basic') {                      $compiledresult.="<hr align='left' width='200' noshade />";
     $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 %groupsearch_db;
             untie %hash;  
         }          }
         else {  
     $r->print('<html><head></head><body>Unable to tie hash to db '.  
   'file</body></html>');  
  }  
  if ($compiledresult) {   if ($compiledresult) {
     $resultflag=1;      $resultflag=1;
               $r->print($compiledresult);
  }   }
         } # End of foreach loop over servers remaining
  $r->print(<<RESULTS);      }   # End of big loop - while($serversleft && $timeremain)
 $compiledresult  
 RESULTS  
         my $percent=sprintf('%3.0f',($servercount/$servernum*100));  
     }  
   }  
     unless ($resultflag) {      unless ($resultflag) {
         $r->print("\nThere were no results that matched your query\n");          $r->print("\nThere were no results that matched your query\n");
     }      }
 #    $r->print('<script type="text/javascript">'.'popwin.close()</script>'."\n"); $r->rflush();       $r->print('<script type="text/javascript">'.'popwin.close()</script>'.
     $r->print(<<RESULTS);                "\n"); 
 </body>      $r->print("</body>\n</html>\n");
 </html>      $r->rflush(); 
 RESULTS      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);
 }  }
   
 ######################################################################  ######################################################################
Line 1314  RESULTS Line 1623  RESULTS
   
 =item &search_results_header  =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  =cut
   
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
 sub search_results_header {  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 = '';      my $result = '';
     # output beginning of search page      # output beginning of search page
     $result.=<<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
Line 1407  SCRIPT Line 1753  SCRIPT
     }      }
 </script>  </script>
 SCRIPT  SCRIPT
       $result.=<<END;
   </head>
   <body bgcolor="#ffffff">
   <img align=right src=/adm/lonIcons/lonlogos.gif>
   <h1>$title</h1>
   END
     return $result;      return $result;
 }  }
   
Line 1432  sub make_popwin { Line 1784  sub make_popwin {
     # rows of 10 each.  No longer used to index images.      # rows of 10 each.  No longer used to index images.
     my $sn=1;      my $sn=1;
     foreach 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_".$hostdomains{$sk}.'_'.$sk."\"".   $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++;
     }      }
Line 1515  ENDPOP Line 1865  ENDPOP
 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 1527  extra custom metadata to show. Line 1877  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 1576  END Line 1911  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 1604  END Line 1936  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 1647  END Line 1974  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 1722  sub filled { Line 2043  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 1768  Output a full html page with an error me Line 2089  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 1800  RESULTS Line 2121  RESULTS
   
 =item &start_fresh_session()  =item &start_fresh_session()
   
 Cleans the global %hash by removing all fields which begin with  Cleans the global %groupsearch_db by removing all fields which begin with
 'pre_' or 'store'.  'pre_' or 'store'.
   
 =cut  =cut
Line 1808  Cleans the global %hash by removing all Line 2129  Cleans the global %hash by removing all
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
 sub start_fresh_session {  sub start_fresh_session {
     delete $hash{'mode_catalog'};      delete $groupsearch_db{'mode_catalog'};
     foreach (keys %hash) {      foreach (keys %groupsearch_db) {
         if ($_ =~ /^pre_/) {          if ($_ =~ /^pre_/) {
             delete $hash{$_};              delete $groupsearch_db{$_};
         }          }
         if ($_ =~ /^store/) {          if ($_ =~ /^store/) {
     delete $hash{$_};      delete $groupsearch_db{$_};
  }   }
     }      }
 }  }
Line 1860  input $r, loncapa server id, and an icon Line 2181  input $r, loncapa server id, and an icon
 ######################################################################  ######################################################################
 sub popwin_imgupdate {  sub popwin_imgupdate {
     my ($r,$server,$icon) = @_;      my ($r,$server,$icon) = @_;
     &popwin_js($r,'popwin.document.img_'.$hostdomains{$server}.'_'.$server.'.'.      &popwin_js($r,'popwin.document.img_'.$Apache::lonnet::hostdom{$server}.
        'src="/adm/lonIcons/'.$icon.'";');                 '_'.$server.'.'.'src="/adm/lonIcons/'.$icon.'";');
 }      }    
   
 1;  1;
Line 1872  __END__ Line 2193  __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.125  
changed lines
  Added in v.1.142


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