Diff for /loncom/interface/lonsearchcat.pm between versions 1.2 and 1.99

version 1.2, 2001/03/08 13:32:04 version 1.99, 2001/08/26 21:49:49
Line 1 Line 1
 # The LearningOnline Network  # The LearningOnline Network with CAPA
   #
 # Search Catalog  # Search Catalog
 #  #
   # YEAR=2001
 # 03/08/2001 Scott Harrison  # 03/08/2001 Scott Harrison
   # Scott Harrison: 03/12/2001, 03/13/2001, 03/14/2001, 03/15/2001, 03/19/2001
   # Scott Harrison: 03/20/2001, 03/21/2001, 03/22/2001, 03/26/2001, 03/27/2001
   # Scott Harrison: 04/02/2001, 08/15/2001, 08/24/2001, 08/25/2001
   
   ###############################################################################
   ##                                                                           ##
   ## ORGANIZATION OF THIS PERL MODULE                                          ##
   ##                                                                           ##
   ## 1. Description of functions                                               ##
   ## 2. Modules used by this module                                            ##
   ## 3. Choices for different output views (detailed, summary, xml, etc)       ##
   ## 4. BEGIN block (to be run once after compilation)                         ##
   ## 5. Handling routine called via Apache and mod_perl                        ##
   ## 6. Other subroutines                                                      ##
   ##                                                                           ##
   ###############################################################################
   
   # ---------------------------------------------------- Description of functions
   #
   #
   # === WEB HANDLER FUNCTIONS
   # BEGIN() : run once after compilation to initialize values
   # handler(server reference) : interacts with the Apache server layer
   #                             (for /adm/searchcat URLs)
   # get_unprocessed_cgi() : reads in critical name/value pairs that may have not
   #                         been processed and passed into %ENV by the web server
   # make_persistent() : makes a set of hidden HTML fields to make
   #                     SQL search interface information to be persistent
   #
   #
   # === WEB INTERFACE COMPONENT FUNCTIONS
   # simpletextfield(name,value) : returns HTML formatted string for simple text
   #                               field
   # simplecheckbox(name,value) : returns HTML formatted string for simple
   #                              checkbox
   # searchphrasefield(title,name,value) : returns HTML formatted string for
   #                                       a search expression phrase field
   # dateboxes(name, defaultmonth, defaultday, defaultyear) : returns HTML
   #                                                          formatted string
   #                                                          for a calendar date
   # selectbox(title,name,value,%HASH=options) : returns HTML formatted string for
   #                                             a selection box field
   #
   #
   # === SEARCH FUNCTIONS
   # advancedsearch(server reference, environment reference) : perform a complex
   #                                  multi-field logical query
   # basicsearch(server reference, environment reference) : perform a simple
   #                               single-field logical query
   # build_SQL_query(field name, logic) : builds a SQL query string from a
   #                                      logical expression with AND/OR keywords
   # build_custommetadata_query(field_name, logic_statement) : builds a perl
   #                 regular expression from a logical expression with AND/OR
   #                 keywords
   # recursive_SQL_query_build(field name, reverse notation expression) : 
   #                 builds a SQL query string from a reverse notation expression
   #                 logical expression with AND/OR keywords
   # build_date_queries(cmonth1, cday1, cyear1, cmonth2, cday2, cyear2,
   #                    lmonth1, lday1, lyear1, lmonth2, lday2, lyear2) :
   #                 Builds a SQL logic query to check time/date entries.
   #
   #
   # === OUTPUTTING RESULTS FUNCTION
   # output_results(output mode,
   #                server reference, 
   #                environment reference,
   #                reply list reference) : outputs results from search
   #
   #
   # === DIFFERENT WAYS TO VIEW METADATA RECORDS
   # detailed_citation_view(ORDERED METADATA LIST FOR A RESULT OBJECT INSTANCE) :
   #          see metadata viewing notes below 
   # summary_view(ORDERED METADATA LIST FOR A RESULT OBJECT INSTANCE) :
   #          see metadata viewing notes below 
   # fielded_format_view(ORDERED METADATA LIST FOR A RESULT OBJECT INSTANCE) :
   #          see metadata viewing notes below 
   # xml_sgml_view(ORDERED METADATA LIST FOR A RESULT OBJECT INSTANCE) :
   #          see metadata viewing notes below 
   #  ___________________________________________________________________________
   # | * Metadata viewing notes                                                  |
   # | Output is a HTML-ified string.                                            |
   # | Input arguments are title, author, subject, url, keywords, version, notes,|
   # | short abstract, mime, language, creation date, last revision date, owner, |
   # | copyright, hostname, httphost, and extra custom metadata to show.         |
   #  ---------------------------------------------------------------------------
   #
   #
   # === TEST CONDITIONAL FUNCTIONS
   # filled(field) : determines whether a given field has been filled
 #  #
   #
   # === ERROR FUNCTIONS
   # output_blank_field_error(server reference) : outputs a message saying that
   #                                              more fields need to be filled in
   # output_date_error(server reference, error message) : outputs
   #         an error message specific to bad date format.
   
 package Apache::lonsearchcat;  package Apache::lonsearchcat;
   
   # ------------------------------------------------- modules used by this module
 use strict;  use strict;
 use Apache::Constants qw(:common);  use Apache::Constants qw(:common);
   use Apache::lonnet();
   use Apache::File();
   use CGI qw(:standard);
   use Text::Query;
   
   # ---------------------------------------- variables used throughout the module
   
   # -- information holders
   my %language; # holds contents of language.tab
   my %cprtag; # holds contents of copyright.tab
   my %mimetag; # holds contents of filetypes.tab
   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
   my $closebutton; # button that closes the search window
   my $importbutton; # button to take the selected results and go to group sorting
   
   # -- miscellaneous variables
   my $scrout; # string that holds portions of the screen output
   my $fnum; # search result counter
   my $yourself; # allows for quickly limiting to oneself
   
   # ------------------------------------------ choices for different output views
   # Detailed Citation View ---> sub detailed_citation_view
   # Summary View ---> sub summary_view
   # Fielded Format ---> sub fielded_format_view
   # XML/SGML ---> sub xml_sgml_view
   my $basicviewselect=<<END;
   <select name='basicviewselect'>
   <option value='Detailed Citation View'>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'>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
   
   # ----------------------------------------------------------------------- BEGIN
   sub BEGIN {
   # --------------------------------- Compute various listings of metadata values
       $language{'any'}='Any language';
       {
    my $fh=Apache::File->new($Apache::lonnet::perlvar{'lonTabDir'}.
    '/language.tab');
    map {
       $_=~/(\w+)\s+([\w\s\-]+)/; chomp;
       $language{$1}=$2;
    } <$fh>;
       }
       $cprtag{'any'}='Any copyright/distribution';
       {
    my $fh=Apache::File->new($Apache::lonnet::perlvar{'lonIncludes'}.
    '/copyright.tab');
    map {
       $_=~/(\w+)\s+([\w\s\-]+)/; chomp;
       $cprtag{$1}=$2;
    } <$fh>;
       }
       $mimetag{'any'}='Any type';
       {
    my $fh=Apache::File->new($Apache::lonnet::perlvar{'lonTabDir'}.
    '/filetypes.tab');
    map {
       $_=~/(\w+)\s+(\w+)\s+([\w\s\-]+)/; chomp;
       $mimetag{$1}=".$1 $3";
    } <$fh>;
       }
       {
    my $fh=Apache::File->new($Apache::lonnet::perlvar{'lonTabDir'}.
    '/hosts.tab');
    map {
       $_=~/(\w+?)\:(\w+?)\:(\w+?)\:(.*)/; chomp;
       if ($3 eq 'library') {
    $hostdomains{$1}=$2;
    $hostips{$1}=$4;
       }
    } <$fh>;
       }
   }
   
   # ----------------------------- Handling routine called via Apache and mod_perl
 sub handler {  sub handler {
     my $r = shift;      my $r = shift;
   
       &get_unprocessed_cgi();
   
     $r->content_type('text/html');      $r->content_type('text/html');
     $r->send_http_header;      $r->send_http_header;
     return OK if $r->header_only;      return OK if $r->header_only;
   
   # ----------------------------------- configure dynamic components of interface
       my $hidden='';
       if ($ENV{'form.catalogmode'} eq 'interactive') {
    $hidden="<input type='hidden' name='catalogmode' value='interactive'>".
       "\n";
           $closebutton="<input type='button' name='close' value='CLOSE' ".
       "onClick='self.close()'>"."\n";
       }
       elsif ($ENV{'form.catalogmode'} eq 'groupsearch') {
    $hidden=<<END;
   <input type='hidden' name='catalogmode' value='groupsearch'>
   END
           $closebutton=<<END;
   <input type='button' name='close' value='CLOSE' onClick='self.close()'>
   END
           $importbutton=<<END;
   <input type='button' name='import' value='IMPORT'
   onClick='javascript:select_group()'>
   END
       }
   
   # ------------------------------------------------------ Determine current user
       $yourself=$ENV{'user.name'}.'@'.$ENV{'user.domain'};
   
   # --- Now, depending on the interface actions, do one of three things here:
   # --- 1. a basic search
   # --- 2. an advanced search
   # --- 3. output a search interface
   
   # ----------------------------------- See if a search invocation should be done
       if ($ENV{'form.basicsubmit'} eq 'SEARCH') {
    return &basicsearch($r,\%ENV);
       }
       elsif ($ENV{'form.advancedsubmit'} eq 'SEARCH') {
    return &advancedsearch($r,\%ENV);
       }
   
   # ----------------------------- Else, begin building search interface to output
       $scrout=''; # building a part of screen output
       $scrout.=&searchphrasefield('Limit by title','title',
    $ENV{'form.title'});
   
       $scrout.=&searchphrasefield('Limit by author','author',
    $ENV{'form.author'});
   
       $scrout.=&searchphrasefield('Limit by subject','subject',
    $ENV{'form.subject'});
   
       $scrout.=&searchphrasefield('Limit by keywords','keywords',
    $ENV{'form.keywords'});
   
       $scrout.=&searchphrasefield('Limit by URL','url',
    $ENV{'form.url'});
   
   #    $scrout.=&searchphrasefield('Limit by version','version',
   # $ENV{'form.version'});
   
       $scrout.=&searchphrasefield('Limit by notes','notes',
    $ENV{'form.notes'});
   
       $scrout.=&searchphrasefield('Limit by abstract','abstract',
    $ENV{'form.abstract'});
   
       $ENV{'form.mime'}='notxxx' unless length($ENV{'form.mime'});
       $scrout.=&selectbox('Limit by MIME type','mime',
    $ENV{'form.mime'},%mimetag);
   
       $ENV{'form.language'}='any' unless length($ENV{'form.language'});
   
       $scrout.=&selectbox('Limit by language','language',
    $ENV{'form.language'},%language);
       
   
   # ------------------------------------------------ Compute date selection boxes
       $scrout.=<<CREATIONDATESTART;
   <p>
   <font color="#800000" face="helvetica"><b>LIMIT BY CREATION DATE RANGE:</b>
   </font>
   <br />
   between:
   CREATIONDATESTART
       $scrout.=&dateboxes('creationdatestart',1,1,1976,
    $ENV{'form.creationdatestart_month'},
    $ENV{'form.creationdatestart_day'},
    $ENV{'form.creationdatestart_year'},
    );
       $scrout.=<<CREATIONDATEEND;
   and:
   CREATIONDATEEND
       $scrout.=&dateboxes('creationdateend',12,31,2051,
    $ENV{'form.creationdateend_month'},
    $ENV{'form.creationdateend_day'},
    $ENV{'form.creationdateend_year'},
    );
       $scrout.="</p>";
   
       $scrout.=<<LASTREVISIONDATESTART;
   <p>
   <font color="#800000" face="helvetica"><b>LIMIT BY LAST REVISION DATE RANGE:
   </b></font>
   <br />between:
   LASTREVISIONDATESTART
       $scrout.=&dateboxes('lastrevisiondatestart',1,1,1976,
    $ENV{'form.lastrevisiondatestart_month'},
    $ENV{'form.lastrevisiondatestart_day'},
    $ENV{'form.lastrevisiondatestart_year'},
    );
       $scrout.=<<LASTREVISIONDATEEND;
   and:
   LASTREVISIONDATEEND
       $scrout.=&dateboxes('lastrevisiondateend',12,31,2051,
    $ENV{'form.lastrevisiondateend_month'},
    $ENV{'form.lastrevisiondateend_day'},
    $ENV{'form.lastrevisiondateend_year'},
    );
       $scrout.='</p>';
   
       $scrout.=&searchphrasefield('Limit by publisher/owner','owner',
    $ENV{'form.owner'});
   
       $ENV{'form.copyright'}='any' unless length($ENV{'form.copyright'});
       $scrout.=&selectbox('Limit by copyright/distribution','copyright',
    $ENV{'form.copyright'},%cprtag);
   
   # ------------------------------------------- Compute customized metadata field
       $scrout.=<<CUSTOMMETADATA;
   <p>
   <font color="#800000" face="helvetica"><b>LIMIT BY SPECIAL METADATA FIELDS:</b>
   </font>
   For resource-specific metadata, enter in an expression in the form of 
   <i>key</i>=<i>value</i> separated by operators such as AND or OR.<br />
   <b>Example:</b> grandmother=75 OR grandfather=85
   <br />
   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;
   <p>
   <font color="#800000" face="helvetica"><b>SHOW SPECIAL METADATA FIELDS:</b>
   </font>
   Enter in a space-separated list of special metadata fields to show
   in a fielded listing for each record result.
   <br />
   CUSTOMSHOW
   $scrout.=&simpletextfield('customshow',$ENV{'form.customshow'});
   $scrout.=' <i>initial users of this system do not need to worry about this option</i>';
   
 # ---------------------------------------------------------------- Print screen  # ---------------------------------------------------------------- Print screen
     $r->print(<<ENDDOCUMENT);      $r->print(<<ENDDOCUMENT);
 <html>  <html>
Line 21  sub handler { Line 360  sub handler {
 <title>The LearningOnline Network with CAPA</title>  <title>The LearningOnline Network with CAPA</title>
 </head>  </head>
 <body bgcolor="#FFFFFF">  <body bgcolor="#FFFFFF">
   <img align='right' src='/adm/lonIcons/lonlogos.gif' />
 <h1>Search Catalog</h1>  <h1>Search Catalog</h1>
 <body bgcolor="#AAFFAA"><form>  <form method="post" action="/adm/searchcat">
 <img src="/adm/lonKaputt/lonconstruct.gif">  $hidden
 <table width="100%">  <hr />
 <tr><td><b>Resource Library Search</b></td>  <h3>Basic Search</h3>
 <td align=right><input type=button value="Close"  <p>
  onClick="javascript:opener.srchclose();"></td>  Enter terms or phrases separated by search operators
 </tr></table>  such as AND or OR then press SEARCH below.  Terms should be specific
 <table bgcolor="#ffffff">  to the title, author, subject, notes, or abstract information associated
 <tr><td><b>title</b> </td>  with a resource.
 <td><INPUT TYPE="TEXT" NAME="title"></td>  <br />
 </tr><tr><td><b>author</b> </td>  ENDDOCUMENT
 <td><INPUT TYPE="TEXT" NAME="author"></td>      $r->print(&simpletextfield('basicexp',$ENV{'form.basicexp'}));
 </tr><tr><td><b>subject</b> </td>      $r->print(' ');
 <td><INPUT TYPE="TEXT" NAME="subject"></td>      $r->print(&simplecheckbox('titleonly',$ENV{'form.titleonly'}));
 </tr><tr><td><b>notes</b> </td>      $r->print('<font color="#800000">Title only</font> ');
 <td><INPUT TYPE="TEXT" NAME="notes"></td>  #    $r->print(&simplecheckbox('allversions',$ENV{'form.allversions'}));
 </tr><tr><td><b>abstract</b> </td>  # <font color="#800000">Search historic archives</font>
 <td><INPUT TYPE="TEXT" NAME="abstract"></td>      $r->print(<<ENDDOCUMENT);
 </tr><tr><td><b>mime</b> </td>  <br />
 <td><INPUT TYPE="TEXT" NAME="mime"></td>  <input type="submit" name="basicsubmit" value='SEARCH' />
 </tr><tr><td><b>language</b> </td>  <input type="reset" name="reset" value='RESET' />
 <td><INPUT TYPE="TEXT" NAME="language"></td>  $closebutton
 </tr><tr><td><b>creationdate</b> </td>  $basicviewselect
 <td><INPUT TYPE="TEXT" NAME="creationdate"></td>  </p>
 </tr><tr><td><b>lastrevisiondate</b> </td>  <hr />
 <td><INPUT TYPE="TEXT" NAME="lastrevisiondate"></td>  <h3>Advanced Search</h3>
 </tr><tr><td><b>owner</b> </td>  $scrout
 <td><INPUT TYPE="TEXT" NAME="owner"></td>  <p>
 </tr><tr><td><b>copyright</b> </td>  <input type="submit" name="advancedsubmit" value='SEARCH' />
 <td><INPUT TYPE="TEXT" NAME="copyright"></td>  <input type="reset" name="reset" value='RESET' />
 </tr>  $closebutton
 </table>  $advancedviewselect
   </p>
   </form>
 </body>  </body>
 </html>  </html>
 ENDDOCUMENT  ENDDOCUMENT
     return OK;      return OK;
 }   } 
   
   # ----------- grab unprocessed CGI variables that may have been appended to URL
   sub get_unprocessed_cgi {
       map {
          my ($name, $value) = split(/=/,$_);
          $value =~ tr/+/ /;
          $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg;
          if ($name eq 'catalogmode') {
      $ENV{'form.'.$name}=$value;
          }
       } (split(/&/,$ENV{'QUERY_STRING'}));
   }
   
   # ------------------------------------------------------------- make persistent
   sub make_persistent {
       my $persistent='';
       
       map {
    if (/^form\./ && !/submit/) {
       my $name=$_;
       my $key=$name;
       $ENV{$key}=~s/\'//g; # do not mess with html field syntax
       $name=~s/^form\.//;
       $persistent.=<<END;
   <input type='hidden' name='$name' value='$ENV{$key}' />
   END
           }
       } (keys %ENV);
       return $persistent;
   }
   
   # --------------------------------------------------------- Various form fields
   
   sub simpletextfield {
       my ($name,$value)=@_;
       return '<input type=text name=\''.$name.
      '\' size=20 value=\''.$value.'\' />';
   }
   
   sub simplecheckbox {
       my ($name,$value)=@_;
       my $checked='';
       $checked="CHECKED" if $value eq 'on';
       return '<input type=checkbox name=\''.$name.'\' '. $checked . '>';
   }
   
   sub searchphrasefield {
       my ($title,$name,$value)=@_;
       my $instruction=<<END;
   Enter terms or phrases separated by search operators such
   as AND or OR.
   END
       my $uctitle=uc($title);
       return "\n<p><font color=\"#800000\" face=\"helvetica\"><b>$uctitle:</b>".
      "</FONT> $instruction<br />".
              '<input type=text name="'.$name.'" size=80 value=\''.$value.'\'>';
   }
   
   sub dateboxes {
       my ($name,$defaultmonth,$defaultday,$defaultyear,
    $currentmonth,$currentday,$currentyear)=@_;
       ($defaultmonth,$defaultday,$defaultyear)=('','','');
       my $month=<<END;
   <select name="${name}_month">
   <option value='$defaultmonth'> </option>
   <option value="1">January</option>
   <option value="2">February</option>
   <option value="3">March</option>
   <option value="4">April</option>
   <option value="5">May</option>
   <option value="6">June</option>
   <option value="7">July</option>
   <option value="8">August</option>
   <option value="9">September</option>
   <option value="10">October</option>
   <option value="11">November</option>
   <option value="12">December</option>
   </select>
   END
       $month=~s/(\"$currentmonth\")/$1 SELECTED/ if length($currentmonth);
       my $day=<<END;
   <select name="${name}_day">
   <option value='$defaultday'> </option>
   <option value="1">1</option>
   <option value="2">2</option>
   <option value="3">3</option>
   <option value="4">4</option>
   <option value="5">5</option>
   <option value="6">6</option>
   <option value="7">7</option>
   <option value="8">8</option>
   <option value="9">9</option>
   <option value="10">10</option>
   <option value="11">11</option>
   <option value="12">12</option>
   <option value="13">13</option>
   <option value="14">14</option>
   <option value="15">15</option>
   <option value="16">16</option>
   <option value="17">17</option>
   <option value="18">18</option>
   <option value="19">19</option>
   <option value="20">20</option>
   <option value="21">21</option>
   <option value="22">22</option>
   <option value="23">23</option>
   <option value="24">24</option>
   <option value="25">25</option>
   <option value="26">26</option>
   <option value="27">27</option>
   <option value="28">28</option>
   <option value="29">29</option>
   <option value="30">30</option>
   <option value="31">31</option>
   </select>
   END
       $day=~s/(\"$currentday\")/$1 SELECTED/ if length($currentday);
       my $year=<<END;
   <select name="${name}_year">
   <option value='$defaultyear'> </option>
   <option value="1976">1976</option>
   <option value="1977">1977</option>
   <option value="1978">1978</option>
   <option value="1979">1979</option>
   <option value="1980">1980</option>
   <option value="1981">1981</option>
   <option value="1982">1982</option>
   <option value="1983">1983</option>
   <option value="1984">1984</option>
   <option value="1985">1985</option>
   <option value="1986">1986</option>
   <option value="1987">1987</option>
   <option value="1988">1988</option>
   <option value="1989">1989</option>
   <option value="1990">1990</option>
   <option value="1991">1991</option>
   <option value="1992">1992</option>
   <option value="1993">1993</option>
   <option value="1994">1994</option>
   <option value="1995">1995</option>
   <option value="1996">1996</option>
   <option value="1997">1997</option>
   <option value="1998">1998</option>
   <option value="1999">1999</option>
   <option value="2000">2000</option>
   <option value="2001">2001</option>
   <option value="2002">2002</option>
   <option value="2003">2003</option>
   <option value="2004">2004</option>
   <option value="2005">2005</option>
   <option value="2006">2006</option>
   <option value="2007">2007</option>
   <option value="2008">2008</option>
   <option value="2009">2009</option>
   <option value="2010">2010</option>
   <option value="2011">2011</option>
   <option value="2012">2012</option>
   <option value="2013">2013</option>
   <option value="2014">2014</option>
   <option value="2015">2015</option>
   <option value="2016">2016</option>
   <option value="2017">2017</option>
   <option value="2018">2018</option>
   <option value="2019">2019</option>
   <option value="2020">2020</option>
   <option value="2021">2021</option>
   <option value="2022">2022</option>
   <option value="2023">2023</option>
   <option value="2024">2024</option>
   <option value="2025">2025</option>
   <option value="2026">2026</option>
   <option value="2027">2027</option>
   <option value="2028">2028</option>
   <option value="2029">2029</option>
   <option value="2030">2030</option>
   <option value="2031">2031</option>
   <option value="2032">2032</option>
   <option value="2033">2033</option>
   <option value="2034">2034</option>
   <option value="2035">2035</option>
   <option value="2036">2036</option>
   <option value="2037">2037</option>
   <option value="2038">2038</option>
   <option value="2039">2039</option>
   <option value="2040">2040</option>
   <option value="2041">2041</option>
   <option value="2042">2042</option>
   <option value="2043">2043</option>
   <option value="2044">2044</option>
   <option value="2045">2045</option>
   <option value="2046">2046</option>
   <option value="2047">2047</option>
   <option value="2048">2048</option>
   <option value="2049">2049</option>
   <option value="2050">2050</option>
   <option value="2051">2051</option>
   </select>
   END
       $year=~s/(\"$currentyear\")/$1 SELECTED/ if length($currentyear);
       return "$month$day$year";
   }
   
   sub selectbox {
       my ($title,$name,$value,%options)=@_;
       my $uctitle=uc($title);
       my $selout="\n<p><font color=\"#800000\" face=\"helvetica\"><b>$uctitle:".
    "</b></font><br />".'<select name="'.$name.'">';
       map {
           $selout.='<option value=\''.$_.'\'';
           if ($_ eq $value) { $selout.=' selected'; }
           $selout.='>'.$options{$_}.'</option>';
       } sort keys %options;
       return $selout.'</select>';
   }
   
   # ----------------------------------------------- Performing an advanced search
   sub advancedsearch {
       my ($r,$envhash)=@_;
       my %ENV=%{$envhash};
   
       my $fillflag=0;
       # Clean up fields for safety
       for my $field ('title','author','subject','keywords','url','version',
      'creationdatestart_month','creationdatestart_day',
      'creationdatestart_year','creationdateend_month',
      'creationdateend_day','creationdateend_year',
      'lastrevisiondatestart_month','lastrevisiondatestart_day',
      'lastrevisiondatestart_year','lastrevisiondateend_month',
      'lastrevisiondateend_day','lastrevisiondateend_year',
      'notes','abstract','mime','language','owner',
      'custommetadata','customshow') {
    $ENV{"form.$field"}=~s/[^\w\s\(\)\=\-\"\']//g;
       }
   
       # Check to see if enough information was filled in
       for my $field ('title','author','subject','keywords','url','version',
      'notes','abstract','mime','language','owner',
      'custommetadata') {
    if (&filled($ENV{"form.$field"})) {
       $fillflag++;
    }
       }
       unless ($fillflag) {
    &output_blank_field_error($r);
    return OK;
       }
   
   
       # Turn the form input into a SQL-based query
       my $query='';
   
       my @queries;
       # Evaluate logical expression AND/OR/NOT phrase fields.
       foreach my $field ('title','author','subject','notes','abstract','url',
          'keywords','version','owner') {
    if ($ENV{'form.'.$field}) {
       push @queries,&build_SQL_query($field,$ENV{'form.'.$field});
    }
       }
       # Evaluate option lists
       if ($ENV{'form.language'} and $ENV{'form.language'} ne 'any') {
    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') {
    push @queries,"(copyright like \"$ENV{'form.copyright'}\")";
       }
       # Evaluate date windows
       my $datequery=&build_date_queries(
    $ENV{'form.creationdatestart_month'},
    $ENV{'form.creationdatestart_day'},
    $ENV{'form.creationdatestart_year'},
    $ENV{'form.creationdateend_month'},
    $ENV{'form.creationdateend_day'},
    $ENV{'form.creationdateend_year'},
    $ENV{'form.lastrevisiondatestart_month'},
    $ENV{'form.lastrevisiondatestart_day'},
    $ENV{'form.lastrevisiondatestart_year'},
    $ENV{'form.lastrevisiondateend_month'},
    $ENV{'form.lastrevisiondateend_day'},
    $ENV{'form.lastrevisiondateend_year'},
    );
       # Test to see if date windows are legitimate
       if ($datequery=~/^Incorrect/) {
    &output_date_error($r,$datequery);
    return OK;
       }
       elsif ($datequery) {
    push @queries,$datequery;
       }
   
       # Process form information for custom metadata querying
       my $customquery='';
       if ($ENV{'form.custommetadata'}) {
    $customquery=&build_custommetadata_query('custommetadata',
         $ENV{'form.custommetadata'});
       }
       my $customshow='';
       if ($ENV{'form.customshow'}) {
    $customshow=$ENV{'form.customshow'};
    $customshow=~s/[^\w\s]//g;
    my @fields=split(/\s+/,$customshow);
    $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
       # metadata).
       if (@queries) {
    $query=join(" AND ",@queries);
    $query="select * from metadata where $query";
    my $reply; # reply hash reference
    unless ($customquery or $customshow) {
       $reply=&Apache::lonnet::metadata_query($query);
    }
    else {
       $reply=&Apache::lonnet::metadata_query($query,
      $customquery,$customshow);
    }
    &output_results('Advanced',$r,$envhash,$customquery,$reply);
       }
       elsif ($customquery) {
    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.';
   }
   
   # --------------------------------------------------- Performing a basic search
   sub basicsearch {
       my ($r,$envhash)=@_;
       my %ENV=%{$envhash};
       # Clean up fields for safety
       for my $field ('basicexp') {
    $ENV{"form.$field"}=~s/[^\w\s\(\)\-]//g;
       }
   
       # Check to see if enough is filled in
       unless (&filled($ENV{'form.basicexp'})) {
    &output_blank_field_error($r);
    return OK;
       }
   
       # Build SQL query string based on form page
       my $query='';
       my $concatarg=join(',"    ",',
          ('title', 'author', 'subject', 'notes', 'abstract'));
       $concatarg='title' if $ENV{'form.titleonly'};
   
       $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
   
       &output_results('Basic',$r,$envhash,$query,$reply);
   
       return OK;
   }
   
   # ------------------------------------------------------------- build_SQL_query
   sub build_SQL_query {
       my ($field_name,$logic_statement)=@_;
       my $q=new Text::Query('abc',
     -parse => 'Text::Query::ParseAdvanced',
     -build => 'Text::Query::Build');
       $q->prepare($logic_statement);
       my $matchexp=${$q}{'matchexp'}; chomp $matchexp;
       my $sql_query=&recursive_SQL_query_build($field_name,$matchexp);
       return $sql_query;
   }
   
   # ------------------------------------------------- build custom metadata query
   sub build_custommetadata_query {
       my ($field_name,$logic_statement)=@_;
       my $q=new Text::Query('abc',
     -parse => 'Text::Query::ParseAdvanced',
     -build => 'Text::Query::BuildAdvancedString');
       $q->prepare($logic_statement);
       my $matchexp=${$q}{'-parse'}{'-build'}{'matchstring'};
       # quick fix to change literal into xml tag-matching
       # will eventually have to write a separate builder module
       my $oldmatchexp=$matchexp;
       $matchexp=~s/(\w+)\\\=([\w\\\+]+)/\\\<$1\\\>\[\^\\\<\]\*$2\[\^\\\<\]\*\\\<\\\/$1\\\>/g;
       return $matchexp;
   }
   
   # - Recursively parse a reverse notation expression into a SQL query expression
   sub recursive_SQL_query_build {
       my ($dkey,$pattern)=@_;
       my @matches=($pattern=~/(\[[^\]|\[]*\])/g);
       return $pattern unless @matches;
       foreach my $match (@matches) {
    $match=~/\[ (\w+)\s(.*) \]/;
    my ($key,$value)=($1,$2);
    my $replacement='';
    if ($key eq 'literal') {
       $replacement="($dkey like \"\%$value\%\")";
    }
    elsif ($key eq 'not') {
       $value=~s/like/not like/;
   #    $replacement="($dkey not like $value)";
       $replacement="$value";
    }
    elsif ($key eq 'and') {
       $value=~/(.*[\"|\)]) ([|\(|\^].*)/;
       $replacement="($1 AND $2)";
    }
    elsif ($key eq 'or') {
       $value=~/(.*[\"|\)]) ([|\(|\^].*)/;
       $replacement="($1 OR $2)";
    }
    substr($pattern,
          index($pattern,$match),
          length($match),
          $replacement
          );
       }
       &recursive_SQL_query_build($dkey,$pattern);
   }
   
   # ------------------------------------------------------------ Build date query
   sub build_date_queries {
       my ($cmonth1,$cday1,$cyear1,$cmonth2,$cday2,$cyear2,
    $lmonth1,$lday1,$lyear1,$lmonth2,$lday2,$lyear2)=@_;
       my @queries;
       if ($cmonth1 or $cday1 or $cyear1 or $cmonth2 or $cday2 or $cyear2) {
    unless ($cmonth1 and $cday1 and $cyear1 and
    $cmonth2 and $cday2 and $cyear2) {
       return "Incorrect entry for the creation date.  You must specify ".
      "a starting month, day, and year and an ending month, ".
      "day, and year.";
    }
    my $cnumeric1=sprintf("%d%2d%2d",$cyear1,$cmonth1,$cday1);
    $cnumeric1+=0;
    my $cnumeric2=sprintf("%d%2d%2d",$cyear2,$cmonth2,$cday2);
    $cnumeric2+=0;
    if ($cnumeric1>$cnumeric2) {
       return "Incorrect entry for the creation date.  The starting ".
      "date must occur before the ending date.";
    }
    my $cquery="(creationdate BETWEEN '$cyear1-$cmonth1-$cday1' AND '".
              "$cyear2-$cmonth2-$cday2 23:59:59')";
    push @queries,$cquery;
       }
       if ($lmonth1 or $lday1 or $lyear1 or $lmonth2 or $lday2 or $lyear2) {
    unless ($lmonth1 and $lday1 and $lyear1 and
    $lmonth2 and $lday2 and $lyear2) {
       return "Incorrect entry for the last revision date.  You must ".
      "specify a starting month, day, and year and an ending ".
      "month, day, and year.";
    }
    my $lnumeric1=sprintf("%d%2d%2d",$lyear1,$lmonth1,$lday1);
    $lnumeric1+=0;
    my $lnumeric2=sprintf("%d%2d%2d",$lyear2,$lmonth2,$lday2);
    $lnumeric2+=0;
    if ($lnumeric1>$lnumeric2) {
       return "Incorrect entry for the last revision date.  The ".
      "starting date must occur before the ending date.";
    }
    my $lquery="(lastrevisiondate BETWEEN '$lyear1-$lmonth1-$lday1' AND '".
              "$lyear2-$lmonth2-$lday2 23:59:59')";
    push @queries,$lquery;
       }
       if (@queries) {
    return join(" AND ",@queries);
       }
       return '';
   }
   
   # ----------------------------- format and output results based on a reply list
   # There are two windows that this function writes to.  The main search
   # window ("srch") has a listing of the results.  A secondary window ("popwin")
   # gives the status of the network search (time elapsed, number of machines
   # contacted, etc.)
   sub output_results {
       my ($mode,$r,$envhash,$query,$replyref)=@_;
       my %ENV=%{$envhash};
       my %rhash=%{$replyref};
       my $compiledresult='';
       my $timeremain=30;
       my $elapsetime=0;
       my $resultflag=0;
       my $tflag=1;
   
       # make query information persistent to allow for subsequent revision
       my $persistent=&make_persistent();
   
       # output beginning of search page
    $r->print(<<BEGINNING);
   <html>
   <head>
   <title>The LearningOnline Network with CAPA</title>
   BEGINNING
   
       # conditional output of script functions dependent on the mode in
       # which the search was invoked
           $r->print(<<SCRIPT) if $ENV{'form.catalogmode'} eq 'interactive';
   <script>
       function select_data(title,url) {
    changeTitle(title);
    changeURL(url);
    self.close();
       }
       function changeTitle(val) {
    if (opener.inf.document.forms.resinfo.elements.t) {
       opener.inf.document.forms.resinfo.elements.t.value=val;
    }
       }
       function changeURL(val) {
    if (opener.inf.document.forms.resinfo.elements.u) {
       opener.inf.document.forms.resinfo.elements.u.value=val;
    }
       }
   </script>
   SCRIPT
           $r->print(<<SCRIPT) if $ENV{'form.catalogmode'} eq 'groupsearch';
   <script>
       function select_data(title,url) {
    alert('DEBUG: Should be storing '+title+' and '+url);
       }
       function queue(val) {
    if (eval("document.forms."+val+".filelink.checked")) {
       document.forms.results.acts.value+='1a'+val+'b';
    }
    else {
       document.forms.results.acts.value+='0a'+val+'b';
    }
       }
       function select_group() {
    alert('DEBUG: Should be moving on to group sorting stage'+' acts');
       }
   </script>
   SCRIPT
           $r->print(<<SCRIPT);                                            ;
   <script>
       function displayinfo(val) {
    popwin.document.forms.popremain.sdetails.value=val;
       }
   </script>
   SCRIPT
       $r->rflush();
   
       # begin showing the cataloged results
       $r->print(<<CATALOGBEGIN);
   </head>
   <body bgcolor="#ffffff">
   <img align=right src=/adm/lonIcons/lonlogos.gif>
   <h1>Search Catalog</h1>
   CATALOGBEGIN
           $r->print(<<CATALOGCONTROLS);
   <form name='results' method="post" action="/adm/searchcat">
   <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)
       my $hcinit;
       my $grid="'<br />'+";
       $grid.="\n";
       my $sn=1;
       for my $sk (sort keys %rhash) {
    # '<a href="
    $grid.="'<a href=\"";
    # javascript:displayinfo('+
    $grid.="javascript:opener.displayinfo('+";
    # "'"+'key
    $grid.="\"'\"+'";
    $grid.=$sk;
    my $hc;
    if ($rhash{$sk} eq 'con_lost') {
       $hc="!!!BAD CONNECTION, CONTACT SYSTEM ADMINISTRATOR!!!";
    }
    else {
       $hc="'+\"'\"+\"+hc['$sk']+\"+\"'\"+'";
       $hcinit.="hc[\"$sk\"]=\"not yet connected...\";";
    }
    $grid.=" hitcount=".$hc;
    $grid.=" domain=".$hostdomains{$sk};
    $grid.=" IP=".$hostips{$sk};
    # '+"'"+'">'+
    $grid.="'+\"'\"+')\">'+";
    $grid.="\n";
    $grid.="'<img border=\"0\" name=\"img".$sn."\"".
       " src=\"/adm/lonIcons/srvnull.gif\" alt=\"".$sk."\" /></a>'+\n";
    $grid.="'<br />'+\n" unless $sn%10;
           $sn++;
       }
       $r->print(<<ENDPOP);
   <script>
       popwin=open('','popwin','scrollbars=1,width=400,height=200');
       popwin.focus();
       popwin.document.writeln('<'+'html>');
       popwin.document.writeln('<'+'head>');
       popwin.document.writeln('<'+'script>');
       popwin.document.writeln('hc=new Array();$hcinit');
       popwin.document.writeln('<'+'/script>');
       popwin.document.writeln('<'+'/head>'+
           '<'+'body bgcolor="#FFFFFF">'+
    '<'+'image align="right" src="/adm/lonIcons/'+
    'lonanim.gif" '+
    'alt="animated logo" />'+
    '<'+'h3>Search Results Progress<'+'/h3>'+
           '<'+'form name="popremain">'+
           '<'+'tt>'+
    '<'+'br clear="all"/><i>PLEASE BE PATIENT</i>'+
    '<'+'br />SCANNING $servernum SERVERS'+
    '<'+'br clear="all" />Number of record hits found '+
    '<'+'input type="text" size="10" name="numhits"'+
    ' value="0" />'+
    '<'+'br clear="all" />Time elapsed '+
    '<'+'input type="text" size="10" name="elapsetime"'+
    ' value="0" />'+
    '<'+'br />'+
    'SERVER GRID (click on any cell for details)'+
           $grid
           '<'+'br />'+
    'Server details '+
    '<'+'input type="text" size="25" name="sdetails"'+
    ' value="" />'+
    '<'+'br />'+
    '<'+'input type="button" name="button"'+
    ' value="revise search" />'+
    ' <'+'input type="button" name="button"'+
    ' value="view results" />'+
    ' <'+'input type="button" name="button"'+
    ' value="help" />'+
    '<'+'/tt>'+
           '<'+'/form>'+
           '<'+'/body><'+'/html>');
       popwin.document.close();
   </script>
   ENDPOP
       $r->rflush();
   
       my $servercount=0;
       $sn=0;
       my $hitcountsum=0;
       foreach my $rkey (sort keys %rhash) {
    $sn++;
    $servercount++;
    $tflag=1;
    $compiledresult='';
    my $hostname=$rkey;
    my $reply=$rhash{$rkey};
    my @results;
   
    my $replyfile='';
   
    if ($reply eq 'con_lost') {
       $r->print('<script>popwin.document.img'.$sn.'.'.
         'src="/adm/lonIcons/srvbad.gif";</script>'.
         "\n");
       $r->rflush();
    }
    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) {
         $r->print('<script>popwin.document.img'.$sn.'.'.
    'src="/adm/lonIcons/srvhalf.gif";</script>'.
    "\n");
         $r->rflush();
         $r->print('<script>popwin.hc["'.$rkey.'"]='.
    '"still transferring..."'.';</script>'.
    "\n");
         $r->rflush();
         $tflag=0;
     }
     last WLOOP if $temp>5;
     if (-e "$replyfile.end") {
         if (-s $replyfile) {
     $r->print('<script>popwin.document.img'.$sn.'.'.
    'src="/adm/lonIcons/srvgood.gif";</script>'.
    "\n");
     $r->rflush();
     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;
     $r->print('<script>popwin.hc["'.$rkey.'"]='.
       $hitcount{$rkey}.';</script>'.
       "\n");
     $r->rflush();
     $hitcountsum+=$hitcount{$rkey};
     $r->print('<script>popwin.document.forms.popremain.'.
       'numhits.value='.$hitcountsum.
       ';</script>'.
       "\n");
     $r->rflush();
         }
         else {
     $r->print('<script>popwin.document.img'.$sn.'.'.
    'src="/adm/lonIcons/srvempty.gif";</script>'.
    "\n");
     $r->rflush();
     $r->print('<script>popwin.hc["'.$rkey.'"]=0'.
       ';</script>'.
       "\n");
     $r->rflush();
         }
         last WLOOP;
     }
     last WLOOP unless $timeremain;
     sleep 1;
     $timeremain--;
     $elapsetime++;
     $r->print('<script>popwin.document.popremain.elapsetime.'.
       'value="'.$elapsetime.'";</script>'."\n");
     $r->rflush();
     $temp++;
         }
       }
    }
    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;
       }
    }
    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;
       my $shortabstract=$abstract;
       $shortabstract=substr($abstract,0,200) if length($abstract)>200;
       $fields[7]=$shortabstract;
       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
               $compiledresult.=<<END if $ENV{'form.catalogmode'} eq 'interactive';
   <font size='-1'><INPUT TYPE="button" NAME="returnvalues" VALUE="SELECT"
   onClick="javascript:select_data('$title','$url')">
   </font>
   <br />
   END
               $compiledresult.=<<END if $ENV{'form.catalogmode'} eq 'groupsearch';
   <font size='-1'><input type="checkbox" name="returnvalues" value="SELECT"
   onClick="javascript:queue($fnum)" />
   </font>
   <input type="hidden" name="title$fnum" value="$title" />
   <input type="hidden" name="url$fnum" value="$url" />
   <br />
   END
               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);
       }
       
           }
   
    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>popwin.close()</script>'."\n"); $r->rflush(); 
       $r->print(<<RESULTS);
   </body>
   </html>
   RESULTS
   }
   
   # ------------------------------------------------------ Detailed Citation View
   sub detailed_citation_view {
       my ($title,$author,$subject,$url,$keywords,$version,
    $notes,$shortabstract,$mime,$lang,
    $creationdate,$lastrevisiondate,$owner,$copyright,
    $hostname,$httphost,$extrashow)=@_;
       my $result=<<END;
   <i>$owner</i>, last revised $lastrevisiondate
   <h3><A HREF="http://$httphost$url" TARGET='search_preview'>$title</A></h3>
   <h3>$author</h3>
   </p>
   <p>
   <b>Subject:</b> $subject<br />
   <b>Keyword(s):</b> $keywords<br />
   <b>Notes:</b> $notes<br />
   <b>MIME Type:</b> $mimetag{$mime}<br />
   <b>Language:</b> $language{$lang}<br />
   <b>Copyright/Distribution:</b> $cprtag{$copyright}<br />
   </p>
   $extrashow
   <p>
   $shortabstract
   </p>
   END
       return $result;
   }
   
   # ---------------------------------------------------------------- Summary View
   sub summary_view {
       my ($title,$author,$subject,$url,$keywords,$version,
    $notes,$shortabstract,$mime,$lang,
    $creationdate,$lastrevisiondate,$owner,$copyright,
    $hostname,$httphost,$extrashow)=@_;
       my $result=<<END;
   <a href="http://$httphost$url" TARGET='search_preview'>$author</a><br />
   $title<br />
   $owner -- $lastrevisiondate<br />
   $cprtag{$copyright}<br />
   $extrashow
   </p>
   END
       return $result;
   }
   
   # -------------------------------------------------------------- Fielded Format
   sub fielded_format_view {
       my ($title,$author,$subject,$url,$keywords,$version,
    $notes,$shortabstract,$mime,$lang,
    $creationdate,$lastrevisiondate,$owner,$copyright,
    $hostname,$httphost,$extrashow)=@_;
       my $result=<<END;
   <b>URL: </b> <A HREF="http://$httphost$url" TARGET='search_preview'>$url</A>
   <br />
   <b>Title:</b> $title<br />
   <b>Author(s):</b> $author<br />
   <b>Subject:</b> $subject<br />
   <b>Keyword(s):</b> $keywords<br />
   <b>Notes:</b> $notes<br />
   <b>MIME Type:</b> $mimetag{$mime}<br />
   <b>Language:</b> $language{$lang}<br />
   <b>Creation Date:</b> $creationdate<br />
   <b>Last Revision Date:</b> $lastrevisiondate<br />
   <b>Publisher/Owner:</b> $owner<br />
   <b>Copyright/Distribution:</b> $cprtag{$copyright}<br />
   <b>Repository Location:</b> $hostname<br />
   <b>Abstract:</b> $shortabstract<br />
   $extrashow
   </p>
   END
       return $result;
   }
   
   # -------------------------------------------------------------------- XML/SGML
   sub xml_sgml_view {
       my ($title,$author,$subject,$url,$keywords,$version,
    $notes,$shortabstract,$mime,$lang,
    $creationdate,$lastrevisiondate,$owner,$copyright,
    $hostname,$httphost,$extrashow)=@_;
       my $result=<<END;
   <pre>
   &lt;LonCapaResource&gt;
   &lt;url&gt;$url&lt;/url&gt;
   &lt;title&gt;$title&lt;/title&gt;
   &lt;author&gt;$author&lt;/author&gt;
   &lt;subject&gt;$subject&lt;/subject&gt;
   &lt;keywords&gt;$keywords&lt;/keywords&gt;
   &lt;notes&gt;$notes&lt;/notes&gt;
   &lt;mimeInfo&gt;
   &lt;mime&gt;$mime&lt;/mime&gt;
   &lt;mimetag&gt;$mimetag{$mime}&lt;/mimetag&gt;
   &lt;/mimeInfo&gt;
   &lt;languageInfo&gt;
   &lt;language&gt;$lang&lt;/language&gt;
   &lt;languagetag&gt;$language{$lang}&lt;/languagetag&gt;
   &lt;/languageInfo&gt;
   &lt;creationdate&gt;$creationdate&lt;/creationdate&gt;
   &lt;lastrevisiondate&gt;$lastrevisiondate&lt;/lastrevisiondate&gt;
   &lt;owner&gt;$owner&lt;/owner&gt;
   &lt;copyrightInfo&gt;
   &lt;copyright&gt;$copyright&lt;/copyright&gt;
   &lt;copyrighttag&gt;$cprtag{$copyright}&lt;/copyrighttag&gt;
   &lt;/copyrightInfo&gt;
   &lt;repositoryLocation&gt;$hostname&lt;/repositoryLocation&gt;
   &lt;shortabstract&gt;$shortabstract&lt;/shortabstract&gt;
   &lt;/LonCapaResource&gt;
   </pre>
   $extrashow
   END
       return $result;
   }
   
   # ---------------------------------------------------- see if a field is filled
   sub filled {
       my ($field)=@_;
       if ($field=~/\S/ && $field ne 'any') {
    return 1;
       }
       else {
    return 0;
       }
   }
   
   # ---------------- Message to output when there are not enough fields filled in
   sub output_blank_field_error {
       my ($r)=@_;
       # make query information persistent to allow for subsequent revision
       my $persistent=&make_persistent();
   
       $r->print(<<BEGINNING);
   <html>
   <head>
   <title>The LearningOnline Network with CAPA</title>
   BEGINNING
       $r->print(<<RESULTS);
   </head>
   <body bgcolor="#ffffff">
   <img align='right' src='/adm/lonIcons/lonlogos.gif' />
   <h1>Search Catalog</h1>
   <form method="post" action="/adm/searchcat">
   $persistent
   <input type='button' value='Revise search request'
   onClick='this.form.submit();' />
   $closebutton
   <hr />
   <h3>Helpful Message</h3>
   <p>
   Incorrect search query due to blank entry fields.
   You need to fill in the relevant
   fields on the search page in order for a query to be
   processed.
   </p>
   </body>
   </html>
   RESULTS
   }
   
   # ----------------------------------------------------------- Output date error
   sub output_date_error {
       my ($r,$message)=@_;
       # make query information persistent to allow for subsequent revision
       my $persistent=&make_persistent();
   
       $r->print(<<BEGINNING);
   <html>
   <head>
   <title>The LearningOnline Network with CAPA</title>
   BEGINNING
       $r->print(<<RESULTS);
   </head>
   <body bgcolor="#ffffff">
   <img align='right' src='/adm/lonIcons/lonlogos.gif' />
   <h1>Search Catalog</h1>
   <form method="post" action="/adm/searchcat">
   $persistent
   <input type='button' value='Revise search request'
   onClick='this.form.submit();' />
   $closebutton
   <hr />
   <h3>Helpful Message</h3>
   <p>
   $message
   </p>
   </body>
   </html>
   RESULTS
   }
   
 1;  1;
   
 __END__  __END__

Removed from v.1.2  
changed lines
  Added in v.1.99


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