--- loncom/interface/lonindexer.pm 2001/05/31 21:38:58 1.8 +++ loncom/interface/lonindexer.pm 2005/03/03 07:53:55 1.132 @@ -1,44 +1,99 @@ # The LearningOnline Network with CAPA # Directory Indexer -# (Login Screen -# 5/21/99,5/22,5/25,5/26,5/31,6/2,6/10,7/12,7/14 Gerd Kortemeyer) -# 11/23 Gerd Kortemeyer -# 07/20-08/04 H.K. Ng -# -# 05/9-05/19/2001 H. K. Ng -# 05/21/2001 H. K. Ng -# 05/23/2001 H. K. Ng -# 05/31/2001 Scott Harrison +# +# $Id: lonindexer.pm,v 1.132 2005/03/03 07:53:55 albertel Exp $ +# +# Copyright Michigan State University Board of Trustees +# +# This file is part of the LearningOnline Network with CAPA (LON-CAPA). +# +# LON-CAPA is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# LON-CAPA is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with LON-CAPA; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# /home/httpd/html/adm/gpl.txt +# +# http://www.lon-capa.org/ +# +### + +############################################################################### +## ## +## 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 ## +## ## +############################################################################### package Apache::lonindexer; +# ------------------------------------------------- modules used by this module use strict; use Apache::lonnet(); +use Apache::loncommon(); +use Apache::lonhtmlcommon(); +use Apache::lonsequence(); use Apache::Constants qw(:common); +use Apache::lonmeta; use Apache::File; +use Apache::lonlocal; +use Apache::lonsource(); use GDBM_File; -my %hash; -my %dirs; -my %language; -my $hidden; -my $extrafield; -my $fnum=0; -sub BEGIN { - my $fh=Apache::File->new($Apache::lonnet::perlvar{'lonTabDir'}.'/language.tab'); - map { - $_=~/(\w+)\s+([\w\s\-]+)/; - $language{$1}=$2; - } <$fh>; -} +# ---------------------------------------- variables used throughout the module +my %hash; # global user-specific gdbm file +my %dirs; # keys are directories, values are the open/close status +my %language; # has the reference information present in language.tab +my %dynhash; # hash of hashes for dynamic metadata +my %dynread; # hash of directories already read for dynamic metadata +my %fieldnames; # Metadata fieldnames +# ----- Values which are set by the handler subroutine and are accessible to +# ----- other methods. +my $extrafield; # default extra table cell +my $fnum; # file counter +my $dnum; # directory counter + +# ----- Used to include or exclude files with certain extensions. +my @Only = (); +my @Omit = (); + + + +# ----------------------------- Handling routine called via Apache and mod_perl sub handler { my $r = shift; - $r->content_type('text/html'); + my $c = $r->connection(); + &Apache::loncommon::content_type($r,'text/html'); + &Apache::loncommon::no_cache($r); $r->send_http_header; return OK if $r->header_only; + $fnum=0; + $dnum=0; + + # Deal with stupid global variables (is there a way around making + # these global to this package? It is just so wrong....) + undef (@Only); + undef (@Omit); + %fieldnames=&Apache::lonmeta::fieldnames(); - my $iconpath= $r->dir_config('lonIconsURL'); +# ------------------------------------- read in machine configuration variables + my $iconpath= $r->dir_config('lonIconsURL') . "/"; my $domain = $r->dir_config('lonDefDomain'); my $role = $r->dir_config('lonRole'); my $loadlim = $r->dir_config('lonLoadLim'); @@ -47,172 +102,452 @@ sub handler { my $lonhost = $r->dir_config('lonHostID'); my $tabdir = $r->dir_config('lonTabDir'); - my $iconpath='/res/adm/pages/indexericons/'; my $fileclr='#ffffe6'; -# -------------------------------------- see if called from an interactive mode - 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'})); + my $line; + my (@attrchk,@openpath); + my $uri=$r->uri; - $hidden=''; my $closebutton=''; +# -------------------------------------- see if called from an interactive mode + # Get the parameters from the query string + &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, + ['catalogmode','launch','acts','mode','form','element', + 'only','omit','titleelement']); + #------------------------------------------------------------------- + my $closebutton=''; my $groupimportbutton=''; my $colspan=''; - if ($ENV{'form.catalogmode'} eq 'interactive') { - $extrafield=''. - ''; - $colspan=" colspan='2' "; - $hidden=< -END - $closebutton=< -END + + $extrafield=''; + my $diropendb = + "/home/httpd/perl/tmp/$ENV{'user.domain'}_$ENV{'user.name'}_indexer.db"; + %hash = (); + { + my %dbfile; + if (tie(%dbfile,'GDBM_File',$diropendb,&GDBM_READER(),0640)) { + while(my($key,$value)=each(%dbfile)) { + $hash{$key}=$value; + } + untie(%dbfile); + } } - elsif ($ENV{'form.catalogmode'} eq 'groupimport') { - $extrafield=''. - ''; - $colspan=" colspan='2' "; - $hidden=< + { + if ($ENV{'form.launch'} eq '1') { + &start_fresh_session(); + } + #Hijack lonindexer to verify a title and be close down. + if ($ENV{'form.launch'} eq '2') { + &Apache::loncommon::content_type($r,'text/html'); + my $extra=''; + if (defined($ENV{'form.titleelement'}) && + $ENV{'form.titleelement'} ne '') { + my $verify_title = &Apache::lonnet::gettitle($ENV{'form.acts'}); +# &Apache::lonnet::logthis("Hrrm $ENV{'form.acts'} -- $verify_title"); + $verify_title=~s/'/\\'/g; + $extra='window.opener.document.forms["'.$ENV{'form.form'}.'"].elements["'.$ENV{'form.titleelement'}.'"].value=\''.$verify_title.'\';'; + } + my $html=&Apache::lonxml::xmlbegin(); + $r->print(< + + + + + + +ENDSUBM + return OK; + } + +# -------------------- refresh environment with user database values (in %hash) + &setvalues(\%hash,'form.catalogmode',\%ENV,'form.catalogmode' ); + +# --------------------- define extra fields and buttons in case of special mode + if ($ENV{'form.catalogmode'} eq 'interactive') { + $extrafield=''. + ''; + $colspan=" colspan='2' "; + my $cl=&mt('Close'); + $closebutton=< END - $closebutton=< + } + elsif ($ENV{'form.catalogmode'} eq 'groupimport') { + $extrafield=''. + ''; + $colspan=" colspan='2' "; + my $cl=&mt('Close'); + my $gi=&mt('Import'); + $closebutton=< END - $groupimportbutton=< + $groupimportbutton=< END - } + } + # Additions made by Matthew to make the browser a little easier to deal + # with in the future. + # + # $mode (at this time) indicates if we are in edit mode. + # $form is the name of the form that the URL is placed when the + # selection is made. + # $element is the name of the element in $formname which receives + # the URL. + #&Apache::lonxml::debug('Checking mode, form, element'); + &setvalues(\%hash,'form.mode' ,\%ENV,'form.mode' ); + &setvalues(\%hash,'form.form' ,\%ENV,'form.form' ); + &setvalues(\%hash,'form.element' ,\%ENV,'form.element'); + &setvalues(\%hash,'form.titleelement',\%ENV,'form.titleelement'); + &setvalues(\%hash,'form.only' ,\%ENV,'form.only' ); + &setvalues(\%hash,'form.omit' ,\%ENV,'form.omit' ); + + # Deal with 'omit' and 'only' + if (exists $ENV{'form.omit'}) { + @Omit = split(',',$ENV{'form.omit'}); + } + if (exists $ENV{'form.only'}) { + @Only = split(',',$ENV{'form.only'}); + } + + my $mode = $ENV{'form.mode'}; + my ($form,$element,$titleelement); + if ($mode eq 'edit' || $mode eq 'parmset') { + $form = $ENV{'form.form'}; + $element = $ENV{'form.element'}; + $titleelement = $ENV{'form.titleelement'}; + } + #&Apache::lonxml::debug("mode=$mode form=$form element=$element titleelement=$titleelement"); +# ------ set catalogmodefunctions to have extra needed javascript functionality + my $catalogmodefunctions=''; + if ($ENV{'form.catalogmode'} eq 'interactive' or + $ENV{'form.catalogmode'} eq 'groupimport') { + # The if statement below sets us up to use the old version + # by default (ie. if $mode is undefined). This is the easy + # way out. Hopefully in the future I'll find a way to get + # the calls dealt with in a more comprehensive manner. - my $catalogmodefunctions=''; - if ($ENV{'form.catalogmode'} eq 'interactive' or - $ENV{'form.catalogmode'} eq 'groupimport') { - $catalogmodefunctions=<print(< + my $html='';#&Apache::lonxml::xmlbegin(); + $r->print(< The LearningOnline Network With CAPA Directory Browser - +function gothere(val) { + window.location=val+'?acts='+document.forms.fileattr.acts.value; +} + - ENDHEADER - - my $line; - my (@attrchk,@openpath); - my $uri=$r->uri; - - $r->print("

The LearningOnline With CAPA Network Directory Browser

\n"); - - my $diropen = "/home/httpd/perl/tmp/$domain\_$ENV{'user.name'}_indexer.db"; - - if (tie(%hash,'GDBM_File',$diropen,&GDBM_WRCREAT,0640)) { - - if ($ENV{'form.attrs'} ne "") { - for (my $i=0; $i<=5; $i++) { +my ($headerdom)=($uri=~/^\/res\/(\w+)\//); +$r->print(&Apache::loncommon::bodytag('Browse Resources',undef,undef,undef, + $headerdom)); +# - Evaluate actions from previous page (both cumulatively and chronologically) + if ($ENV{'form.catalogmode'} eq 'groupimport') { + my $acts=$ENV{'form.acts'}; + my @Acts=split(/b/,$acts); + my %ahash; + my %achash; + my $ac=0; + # some initial hashes for working with data + foreach (@Acts) { + my ($state,$ref)=split(/a/); + $ahash{$ref}=$state; + $achash{$ref}=$ac; + $ac++; + } + # sorting through the actions and changing the global database hash + foreach (sort {$achash{$a}<=>$achash{$b}} (keys %ahash)) { + my $key=$_; + if ($ahash{$key} eq '1') { + $hash{'store_'.$hash{'pre_'.$key.'_link'}}= + $hash{'pre_'.$key.'_title'}; + $hash{'storectr_'.$hash{'pre_'.$key.'_link'}}= + $hash{'storectr'}+0; + $hash{'storectr'}++; + } + if ($ahash{$key} eq '0') { + if ($hash{'store_'.$hash{'pre_'.$key.'_link'}}) { + delete $hash{'store_'.$hash{'pre_'.$key.'_link'}}; + } + } + } + # deleting the previously cached listing + foreach (keys %hash) { + if ($_ =~ /^pre_/ && $_ =~/link$/) { + my $key = $_; + $key =~ s/^pre_//; + $key =~ s/_[^_]*$//; + delete $hash{'pre_'.$key.'_title'}; + delete $hash{'pre_'.$key.'_link'}; + } + } + } + +# ---------------------------------- get state of file attributes to be showing + if ($ENV{'form.attrs'}) { + for (my $i=0; $i<=11; $i++) { delete $hash{'display_attrs_'.$i}; if ($ENV{'form.attr'.$i} == 1) { - $attrchk[$i] = "checked"; + $attrchk[$i] = 'checked'; $hash{'display_attrs_'.$i} = 1; } } } else { - for (my $i=0; $i<=5; $i++) { - $attrchk[$i] = "checked" if $hash{'display_attrs_'.$i} == 1; + for (my $i=0; $i<=11; $i++) { + $attrchk[$i] = 'checked' if $hash{'display_attrs_'.$i} == 1; } } - $r->print(<Display file attributes
-
- - - - - - - - -
Size Last access Last modified
Author Keywords Language
-  - -$hidden -$closebutton -$groupimportbutton -
-END - my $titleclr="#ddffff"; - $r->print("
\n"); - $r->print("\n"); - $r->print("\n"); - $r->print("\n") if ($hash{'display_attrs_0'} == 1); - $r->print("\n") if ($hash{'display_attrs_1'} == 1); - $r->print("\n") if ($hash{'display_attrs_2'} == 1); - $r->print("\n") if ($hash{'display_attrs_3'} == 1); - $r->print("\n") if ($hash{'display_attrs_4'} == 1); - $r->print("\n") if ($hash{'display_attrs_5'} == 1); - $r->print(""); +# ------------------------------- output state of file attributes to be showing +# All versions has to the last item +# since it does not take an extra col + my %lt=&Apache::lonlocal::texthash( + 'ti' => 'Title', + 'si' => 'Size', + 'la' => 'Last access', + 'lm' => 'Last modified', + 'st' => 'Statistics', + 'au' => 'Author', + 'kw' => 'Keywords', + 'ln' => 'Language', + 'sa' => 'Source Available', + 'sr' => 'Show resource', + 'li' => 'Linked/Related Resources', + 'av' => 'All versions', + 'ud' => 'Update Display' + ); + $r->print(< + +
NameSize (bytes) Last accessedLast modifiedAuthor(s)KeywordsLanguage
+ + + + + + + + + + + + + + + + + + +
 
+ + + +$closebutton $groupimportbutton +END +# -------------- Filter out sequence containment in crumbs and "recent folders" + my $storeuri=$uri; + $storeuri='/'.(split(/\.(page|sequence)\/\//,$uri))[-1]; + $storeuri=~s/\/+/\//g; +# ---------------------------------------------------------------- Bread crumbs + $r->print(&Apache::lonhtmlcommon::crumbs($storeuri,'','', + (($ENV{'form.catalogmode'} eq 'groupimport')? + 'document.forms.fileattr':'')). + &Apache::lonhtmlcommon::select_recent('residx','resrecent', +'window.status=this.form.resrecent.options[this.form.resrecent.selectedIndex].value;this.form.action=this.form.resrecent.options[this.form.resrecent.selectedIndex].value;this.form.submit();')); +# -------------------------------------------------------- Resource Home Button + my $reshome=$ENV{'course.'.$ENV{'request.course.id'}.'.reshome'}; + if ($reshome) { + $r->print("print('javascript:document.forms.fileattr.action="'.$reshome.'";document.forms.fileattr.submit();'); + } else { + $r->print($reshome); + } + $r->print("'>".&mt('Home').''); + } + $r->print(''); +# ------------------------------------------------------ Remember where we were + &Apache::loncommon::storeresurl($storeuri); + &Apache::lonhtmlcommon::store_recent('residx',$storeuri,$storeuri); +# ----------------- output starting row to the indexed file/directory hierarchy + my $titleclr="#ddffff"; + #$r->print(&initdebug()); + #$r->print(&writedebug("Omit:@Omit")) if (@Omit); + #$r->print(&writedebug("Only:@Only")) if (@Only); + $r->print('
'."\n"); + $r->print(''."\n"); + $r->print("\n"); + $r->print("\n") + if ($hash{'display_attrs_0'} == 1); + $r->print("\n") if ($hash{'display_attrs_1'} == 1); + $r->print("\n") + if ($hash{'display_attrs_2'} == 1); + $r->print("\n") + if ($hash{'display_attrs_3'} == 1); + $r->print("\n") + if ($hash{'display_attrs_4'} == 1); + $r->print("\n") + if ($hash{'display_attrs_5'} == 1); + $r->print("\n") + if ($hash{'display_attrs_6'} == 1); + $r->print("\n") + if ($hash{'display_attrs_8'} == 1); + $r->print("\n") + if ($hash{'display_attrs_10'} == 1); + $r->print("\n") + if ($hash{'display_attrs_11'} == 1); + $r->print("\n") + if ($hash{'display_attrs_7'} == 1); + $r->print(''); - map { +# ----------------- read in what directories have previously been set to "open" + foreach (keys %hash) { if ($_ =~ /^diropen_status_/) { my $key = $_; $key =~ s/^diropen_status_//; $dirs{$key} = $hash{$_}; } - } keys %hash; + } if ($ENV{'form.openuri'}) { # take care of review and refresh options my $uri=$ENV{'form.openuri'}; @@ -229,81 +564,187 @@ END $dirs{$uri} = 'open'; } } - - my $toplevel = "/res/"; + + my $toplevel; my $indent = 0; - &scanDir ($r,$toplevel,$indent); + $uri = $uri.'/' if $uri !~ /.*\/$/; + + if ($ENV{'form.dirPointer'} ne 'on') { + $hash{'top.level'} = $uri; + $toplevel = $uri; + } else { + $toplevel = $hash{'top.level'}; + } + +# -------------------------------- if not at top level, provide an uplink arrow + if ($toplevel ne '/res/'){ + my (@uri_com) = split(/\//,$uri); + pop @uri_com; + my $upone = join('/',@uri_com); + my @list = qw (0); + &display_line ($r,'opened',$upone.'&viewOneUp',0,$upone,@list); + $indent = 1; + } +# -------- recursively go through all the directories and output as appropriate + &scanDir ($r,$toplevel,$indent,\%hash); + +# ---------------------------- embed hidden information useful for group import $r->print(""); - $r->print(""); - $r->print("
".&mt('Name')."".&mt('Title')."".&mt("Size")." (".&mt("bytes").") ". + "".&mt("Last accessed")."".&mt("Last modified")."".&mt("Author(s)")."".&mt("Keywords")."".&mt("Language")."".&mt("Usage Statistics")."
(". + &mt("Courses/Network Hits").")
".&mt('updated periodically')."
".&mt("Source Available")."".&mt("Linked/Related Resources")."".&mt("Resource")."
"); - $r->print("
"); - $r->print("\n"); - untie(%hash); - } else { - $r->print("Unable to tie hash to db file"); + $r->print(""); + +# -------------------------------------------------------------- end the tables + $r->print('
'); + $r->print(''); + +# --------------------------------------------------- end the output and return + $r->print(''."\n"); } + if(! $c->aborted()) { +# write back into the temporary file + my %dbfile; + if (tie(%dbfile,'GDBM_File',$diropendb,&GDBM_NEWDB(),0640)) { + while (my($key,$value) = each(%hash)) { + $dbfile{$key}=$value; + } + untie(%dbfile); + } + } + return OK; } - -# --------------------recursive scan of a directory +# ----------------------------------------------- recursive scan of a directory sub scanDir { - my ($r,$startdir,$indent)=@_; + my ($r,$startdir,$indent,$hashref)=@_; + my $c = $r->connection(); my ($compuri,$curdir); my $dirptr=16384; + my $obs; $indent++; - my %dupdirs = %dirs; my @list=&get_list($r,$startdir); foreach my $line (@list) { - my ($strip,$dom,$foo,$testdir,$foo)=split(/\&/,$line,5); - next if $strip =~ /.*\.meta$/; - if ($dom eq "domain") { - $compuri = join('',$strip,"/"); # domain list has /res/ - $curdir = $compuri; + return if ($c->aborted()); + #This is a kludge, sorry aboot this + my ($strip,$dom,undef,$testdir,undef,undef,undef,undef,undef,undef,undef,undef,undef,undef,$obs,undef)=split(/\&/,$line,16); + next if($strip =~ /.*\.meta$/ | $obs eq '1'); + my (@fileparts) = split(/\./,$strip); + if ($hash{'display_attrs_9'} != 1) { +# if not all versions to be shown + if (scalar(@fileparts) >= 3) { + my $fext = pop @fileparts; + my $ov = pop @fileparts; + my $fname = join ('.',@fileparts,$fext); + next if (grep /\Q$fname\E/,@list and $ov =~ /^\d+$/); + } + } + + if ($dom eq 'domain') { + # dom list has full path /res// already + $curdir=''; + $compuri = (split(/\&/,$line))[0]; } else { - $compuri = join('',$startdir,$strip,"/"); # user, dir & file having name only, i.e., w/o path + # user, dir & file have name only, i.e., w/o path + $compuri = join('',$startdir,$strip,'/'); $curdir = $startdir; } - my $diropen = 0; - if (($dirptr&$testdir) or ($dom =~ /^(domain|user)$/)) { + my $diropen = 'closed'; + if (($dirptr&$testdir) or ($dom =~ /^(domain|user)$/) or ($compuri=~/\.(sequence|page)\/$/)) { while (my ($key,$val)= each %dupdirs) { if ($key eq $compuri and $val eq "open") { - $diropen = 1; - delete $dupdirs{key},$dirs{$key}; + $diropen = "opened"; + delete($dupdirs{$key}); + delete($dirs{$key}); } } } - &display_line($r,$diropen,$line,$indent,$curdir,@list); - &scanDir ($r,$compuri,$indent) if $diropen == 1; + &display_line($r,$diropen,$line,$indent,$curdir,$hashref,@list); + &scanDir ($r,$compuri,$indent) if $diropen eq 'opened'; } $indent--; } -# ----------------- get complete matched list based on the uri ------ +# --------------- get complete matched list based on the uri (returns an array) sub get_list { my ($r,$uri)=@_; - my @list; - my $luri = $uri; - $luri =~ s/\//_/g; - - if ($ENV{'form.attrs'} eq "Refresh") { - map { + my @list=(); + (my $luri = $uri) =~ s/\//_/g; + if ($ENV{'form.updatedisplay'}) { + foreach (keys %hash) { delete $hash{$_} if ($_ =~ /^dirlist_files_/); - } keys %hash; + delete $hash{$_} if ($_ =~ /^dirlist_timestamp_files_/); + } } - if ($hash{'dirlist_files'.$luri}) { + if (defined($hash{'dirlist_files_'.$luri}) && + $hash{'dirlist_timestamp_files_'.$luri}+600 > (time)) { @list = split(/\n/,$hash{'dirlist_files_'.$luri}); + } elsif ($uri=~/\.(page|sequence)\/$/) { +# is a page or a sequence + $uri=~s/\/$//; + $uri='/'.(split(/\.(page|sequence)\/\//,$uri))[-1]; + $uri=~s/\/+/\//g; + foreach (&Apache::lonsequence::attemptread(&Apache::lonnet::filelocation('',$uri))) { + my @ratpart=split(/\:/,$_); + push @list,$ratpart[1]; + } + $hash{'dirlist_files_'.$luri} = join("\n",@list); } else { +# is really a directory @list = &Apache::lonnet::dirlist($uri); - $hash{'dirlist_files_'.$luri} = join('\n',@list); + $hash{'dirlist_files_'.$luri} = join("\n",@list); + $hash{'dirlist_timestamp_files_'.$luri} = time; } return @list=&match_ext($r,@list); } -#-------------------------- filters out files based on extensions +sub dynmetaread { + my $uri=shift; + if (($hash{'display_attrs_8'}==1) || ($hash{'display_attrs_11'}==1)) { +# We don't want the filename + $uri=~s/\/[^\/]+$//; +# Did we already see this? + my $builddir=$uri; + while ($builddir) { + if ($dynread{$builddir}) { + return 0; + } + $builddir=~s/\/[^\/]+$//; + } +# Actually get the data + %dynhash= + (%dynhash,&Apache::lonmeta::get_dynamic_metadata_from_sql($uri)); +# Remember that we got it + $dynread{$uri}=1; + } +} + +sub initdebug { + my $html=&Apache::lonxml::xmlbegin(); + return < +var debugging = true; +if (debugging) { + var debuggingWindow = window.open('','Debug','width=400,height=300',true); +} + +function output(text) { + if (debugging) { + debuggingWindow.document.writeln(text); + } +} +output('$htmlDebugging Window
');   
+
+ENDJS
+}
+
+sub writedebug {
+    my $text = shift;
+    return "";
+}
+
+# -------------------- filters out files based on extensions (returns an array)
 sub match_ext {
     my ($r,@packlist)=@_;
     my @trimlist;
@@ -311,209 +752,635 @@ sub match_ext {
     my @fileext;
     my $dirptr=16384;
 
-    my $tabdir  = $r->dir_config('lonTabDir');
-    my $fn = $tabdir."/filetypes.tab";
-    if (-e $fn) {
-	my $FH=Apache::File->new($fn);
-	my @content=<$FH>;
-	foreach my $line (@content) {
-	    (my $ext,my $foo) = split /\s+/,$line;
-	    push @fileext,$ext;
-	}
-    }
     foreach my $line (@packlist) {
 	chomp $line;
 	$line =~ s/^\/home\/httpd\/html//;
 	my @unpackline = split (/\&/,$line);
-	next if ($unpackline[0] eq ".");
-	next if ($unpackline[0] eq "..");
+	next if ($unpackline[0] eq '.');
+	next if ($unpackline[0] eq '..');
 	my @filecom = split (/\./,$unpackline[0]);
 	my $fext = pop(@filecom);
-	my $fnptr = $unpackline[3]&$dirptr;
+	my $fnptr = ($unpackline[3]&$dirptr) || ($fext=~/\.(page|sequence)$/);
  	if ($fnptr == 0 and $unpackline[3] ne "") {
-	    foreach my $nextline (@fileext) {
-		push @trimlist,$line if $nextline eq $fext;
-	    }
+	    my $embstyle = &Apache::loncommon::fileembstyle($fext);
+            push @trimlist,$line if (defined($embstyle) && 
+				     ($embstyle ne 'hdn' or $fext eq 'meta'));
 	} else {
 	    push @trimlist,$line;
 	}
     }
-    @trimlist = sort (@trimlist);
+    @trimlist = sort {uc($a) cmp uc($b)} (@trimlist);
     return @trimlist;
 }
 
-#------------------- displays one line in appropriate table format
-sub display_line{
-    my ($r,$diropen,$line,$indent,$startdir,@list)=@_;
-    my (@pathfn, $fndir, $fnptr);
+# ------------------------------- displays one line in appropriate table format
+sub display_line {
+    my ($r,$diropen,$line,$indent,$startdir,$hashref,@list)=@_;
+    my (@pathfn, $fndir);
+# there could be relative paths (files actually belonging into this directory)
+# or absolute paths (for example, from sequences)
+    my $absolute;
+    my $pathprefix;
+    if ($line=~m|^/res/| && $startdir ne '') {
+	$absolute=1;
+	$pathprefix='';
+    } else {
+	$absolute=0;
+	$pathprefix=$startdir;
+    }
     my $dirptr=16384;
     my $fileclr="#ffffe6";
-    my $iconpath="/res/adm/pages/indexericons/";
+    my $iconpath= $r->dir_config('lonIconsURL') . '/';
 
     my @filecom = split (/\&/,$line);
     my @pathcom = split (/\//,$filecom[0]);
     my $listname = $pathcom[scalar(@pathcom)-1];
     my $fnptr = $filecom[3]&$dirptr;
-    my $msg = 'View '.$filecom[0].' resources';
-    $msg = 'Close '.$filecom[0].' directory' if $diropen == 1;
+    my $msg = &mt('View').' '.$filecom[0].' '.&mt('resources');
+    $msg = &mt('Close').' '.$filecom[0].' '.&mt('directory') if $diropen eq 'opened';
 
-    my $tabtag="";
+    my $tabtag='';
     my $i=0;
-
-    while ($i<=5) {
-#	my $key="form.attr".$i;
-#	$tabtag=join('',$tabtag," ") if $ENV{$key} == 1;
-	$tabtag=join('',$tabtag," ") if $hash{'display_attrs_'.$i} == 1;
+    while ($i<=11) {
+	$tabtag=join('',$tabtag," ")
+	    if $hash{'display_attrs_'.$i} == 1;
 	$i++;
     }
-    if ($filecom[1] eq "domain") {
-	$r->print("$extrafield");
-	$r->print("");
-	&begin_form ($r,$filecom[0].'/');
-	my $anchor = $filecom[0].'/';
+    my $valign = ($hash{'display_attrs_7'} == 1 ? 'top' : 'bottom');
+
+# display uplink arrow
+    if ($filecom[1] eq 'viewOneUp') {
+	my $updir=$startdir;
+# -------------- Filter out sequence containment in crumbs and "recent folders"
+	$updir='/'.(split(/\.(page|sequence)\/\//,$startdir))[-1];
+	$updir=~s/\/+/\//g;
+
+	$r->print("$extrafield");
+	$r->print("\n");
+	$r->print ('
'."\n"); + $r->print (''."\n"); + $r->print (''."\n"); + $r->print ('print (' name="'.$msg.'" height="22" type="image" border="0" />'. + "\n"); + $r->print(&mt("Up")."
$tabtag\n"); + return OK; + } +# Do we have permission to look at this? + + if($filecom[15] ne '1') { return OK if (!&Apache::lonnet::allowed('bre',$pathprefix.$filecom[0])); } + +# make absolute links appear on different background + if ($absolute) { $fileclr='#ccdd99'; } + +# display domain + if ($filecom[1] eq 'domain') { + $r->print (''."\n") + if ($ENV{'form.dirPointer'} eq "on"); + $r->print("$extrafield"); + $r->print(""); + &begin_form ($r,$filecom[0]); + my $anchor = $filecom[0]; $anchor =~ s/\///g; - $r->print ("
\nprint (" name=\"$msg\" height=\"22\" type=\"image\" border=\"0\">\n"); - $r->print("Domain - $listname $tabtag\n"); + $r->print (''); + $r->print (''); + $r->print ('print (' name="'.$msg.'" height="22" type="image" border="0" />'. + "\n"); + my $quotable_filecom = &Apache::loncommon::escape_single($filecom[0]); + $r->print ('print (' border="0" />'."\n"); + $r->print (&mt("Domain")." - $listname "); + if ($Apache::lonnet::domaindescription{$listname}) { + $r->print("(".$Apache::lonnet::domaindescription{$listname}. + ")"); + } + $r->print (" $tabtag\n"); return OK; + +# display user directory } - if ($filecom[1] eq "user") { - $r->print("$extrafield"); - $r->print("\n"); + if ($filecom[1] eq 'user') { + $r->print("$extrafield"); + $r->print("\n"); my $curdir = $startdir.$filecom[0].'/'; - &begin_form ($r,$curdir); my $anchor = $curdir; $anchor =~ s/\///g; -# $r->print ("\n\n"); - $r->print ("\n\n"); - $r->print ("print ("folder_pointer_closed.gif\"") if $diropen == 0; - $r->print ("folder_pointer_opened.gif\"") if $diropen == 1; - $r->print (" name=\"$msg\" height=\"22\" type=\"image\" border=\"0\">\n"); - $r->print ("\n"); - $r->print ("$listname $tabtag\n"); + &begin_form ($r,$curdir); + $r->print (''."\n"); + $r->print (''); + $r->print ('print (' name="'.$msg.'" height="22" type="image" border="0" />'. + "\n"); + my $quotable_curdir = &Apache::loncommon::escape_single($curdir); + $r->print (''); + my $domain=(split(m|/|,$startdir))[2]; + my $plainname=&Apache::loncommon::plainname($listname,$domain); + $r->print ($listname); + if (defined($plainname) && $plainname) { $r->print(" ($plainname) "); } + $r->print (''.$tabtag.''."\n"); return OK; } + # display file - if ($fnptr == 0 and $filecom[3] ne "") { + if (($fnptr == 0 and $filecom[3] ne '') or $absolute) { + my $filelink = $pathprefix.$filecom[0]; my @file_ext = split (/\./,$listname); - my $curfext = $file_ext[scalar(@file_ext)-1]; - my $filelink = $startdir.$filecom[0]; - $r->print(""); - my $metafile = grep /^$filecom[0]\.meta\&/, @list; - my $title; + my $curfext = $file_ext[-1]; + if (@Omit) { + foreach (@Omit) { return OK if ($curfext eq $_); } + } + if (@Only) { + my $skip = 1; + foreach (@Only) { $skip = 0 if ($curfext eq $_); } + return OK if ($skip > 0); + } + # Set the icon for the file + my $iconname = &Apache::loncommon::icon($listname); + $r->print(""); + if ($ENV{'form.catalogmode'} eq 'interactive') { - $title=$listname; - $title = &Apache::lonnet::metadata($filelink,'title') - if ($metafile == 1); - $title=$listname unless $title; - $r->print(""); - $r->print("\n"); - $r->print(""); - } - elsif ($ENV{'form.catalogmode'} eq 'groupimport') { - $title=$listname; - $title = &Apache::lonnet::metadata($filelink,'title') - if ($metafile == 1); - $title=$listname unless $title; + my $quotable_filelink = &Apache::loncommon::escape_single($filelink); + $r->print(""); + $r->print("". + "\n"); + $r->print(""); + } elsif ($ENV{'form.catalogmode'} eq 'groupimport') { $r->print("
\n"); $r->print("\n"); - $r->print("\n"); + "value='$filelink' onClick='". + "javascript:queue(\"form$fnum\")' "); + if ($hash{'store_'.$filelink}) { + $r->print("checked"); + } + $r->print(" />\n"); $r->print("
\n"); - $r->print(""); + $r->print(""); + $hash{"pre_${fnum}_link"}=$filelink; $fnum++; } - - if ($indent < 11) { - $r->print("\n"); - } else { +# Form to open or close sequences + if ($filelink=~/\.(page|sequence)$/) { + my $curdir = $startdir.$filecom[0].'/'; + my $anchor = $curdir; + $anchor =~ s/\///g; + &begin_form($r,$curdir); + $indent--; + } +# General indentation + if ($indent > 0 and $indent < 11) { + $r->print("\n"); + } elsif ($indent >0) { my $ten = int($indent/10.); my $rem = $indent%10.0; my $count = 0; while ($count < $ten) { - $r->print("\n"); + $r->print("\n"); $count++; } - $r->print("\n") if $rem > 0; + $r->print("\n") if $rem > 0; } +# Sequence open/close icon + if ($filelink=~/\.(page|sequence)$/) { + my $curdir = $startdir.$filecom[0].'/'; + my $anchor = $curdir; + $anchor =~ s/\///g; + $r->print (''); + $r->print ('print (' name="'.$msg.'" height="22" type="image" border="0" />'. + "\n"); + } +# Filetype icons + $r->print("\n"); +# Close form to open/close sequence + if ($filelink=~/\.(page|sequence)$/) { + $r->print(''); + } + my $quotable_filelink = &Apache::loncommon::escape_single($filelink); - $r->print("\n"); - $r->print(" ",$listname,"\n"); - $r->print (" (metadata) ") if ($metafile == 1); + $r->print (" $listname "); + $r->print (" (metadata) "); $r->print("\n"); -# $r->print(" ",$filecom[8]," \n") if $ENV{'form.attr0'} == 1; - $r->print(" ",$filecom[8]," \n") if $hash{'display_attrs_0'} == 1; - $r->print(" ".(localtime($filecom[9]))." \n") if $hash{'display_attrs_1'} == 1; - $r->print(" ".(localtime($filecom[10]))." \n") if $hash{'display_attrs_2'} == 1; - - if ($hash{'display_attrs_3'} == 1) { - my $author = &Apache::lonnet::metadata($filelink,'author') if ($metafile == 1); - $author = ' ' if (!$author); - $r->print(" ".$author." \n"); + if ($hash{'display_attrs_0'} == 1) { + my $title = &Apache::lonnet::gettitle($filelink,'title'); + $r->print(' '.($title eq '' ? ' ' : $title). + ' '."\n"); } + $r->print(' ', + $filecom[8]," \n") + if $hash{'display_attrs_1'} == 1; + $r->print(' '. + (localtime($filecom[9]))." \n") + if $hash{'display_attrs_2'} == 1; + $r->print(' '. + (localtime($filecom[10]))." \n") + if $hash{'display_attrs_3'} == 1; + if ($hash{'display_attrs_4'} == 1) { - my $keywords = &Apache::lonnet::metadata($filelink,'keywords') if ($metafile == 1); - $keywords = ' ' if (!$keywords); - $r->print(" ".$keywords." \n"); + my $author = &Apache::lonnet::metadata($filelink,'author'); + $r->print(' '.($author eq '' ? ' ' : $author). + " \n"); } if ($hash{'display_attrs_5'} == 1) { - my $lang = &Apache::lonnet::metadata($filelink,'language') if ($metafile == 1); - $lang = $language{$lang}; - $lang = ' ' if (!$lang); - $r->print(" ".$lang." \n"); + my $keywords = &Apache::lonnet::metadata($filelink,'keywords'); + # $keywords = ' ' if (!$keywords); + $r->print(' '.($keywords eq '' ? ' ' : $keywords). + " \n"); } +#' + + if ($hash{'display_attrs_6'} == 1) { + my $lang = &Apache::lonnet::metadata($filelink,'language'); + $lang = &Apache::loncommon::languagedescription($lang); + $r->print(' '.($lang eq '' ? ' ' : $lang). + " \n"); + } + if ($hash{'display_attrs_8'} == 1) { +# statistics + &dynmetaread($filelink); + $r->print(""); + &dynmetaprint($r,$filelink,'count'); + &dynmetaprint($r,$filelink,'course'); + &dynmetaprint($r,$filelink,'stdno'); + &dynmetaprint($r,$filelink,'avetries'); + &dynmetaprint($r,$filelink,'difficulty'); + &dynmetaprint($r,$filelink,'disc'); + &dynmetaprint($r,$filelink,'clear'); + &dynmetaprint($r,$filelink,'technical'); + &dynmetaprint($r,$filelink,'correct'); + &dynmetaprint($r,$filelink,'helpful'); + &dynmetaprint($r,$filelink,'depth'); + $r->print(" \n"); + + } + if ($hash{'display_attrs_10'} == 1) { + my $source = &Apache::lonnet::metadata($filelink,'sourceavail'); + if($source eq 'open') { + my $sourcelink = &Apache::lonsource::make_link($filelink,$listname); + my $quotable_sourcelink = &Apache::loncommon::escape_single($sourcelink); + $r->print(''."Yes "."\n"); + } else { #A cuddled else. :P + $r->print(" \n"); + } + } + if ($hash{'display_attrs_11'} == 1) { +# links + &dynmetaread($filelink); + $r->print(''); + &dynmetaprint($r,$filelink,'goto_list'); + &dynmetaprint($r,$filelink,'comefrom_list'); + &dynmetaprint($r,$filelink,'sequsage_list'); + &dynmetaprint($r,$filelink,'dependencies'); + $r->print(''); + } + if ($hash{'display_attrs_7'} == 1) { +# Show resource + my $output=''; + my $embstyle=&Apache::loncommon::fileembstyle($curfext); + if ($embstyle eq 'ssi') { + my $cache=$Apache::lonnet::perlvar{'lonDocRoot'}.$filelink. + '.tmp'; + if ((!$ENV{'form.updatedisplay'}) && + (-e $cache)) { + open(FH,$cache); + $output=join("\n",); + close(FH); + } else { + $output=&Apache::lonnet::ssi_body($filelink); + open(FH,">$cache"); + print FH $output; + close(FH); + } + $output=''.$output.''; + } elsif ($embstyle eq 'img') { + $output=''; + } elsif ($filelink=~/^\/res\/(\w+)\/(\w+)\//) { + $output=''; + } + $r->print(' '.($output eq '' ? ' ':$output). + " \n"); + } $r->print("\n"); } + # -- display directory if ($fnptr == $dirptr) { - my @file_ext = split (/\./,$listname); - my $curfext = $file_ext[scalar(@file_ext)-1]; my $curdir = $startdir.$filecom[0].'/'; my $anchor = $curdir; $anchor =~ s/\///g; - $r->print("$extrafield"); + $r->print("$extrafield"); &begin_form ($r,$curdir); my $indentm1 = $indent-1; - if ($indentm1 < 11) { - $r->print("\n"); + if ($indentm1 < 11 and $indentm1 > 0) { + $r->print("\n"); } else { my $ten = int($indentm1/10.); my $rem = $indentm1%10.0; my $count = 0; while ($count < $ten) { - $r->print("\n"); - $count++; + $r->print ("\n"); + $count++; } - $r->print("\n") if $rem > 0; + $r->print ("\n") if $rem > 0; } - $r->print ("\nprint ("folder_pointer_closed.gif\"") if $diropen == 0; - $r->print ("folder_pointer_opened.gif\"") if $diropen == 1; - $r->print (" name=\"$msg\" height=\"22\" type=\"image\" border=\"0\">\n"); - $r->print("\n") if $diropen == 0; - $r->print("\n") if $diropen == 1; - $r->print("$listname $tabtag\n"); + $r->print (''); + $r->print ('print (' name="'.$msg.'" height="22" type="image" border="0" />'. + "\n"); + my $quotable_curdir = &Apache::loncommon::escape_single($curdir); + $r->print (''. + "\n"); + $r->print ("$listname\n"); +# Attributes + my $filelink = $startdir.$filecom[0].'/default'; + + if ($hash{'display_attrs_0'} == 1) { + my $title = &Apache::lonnet::gettitle($filelink,'title'); + $r->print(' '.($title eq '' ? ' ' : $title). + ' '."\n"); + } + $r->print(' ', + $filecom[8]," \n") + if $hash{'display_attrs_1'} == 1; + $r->print(' '. + (localtime($filecom[9]))." \n") + if $hash{'display_attrs_2'} == 1; + $r->print(' '. + (localtime($filecom[10]))." \n") + if $hash{'display_attrs_3'} == 1; + + if ($hash{'display_attrs_4'} == 1) { + my $author = &Apache::lonnet::metadata($filelink,'author'); + $r->print(' '.($author eq '' ? ' ' : $author). + " \n"); + } + if ($hash{'display_attrs_5'} == 1) { + my $keywords = &Apache::lonnet::metadata($filelink,'keywords'); + # $keywords = ' ' if (!$keywords); + $r->print(' '.($keywords eq '' ? ' ' : $keywords). + " \n"); + } + if ($hash{'display_attrs_6'} == 1) { + my $lang = &Apache::lonnet::metadata($filelink,'language'); + $lang = &Apache::loncommon::languagedescription($lang); + $r->print(' '.($lang eq '' ? ' ' : $lang). + " \n"); + } + if ($hash{'display_attrs_8'} == 1) { + $r->print(' '); + } + if ($hash{'display_attrs_10'} == 1) { + $r->print(' '); + } + if ($hash{'display_attrs_11'} == 1) { + $r->print(' '); + } + if ($hash{'display_attrs_7'} == 1) { + $r->print(' '); + } + $r->print(''); } } -#---------------------prints the beginning of a form for directory or file link +sub dynmetaprint { + my ($r,$filelink,$item)=@_; + if ($dynhash{$filelink}->{$item}) { + $r->print("\n
".$fieldnames{$item}.': '. + &Apache::lonmeta::prettyprint($item, + $dynhash{$filelink}->{$item}, + (($ENV{'form.catalogmode'} ne 'groupimport')?'preview':''), + '', + (($ENV{'form.catalogmode'} eq 'groupimport')?'document.forms.fileattr':''),1)); + } +} + +# ------------------- prints the beginning of a form for directory or file link sub begin_form { my ($r,$uri) = @_; my $anchor = $uri; $anchor =~ s/\///g; - $r->print ("
\n"); - $r->print ("$hidden\n"); + $r->print (''."\n"); + $r->print (''. + "\n"); + $r->print (''."\n"); + $dnum++; +} + +# --------- settings whenever the user causes the indexer window to be launched +sub start_fresh_session { + delete $hash{'form.catalogmode'}; + delete $hash{'form.mode'}; + delete $hash{'form.form'}; + delete $hash{'form.element'}; + delete $hash{'form.omit'}; + delete $hash{'form.only'}; + foreach (keys %hash) { + delete $hash{$_} if (/^(pre_|store)/); + } +} -# for (my $i=0; $i<=5; $i++) { -# $r->print ("\n") if $ENV{'form.attr'.$i} == 1; -# } +# ------------------------------------------------------------------- setvalues +sub setvalues { + # setvalues is used in registerurl to synchronize the database + # hash and environment hashes + my ($H1,$h1key,$H2,$h2key) =@_; + # + if (exists $H2->{$h2key}) { + $H1->{$h1key} = $H2->{$h2key}; + } elsif (exists $H1->{$h1key}) { + $H2->{$h2key} = $H1->{$h1key}; + } } 1; -__END__ + +sub cleanup { + if (tied(%hash)){ + &Apache::lonnet::logthis('Cleanup indexer: hash'); + } +} + + + + + +=head1 NAME + +Apache::lonindexer - mod_perl module for cross server filesystem browsing + +=head1 SYNOPSIS + +Invoked by /etc/httpd/conf/srm.conf: + + + SetHandler perl-script + PerlHandler Apache::lonindexer + + +=head1 INTRODUCTION + +This module enables a scheme of browsing across a cross server. + +This is part of the LearningOnline Network with CAPA project +described at http://www.lon-capa.org. + +=head1 BEGIN SUBROUTINE + +This routine is only run once after compilation. + +=over 4 + +=item * + +Initializes %language hash table. + +=back + +=head1 HANDLER SUBROUTINE + +This routine is called by Apache and mod_perl. + +=over 4 + +=item * + +read in machine configuration variables + +=item * + +see if called from an interactive mode + +=item * + +refresh environment with user database values (in %hash) + +=item * + +define extra fields and buttons in case of special mode + +=item * + +set catalogmodefunctions to have extra needed javascript functionality + +=item * + +print header + +=item * + +evaluate actions from previous page (both cumulatively and chronologically) + +=item * + +output title + +=item * + +get state of file attributes to be showing + +=item * + +output state of file attributes to be showing + +=item * + +output starting row to the indexed file/directory hierarchy + +=item * + +read in what directories have previously been set to "open" + +=item * + +if not at top level, provide an uplink arrow + +=item * + +recursively go through all the directories and output as appropriate + +=item * + +information useful for group import + +=item * + +end the tables + +=item * + +end the output and return + +=back + +=head1 OTHER SUBROUTINES + +=over 4 + +=item * + +scanDir - recursive scan of a directory + +=item * + +get_list - get complete matched list based on the uri (returns an array) + +=item * + +match_ext - filters out files based on extensions (returns an array) + +=item * + +display_line - displays one line in appropriate table format + +=item * + +begin_form - prints the beginning of a form for directory or file link + +=item * + +start_fresh_session - settings whenever the user causes the indexer window +to be launched + +=back + +=cut 500 Internal Server Error

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.

More information about this error may be available in the server error log.