Diff for /loncom/interface/lonsearchcat.pm between versions 1.313 and 1.331.4.10

version 1.313, 2009/07/31 16:01:48 version 1.331.4.10, 2014/02/23 22:16:20
Line 52  search (on a server basis) is displayed Line 52  search (on a server basis) is displayed
   
 =head1 Internals  =head1 Internals
   
 =over 4  
   
 =cut  =cut
   
 ###############################################################################  ###############################################################################
Line 78  use HTML::Entities(); Line 76  use HTML::Entities();
 use Parse::RecDescent;  use Parse::RecDescent;
 use Apache::lonnavmaps;  use Apache::lonnavmaps;
 use Apache::lonindexer();  use Apache::lonindexer();
   use Apache::lonwishlist();
 use LONCAPA;  use LONCAPA;
   
 ######################################################################  ######################################################################
Line 118  sub handler { Line 117  sub handler {
                       # This is set and used in &handler() and is also used in                         # This is set and used in &handler() and is also used in 
                       # &output_results().                        # &output_results().
   
     my $loaderror=&Apache::lonnet::overloaderror($r);  
     if ($loaderror) { return $loaderror; }  
     #      #
     my $closebutton;  # button that closes the search window       my $closebutton;  # button that closes the search window 
                       # This button is different for the RAT compared to                        # This button is different for the RAT compared to
Line 153  sub handler { Line 150  sub handler {
     ## Initialize global variables      ## Initialize global variables
     ##      ##
     my $domain  = $r->dir_config('lonDefDomain');      my $domain  = $r->dir_config('lonDefDomain');
     $diropendb= "/home/httpd/perl/tmp/".      my $temp_file_dir = LONCAPA::tempdir();
       $diropendb= $temp_file_dir .
         "$env{'user.domain'}_$env{'user.name'}_sel_res.db";          "$env{'user.domain'}_$env{'user.name'}_sel_res.db";
     #      #
     # set the name of the persistent database      # set the name of the persistent database
Line 164  sub handler { Line 162  sub handler {
         $env{'form.persistent_db_id'} = time;          $env{'form.persistent_db_id'} = time;
     }      }
   
     my $persistent_db_file = "/home/httpd/perl/tmp/".      my $persistent_db_file = $temp_file_dir .
         &escape($domain).          &escape($domain).
             '_'.&escape($env{'user.name'}).              '_'.&escape($env{'user.name'}).
                 '_'.$env{'form.persistent_db_id'}.'_persistent_search.db';                  '_'.$env{'form.persistent_db_id'}.'_persistent_search.db';
Line 172  sub handler { Line 170  sub handler {
     &Apache::lonhtmlcommon::clear_breadcrumbs();      &Apache::lonhtmlcommon::clear_breadcrumbs();
   
     my @allowed_searches = ('portfolio');      my @allowed_searches = ('portfolio');
     if (&Apache::lonnet::allowed('bre',$env{'request.role.domain'})) {      if (&Apache::lonnet::allowed('bre',$env{'request.role.domain'}) eq 'F') {
         push(@allowed_searches,'res');          push(@allowed_searches,'res');
     }       } 
     if (exists($env{'request.course.id'}) && $env{'request.course.id'} ne '') {  
         push(@allowed_searches,'course');  
     }  
     my $crumb_text = 'Portfolio Search';      my $crumb_text = 'Portfolio Search';
     if (@allowed_searches == 3) {      if (@allowed_searches ==2) {
         $crumb_text = 'Course, Portfolio and Catalog Search';         $crumb_text = 'Portfolio and Catalog Search'; 
     } elsif (@allowed_searches ==2) {  
         if (grep(/^res$/,@allowed_searches)) {  
             $crumb_text = 'Portfolio and Catalog Search';   
         } elsif (grep(/^course$/,@allowed_searches)) {  
             $crumb_text = 'Portfolio and Course Search';  
         }  
     }      }
     &Apache::lonhtmlcommon::add_breadcrumb      &Apache::lonhtmlcommon::add_breadcrumb
        ({href=>'/adm/searchcat?'.         ({href=>'/adm/searchcat?'.
Line 204  sub handler { Line 193  sub handler {
                 &Apache::lonnet::logthis('lonsearchcat:'.                  &Apache::lonnet::logthis('lonsearchcat:'.
                                          'Unable to recover data from '.                                           'Unable to recover data from '.
                                          $persistent_db_file);                                           $persistent_db_file);
  my $msg =                  my $msg =
     'We were unable to retrieve data describing your search. '.                      &mt('We were unable to retrieve data describing your search.').
     'This is a serious error and has been logged. '.                      ' '.&mt('This is a serious error and has been logged.').
     'Please alert your LON-CAPA administrator.';                      '<br />'.
  &Apache::loncommon::simple_error_page($r,'Search Error',                      &mt('Please alert your LON-CAPA administrator.');
       $msg);                  &Apache::loncommon::simple_error_page(
                       $r,'Search Error',
                       $msg,
                       {'no_auto_mt_msg' => 1});
  return OK;   return OK;
             }              }
         }          }
Line 268  sub handler { Line 260  sub handler {
     if ($env{'form.catalogmode'} eq 'interactive') {      if ($env{'form.catalogmode'} eq 'interactive') {
         $closebutton="<input type='button' name='close' value='".&mt('Close')."' ";          $closebutton="<input type='button' name='close' value='".&mt('Close')."' ";
         if ($env{'form.phase'} =~ /(results|run_search)/) {          if ($env{'form.phase'} =~ /(results|run_search)/) {
     $closebutton .="onclick='parent.close()'";              $closebutton .="onclick='parent.close()'";
         } else {          } else {
             $closebutton .="onclick='self.close()'";              $closebutton .="onclick='self.close()'";
         }          }
         $closebutton .=">\n";          $closebutton .=" />\n";
     } elsif ($env{'form.catalogmode'} eq 'import') {      } elsif ($env{'form.catalogmode'} eq 'import') {
         $closebutton="<input type='button' name='close' value='".&mt('Close')."' ";          $closebutton="<input type='button' name='close' value='".&mt('Close')."' ";
         if ($env{'form.phase'} =~ /(results|run_search)/) {          if ($env{'form.phase'} =~ /(results|run_search)/) {
     $closebutton .="onclick='parent.close()'";              $closebutton .="onclick='parent.close()'";
         } else {          } else {
             $closebutton .="onclick='self.close()'";              $closebutton .="onclick='self.close()'";
         }          }
         $closebutton .= ">";          $closebutton .= " />";
         my $txt_import = &mt('IMPORT');          my $txt_import = &mt('IMPORT');
         $importbutton=<<END;          $importbutton=<<END;
 <input type='button' name='import' value='$txt_import'  <input type='button' name='import' value='$txt_import'
 onclick='javascript:select_group()'>  onclick='javascript:select_group()' />
 END  END
     } else {      } else {
         $closebutton = '';          $closebutton = '';
Line 303  END Line 295  END
     if ($env{'form.phase'} eq 'adv_search' ||      if ($env{'form.phase'} eq 'adv_search' ||
         $env{'form.phase'} eq 'disp_adv') {          $env{'form.phase'} eq 'disp_adv') {
         $env{'form.searchmode'} = 'advanced';          $env{'form.searchmode'} = 'advanced';
     } elsif ($env{'form.phase'} eq 'course_search') {  
         $env{'form.searchmode'} = 'course_search';  
     }      }
     #      #
     if ($env{'form.searchmode'} eq 'advanced') {      if ($env{'form.searchmode'} eq 'advanced') {
Line 320  END Line 310  END
                   '&amp;mode='.$env{'form.mode'},                    '&amp;mode='.$env{'form.mode'},
                   text=>"Advanced $srchtype Search",                    text=>"Advanced $srchtype Search",
                   bug=>'Searching',});                    bug=>'Searching',});
     } elsif ($env{'form.searchmode'} eq 'course search') {      } 
         &Apache::lonhtmlcommon::add_breadcrumb  
             ({href=>'/adm/searchcat?'.&Apache::loncommon::inhibit_menu_check().  
                   '&amp;phase=disp_adv'.  
                   'catalogmode='.$env{'form.catalogmode'}.  
                   '&amp;launch='.$env{'form.launch'}.  
                   '&amp;mode='.$env{'form.mode'},  
                   text=>"Course Search",  
                   bug=>'Searching',});  
     }  
     ##      ##
     ## Switch on the phase      ## Switch on the phase
     ##      ##
Line 341  END Line 322  END
         &display_results($r,$importbutton,$closebutton,$diropendb,          &display_results($r,$importbutton,$closebutton,$diropendb,
                          $env{'form.area'});                           $env{'form.area'});
     } elsif ($env{'form.phase'} =~ /^(sort|run_search)$/) {      } elsif ($env{'form.phase'} =~ /^(sort|run_search)$/) {
         my ($query,$customquery,$customshow,$libraries,$pretty_string) =          my ($query,$customquery,$customshow,$libraries,$pretty_string,$domainsref) =
             &get_persistent_data($persistent_db_file,              &get_persistent_data($persistent_db_file,
                  ['query','customquery','customshow',                   ['query','customquery','customshow',
                   'libraries','pretty_string']);                    'libraries','pretty_string','domains']);
         if ($env{'form.phase'} eq 'sort') {          if ($env{'form.phase'} eq 'sort') {
             &print_sort_form($r,$pretty_string);              &print_sort_form($r,$pretty_string);
         } elsif ($env{'form.phase'} eq 'run_search') {          } elsif ($env{'form.phase'} eq 'run_search') {
             &run_search($r,$query,$customquery,$customshow,              &run_search($r,$query,$customquery,$customshow,
                         $libraries,$pretty_string,$env{'form.area'});                          $libraries,$pretty_string,$env{'form.area'},$domainsref);
         }          }
     } elsif ($env{'form.phase'} eq 'course_search') {  
         &course_search($r);  
     } elsif(($env{'form.phase'} eq 'basic_search') ||      } elsif(($env{'form.phase'} eq 'basic_search') ||
             ($env{'form.phase'} eq 'adv_search')) {              ($env{'form.phase'} eq 'adv_search')) {
         #          #
         # We are running a search, try to parse it          # We are running a search, try to parse it
         my ($query,$customquery,$customshow,$libraries) =           my ($query,$customquery,$customshow,$libraries,$domains) = 
             (undef,undef,undef,undef);              (undef,undef,undef,undef,undef);
         my $pretty_string;          my $pretty_string;
         if ($env{'form.phase'} eq 'basic_search') {          if ($env{'form.phase'} eq 'basic_search') {
             ($query,$pretty_string,$libraries) =               ($query,$pretty_string,$libraries,$domains) = 
                 &parse_basic_search($r,$closebutton,$hidden_fields);                  &parse_basic_search($r,$closebutton,$hidden_fields);
             return OK if (! defined($query));              return OK if (! defined($query));
             &make_persistent({ basicexp => $env{'form.basicexp'}},              &make_persistent({ basicexp => $env{'form.basicexp'}},
                              $persistent_db_file);                               $persistent_db_file);
         } else {                      # Advanced search          } else {                      # Advanced search
             ($query,$customquery,$customshow,$libraries,$pretty_string)               ($query,$customquery,$customshow,$libraries,$pretty_string,$domains) 
                 = &parse_advanced_search($r,$closebutton,$hidden_fields);                  = &parse_advanced_search($r,$closebutton,$hidden_fields);
             return OK if (! defined($query));              return OK if (! defined($query));
         }          }
Line 375  END Line 354  END
                            customquery => $customquery,                             customquery => $customquery,
                            customshow => $customshow,                             customshow => $customshow,
                            libraries => $libraries,                             libraries => $libraries,
                            pretty_string => $pretty_string },                             pretty_string => $pretty_string,
                              domains => $domains },
                          $persistent_db_file);                           $persistent_db_file);
         #          #
         # Set up table          # Set up table
Line 448  sub hidden_field { Line 428  sub hidden_field {
 }  }
   
 ######################################################################  ######################################################################
 ######################################################################  
 ##  
 ##   Course Search  
 ##  
 ######################################################################  
 ######################################################################  
 {   # Scope the course search to avoid global variables  
 #  
 # Variables For course search  
 my %alreadyseen;  
 my %hash;  
 my $totalfound;  
   
 sub make_symb {  
     my ($id)=@_;  
     my ($mapid,$resid)=split(/\./,$id);  
     my $map=$hash{'map_id_'.$mapid};  
     my $res=$hash{'src_'.$id};  
     my $symb=&Apache::lonnet::encode_symb($map,$resid,$res);  
     return $symb;  
 }  
   
 sub course_search {  
     my $r=shift;  
     my $pretty_search_string = '<b>'.$env{'form.courseexp'}.'</b>';  
     my $search_string = $env{'form.courseexp'};  
     my @New_Words;  
     undef(%alreadyseen);  
     if ($env{'form.crsrelated'}) {  
         ($search_string,@New_Words) = &related_version($env{'form.courseexp'});  
         if (@New_Words) {  
             $pretty_search_string .= ' '.&mt("with related words").": <b>@New_Words</b>.";  
         } else {  
             $pretty_search_string .= ' '.&mt('with no related words').".";  
         }  
     }  
     my $fulltext=$env{'form.crsfulltext'};  
     my $discuss=$env{'form.crsdiscuss'};  
     my @allwords=($search_string,@New_Words);  
     $totalfound=0;  
   
     &Apache::lonhtmlcommon::add_breadcrumb  
         ({href=>'/adm/searchcat?'.&Apache::loncommon::inhibit_menu_check().  
               '&amp;phase=disp_adv'.  
               'catalogmode='.$env{'form.catalogmode'}.  
               '&amp;launch='.$env{'form.launch'}.  
               '&amp;mode='.$env{'form.mode'},  
               text=>"Course Search",  
               bug=>'Searching',});  
     $r->print(&Apache::loncommon::start_page('Course Search'));  
     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Searching','Searching',  
                         $env{'form.catalogmode'} ne 'import'));  
   
     $r->print(  
       '<hr /><center><font size="+2" face="arial">'.  
       $pretty_search_string.'</font></center>'.  
       '<hr /><b>'.&mt('Course content').':</b><br />');  
     $r->rflush();  
 # ======================================================= Go through the course  
     my $c=$r->connection;  
     if (tie(%hash,'GDBM_File',$env{'request.course.fn'}.".db",  
             &GDBM_READER(),0640)) {  
         foreach (sort(keys(%hash))) {  
             if ($c->aborted()) { last; }  
             if (($_=~/^src\_(.+)$/)) {  
  if ($hash{'randomout_'.$1} & !$env{'request.role.adv'}) {  
     next;   
  }  
  my $symb=&make_symb($1);  
                 &checkonthis($r,$1,$hash{$_},0,&Apache::lonnet::gettitle($symb),  
      $fulltext,$symb,@allwords);  
             }  
         }  
         untie(%hash);  
     }  
     unless ($totalfound) {  
  $r->print('<p class="LC_info">'.&mt('No matches found in resources.').'</p>');  
     }  
   
 # Check discussions if requested  
     if ($discuss) {  
         my $totaldiscussions = 0;  
         $r->print('<br /><br /><b>'.&mt('Discussion postings').':</b><br />');   
         my $navmap = Apache::lonnavmaps::navmap->new();  
         if (defined($navmap)) {  
             my @allres=$navmap->retrieveResources();  
             my %discussiontime = &Apache::lonnet::dump('discussiontimes',  
                                    $env{'course.'.$env{'request.course.id'}.'.domain'},  
                                    $env{'course.'.$env{'request.course.id'}.'.num'});  
             foreach my $resource (@allres) {  
                 my $result = '';  
                 my $applies = 0;  
                 my $symb = $resource->symb();  
                 my $ressymb = $symb;  
                 if ($symb =~ m#(___adm/$LONCAPA::domain_re/$LONCAPA::username_re)/(\d+)/bulletinboard$#) {  
                     $ressymb = 'bulletin___'.$2.$1.'/'.$2.'/bulletinboard';  
                     unless ($ressymb =~ m#bulletin___\d+___adm/wrapper#) {  
                         $ressymb=~s#(bulletin___\d+___)#$1adm/wrapper/#;  
                     }  
                 }  
                 if (defined($discussiontime{$ressymb})) {   
                     my %contrib = &Apache::lonnet::restore($ressymb,$env{'request.course.id'},  
                          $env{'course.'.$env{'request.course.id'}.'.domain'},  
                          $env{'course.'.$env{'request.course.id'}.'.num'});  
                     if ($contrib{'version'}) {  
                         for (my $id=1;$id<=$contrib{'version'};$id++) {  
                             unless (($contrib{'hidden'}=~/\.$id\./) || ($contrib{'deleted'}=~/\.$id\./)) {   
                                 if ($contrib{$id.':subject'}) {  
                                     $result .= $contrib{$id.':subject'};  
                                 }  
                                 if ($contrib{$id.':message'}) {  
                                     $result .= $contrib{$id.':message'};  
                                 }  
                                 if ($contrib{$id,':attachmenturl'}) {  
                                     if ($contrib{$id,':attachmenturl'} =~ m-/([^/]+)$-) {  
                                         $result .= $1;  
                                     }  
                                 }  
                                 $applies = &checkwords($result,$applies,@allwords);  
                             }  
                         }  
                     }  
                 }  
 # Does this discussion apply?  
                 if ($applies) {  
                     my ($map,$ind,$url)=&Apache::lonnet::decode_symb($ressymb);  
                     my $disctype = &mt('resource');  
                     if ($url =~ m#/bulletinboard$#) {  
                         if ($url =~m#^adm/wrapper/adm/.*/bulletinboard$#) {  
                             $url =~s#^adm/wrapper##;  
                         }  
                         $disctype = &mt('discussion board');  
                     } else {  
                         $url = '/res/'.$url;  
                     }  
                     if ($url =~ /\?/) {  
                         $url .= '&amp;symb=';  
                     } else {  
                         $url .= '?symb=';  
                     }  
                     $url .= &escape($resource->symb());  
                     my $title = $resource->compTitle();  
                     $r->print('<br /><a href="'.$url.'" target="cat">'.  
                          ($title?$title:$url).'</a>&nbsp;&nbsp;-&nbsp;'.  
                          $disctype.'<br />');  
                     $totaldiscussions++;  
                 } else {  
                     $r->print(' .');  
                 }  
             }  
             unless ($totaldiscussions) {  
                 $r->print('<p class="LC_info">'.&mt('No matches found in postings.').'</p>');  
             }  
         } else {  
             $r->print('<div class="LC_error">'.&mt('An error occurred retrieving information about resources in the course.').'<br />'.&mt('It is recommended that you [_1]re-initialize the course[_2] and then try your search again.','<a href="/adm/roles">','</a>').'</div>');  
         }  
     }  
    
 # =================================================== Done going through course  
     $r->print(&Apache::loncommon::end_page());  
 }  
   
 # =============================== This pulls up a resource and its dependencies  =pod
   
 sub checkonthis {  
     my ($r,$id,$url,$level,$title,$fulltext,$symb,@allwords)=@_;  
     $alreadyseen{$id}=1;  
     if (&Apache::loncommon::connection_aborted($r)) { return; }  
     $r->rflush();  
       
     my $result=$title.' ';  
     if ($env{'request.role.adv'} || !$hash{'encrypted_'.$id}) {  
  $result.=&Apache::lonnet::metadata($url,'title').' '.  
     &Apache::lonnet::metadata($url,'subject').' '.  
     &Apache::lonnet::metadata($url,'abstract').' '.  
     &Apache::lonnet::metadata($url,'keywords');  
     }  
     my ($extension)=($url=~/\.(\w+)$/);  
     if (&Apache::loncommon::fileembstyle($extension) eq 'ssi' &&  
  ($url) && ($fulltext)) {  
  $result.=&Apache::lonnet::ssi_body($url.'?symb='.&escape($symb));  
     }  
     $result=~s/\s+/ /gs;  
     my $applies = 0;  
     $applies = &checkwords($result,$applies,@allwords);  
 # Does this resource apply?  
     if ($applies) {  
        $r->print('<br />');  
        for (my $i=0;$i<=$level*5;$i++) {  
            $r->print('&nbsp;');  
        }  
        my $href=$url;  
        if ($hash{'encrypted_'.$id} && !$env{'request.role.adv'}) {  
    $href=&Apache::lonenc::encrypted($href)  
        .'?symb='.&Apache::lonenc::encrypted($symb);  
        } else {  
    $href.='?symb='.&escape($symb);  
        }  
        $r->print('<a href="'.$href.'" target="cat">'.($title?$title:$url).  
  '</a><br />');  
        $totalfound++;  
     } elsif ($fulltext) {  
        $r->print(' .');  
     }  
     $r->rflush();  
 # Check also the dependencies of this one  
     my $dependencies=  
                 &Apache::lonnet::metadata($url,'dependencies');  
     foreach (split(/\,/,$dependencies)) {  
        if (($_=~/^\/res\//) && (!$alreadyseen{$id})) {   
           &checkonthis($r,$id,$_,$level+1,'',$fulltext,undef,@allwords);  
        }  
     }  
 }  
   
 sub checkwords {  
     my ($result,$applies,@allwords) = @_;  
     foreach (@allwords) {  
         if ($_=~/\w/) {  
             if ($result=~/$_/si) {  
                 $applies++;  
             }  
         }  
     }  
     return $applies;  
 }  
   
 sub untiehash {  
     if (tied(%hash)) {  
         untie(%hash);  
     }  
 }  
   
 } # End of course search scoping  
   
   
 ######################################################################  
 ######################################################################  
   
 =pod   =over 4
   
 =item &print_basic_search_form()   =item &print_basic_search_form() 
   
Line 705  sub print_basic_search_form { Line 449  sub print_basic_search_form {
     $env{'form.catalogmode'} ne 'import');      $env{'form.catalogmode'} ne 'import');
     my $scrout = &Apache::loncommon::start_page('Content Library').$bread_crumb;      my $scrout = &Apache::loncommon::start_page('Content Library').$bread_crumb;
 # Search form for resource space   # Search form for resource space 
     if (&Apache::lonnet::allowed('bre',$env{'request.role.domain'})) {      if (&Apache::lonnet::allowed('bre',$env{'request.role.domain'}) eq 'F') {
         $scrout .= &setup_basic_search($r,'res',$hidden_fields,$closebutton);          $scrout .= &setup_basic_search($r,'res',$hidden_fields,$closebutton);
         $scrout .= '<hr /><br />';          $scrout .= '<hr /><br />';
     }      }
 # Search form for accessible portfolio files  # Search form for accessible portfolio files
     $scrout.= &setup_basic_search($r,'portfolio',$hidden_fields,$closebutton);      $scrout.= &setup_basic_search($r,'portfolio',$hidden_fields,$closebutton);
     if ($env{'request.course.id'}) {  
  my %lt=&Apache::lonlocal::texthash('srch' => 'Search',  
                                            'header' => 'Course Search',  
  'note' => 'Enter terms or phrases, then press "Search" below',  
  'use' => 'use related words',  
  'full' =>'fulltext search (time consuming)',  
          'disc' => 'search discussion postings (resources and discussion boards)',  
    );  
         $scrout.=(<<ENDCOURSESEARCH);  
 <form name="loncapa_search" method="post" action="/adm/searchcat">  
 <center>  
 <hr />  
 <h1>$lt{'header'}</h1>      
 <input type="hidden" name="phase" value="course_search" />  
 $hidden_fields  
 <p>  
 $lt{'note'}.  
 </p>  
 <table>  
 <tr><td>  
 ENDCOURSESEARCH  
         $scrout.='&nbsp;'.  
             &Apache::lonhtmlcommon::textbox('courseexp',  
                                   $env{'form.courseexp'},40);  
         my $crscheckbox =   
             &Apache::lonhtmlcommon::checkbox('crsfulltext',  
                                    $env{'form.crsfulltext'});  
         my $relcheckbox =   
             &Apache::lonhtmlcommon::checkbox('crsrelated',  
    $env{'form.crsrelated'});  
         my $discheckbox =   
             &Apache::lonhtmlcommon::checkbox('crsdiscuss',  
                                    $env{'form.crsrelated'});  
         $scrout.=(<<ENDENDCOURSE);  
 </td></tr>  
 <tr><td><label>$relcheckbox $lt{'use'}</label></td><td></td></tr>  
 <tr><td><label>$crscheckbox $lt{'full'}</label></td><td></td></tr>  
 <tr><td><label>$discheckbox $lt{'disc'}</label></td><td></td></tr>  
 </table>  
 <p>  
 <input type="submit" name="coursesubmit" value='$lt{'srch'}' />  
 </p>  
 </center>  
 </form>  
 ENDENDCOURSE  
     }  
     $scrout .= &Apache::loncommon::end_page();      $scrout .= &Apache::loncommon::end_page();
     $r->print($scrout);      $r->print($scrout);
     return;      return;
Line 770  sub setup_basic_search { Line 468  sub setup_basic_search {
                               portfolio => 'Portfolio Search',                                portfolio => 'Portfolio Search',
     );      );
     my ($userelatedwords,$onlysearchdomain,$inclext,$adv_search_link,$scrout);      my ($userelatedwords,$onlysearchdomain,$inclext,$adv_search_link,$scrout);
     $userelatedwords = '<label>'.&mt('[_1] use related words',  
       &Apache::lonhtmlcommon::checkbox('related',$env{'form.related'},'related')).      $userelatedwords = '<label>'
                        '</label>';                        .&Apache::lonhtmlcommon::checkbox(
     $onlysearchdomain = '<label>'.&mt('[_1] only search domain [_2]',                             'related',
       &Apache::lonhtmlcommon::checkbox('domains',$env{'form.domains'},                             $env{'form.related'},
                                        $r->dir_config('lonDefDomain')),                             'related')
       $r->dir_config('lonDefDomain')).                        .' '
                         '</label>';                       .&mt('use related words')
                        .'</label>';
   
       $onlysearchdomain = '<label>'
                          .&Apache::lonhtmlcommon::checkbox(
                              'domains',
                              $env{'form.domains'},
                              $r->dir_config('lonDefDomain'))
                          .' '
                          .&mt('only search domain [_1]'
                                  ,'<b>'.$r->dir_config('lonDefDomain').'</b>')
                          .'</label>';
   
     $adv_search_link = '<a href="/adm/searchcat?'.      $adv_search_link = '<a href="/adm/searchcat?'.
                &Apache::loncommon::inhibit_menu_check().                 &Apache::loncommon::inhibit_menu_check().
        '&amp;phase=disp_adv'.         '&amp;phase=disp_adv'.
Line 856  sub print_advanced_search_form{ Line 566  sub print_advanced_search_form{
        'reset' => 'Reset',         'reset' => 'Reset',
        'help' => 'Help');         'help' => 'Help');
     my $advanced_buttons=<<"END";      my $advanced_buttons=<<"END";
   <p>
 <input type="submit" name="advancedsubmit" value='$lt{"srch"}' />  <input type="submit" name="advancedsubmit" value='$lt{"srch"}' />
 <input type="reset" name="reset" value='$lt{"reset"}' />  <input type="reset" name="reset" value='$lt{"reset"}' />
 $closebutton  $closebutton
   </p>
 END  END
     my $srchtype = 'Catalog';      my $srchtype = 'Catalog';
     my $jscript;      my $jscript;
Line 878  function additional_metadata() { Line 590  function additional_metadata() {
     }      }
     my $scrout= &Apache::loncommon::start_page("Advanced $srchtype Search",      my $scrout= &Apache::loncommon::start_page("Advanced $srchtype Search",
                                                $jscript);                                                 $jscript);
     $scrout .= <<"ENDHEADER";      $scrout .= $bread_crumb;
 $bread_crumb  
 <form method="post" action="/adm/searchcat" name="advsearch">      $scrout .= '<form method="post" action="/adm/searchcat" name="advsearch">'
 <p>                .$hidden_fields 
 $advanced_buttons                .'<input type="hidden" name="phase" value="adv_search" />';
 ENDHEADER  
     $scrout.=('&nbsp;'x2).&viewoptions().'</p>'.$hidden_fields.       $scrout .= '<fieldset>'."\n"
         '<input type="hidden" name="phase" value="adv_search" />';                .'<legend>'.&mt('Display Options').'</legend>'."\n"
                 .&viewoptions()
                 .'</fieldset>';
   
       $scrout .= $advanced_buttons;
   
       $scrout .= &Apache::lonhtmlcommon::start_pick_box();
   
     my %fields=&Apache::lonmeta::fieldnames();      my %fields=&Apache::lonmeta::fieldnames();
     #  
     $scrout .= '<h3>'.&mt("Standard $srchtype Metadata").'</h3>';      # Standard Metadata
     $scrout .= "<table>\n";      $scrout .= &Apache::lonhtmlcommon::row_headline()
     $scrout .= '<tr><td>&nbsp;</td><td colspan="2"><font size="-1">'.                .'<h3>'.&mt("Standard $srchtype Metadata").'</h3>'
         ('&nbsp;'x2).&searchhelp()."</font></td></tr>\n";                .&searchhelp()
                 .&Apache::lonhtmlcommon::row_closure();
     my %related_word_search =       my %related_word_search = 
         ('title'    => 1,          ('title'    => 1,
          'author'   => 0,           'author'   => 0,
Line 903  ENDHEADER Line 623  ENDHEADER
          'abstract' => 1,           'abstract' => 1,
          'standards'=> 1,           'standards'=> 1,
          'mime'     => 1,           'mime'     => 1,
  'subject'  => 1,           'subject'  => 1,
          );           );
     #      #
     foreach my $field ('title','author','subject','owner','authorspace',      foreach my $field ('title','author','subject','owner','authorspace',
        'modifyinguser','keywords','notes','abstract',                         'modifyinguser','keywords','notes','abstract',
        'standards','mime') {                         'standards','mime') {
  $scrout.='<tr><td align="right">'.&titlefield($fields{$field}).'</td><td>'.          $scrout .= &Apache::lonhtmlcommon::row_title(&titlefield($fields{$field}))
     &Apache::lonmeta::prettyinput($field,                    .&Apache::lonmeta::prettyinput($field,
                                           $env{'form.'.$field},                                            $env{'form.'.$field},
                                           $field,                                            $field,
                                           'advsearch',                                            'advsearch',
   $related_word_search{$field},                                            $related_word_search{$field},
                                           '</td><td align="left">',                                            '',
                                           $env{'form.'.$field.'_related'},                                            $env{'form.'.$field.'_related'},
                                           50);                                            50);
         if ($related_word_search{$field}) {          if ($related_word_search{$field}) {
             $scrout .= &mt('related words');              $scrout .= &mt('related words');
         } else {          } else {
             $scrout .= '</td><td>&nbsp;';              $scrout .= '';
         }          }
         $scrout .= '</td></tr>'.$/;          $scrout .= &Apache::lonhtmlcommon::row_closure();
     }      }
     foreach my $field ('lowestgradelevel','highestgradelevel') {      foreach my $field ('lowestgradelevel','highestgradelevel') {
  $scrout.='<tr>'.          $scrout .= &Apache::lonhtmlcommon::row_title(&titlefield($fields{$field}))
             '<td align="right">'.&titlefield($fields{$field}).'</td>'.                    .&Apache::lonmeta::prettyinput($field,
             '<td colspan="2">'.  
     &Apache::lonmeta::prettyinput($field,  
                                           $env{'form.'.$field},                                            $env{'form.'.$field},
                                           $field,                                            $field,
                                           'advsearch',                                            'advsearch',
   0).                                            0)
                                           '</td></tr>'.$/;                    .&Apache::lonhtmlcommon::row_closure();
     }      }
     $scrout.='<tr><td align="right">'.  
  &titlefield(&mt('MIME Type Category')).'</td><td colspan="2">'.       $scrout .= &Apache::lonhtmlcommon::row_title(&titlefield(&mt('MIME Type Category')))
     &Apache::loncommon::filecategoryselect('category',                .&Apache::loncommon::filecategoryselect('category',
    $env{'form.category'}).                     $env{'form.category'})
     '</td></tr>'.$/;                .&Apache::lonhtmlcommon::row_closure();
     $scrout.='<tr><td align="right" valign="top">'.  
  &titlefield(&mt('Domains')).'</td><td colspan="2">'.       $scrout .= &Apache::lonhtmlcommon::row_title(&titlefield(&mt('Domains')))
     &Apache::loncommon::domain_select('domains',                .&Apache::loncommon::domain_select('domains',
    $env{'form.domains'},1).                     $env{'form.domains'},1)
    '<br />';                .&Apache::lonhtmlcommon::row_closure();
      $scrout .= '</td></tr>'.$/;  
     #  
     # Misc metadata      # Misc metadata
     if ($env{'form.area'} ne 'portfolio') {      if ($env{'form.area'} ne 'portfolio') {
         $scrout.='<tr><td align="right" valign="top">'.          $scrout .= &Apache::lonhtmlcommon::row_title(&titlefield(&mt('Copyright/Distribution')))
          &titlefield(&mt('Copyright/Distribution')).                    .&Apache::lonmeta::selectbox('copyright',
                  '</td><td colspan="2">'.  
                  &Apache::lonmeta::selectbox('copyright',  
                                              $env{'form.copyright'},                                               $env{'form.copyright'},
                                 \&Apache::loncommon::copyrightdescription,                                  \&Apache::loncommon::copyrightdescription,
                                        ( undef,                                         ( undef,
                                         &Apache::loncommon::copyrightids)                                          &Apache::loncommon::copyrightids)
                                 ).'</td></tr>'.$/;                                  )
                     .&Apache::lonhtmlcommon::row_closure();
     }      }
     $scrout.='<tr><td align="right" valign="top">'.  
  &titlefield(&mt('Language')).'</td><td colspan="2">'.      $scrout .= &Apache::lonhtmlcommon::row_title(&titlefield(&mt('Language')))
         &Apache::lonmeta::selectbox('language',                .&Apache::lonmeta::selectbox('language',
                                     $env{'form.language'},                                      $env{'form.language'},
                                     \&Apache::loncommon::languagedescription,                                      \&Apache::loncommon::languagedescription,
                                     ('any',&Apache::loncommon::languageids)                                      ('any',&Apache::loncommon::languageids)
                                     ).'</td></tr>';                                      )
     $scrout .= "</table>\n";                .&Apache::lonhtmlcommon::row_closure();
   
           
       # Portfolio Metadata
     if ($env{'form.area'} eq 'portfolio') {      if ($env{'form.area'} eq 'portfolio') {
         # Added fields          # Added fields
         my $curnumadd = $env{'form.numaddedfields'};          my $curnumadd = $env{'form.numaddedfields'};
         if ($curnumadd eq '') {          if ($curnumadd eq '') {
             $curnumadd = 1;              $curnumadd = 1;
         }          }
         $scrout .= '<h3>'.&mt('Custom Metadata fields').'</h3>';          $scrout .= &Apache::lonhtmlcommon::row_headline()
         $scrout .= "<table>\n";                    .'<h3>'.&mt('Custom Metadata fields').'</h3>'
         $scrout .= '<tr><td>&nbsp;</td><td align="center">'.                    .&Apache::lonhtmlcommon::row_closure()
                    &mt('Field Name').'</td>'.'<td align="center">'.                    .&Apache::lonhtmlcommon::row_title('')
                    &mt('Field Value(s)').'</td></tr>';                    .&mt('Field Name').' | '.&mt('Field Value(s)')
                     .&Apache::lonhtmlcommon::row_closure();
   
         for (my $j=0; $j<$curnumadd; $j++) {          for (my $j=0; $j<$curnumadd; $j++) {
             my $num = $j+1;              my $num = $j+1;
             $scrout .= '<tr><td>'.&mt('Custom metadata [_1]: ',$num).              $scrout .= &Apache::lonhtmlcommon::row_title(&mt('Custom metadata [_1]',$num))
                        '</td><td align="center">'.                        .'<input type="text"'
                        '<input type="text" name="addedfield_'.$j.                        .' name="addedfield_'.$j.'" size="10"'
                        '" size="10" value="'.$env{'form.addedfield_'.$j}.                        .' value="'.$env{'form.addedfield_'.$j}.'" />'
                        '" /></td>'.                        .' '
                        '<td align="center"><input type="text" '.                        .'<input type="text" '
                        'name="addedvalues_'.$j.'" size="15" value="'.                        .'name="addedvalues_'.$j.'" size="15"'
                        $env{'form.addedvalues_'.$j}.'" /></td></tr>';                        .' value="'.$env{'form.addedvalues_'.$j}.'" />'
         }                        .&Apache::lonhtmlcommon::row_closure();
         $scrout .= '<tr><td align="left" colspan="3"><label>'.          }
                    '<input type="checkbox" name="newfield" '.          $scrout .= &Apache::lonhtmlcommon::row_title('')
                    'value="1" onclick="javascript:additional_metadata()" />'.                    .'<label>'
                    &mt('Another custom field/value pair?').'</label>'.                    .'<input type="checkbox" name="newfield"'
                    '<input type="hidden" name="numaddedfields" value="'.                    .' value="1" onclick="javascript:additional_metadata()" />'
                    $curnumadd.'" /></td></tr></table>';                    .&mt('Another custom field/value pair?').'</label>'
     } else {                    .'<input type="hidden" name="numaddedfields"'
                     .' value="'.$curnumadd.'" />'
                     .&Apache::lonhtmlcommon::row_closure();
   } else {
         #          #
         # Dynamic metadata          # Dynamic metadata
         $scrout .= '<h3>'.&mt('Problem Statistics').'</h3>';          $scrout .= &Apache::lonhtmlcommon::row_headline()
         $scrout .= "<table>\n";                    .'<h3>'.&mt('Problem Statistics').'</h3>'
         $scrout .= '<tr><td>&nbsp;</td><td align="center">'.                    .&Apache::lonhtmlcommon::row_closure();
                    &mt('Minimum').'</td>'.'<td align="center">'.          $scrout .= &Apache::lonhtmlcommon::row_title('')
                    &mt('Maximum').'</td></tr>'."\n";                    .&mt('Minimum').' | '.&mt('Maximum')
                     .&Apache::lonhtmlcommon::row_closure();
         foreach my $statistic           foreach my $statistic 
             ({ name=>'count',              ({ name=>'count',
                description=>'Network-wide number of accesses (hits)',},                 description=>'Network-wide number of accesses (hits)',},
Line 1019  ENDHEADER Line 740  ENDHEADER
                description=>'Degree of difficulty',},                 description=>'Degree of difficulty',},
              { name => 'disc',               { name => 'disc',
                description=>'Degree of discrimination'}) {                 description=>'Degree of discrimination'}) {
               $scrout .= '<tr><td align="right">'.                $scrout .= &Apache::lonhtmlcommon::row_title(&titlefield(&mt($statistic->{'description'})))
                          &titlefield(&mt($statistic->{'description'})).                          .'<input type="text" name="'.$statistic->{'name'}
                          '</td><td align="center">'.                          .'_min" value="" size="6" />'
                          '<input type="text" name="'.$statistic->{'name'}.                          .' '
                          '_min" value="" size="6" /></td><td align="center">'.                          .'<input type="text" name="'.$statistic->{'name'}
                          '<input type="text" name="'.$statistic->{'name'}.                          .'_max" value="" size="6" />'
                          '_max" value="" size="6" /></td></tr>'.$/;                          .&Apache::lonhtmlcommon::row_closure();
         }          }
         $scrout .= "</table>\n";  
         $scrout .= '<h3>'.&mt('Evaluation Data').'</h3>';          $scrout .= &Apache::lonhtmlcommon::row_headline()
         $scrout .= "<table>\n";                    .'<h3>'.&mt('Evaluation Data').'</h3>'
         $scrout .= '<tr><td>&nbsp;</td><td align="center">'.                    .&Apache::lonhtmlcommon::row_closure();
                    &mt('Minimum').'</td>'.'<td align="center">'.          $scrout .= &Apache::lonhtmlcommon::row_title('')
                    &mt('Maximum').'</td></tr>'."\n";                    .&mt('Minimum').' | '.&mt('Maximum')
                     .&Apache::lonhtmlcommon::row_closure();
         foreach my $evaluation          foreach my $evaluation
             ( { name => 'clear',              ( { name => 'clear',
                 description => 'Material presented in clear way'},                  description => 'Material presented in clear way'},
Line 1044  ENDHEADER Line 766  ENDHEADER
                 description => 'Material appears to be correct'},                  description => 'Material appears to be correct'},
               { name => 'technical',                { name => 'technical',
                 description => 'Resource is technically correct'}){                  description => 'Resource is technically correct'}){
             $scrout .= '<tr><td align="right">'.              $scrout .= &Apache::lonhtmlcommon::row_title(&titlefield(&mt($evaluation->{'description'})))
                        &titlefield(&mt($evaluation->{'description'})).                        .'<input type="text" name="'
                        '</td><td align="center">'.                        .$evaluation->{'name'}.'_min" value="" size="6" />'
                        '<input type="text" name="'.                        .' '
                        $evaluation->{'name'}.'_min" value="" size="6" />'.                        .'<input type="text" name="'
                        '</td><td align="center"><input type="text" name="'.                        .$evaluation->{'name'}.'_max" value="" size="6" />'
                        $evaluation->{'name'}.'_max" value="" size="6" />'.                        .&Apache::lonhtmlcommon::row_closure();
                        '</td></tr>'.$/;  
         }          }
         $scrout .= "</table>\n";  
     }      }
     #      #
     # Creation/Modification date limits      # Creation/Modification date limits
     $scrout .= '<h3>'.&mt('Creation and Modification dates').'</h3>';      $scrout .= &Apache::lonhtmlcommon::row_headline()
     $scrout .= "\n<table>\n";                .'<h3>'.&mt('Creation and Modification dates').'</h3>'
     $scrout .= "<tr><td>&nbsp;</td><td>".&mt('Month[_1]Day[_2]Year','&nbsp;'x14,'&nbsp;'x6)."</td></tr>\n";                .&Apache::lonhtmlcommon::row_closure();
       $scrout .= &Apache::lonhtmlcommon::row_title('')
                 .&mt('Month[_1]Day[_2]Year','&nbsp;'x14,'&nbsp;'x6)
                 .&Apache::lonhtmlcommon::row_closure();
   
     my $cafter =       my $cafter = 
         &Apache::lonhtmlcommon::date_setter('advsearch',         # formname          &Apache::lonhtmlcommon::date_setter('advsearch',         # formname
                                             'creationdate1', # fieldname                                              'creationdate1', # fieldname
Line 1078  ENDHEADER Line 802  ENDHEADER
                                             '',          # state                                              '',          # state
                                             1,           # no_hh_mm_ss                                              1,           # no_hh_mm_ss
                                             );                                              );
     $scrout .= '<tr><td align="right">'.&mt('Created between').'</td>'      $scrout .= &Apache::lonhtmlcommon::row_title(&mt('Created between'))
               .'<td>'.$cafter.'</td></tr>'                .$cafter
               .'<tr><td align="right">'.&mt('and').'</td>'                .&Apache::lonhtmlcommon::row_closure(1)
               .'<td>'.$cbefore.'</td></tr>';                .&Apache::lonhtmlcommon::row_title(&mt('and'))
                 .$cbefore
                 .&Apache::lonhtmlcommon::row_closure();
   
     my $lafter =       my $lafter = 
         &Apache::lonhtmlcommon::date_setter('advsearch',          &Apache::lonhtmlcommon::date_setter('advsearch',
                                             'revisiondate1',                                               'revisiondate1', 
Line 1100  ENDHEADER Line 827  ENDHEADER
                                             '',          # state                                              '',          # state
                                             1,           # no_hh_mm_ss                                              1,           # no_hh_mm_ss
                                             );                                              );
     $scrout .= '<tr><td align="right">'.&mt('Last modified between').'</td>'      $scrout .= &Apache::lonhtmlcommon::row_title(&mt('Last modified between'))
               .'<td>'.$lafter.'</td></tr>'                .$lafter
               .'<tr><td align="right">'.&mt('and').'</td>'                .&Apache::lonhtmlcommon::row_closure(1)
               .'<td>'.$lbefore.'</td></tr>';                .&Apache::lonhtmlcommon::row_title(&mt('and'))
     $scrout.="</table>\n";                .$lbefore
     $scrout.=<<ENDDOCUMENT;                .&Apache::lonhtmlcommon::row_closure(1); # Last row of total pick_box
 $advanced_buttons  
 </form>      $scrout .= &Apache::lonhtmlcommon::end_pick_box();
 ENDDOCUMENT  
       $scrout .= $advanced_buttons
                 .'</form>';
   
     $scrout .= &Apache::loncommon::end_page();      $scrout .= &Apache::loncommon::end_page();
     $r->print($scrout);      $r->print($scrout);
     return;      return;
Line 1286  Outputs: array of values.  Returns undef Line 1016  Outputs: array of values.  Returns undef
   
 This function is the reverse of &make_persistent();  This function is the reverse of &make_persistent();
 Retrieve persistent data from %persistent_db.  Retrieved items will have their  Retrieve persistent data from %persistent_db.  Retrieved items will have their
 values unescaped.  If the item contains commas (before unescaping), the  values unescaped.  If the item is 'domains; then the returned
 returned value will be an array pointer.   value will be a hash pointer.  Otherwise, if the item contains
   commas (before unescaping), the returned value will be an array pointer.
   
 =cut  =cut
   
Line 1305  sub get_persistent_data { Line 1036  sub get_persistent_data {
             push @Values, undef;              push @Values, undef;
             next;              next;
         }          }
         my @values = map {           if ($name eq 'domains') {
             &unescape($_);              my %valueshash;
         } split(',',$persistent_db{$name});              my @items= map { &unescape($_); } split(',',$persistent_db{$name});
         if (@values <= 1) {              foreach my $item (@items) {
             push @Values,$values[0];                  if ($item =~ /=/) {
                       my ($key,$val) = map { &unescape($_); } split(/=/,$item);
                       $valueshash{$key} = $val;
                   }
               }
               push(@Values,\%valueshash);
         } else {          } else {
             push @Values,\@values;              my @values = map { 
                   &unescape($_);
               } split(',',$persistent_db{$name});
               if (@values <= 1) {
                   push @Values,$values[0];
               } else {
                   push @Values,\@values;
               }
         }          }
     }      }
     untie (%persistent_db);      untie (%persistent_db);
Line 1329  Inputs: Hash of values to save, filename Line 1072  Inputs: Hash of values to save, filename
   
 Store variables away to the %persistent_db.  Store variables away to the %persistent_db.
 Values will be escaped.  Values that are array pointers will have their  Values will be escaped.  Values that are array pointers will have their
 elements escaped and concatenated in a comma separated string.    elements escaped and concatenated in a comma separated string. Values 
   that are hash pointers will have their keys and values escaped and 
   concatenated in a comma separated string.
   
 =cut  =cut
   
Line 1341  sub make_persistent { Line 1086  sub make_persistent {
     return undef if (! tie(%persistent_db,'GDBM_File',      return undef if (! tie(%persistent_db,'GDBM_File',
                            $filename,&GDBM_WRCREAT(),0640));                             $filename,&GDBM_WRCREAT(),0640));
     foreach my $name (keys(%save)) {      foreach my $name (keys(%save)) {
         my @values = (ref($save{$name}) ? @{$save{$name}} : ($save{$name}));          my @values=();
         # We handle array references, but not recursively.          if (ref($save{$name}) eq 'ARRAY') {
               @values = @{$save{$name}};
           } elsif (ref($save{$name}) eq 'HASH') {
               foreach my $key (%{$save{$name}}) {
                   push(@values,&escape($key).'='.&escape($save{$name}{$key}));
               }
           } else {
               @values = $save{$name};
           }
           # We handle array and hash references, but not recursively.
         my $store = join(',', map { &escape($_); } @values );          my $store = join(',', map { &escape($_); } @values );
         $persistent_db{$name} = $store;          $persistent_db{$name} = $store;
     }      }
Line 1659  sub parse_advanced_search { Line 1413  sub parse_advanced_search {
     ##      ##
     ## Deal with restrictions to given domains      ## Deal with restrictions to given domains
     ##       ## 
     my ($libraries_to_query,$pretty_domains_string) = &parse_domain_restrictions();      my ($libraries_to_query,$pretty_domains_string,$domains_to_query) = 
           &parse_domain_restrictions();
     if ($pretty_domains_string) {      if ($pretty_domains_string) {
        $pretty_search_string .= $pretty_domains_string."<br />\n";         $pretty_search_string .= $pretty_domains_string."<br />\n";
     }      }
Line 1675  sub parse_advanced_search { Line 1430  sub parse_advanced_search {
     }      }
     #&Apache::lonnet::logthis('advanced query = '.$/.$query);      #&Apache::lonnet::logthis('advanced query = '.$/.$query);
     return ($query,$customquery,$customshow,$libraries_to_query,      return ($query,$customquery,$customshow,$libraries_to_query,
             $pretty_search_string);              $pretty_search_string,$domains_to_query);
 }  }
   
 sub parse_domain_restrictions {  sub parse_domain_restrictions {
     my $libraries_to_query = undef;      my $libraries_to_query = undef;
       my $domains_to_query = undef;
     # $env{'form.domains'} can be either a scalar or an array reference.      # $env{'form.domains'} can be either a scalar or an array reference.
     # We need an array.      # We need an array.
     if (! exists($env{'form.domains'}) || $env{'form.domains'} eq '') {      if (! exists($env{'form.domains'}) || $env{'form.domains'} eq '') {
Line 1703  sub parse_domain_restrictions { Line 1459  sub parse_domain_restrictions {
         foreach (sort @allowed_domains) {          foreach (sort @allowed_domains) {
             $pretty_domains_string .= "<b>".$_."</b> ";              $pretty_domains_string .= "<b>".$_."</b> ";
         }          }
  my %servers = &Apache::lonnet::get_servers(\@allowed_domains,   my %library_servers = &Apache::lonnet::get_unique_servers(\@allowed_domains,
    'library');                    'library');
           my (%older_library_servers,%okdoms,%domains_for_id);
           map { $okdoms{$_} = 1; } @allowed_domains;
           foreach my $key (keys(%library_servers)) {
               if (&Apache::lonnet::get_server_loncaparev('',$key) =~ /^\'?(\d+)\.(\d+)/) {
                   my $major = $1;
                   my $minor = $2;
                   if (($major < 2) || (($major == 2) && ($minor < 11))) {
                       map { $older_library_servers{$_} = 1; }
                           &Apache::lonnet::machine_ids($library_servers{$key});
                   } else {
                       my %possdoms;
                       map { $possdoms{$_}=1 if ($okdoms{$_}); }
                           &Apache::lonnet::machine_domains($library_servers{$key});
                       $domains_for_id{$key} = join(',',sort(keys(%possdoms)));
                   }
               }
           }
           my %servers = (%library_servers,%older_library_servers);
  $libraries_to_query = [keys(%servers)];   $libraries_to_query = [keys(%servers)];
           $domains_to_query = \%domains_for_id;
     }      }
     return ($libraries_to_query,      return ($libraries_to_query,
             $pretty_domains_string);              $pretty_domains_string,
               $domains_to_query);
 }  }
   
 ######################################################################  ######################################################################
Line 1737  sub parse_basic_search { Line 1513  sub parse_basic_search {
  $env{"form.$_"}=&unescape($env{"form.$_"});   $env{"form.$_"}=&unescape($env{"form.$_"});
  $env{"form.$_"}=~s/[^\w\/\s\(\)\=\-\"\']//g;   $env{"form.$_"}=~s/[^\w\/\s\(\)\=\-\"\']//g;
     }      }
     my ($libraries_to_query,$pretty_domains_string) = &parse_domain_restrictions();      my ($libraries_to_query,$pretty_domains_string,$domains_to_query) = 
           &parse_domain_restrictions();
     #      #
     # Check to see if enough of a query is filled in      # Check to see if enough of a query is filled in
     my $search_string = $env{'form.basicexp'};      my $search_string = $env{'form.basicexp'};
Line 1783  sub parse_basic_search { Line 1560  sub parse_basic_search {
     $pretty_search_string =~ s:^<br /> and ::;      $pretty_search_string =~ s:^<br /> and ::;
     &Apache::lonnet::logthis('simple search final query = '.$/.$final_query);      &Apache::lonnet::logthis('simple search final query = '.$/.$final_query);
     return ($final_query,$pretty_search_string,      return ($final_query,$pretty_search_string,
             $libraries_to_query);              $libraries_to_query,$domains_to_query);
 }  }
   
   
Line 2055  sub build_date_queries { Line 1832  sub build_date_queries {
     if ((defined($cafter)  && ! defined($cbefore)) ||      if ((defined($cafter)  && ! defined($cbefore)) ||
         (defined($cbefore) && ! defined($cafter))) {          (defined($cbefore) && ! defined($cafter))) {
         # This is bad, so let them know          # This is bad, so let them know
         $error = &mt('Incorrect entry for the creation date.  '.          $error = &mt('Incorrect entry for the creation date. '.
                     'You must specify both the beginning and ending dates.');                      'You must specify both the beginning and ending dates.');
     }      }
     if (! defined($error) &&       if (! defined($error) && 
         ((defined($mafter)  && ! defined($mbefore)) ||          ((defined($mafter)  && ! defined($mbefore)) ||
         (defined($mbefore) && ! defined($mafter)))) {          (defined($mbefore) && ! defined($mafter)))) {
         # This is also bad, so let them know          # This is also bad, so let them know
         $error = &mt('Incorrect entry for the last revision date.  '.          $error = &mt('Incorrect entry for the last revision date. '.
                      'You must specify both the beginning and ending dates.');                       'You must specify both the beginning and ending dates.');
     }      }
     if (! defined($error)) {      if (! defined($error)) {
Line 2175  sub ensure_db_and_table { Line 1952  sub ensure_db_and_table {
     ## Sanity check the table id.      ## Sanity check the table id.
     ##      ##
     if (! defined($table) || $table eq '' || $table =~ /\D/ ) {      if (! defined($table) || $table eq '' || $table =~ /\D/ ) {
         $r->print(&Apache::loncommon::start_page(&mt('Error'))          $r->print(&Apache::loncommon::start_page('Error')
 . '<p>table: |'.$table.'|</p>' # SB  
                  .'<p class="LC_error">'                   .'<p class="LC_error">'
                  .&mt('Unable to retrieve search results. '                   .&mt('Unable to retrieve search results. '
                      .'Unable to determine the table results were saved in.')                       .'Unable to determine the table results were saved in.')
                    .'</p>'
                    . '<p>'.&mt('Internal info:').'</p>'
                    .'<pre>'.$table.'</pre>'
                  .&Apache::loncommon::end_page()                   .&Apache::loncommon::end_page()
         );          );
         return undef;          return undef;
Line 2189  sub ensure_db_and_table { Line 1968  sub ensure_db_and_table {
     ##      ##
     my $connection_result = &Apache::lonmysql::connect_to_db();      my $connection_result = &Apache::lonmysql::connect_to_db();
     if (!defined($connection_result)) {      if (!defined($connection_result)) {
         $r->print("Unable to connect to the MySQL database where your results".          $r->print(
                   " are saved.".              '<p class="LC_error">'
   &Apache::loncommon::end_page());             .&mt('Unable to connect to the MySQL database where your results are saved.')
              .'</p>'
              .&Apache::loncommon::end_page()
           );
         &Apache::lonnet::logthis("lonsearchcat: unable to get lonmysql to".          &Apache::lonnet::logthis("lonsearchcat: unable to get lonmysql to".
                                  " connect to database.");                                   " connect to database.");
         &Apache::lonnet::logthis(&Apache::lonmysql::get_error());          &Apache::lonnet::logthis(&Apache::lonmysql::get_error());
Line 2199  sub ensure_db_and_table { Line 1981  sub ensure_db_and_table {
     }      }
     my $table_check = &Apache::lonmysql::check_table($table);      my $table_check = &Apache::lonmysql::check_table($table);
     if (! defined($table_check)) {      if (! defined($table_check)) {
         $r->print("A MySQL error has occurred.</form>".          $r->print(
   &Apache::loncommon::end_page());              '<p class="LC_error">'
              .&mt('A MySQL error has occurred.')
              .'</p></form>'
              .&Apache::loncommon::end_page());
         &Apache::lonnet::logthis("lonmysql was unable to determine the status".          &Apache::lonnet::logthis("lonmysql was unable to determine the status".
                                  " of table ".$table);                                   " of table ".$table);
         return undef;          return undef;
     } elsif (! $table_check) {      } elsif (! $table_check) {
         $r->print("The table of results could not be found.");          $r->print(
               '<p class="LC_error">'
              .&mt('The table of results could not be found.')
              .'</p>'
           );
         &Apache::lonnet::logthis("The user requested a table, ".$table.          &Apache::lonnet::logthis("The user requested a table, ".$table.
                                  ", that could not be found.");                                   ", that could not be found.");
         return undef;          return undef;
Line 2266  sub print_sort_form { Line 2055  sub print_sort_form {
 // <![CDATA[  // <![CDATA[
     function change_sort() {      function change_sort() {
         var newloc = "/adm/searchcat?phase=results";          var newloc = "/adm/searchcat?phase=results";
         newloc += "&amp;persistent_db_id=$env{'form.persistent_db_id'}";          newloc += "&persistent_db_id=$env{'form.persistent_db_id'}";
         newloc += "&amp;sortby=";          newloc += "&sortby=";
         newloc += document.forms.statusform.elements.sortby.value;          newloc += document.forms.statusform.elements.sortby.value;
         parent.resultsframe.location= newloc;          parent.resultsframe.location= newloc;
     }      }
Line 2301  END Line 2090  END
 #    $result.="</select>\n";  #    $result.="</select>\n";
     my $revise = &revise_button();      my $revise = &revise_button();
     $result.='<p>'      $result.='<p>'
             .&mt('There are [_1] matches to your query.',$total_results)              .&mt('Total of [quant,_1,match,matches] to your query.',$total_results)
             .' '.$revise.'</p>'              .' '.$revise.'</p>'
             .'<p>'.&mt('Search: ').$pretty_query_string              .'<p>'.&mt('Search: ').$pretty_query_string
             .'</p></form>';              .'</p></form>';
Line 2521  results into MySQL. Line 2310  results into MySQL.
 ######################################################################  ######################################################################
 sub run_search {  sub run_search {
     my ($r,$query,$customquery,$customshow,$serverlist,      my ($r,$query,$customquery,$customshow,$serverlist,
         $pretty_string,$area) = @_;          $pretty_string,$area,$domainsref) = @_;
     my $tabletype = 'metadata';      my $tabletype = 'metadata';
     if ($area eq 'portfolio') {      if ($area eq 'portfolio') {
         $tabletype = 'portfolio_search';          $tabletype = 'portfolio_search';
Line 2553  END Line 2342  END
     $r->rflush();      $r->rflush();
     #      #
     # Determine the servers we need to contact.      # Determine the servers we need to contact.
     my @Servers_to_contact;      my (@Servers_to_contact,%domains_by_server);
     if (defined($serverlist)) {      if (defined($serverlist)) {
         if (ref($serverlist) eq 'ARRAY') {          if (ref($serverlist) eq 'ARRAY') {
             @Servers_to_contact = @$serverlist;              @Servers_to_contact = @$serverlist;
         } else {          } else {
             @Servers_to_contact = ($serverlist);              @Servers_to_contact = ($serverlist);
         }          }
           if (ref($domainsref) eq 'HASH') {
               foreach my $server (@Servers_to_contact) {
                   $domains_by_server{$server} = $domainsref->{$server};
               }
           }
     } else {      } else {
  my %all_library_servers = &Apache::lonnet::all_library();   my %library_servers = &Apache::lonnet::unique_library();
           my (%all_library_servers, %older_library_servers);
           foreach my $key (keys(%library_servers)) {
               if (&Apache::lonnet::get_server_loncaparev('',$key) =~ /^\'?(\d+)\.(\d+)/) {
                   my $major = $1;
                   my $minor = $2;
                   if (($major < 2) || (($major == 2) && ($minor < 11))) {
                       map { $older_library_servers{$_} = 1; }
                           &Apache::lonnet::machine_ids($library_servers{$key});
                   }
               }
           }
           %all_library_servers = (%library_servers,%older_library_servers);
         @Servers_to_contact = sort(keys(%all_library_servers));          @Servers_to_contact = sort(keys(%all_library_servers));
           foreach my $server (@Servers_to_contact) {
               my %possdoms;
               map { $possdoms{$_}=1;  } &Apache::lonnet::machine_domains($all_library_servers{$server});
               $domains_by_server{$server} =
                   join(',',sort(&Apache::lonnet::machine_domains($all_library_servers{$server})));
           }
     }      }
     my %Server_status;      my %Server_status;
     #      #
Line 2632  END Line 2444  END
             my $server = shift(@Servers_to_contact);              my $server = shift(@Servers_to_contact);
             &update_status($r,&mt('contacting [_1]',$server));              &update_status($r,&mt('contacting [_1]',$server));
             my $reply=&Apache::lonnet::metadata_query($query,$customquery,              my $reply=&Apache::lonnet::metadata_query($query,$customquery,
                                                       $customshow,[$server]);                                                        $customshow,[$server],\%domains_by_server);
             ($server) = keys(%$reply);              ($server) = keys(%$reply);
             $Server_status{$server} = $reply->{$server};              $Server_status{$server} = $reply->{$server};
         } else {          } else {
Line 2658  END Line 2470  END
                 next;                  next;
             }              }
             $status=~s|/||g;              $status=~s|/||g;
            my $datafile=$r->dir_config('lonDaemons').'/tmp/'.$status;  
   
   
              my $datafile=LONCAPA::tempdir().$status;
             if (-e $datafile && ! -e "$datafile.end") {              if (-e $datafile && ! -e "$datafile.end") {
                 &update_status($r,&mt('Receiving results from [_1]',$server));                  &update_status($r,&mt('Receiving results from [_1]',$server));
                 next;                  next;
Line 2940  sub display_results { Line 2755  sub display_results {
                   .&mt('Sort by:').' '                    .&mt('Sort by:').' '
                   .&Apache::loncommon::select_form($env{'form.sortfield'},                    .&Apache::loncommon::select_form($env{'form.sortfield'},
                                                       'sortfield',                                                        'sortfield',
                                                       %sort_fields)                                                        \%sort_fields)
                   .' '                    .' '
                   .&Apache::loncommon::select_form($env{'form.sortorder'},                    .&Apache::loncommon::select_form($env{'form.sortorder'},
                                                       'sortorder',                                                        'sortorder',
                                                       (asc =>&mt('Ascending'),                                                        {asc =>&mt('Ascending'),
                                                        desc=>&mt('Descending')                                                         desc=>&mt('Descending')
                                                        ))                                                         })
                   .'</span>';                    .'</span>';
     ##      ##
     ## Display links for 'prev' and 'next' pages (if necessary) and Display Options      ## Display links for 'prev' and 'next' pages (if necessary) and Display Options
Line 3327  SCRIPT Line 3142  SCRIPT
     }      }
     function select_group() {      function select_group() {
  parent.window.location=   parent.window.location=
     "/adm/groupsort?mode=$env{'form.mode'}&amp;catalogmode=import$inhibit_menu&amp;acts="+      "/adm/groupsort?mode=$env{'form.mode'}&catalogmode=import$inhibit_menu&acts="+
     parent.statusframe.document.forms.statusform.elements.acts.value;      parent.statusframe.document.forms.statusform.elements.acts.value;
     }      }
 // ]]>  // ]]>
Line 3335  SCRIPT Line 3150  SCRIPT
 SCRIPT  SCRIPT
   
     my $start_page  = &Apache::loncommon::start_page(undef,$js,      my $start_page  = &Apache::loncommon::start_page(undef,$js,
      {'only_body' =>1});       {'only_body' =>1,
                                                         'add_wishlist' =>1,
                                                         'add_modal' =>1});
     my $result=<<END;      my $result=<<END;
 $start_page  $start_page
 <form name="results" method="post" action="/adm/searchcat">  <form name="results" method="post" action="/adm/searchcat">
Line 3427  sub evalfields { Line 3244  sub evalfields {
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
   
   sub display_tools {
       my ($title, $jumpurl) = @_;
       my $result;
       # Metadata
       $result.=
           &Apache::loncommon::modal_link(
               $jumpurl.'.meta?inhibitmenu=yes',
               '<img class="LC_icon" src="/res/adm/pages/catalog.png" alt="Info" />',
               500,500,'_blank',undef,&mt('Metadata'));
       # Stored Links
       $result.=
           ' <a href="javascript:;"'.
           ' onclick="set_wishlistlink('."'$title','$jumpurl'".')" '.
           'title="'.&mt('Save a link for this resource in your personal Stored Links repository').'">'.
           '<img class="LC_icon" src="/res/adm/pages/wishlist.png" '.
           'alt="Stored Links" style="width:22px;"/></a>';
       return $result;
   }
   
   ######################################################################
   ######################################################################
   
 =pod   =pod 
   
 =item Metadata Viewing Functions  =item Metadata Viewing Functions
Line 3451  sub detailed_citation_view { Line 3290  sub detailed_citation_view {
     my $result;      my $result;
     my $jumpurl=$values{'url'};      my $jumpurl=$values{'url'};
     $jumpurl=~s|^/ext/|http://|;      $jumpurl=~s|^/ext/|http://|;
     $result .= '<b>'.$prefix.      $result .=
           '<b>'.$prefix.
         '<img src="'.&Apache::loncommon::icon($values{'url'}).'" alt="" />'.'&nbsp;'.          '<img src="'.&Apache::loncommon::icon($values{'url'}).'" alt="" />'.'&nbsp;'.
         '<a href="'.$jumpurl.'?inhibitmenu=yes" '.          '<a href="'.$jumpurl.'?inhibitmenu=yes" '.
         'target="preview">'.$values{'title'}."</a></b>\n";          'target="preview">'.$values{'title'}."</a></b>\n".
     $result .= "<p>\n";          &display_tools($values{'title'}, $jumpurl).
     $result .= '<b>'.$values{'author'}.'</b>,'.          "<p>\n".
           '<b>'.$values{'author'}.'</b>,'.
         ' <i>'.$values{'owner'}.'</i><br />';          ' <i>'.$values{'owner'}.'</i><br />';
     foreach my $field       foreach my $field 
         (          (
Line 3521  sub detailed_citation_view { Line 3362  sub detailed_citation_view {
             $result .= '<b>'.&mt($field->{'translate'}).'</b>';              $result .= '<b>'.&mt($field->{'translate'}).'</b>';
             foreach my $item (split(',',$values{$field->{'name'}})){              foreach my $item (split(',',$values{$field->{'name'}})){
                 $item = &Apache::lonnet::clutter($item);                  $item = &Apache::lonnet::clutter($item);
                 $result .= &display_url($item,[2,0,1]);                  $result .= '<br />'.&display_url($item,1).'<br />';
             }              }
         } elsif (exists($field->{'format'}) && $field->{'format'} ne ''){          } elsif (exists($field->{'format'}) && $field->{'format'} ne ''){
             $result.= &mt($field->{'translate'},              $result.= &mt($field->{'translate'},
Line 3529  sub detailed_citation_view { Line 3370  sub detailed_citation_view {
                                   $values{$field->{'name'}}))."<br />\n";                                    $values{$field->{'name'}}))."<br />\n";
         } else {          } else {
             if ($field->{'special'} eq 'url link') {              if ($field->{'special'} eq 'url link') {
                 $result .= &display_url($jumpurl,[3,0,1]);                  $result .= '<br />'.&display_url($jumpurl,1).'<br />';
             } else {              } else {
                 $result.= &mt($field->{'translate'},                  $result.= &mt($field->{'translate'},
                               $values{$field->{'name'}});                                $values{$field->{'name'}});
Line 3583  sub summary_view { Line 3424  sub summary_view {
     }      }
     my $jumpurl=$values{'url'};      my $jumpurl=$values{'url'};
     $jumpurl=~s|^/ext/|http://|;      $jumpurl=~s|^/ext/|http://|;
     my $link = &display_url($jumpurl,[2,0,1]);      my $link = '<br />'.&display_url($jumpurl,1).'<br />';
       $result .=
     $result.=<<END;          '<a href="'.$jumpurl.'?inhibitmenu=yes"'.
 <a href="$jumpurl?inhibitmenu=yes"           ' target="preview">'.$values{'title'}.'</a>'.
    target="preview">$values{'title'}</a><br />          &display_tools($values{'title'}, $jumpurl).<<END;
   <br />
 $link<br />  $link<br />
 $values{'author'}, $values{'owner'} -- $values{'lastrevisiondate'}<br />  $values{'author'}, $values{'owner'} -- $values{'lastrevisiondate'}<br />
 $values{'copyrighttag'}<br />  $values{'copyrighttag'}<br />
Line 3619  sub compact_view { Line 3461  sub compact_view {
     my $jumpurl=$values{'url'};      my $jumpurl=$values{'url'};
     $jumpurl=~s|^/ext/|http://|;      $jumpurl=~s|^/ext/|http://|;
   
     my $link = &display_url($jumpurl,[1,1,1]);      my $link = &display_url($jumpurl,1);
           
     my $result =       my $result = 
         $prefix.'<img src="'.&Apache::loncommon::icon($values{'url'}).'" alt="" />';          $prefix.'<img src="'.&Apache::loncommon::icon($values{'url'}).'" alt="" />';
Line 3633  sub compact_view { Line 3475  sub compact_view {
     $result.=' <span class="LC_nobreak">'.      $result.=' <span class="LC_nobreak">'.
  '<a href="'.$jumpurl.'?inhibitmenu=yes" target="preview">'.   '<a href="'.$jumpurl.'?inhibitmenu=yes" target="preview">'.
         &HTML::Entities::encode($values{'title'},'<>&"').'</a></span> '.          &HTML::Entities::encode($values{'title'},'<>&"').'</a></span> '.
           &display_tools($values{'title'}, $jumpurl).
  $link.' <b>'.$values{'author'}.'</b> ('.$values{'domain'}.')';   $link.' <b>'.$values{'author'}.'</b> ('.$values{'domain'}.')';
     return $result;      return $result;
 }  }
   
 sub display_url {  sub display_url {
     my ($url,$crumb_args) = @_;      my ($url,$skiplast) = @_;
     my $link;      my $link;
     if ($url=~m|^/ext/|) {      if ($url=~m|^/ext/|) {
  $url=~s|^/ext/|http://|;   $url=~s|^/ext/|http://|;
Line 3646  sub display_url { Line 3489  sub display_url {
     } elsif ($url=~m{^(http://|/uploaded/)}) {      } elsif ($url=~m{^(http://|/uploaded/)}) {
  $link='<span class="LC_filename">'.$url.'</span>';   $link='<span class="LC_filename">'.$url.'</span>';
     } else {      } else {
         $link=&Apache::lonhtmlcommon::crumbs($url,          $link=&Apache::lonhtmlcommon::crumbs(
   'preview',                    $url,
   '',                    'preview',
   (($env{'form.catalogmode'} eq 'import')?'parent.statusframe.document.forms.statusform':''),@{$crumb_args}).' ';                    '',
                     (($env{'form.catalogmode'} eq 'import')?'parent.statusframe.document.forms.statusform':''),
                     $skiplast).' ';
     }      }
     return $link;      return $link;
 }  }
Line 3677  $prefix <img src="$icon" alt="" /> Line 3522  $prefix <img src="$icon" alt="" />
 <dl>  <dl>
 <dt>URL:</dt>  <dt>URL:</dt>
     <dd><a href="$jumpurl?inhibitmenu=yes"       <dd><a href="$jumpurl?inhibitmenu=yes" 
          target='preview'>$values{'url'}</a></dd>           target='preview'>$values{'url'}</a>
 END  END
       $result .=
           &display_tools($values{'title'}, $jumpurl).'
       </dd>';
     foreach my $field ('title','author','domain','subject','keywords','notes',      foreach my $field ('title','author','domain','subject','keywords','notes',
                        'mimetag','language','creationdate','lastrevisiondate',                         'mimetag','language','creationdate','lastrevisiondate',
                        'owner','copyrighttag','hostname','abstract') {                         'owner','copyrighttag','hostname','abstract') {
Line 3864  sub output_blank_field_error { Line 3712  sub output_blank_field_error {
     my ($r,$closebutton,$parms,$hidden_fields)=@_;      my ($r,$closebutton,$parms,$hidden_fields)=@_;
     my $errormsg = &mt('You did not fill in enough information for the search to be started. You need to fill in relevant fields on the search page in order for a query to be processed.');      my $errormsg = &mt('You did not fill in enough information for the search to be started. You need to fill in relevant fields on the search page in order for a query to be processed.');
     my $revise = &mt('Revise Search Request');      my $revise = &mt('Revise Search Request');
     my $heading = &mt('Unactionable Search Queary');      my $heading = &mt('Unactionable Search Query');
     my $start_page = &Apache::loncommon::start_page('Search');      my $start_page = &Apache::loncommon::start_page('Search');
     my $end_page   = &Apache::loncommon::end_page();      my $end_page   = &Apache::loncommon::end_page();
       if ($closebutton) {
           $closebutton = '<p>'.$closebutton.'</p><hr />';
       } else {
           &Apache::lonhtmlcommon::add_breadcrumb
               ({href=>'',
                 text=>$heading,});
           $start_page .= &Apache::lonhtmlcommon::breadcrumbs();
       }
   
     $r->print(<<ENDPAGE);      $r->print(<<ENDPAGE);
 $start_page  $start_page
 <form method="post" action="/adm/searchcat">  <form method="post" action="/adm/searchcat">
 $hidden_fields  $hidden_fields
 $closebutton  $closebutton
 <hr />  </form>
 <h2>$heading</h2>  <h2>$heading</h2>
 <p class="LC_warning">  <p class="LC_warning">
 $errormsg  $errormsg
 </p>  </p>
 <p>  <p>
 <a href="/adm/searchcat?$parms&amp;persistent_db_id=$env{'form.persistent_db_id'}">$revise</a>&nbsp;  <a href="/adm/searchcat?$parms&amp;persistent_db_id=$env{'form.persistent_db_id'}">$revise</a>
 </p>  </p>
 $end_page  $end_page
 ENDPAGE  ENDPAGE
Line 3961  sub cleanup { Line 3818  sub cleanup {
   &Apache::lonnet::logthis('Failed cleanup searchcat: groupsearch_db');    &Apache::lonnet::logthis('Failed cleanup searchcat: groupsearch_db');
         }          }
     }      }
     &untiehash();  
     &Apache::lonmysql::disconnect_from_db();      &Apache::lonmysql::disconnect_from_db();
     return OK;      return OK;
 }  }

Removed from v.1.313  
changed lines
  Added in v.1.331.4.10


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