![]() ![]() | ![]() |
- lots of \w -> probper regexp replacements
1: # The LearningOnline Network with CAPA 2: # Directory Indexer 3: # 4: # $Id: lonindexer.pm,v 1.154 2006/12/05 02:55:53 albertel Exp $ 5: # 6: # Copyright Michigan State University Board of Trustees 7: # 8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA). 9: # 10: # LON-CAPA is free software; you can redistribute it and/or modify 11: # it under the terms of the GNU General Public License as published by 12: # the Free Software Foundation; either version 2 of the License, or 13: # (at your option) any later version. 14: # 15: # LON-CAPA is distributed in the hope that it will be useful, 16: # but WITHOUT ANY WARRANTY; without even the implied warranty of 17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18: # GNU General Public License for more details. 19: # 20: # You should have received a copy of the GNU General Public License 21: # along with LON-CAPA; if not, write to the Free Software 22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23: # 24: # /home/httpd/html/adm/gpl.txt 25: # 26: # http://www.lon-capa.org/ 27: # 28: ### 29: 30: ############################################################################### 31: ## ## 32: ## ORGANIZATION OF THIS PERL MODULE ## 33: ## ## 34: ## 1. Description of functions ## 35: ## 2. Modules used by this module ## 36: ## 3. Choices for different output views (detailed, summary, xml, etc) ## 37: ## 4. BEGIN block (to be run once after compilation) ## 38: ## 5. Handling routine called via Apache and mod_perl ## 39: ## 6. Other subroutines ## 40: ## ## 41: ############################################################################### 42: 43: package Apache::lonindexer; 44: 45: # ------------------------------------------------- modules used by this module 46: use strict; 47: use Apache::lonnet; 48: use Apache::loncommon(); 49: use Apache::lonhtmlcommon(); 50: use Apache::lonsequence(); 51: use Apache::Constants qw(:common); 52: use Apache::lonmeta; 53: use Apache::File; 54: use Apache::lonlocal; 55: use Apache::lonsource(); 56: use GDBM_File; 57: use LONCAPA qw(:match); 58: 59: # ---------------------------------------- variables used throughout the module 60: my %hash; # global user-specific gdbm file 61: my %dirs; # keys are directories, values are the open/close status 62: my %language; # has the reference information present in language.tab 63: my %dynhash; # hash of hashes for dynamic metadata 64: my %dynread; # hash of directories already read for dynamic metadata 65: my %fieldnames; # Metadata fieldnames 66: # ----- Values which are set by the handler subroutine and are accessible to 67: # ----- other methods. 68: my $extrafield; # default extra table cell 69: my $fnum; # file counter 70: my $dnum; # directory counter 71: 72: # ----- Used to include or exclude files with certain extensions. 73: my @Only = (); 74: my @Omit = (); 75: 76: 77: 78: 79: # ----------------------------- Handling routine called via Apache and mod_perl 80: sub handler { 81: my $r = shift; 82: my $c = $r->connection(); 83: &Apache::loncommon::content_type($r,'text/html'); 84: &Apache::loncommon::no_cache($r); 85: $r->send_http_header; 86: return OK if $r->header_only; 87: $fnum=0; 88: $dnum=0; 89: 90: # Deal with stupid global variables (is there a way around making 91: # these global to this package? It is just so wrong....) 92: undef (@Only); 93: undef (@Omit); 94: %fieldnames=&Apache::lonmeta::fieldnames(); 95: 96: # ------------------------------------- read in machine configuration variables 97: my $iconpath= $r->dir_config('lonIconsURL') . "/"; 98: my $domain = $r->dir_config('lonDefDomain'); 99: my $role = $r->dir_config('lonRole'); 100: my $loadlim = $r->dir_config('lonLoadLim'); 101: my $servadm = $r->dir_config('lonAdmEMail'); 102: my $sysadm = $r->dir_config('lonSysEMail'); 103: my $lonhost = $r->dir_config('lonHostID'); 104: my $tabdir = $r->dir_config('lonTabDir'); 105: 106: my $fileclr='#ffffe6'; 107: my $line; 108: my (@attrchk,@openpath); 109: my $uri=$r->uri; 110: 111: # -------------------------------------- see if called from an interactive mode 112: # Get the parameters from the query string 113: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, 114: ['catalogmode','launch','acts','mode','form','element', 115: 'only','omit','titleelement']); 116: #------------------------------------------------------------------- 117: my $closebutton=''; 118: my $groupimportbutton=''; 119: my $colspan=''; 120: 121: $extrafield=''; 122: my $diropendb = 123: "/home/httpd/perl/tmp/$env{'user.domain'}_$env{'user.name'}_sel_res.db"; 124: %hash = (); 125: { 126: my %dbfile; 127: if (tie(%dbfile,'GDBM_File',$diropendb,&GDBM_WRITER(),0640)) { 128: if ($env{'form.launch'} eq '1') { 129: &start_fresh_session(\%dbfile); 130: } 131: 132: while(my($key,$value)=each(%dbfile)) { 133: $hash{$key}=$value; 134: } 135: untie(%dbfile); 136: } 137: } 138: { 139: #Hijack lonindexer to verify a title and be close down. 140: if ($env{'form.launch'} eq '2') { 141: &Apache::loncommon::content_type($r,'text/html'); 142: my $extra=''; 143: if (defined($env{'form.titleelement'}) && 144: $env{'form.titleelement'} ne '') { 145: my $verify_title = &Apache::lonnet::gettitle($env{'form.acts'}); 146: # &Apache::lonnet::logthis("Hrrm $env{'form.acts'} -- $verify_title"); 147: $verify_title=~s/'/\\'/g; 148: $extra='window.opener.document.forms["'.$env{'form.form'}.'"].elements["'.$env{'form.titleelement'}.'"].value=\''.$verify_title.'\';'; 149: } 150: my $js = <<ENDSUBM; 151: <script type="text/javascript"> 152: function load() { 153: window.opener.document.forms["$env{'form.form'}"] 154: .elements["$env{'form.element'}"] 155: .value='$env{'form.acts'}'; 156: $extra 157: window.close(); 158: } 159: </script> 160: ENDSUBM 161: $r->print(&Apache::loncommon::start_page(undef,$js, 162: {'only_body' =>1, 163: 'add_entries' => 164: {'onload' => "load();"},} 165: ). 166: &Apache::loncommon::end_page()); 167: return OK; 168: } 169: 170: # -------------------- refresh environment with user database values (in %hash) 171: &setvalues(\%hash,'form.catalogmode',\%env,'form.catalogmode' ); 172: 173: # --------------------- define extra fields and buttons in case of special mode 174: if ($env{'form.catalogmode'} eq 'interactive') { 175: $extrafield='<td bgcolor="'.$fileclr.'" valign="bottom">'. 176: '<img alt="" src="'.$iconpath.'whitespace1.gif"'. 177: ' border="0" /></td>'; 178: $colspan=" colspan='2' "; 179: my $cl=&mt('Close'); 180: $closebutton=<<END; 181: <input type="button" name="close" value='$cl' onClick="self.close()" /> 182: END 183: } 184: elsif ($env{'form.catalogmode'} eq 'import') { 185: $extrafield='<td bgcolor="'.$fileclr.'" valign="bottom">'. 186: '<img alt="" src="'.$iconpath.'whitespace1.gif"'. 187: ' border="0" /></td>'; 188: $colspan=" colspan='2' "; 189: my $cl=&mt('Close'); 190: my $gi=&mt('Import'); 191: $closebutton=<<END; 192: <input type="button" name="close" value='$cl' onClick="self.close()" /> 193: END 194: $groupimportbutton=<<END; 195: <input type="button" name="groupimport" value='$gi' 196: onClick="javascript:select_group()" /> 197: END 198: } 199: # Additions made by Matthew to make the browser a little easier to deal 200: # with in the future. 201: # 202: # $mode (at this time) indicates if we are in edit mode. 203: # $form is the name of the form that the URL is placed when the 204: # selection is made. 205: # $element is the name of the element in $formname which receives 206: # the URL. 207: #&Apache::lonxml::debug('Checking mode, form, element'); 208: &setvalues(\%hash,'form.mode' ,\%env,'form.mode' ); 209: &setvalues(\%hash,'form.form' ,\%env,'form.form' ); 210: &setvalues(\%hash,'form.element' ,\%env,'form.element'); 211: &setvalues(\%hash,'form.titleelement',\%env,'form.titleelement'); 212: &setvalues(\%hash,'form.only' ,\%env,'form.only' ); 213: &setvalues(\%hash,'form.omit' ,\%env,'form.omit' ); 214: 215: # Deal with 'omit' and 'only' 216: if (exists $env{'form.omit'}) { 217: @Omit = split(',',$env{'form.omit'}); 218: } 219: if (exists $env{'form.only'}) { 220: @Only = split(',',$env{'form.only'}); 221: } 222: 223: my $mode = $env{'form.mode'}; 224: my ($form,$element,$titleelement); 225: if ($mode eq 'edit' || $mode eq 'parmset') { 226: $form = $env{'form.form'}; 227: $element = $env{'form.element'}; 228: $titleelement = $env{'form.titleelement'}; 229: } 230: #&Apache::lonxml::debug("mode=$mode form=$form element=$element titleelement=$titleelement"); 231: # ------ set catalogmodefunctions to have extra needed javascript functionality 232: my $catalogmodefunctions=''; 233: if ($env{'form.catalogmode'} eq 'interactive' or 234: $env{'form.catalogmode'} eq 'import') { 235: # The if statement below sets us up to use the old version 236: # by default (ie. if $mode is undefined). This is the easy 237: # way out. Hopefully in the future I'll find a way to get 238: # the calls dealt with in a more comprehensive manner. 239: 240: # 241: # There is now also mode "simple", which is for the simple version of the rat 242: # 243: # 244: if (!defined($mode) || ($mode ne 'edit' && $mode ne 'parmset')) { 245: my $location = "/adm/groupsort?catalogmode=import&"; 246: $location .= "mode=".$mode."&"; 247: $location .= "acts="; 248: $catalogmodefunctions=<<"END"; 249: function select_data(url) { 250: changeURL(url); 251: self.close(); 252: } 253: function select_group() { 254: window.location="$location"+document.forms.fileattr.acts.value; 255: } 256: function changeURL(val) { 257: if (opener.inf) { 258: if (opener.inf.document.forms.resinfo.elements.u) { 259: opener.inf.document.forms.resinfo.elements.u.value=val; 260: } 261: } 262: } 263: END 264: } elsif ($mode eq 'edit') { # we are in 'edit' mode 265: my $location = "/adm/groupsort?catalogmode=interactive&"; 266: $location .= "form=$form&element=$element&mode=edit&acts="; 267: $catalogmodefunctions=<<END; 268: // mode = $mode 269: function select_data(url) { 270: var location = "/res/?launch=2&form=$form&element=$element&titleelement=$titleelement&acts=" + url; 271: window.location=location; 272: } 273: function select_group() { 274: window.location="$location"+document.forms.fileattr.acts.value; 275: } 276: 277: function changeURL(val) { 278: if (window.opener.document) { 279: window.opener.document.forms["$form"].elements["$element"].value=val; 280: } else { 281: alert("The file you selected is: "+val); 282: } 283: } 284: END 285: if (!$titleelement) { 286: $catalogmodefunctions.='function changeTitle(val) {}'; 287: } else { 288: $catalogmodefunctions.=<<END; 289: function changeTitle(val) { 290: if (window.opener.document) { 291: window.opener.document.forms["$form"].elements["$titleelement"].value=val; 292: } else { 293: alert("The title of the file you selected is: "+val); 294: } 295: } 296: END 297: } 298: } elsif ($mode eq 'parmset') { 299: my $location = "/adm/groupsort?catalogmode=interactive&"; 300: $location .= "form=$form&element=$element&mode=parmset&acts="; 301: $catalogmodefunctions=<<END; 302: // mode = $mode 303: function select_data(url) { 304: changeURL(url); 305: self.close(); 306: } 307: 308: function select_group() { 309: window.location="$location"+document.forms.fileattr.acts.value; 310: } 311: 312: function changeURL(val) { 313: if (window.opener.document) { 314: var elementname = "$element"+"_value"; 315: var checkboxname = "$element"+"_setparmval"; 316: window.opener.document.forms["$form"].elements[elementname].value=val; 317: window.opener.document.forms["$form"].elements[checkboxname].checked=true; 318: } else { 319: alert("The file you selected is: "+val); 320: } 321: } 322: 323: END 324: } 325: } 326: $catalogmodefunctions.=<<END; 327: var acts=''; 328: function rep_dirpath(suffix,val) { 329: eval("document.forms.dirpath"+suffix+".acts.value=val"); 330: } 331: END 332: if ($env{'form.catalogmode'} eq 'import') { 333: $catalogmodefunctions.=<<END; 334: function queue(val) { 335: if (eval("document.forms."+val+".filelink.checked")) { 336: var l=val.length; 337: var v=val.substring(4,l); 338: document.forms.fileattr.acts.value+='1a'+v+'b'; 339: } 340: else { 341: var l=val.length; 342: var v=val.substring(4,l); 343: document.forms.fileattr.acts.value+='0a'+v+'b'; 344: } 345: } 346: END 347: } 348: 349: # ---------------------------------------------------------------- Print Header 350: my $js = <<"ENDHEADER"; 351: <script type="text/javascript"> 352: $catalogmodefunctions 353: function openWindow(url, wdwName, w, h, toolbar,scrollbar,locationbar) { 354: var xpos = (screen.width-w)/2; 355: xpos = (xpos < 0) ? '0' : xpos; 356: var ypos = (screen.height-h)/2-30; 357: ypos = (ypos < 0) ? '0' : ypos; 358: var options = "width=" + w + ",height=" + h + ",screenx="+xpos+",screeny="+ypos+","; 359: options += "resizable=yes,scrollbars="+scrollbar+",status=no,"; 360: options += "menubar=no,toolbar="+toolbar+",location="+locationbar+",directories=no"; 361: var newWin = window.open(url, wdwName, options); 362: newWin.focus(); 363: } 364: function gothere(val) { 365: window.location=val+'?acts='+document.forms.fileattr.acts.value; 366: } 367: </script> 368: ENDHEADER 369: 370: my ($headerdom)=($uri=~m{^/res/($match_domain)/}); 371: $r->print(&Apache::loncommon::start_page('Browse Resources',$js, 372: {'domain' => $headerdom,})); 373: # - Evaluate actions from previous page (both cumulatively and chronologically) 374: if ($env{'form.catalogmode'} eq 'import') { 375: my $acts=$env{'form.acts'}; 376: my @Acts=split(/b/,$acts); 377: my %ahash; 378: my %achash; 379: my $ac=0; 380: # some initial hashes for working with data 381: foreach (@Acts) { 382: my ($state,$ref)=split(/a/); 383: $ahash{$ref}=$state; 384: $achash{$ref}=$ac; 385: $ac++; 386: } 387: # sorting through the actions and changing the global database hash 388: foreach (sort {$achash{$a}<=>$achash{$b}} (keys %ahash)) { 389: my $key=$_; 390: if ($ahash{$key} eq '1') { 391: $hash{'store_'.$hash{'pre_'.$key.'_link'}}= 392: $hash{'pre_'.$key.'_title'}; 393: $hash{'storectr_'.$hash{'pre_'.$key.'_link'}}= 394: $hash{'storectr'}+0; 395: $hash{'storectr'}++; 396: } 397: if ($ahash{$key} eq '0') { 398: if ($hash{'store_'.$hash{'pre_'.$key.'_link'}}) { 399: delete $hash{'store_'.$hash{'pre_'.$key.'_link'}}; 400: } 401: } 402: } 403: # deleting the previously cached listing 404: foreach (keys %hash) { 405: if ($_ =~ /^pre_/ && $_ =~/link$/) { 406: my $key = $_; 407: $key =~ s/^pre_//; 408: $key =~ s/_[^_]*$//; 409: delete $hash{'pre_'.$key.'_title'}; 410: delete $hash{'pre_'.$key.'_link'}; 411: } 412: } 413: } 414: 415: # ---------------------------------- get state of file attributes to be showing 416: if ($env{'form.attrs'}) { 417: for (my $i=0; $i<=11; $i++) { 418: delete $hash{'display_attrs_'.$i}; 419: if ($env{'form.attr'.$i} == 1) { 420: $attrchk[$i] = 'checked'; 421: $hash{'display_attrs_'.$i} = 1; 422: } 423: } 424: } else { 425: for (my $i=0; $i<=11; $i++) { 426: $attrchk[$i] = 'checked' if $hash{'display_attrs_'.$i} == 1; 427: } 428: } 429: 430: # ------------------------------- output state of file attributes to be showing 431: # All versions has to the last item 432: # since it does not take an extra col 433: my %lt=&Apache::lonlocal::texthash( 434: 'ti' => 'Title', 435: 'si' => 'Size', 436: 'la' => 'Last access', 437: 'lm' => 'Last modified', 438: 'st' => 'Statistics', 439: 'au' => 'Author', 440: 'kw' => 'Keywords', 441: 'ln' => 'Language', 442: 'sa' => 'Source Available', 443: 'sr' => 'Show resource', 444: 'li' => 'Linked/Related Resources', 445: 'av' => 'All versions', 446: 'ud' => 'Update Display' 447: ); 448: $r->print(<<END); 449: <form method="post" name="fileattr" action="$uri" 450: enctype="application/x-www-form-urlencoded"> 451: <label><input type="checkbox" name="attr9" value="1" $attrchk[9] onClick="this.form.submit();" /> $lt{'av'}</label> 452: <table border="0"> 453: <tr> 454: <td><label><input type="checkbox" name="attr0" value="1" $attrchk[0] onClick="this.form.submit();" /> $lt{'ti'}</label></td> 455: <td><label><input type="checkbox" name="attr4" value="1" $attrchk[4] onClick="this.form.submit();" /> $lt{'au'}</label></td> 456: <td><label><input type="checkbox" name="attr5" value="1" $attrchk[5] onClick="this.form.submit();" /> $lt{'kw'}</label></td> 457: <td><label><input type="checkbox" name="attr6" value="1" $attrchk[6] onClick="this.form.submit();" /> $lt{'ln'}</label></td> 458: </tr> 459: <tr> 460: <td><label><input type="checkbox" name="attr1" value="1" $attrchk[1] onClick="this.form.submit();" /> $lt{'si'}</label></td> 461: <td><label><input type="checkbox" name="attr2" value="1" $attrchk[2] onClick="this.form.submit();" /> $lt{'la'}</label></td> 462: <td><label><input type="checkbox" name="attr3" value="1" $attrchk[3] onClick="this.form.submit();" /> $lt{'lm'}</label></td> 463: <td><label><input type="checkbox" name="attr10" value="1" $attrchk[10] onClick="this.form.submit();" /> $lt{'sa'}</label></td> 464: </tr> 465: <tr> 466: <td><label><input type="checkbox" name="attr8" value="1" $attrchk[8] onClick="this.form.submit();" /> $lt{'st'}</label></td> 467: <td><label><input type="checkbox" name="attr11" value="1" $attrchk[11] onClick="this.form.submit();" /> $lt{'li'}</label></td> 468: <td><label><input type="checkbox" name="attr7" value="1" $attrchk[7] onClick="this.form.submit();" /> $lt{'sr'}</label></td> 469: <td> </td> 470: </tr> 471: </table> 472: <input type="hidden" name="attrs" value="1" /> 473: <input type="submit" name="updatedisplay" value="$lt{'ud'}" /> 474: <input type="hidden" name="acts" value="" /> 475: $closebutton $groupimportbutton 476: END 477: # -------------- Filter out sequence containment in crumbs and "recent folders" 478: my $storeuri=$uri; 479: $storeuri='/'.(split(/\.(page|sequence)\/\//,$uri))[-1]; 480: $storeuri=~s/\/+/\//g; 481: # ---------------------------------------------------------------- Bread crumbs 482: $r->print(&Apache::lonhtmlcommon::crumbs($storeuri,'','', 483: (($env{'form.catalogmode'} eq 'import')? 484: 'document.forms.fileattr':'')). 485: &Apache::lonhtmlcommon::select_recent('residx','resrecent', 486: '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();')); 487: # -------------------------------------------------------- Resource Home Button 488: my $reshome=$env{'course.'.$env{'request.course.id'}.'.reshome'}; 489: if ($reshome) { 490: $r->print("<font size='+2'><a href='"); 491: if ($env{'form.catalogmode'} eq 'import') { 492: $r->print('javascript:document.forms.fileattr.action="'.$reshome.'";document.forms.fileattr.submit();'); 493: } else { 494: $r->print($reshome); 495: } 496: $r->print("'>".&mt('Home').'</a></font>'); 497: } 498: $r->print('</form>'); 499: # ------------------------------------------------------ Remember where we were 500: &Apache::loncommon::storeresurl($storeuri); 501: &Apache::lonhtmlcommon::store_recent('residx',$storeuri,$storeuri); 502: # ----------------- output starting row to the indexed file/directory hierarchy 503: my $titleclr="#ddffff"; 504: #$r->print(&initdebug()); 505: #$r->print(&writedebug("Omit:@Omit")) if (@Omit); 506: #$r->print(&writedebug("Only:@Only")) if (@Only); 507: $r->print('<table width="100%" border="0"><tr><td bgcolor="#777777">'."\n"); 508: $r->print('<table width="100%" border="0"><tr bgcolor="'.$titleclr.'">'."\n"); 509: $r->print("<td $colspan><b>".&mt('Name')."</b></td>\n"); 510: $r->print("<td><b>".&mt('Title')."</b></td>\n") 511: if ($hash{'display_attrs_0'} == 1); 512: $r->print("<td align=right><b>".&mt("Size")." (".&mt("bytes").") ". 513: "</b></td>\n") if ($hash{'display_attrs_1'} == 1); 514: $r->print("<td><b>".&mt("Last accessed")."</b></td>\n") 515: if ($hash{'display_attrs_2'} == 1); 516: $r->print("<td><b>".&mt("Last modified")."</b></td>\n") 517: if ($hash{'display_attrs_3'} == 1); 518: $r->print("<td><b>".&mt("Author(s)")."</b></td>\n") 519: if ($hash{'display_attrs_4'} == 1); 520: $r->print("<td><b>".&mt("Keywords")."</b></td>\n") 521: if ($hash{'display_attrs_5'} == 1); 522: $r->print("<td><b>".&mt("Language")."</b></td>\n") 523: if ($hash{'display_attrs_6'} == 1); 524: $r->print("<td><b>".&mt("Usage Statistics")." <br />(". 525: &mt("Courses/Network Hits").")</b> ".&mt('updated periodically')."</td>\n") 526: if ($hash{'display_attrs_8'} == 1); 527: $r->print("<td><b>".&mt("Source Available")."</b></td>\n") 528: if ($hash{'display_attrs_10'} == 1); 529: $r->print("<td><b>".&mt("Linked/Related Resources")."</b></td>\n") 530: if ($hash{'display_attrs_11'} == 1); 531: $r->print("<td><b>".&mt("Resource")."</b></td>\n") 532: if ($hash{'display_attrs_7'} == 1); 533: $r->print('</tr>'); 534: 535: # ----------------- read in what directories have previously been set to "open" 536: foreach (keys %hash) { 537: if ($_ =~ /^diropen_status_/) { 538: my $key = $_; 539: $key =~ s/^diropen_status_//; 540: $dirs{$key} = $hash{$_}; 541: } 542: } 543: 544: if ($env{'form.openuri'}) { # take care of review and refresh options 545: my $uri=$env{'form.openuri'}; 546: if (exists($hash{'diropen_status_'.$uri})) { 547: my $cursta = $hash{'diropen_status_'.$uri}; 548: $dirs{$uri} = 'open'; 549: $hash{'diropen_status_'.$uri} = 'open'; 550: if ($cursta eq 'open') { 551: $dirs{$uri} = 'closed'; 552: $hash{'diropen_status_'.$uri} = 'closed'; 553: } 554: } else { 555: $hash{'diropen_status_'.$uri} = 'open'; 556: $dirs{$uri} = 'open'; 557: } 558: } 559: 560: my $toplevel; 561: my $indent = 0; 562: $uri = $uri.'/' if $uri !~ /.*\/$/; 563: 564: if ($env{'form.dirPointer'} ne 'on') { 565: $hash{'top.level'} = $uri; 566: $toplevel = $uri; 567: } else { 568: $toplevel = $hash{'top.level'}; 569: } 570: 571: # -------------------------------- if not at top level, provide an uplink arrow 572: if ($toplevel ne '/res/'){ 573: my (@uri_com) = split(/\//,$uri); 574: pop @uri_com; 575: my $upone = join('/',@uri_com); 576: my @list = qw (0); 577: &display_line ($r,'opened',$upone.'&viewOneUp',0,$upone,@list); 578: $indent = 1; 579: } 580: 581: # -------- recursively go through all the directories and output as appropriate 582: &scanDir ($r,$toplevel,$indent,\%hash); 583: 584: 585: # -------------------------------------------------------------- end the tables 586: $r->print('</table>'); 587: # ---------------------------- embed hidden information useful for group import 588: $r->print("<form name='fnum' action=''>"); 589: $r->print("<input type='hidden' name='fnum' value='$fnum' /></form>"); 590: # -------------------------------------------------------------- end the tables 591: $r->print('</td></tr></table>'); 592: 593: # --------------------------------------------------- end the output and return 594: $r->print(&Apache::loncommon::end_page()."\n"); 595: } 596: if(! $c->aborted()) { 597: # write back into the temporary file 598: my %dbfile; 599: if (tie(%dbfile,'GDBM_File',$diropendb,&GDBM_NEWDB(),0640)) { 600: while (my($key,$value) = each(%hash)) { 601: $dbfile{$key}=$value; 602: } 603: untie(%dbfile); 604: } 605: } 606: 607: return OK; 608: } 609: 610: # ----------------------------------------------- recursive scan of a directory 611: sub scanDir { 612: my ($r,$startdir,$indent,$hashref)=@_; 613: my $c = $r->connection(); 614: my ($compuri,$curdir); 615: my $dirptr=16384; 616: my $obs; 617: $indent++; 618: my %dupdirs = %dirs; 619: my @list=&get_list($r,$startdir); 620: foreach my $line (@list) { 621: return if ($c->aborted()); 622: #This is a kludge, sorry aboot this 623: my ($strip,$dom,undef,$testdir,undef,undef,undef,undef,undef,undef,undef,undef,undef,undef,$obs,undef)=split(/\&/,$line,16); 624: next if($strip =~ /.*\.meta$/ | $obs eq '1'); 625: my (@fileparts) = split(/\./,$strip); 626: if ($hash{'display_attrs_9'} != 1) { 627: # if not all versions to be shown 628: if (scalar(@fileparts) >= 3) { 629: my $fext = pop @fileparts; 630: my $ov = pop @fileparts; 631: my $fname = join ('.',@fileparts,$fext); 632: next if (grep /\Q$fname\E/,@list and $ov =~ /^\d+$/); 633: } 634: } 635: 636: if ($dom eq 'domain') { 637: # dom list has full path /res/<domain name>/ already 638: $curdir=''; 639: $compuri = (split(/\&/,$line))[0]; 640: } else { 641: # user, dir & file have name only, i.e., w/o path 642: $compuri = join('',$startdir,$strip,'/'); 643: $curdir = $startdir; 644: } 645: my $diropen = 'closed'; 646: if (($dirptr&$testdir) or ($dom =~ /^(domain|user)$/) or ($compuri=~/\.(sequence|page)\/$/)) { 647: while (my ($key,$val)= each %dupdirs) { 648: if ($key eq $compuri and $val eq "open") { 649: $diropen = "opened"; 650: delete($dupdirs{$key}); 651: delete($dirs{$key}); 652: } 653: } 654: } 655: &display_line($r,$diropen,$line,$indent,$curdir,$hashref,@list); 656: &scanDir ($r,$compuri,$indent) if $diropen eq 'opened'; 657: } 658: $indent--; 659: } 660: 661: # --------------- get complete matched list based on the uri (returns an array) 662: sub get_list { 663: my ($r,$uri)=@_; 664: my @list=(); 665: (my $luri = $uri) =~ s/\//_/g; 666: if ($env{'form.updatedisplay'}) { 667: foreach (keys %hash) { 668: delete $hash{$_} if ($_ =~ /^dirlist_files_/); 669: delete $hash{$_} if ($_ =~ /^dirlist_timestamp_files_/); 670: } 671: } 672: 673: if (defined($hash{'dirlist_files_'.$luri}) && 674: $hash{'dirlist_timestamp_files_'.$luri}+600 > (time)) { 675: @list = split(/\n/,$hash{'dirlist_files_'.$luri}); 676: } elsif ($uri=~/\.(page|sequence)\/$/) { 677: # is a page or a sequence 678: $uri=~s/\/$//; 679: $uri='/'.(split(/\.(page|sequence)\/\//,$uri))[-1]; 680: $uri=~s/\/+/\//g; 681: foreach (&Apache::lonsequence::attemptread(&Apache::lonnet::filelocation('',$uri))) { 682: my @ratpart=split(/\:/,$_); 683: push @list,$ratpart[1]; 684: } 685: $hash{'dirlist_files_'.$luri} = join("\n",@list); 686: } else { 687: # is really a directory 688: @list = &Apache::lonnet::dirlist($uri); 689: $hash{'dirlist_files_'.$luri} = join("\n",@list); 690: $hash{'dirlist_timestamp_files_'.$luri} = time; 691: } 692: return @list=&match_ext($r,@list); 693: } 694: 695: sub dynmetaread { 696: my $uri=shift; 697: if (($hash{'display_attrs_8'}==1) || ($hash{'display_attrs_11'}==1)) { 698: # We don't want the filename 699: $uri=~s/\/[^\/]+$//; 700: # Did we already see this? 701: my $builddir=$uri; 702: while ($builddir) { 703: if ($dynread{$builddir}) { 704: return 0; 705: } 706: $builddir=~s/\/[^\/]+$//; 707: } 708: # Actually get the data 709: %dynhash= 710: (%dynhash,&Apache::lonmeta::get_dynamic_metadata_from_sql($uri.'/')); 711: # Remember that we got it 712: $dynread{$uri}=1; 713: } 714: } 715: 716: sub initdebug { 717: my $start_page= 718: &Apache::loncommon::start_page('Debug',undef, 719: {'only_body' => 1,}); 720: $start_page =~ s/\n/ /g; 721: return <<ENDJS; 722: <script type="text/javascript"> 723: var debugging = true; 724: if (debugging) { 725: var debuggingWindow = window.open('','Debug','width=400,height=300',true); 726: } 727: 728: function output(text) { 729: if (debugging) { 730: debuggingWindow.document.writeln(text); 731: } 732: } 733: output('$start_page<pre>'); 734: </script> 735: ENDJS 736: } 737: 738: sub writedebug { 739: my ($text) = @_; 740: return "<script type=\"text/javascript\">output('$text');</script>"; 741: } 742: 743: # -------------------- filters out files based on extensions (returns an array) 744: sub match_ext { 745: my ($r,@packlist)=@_; 746: my @trimlist; 747: my $nextline; 748: my @fileext; 749: my $dirptr=16384; 750: 751: foreach my $line (@packlist) { 752: chomp $line; 753: $line =~ s/^\/home\/httpd\/html//; 754: my @unpackline = split (/\&/,$line); 755: next if ($unpackline[0] eq '.'); 756: next if ($unpackline[0] eq '..'); 757: my @filecom = split (/\./,$unpackline[0]); 758: my $fext = pop(@filecom); 759: my $fnptr = ($unpackline[3]&$dirptr) || ($fext=~/\.(page|sequence)$/); 760: if ($fnptr == 0 and $unpackline[3] ne "") { 761: my $embstyle = &Apache::loncommon::fileembstyle($fext); 762: push @trimlist,$line if (defined($embstyle) && 763: ($embstyle ne 'hdn' or $fext eq 'meta')); 764: } else { 765: push @trimlist,$line; 766: } 767: } 768: @trimlist = sort {uc($a) cmp uc($b)} (@trimlist); 769: return @trimlist; 770: } 771: 772: # ------------------------------- displays one line in appropriate table format 773: sub display_line { 774: my ($r,$diropen,$line,$indent,$startdir,$hashref,@list)=@_; 775: my (@pathfn, $fndir); 776: # there could be relative paths (files actually belonging into this directory) 777: # or absolute paths (for example, from sequences) 778: my $absolute; 779: my $pathprefix; 780: if ($line=~m|^/res/| && $startdir ne '') { 781: $absolute=1; 782: $pathprefix=''; 783: } else { 784: $absolute=0; 785: $pathprefix=$startdir; 786: } 787: my $dirptr=16384; 788: my $fileclr="#ffffe6"; 789: my $iconpath= $r->dir_config('lonIconsURL') . '/'; 790: 791: my @filecom = split (/\&/,$line); 792: my @pathcom = split (/\//,$filecom[0]); 793: my $listname = $pathcom[scalar(@pathcom)-1]; 794: my $fnptr = $filecom[3]&$dirptr; 795: my $msg = &mt('View').' '.$filecom[0].' '.&mt('resources'); 796: $msg = &mt('Close').' '.$filecom[0].' '.&mt('directory') if $diropen eq 'opened'; 797: 798: my $tabtag='</td>'; 799: my $i=0; 800: while ($i<=11) { 801: $tabtag=join('',$tabtag,"<td> </td>") 802: if $hash{'display_attrs_'.$i} == 1; 803: $i++; 804: } 805: my $valign = ($hash{'display_attrs_7'} == 1 ? 'top' : 'bottom'); 806: 807: # display uplink arrow 808: if ($filecom[1] eq 'viewOneUp') { 809: my $updir=$startdir; 810: # -------------- Filter out sequence containment in crumbs and "recent folders" 811: $updir='/'.(split(/\.(page|sequence)\/\//,$startdir))[-1]; 812: $updir=~s/\/+/\//g; 813: 814: $r->print("<tr valign='$valign' bgcolor=$fileclr>$extrafield"); 815: $r->print("<td>\n"); 816: $r->print ('<form method="post" name="dirpathUP" action="'.$updir. 817: '/" '. 818: 'onSubmit="return rep_dirpath(\'UP\','. 819: 'document.forms.fileattr.acts.value)" '. 820: 'enctype="application/x-www-form-urlencoded"'. 821: '>'."\n"); 822: $r->print ('<input type=hidden name=openuri value="'. 823: $startdir.'" />'."\n"); 824: $r->print ('<input type="hidden" name="acts" value="" />'."\n"); 825: $r->print ('<input src="'.$iconpath.'arrow_up.gif"'); 826: $r->print (' name="'.$msg.'" height="22" type="image" border="0" />'. 827: "\n"); 828: $r->print(&mt("Up")."</form>$tabtag</tr>\n"); 829: return OK; 830: } 831: # Do we have permission to look at this? 832: 833: if($filecom[15] ne '1') { return OK if (!&Apache::lonnet::allowed('bre',$pathprefix.$filecom[0])); } 834: 835: # make absolute links appear on different background 836: if ($absolute) { $fileclr='#ccdd99'; } 837: 838: # display domain 839: if ($filecom[1] eq 'domain') { 840: $r->print ('<input type="hidden" name="dirPointer" value="on" />'."\n") 841: if ($env{'form.dirPointer'} eq "on"); 842: $r->print("<tr valign='$valign' bgcolor=$fileclr>$extrafield"); 843: $r->print("<td>"); 844: &begin_form ($r,$filecom[0]); 845: my $anchor = $filecom[0]; 846: $anchor =~ s/\///g; 847: $r->print ('<a name="'.$anchor.'"></a>'); 848: $r->print ('<input type="hidden" name="acts" value="" />'); 849: $r->print ('<input src="'.$iconpath.'folder_pointer_'. 850: $diropen.'.gif"'); 851: $r->print (' name="'.$msg.'" height="22" type="image" border="0" />'. 852: "\n"); 853: my $quotable_filecom = &Apache::loncommon::escape_single($filecom[0]); 854: $r->print ('<a href="javascript:gothere(\''.$quotable_filecom. 855: '\')"><img alt="" src="'.$iconpath.'server.gif"'); 856: $r->print (' border="0" /></a>'."\n"); 857: $r->print (&mt("Domain")." - $listname "); 858: if ($Apache::lonnet::domaindescription{$listname}) { 859: $r->print("(".$Apache::lonnet::domaindescription{$listname}. 860: ")"); 861: } 862: $r->print ("</form>$tabtag</tr>\n"); 863: return OK; 864: 865: # display user directory 866: } 867: if ($filecom[1] eq 'user') { 868: $r->print("<tr valign=$valign bgcolor=$fileclr>$extrafield"); 869: $r->print("<td nowrap>\n"); 870: my $curdir = $startdir.$filecom[0].'/'; 871: my $anchor = $curdir; 872: $anchor =~ s/\///g; 873: &begin_form ($r,$curdir); 874: $r->print ('<a name="'.$anchor.'"></a><img alt="" src="'.$iconpath. 875: 'whitespace1.gif" border="0" />'."\n"); 876: $r->print ('<input type="hidden" name="acts" value="" />'); 877: $r->print ('<input src="'.$iconpath.'folder_pointer_'.$diropen. 878: '.gif"'); 879: $r->print (' name="'.$msg.'" height="22" type="image" border="0" />'. 880: "\n"); 881: my $quotable_curdir = &Apache::loncommon::escape_single($curdir); 882: $r->print ('<a href="javascript:gothere(\''.$quotable_curdir 883: .'\')"><img alt="" src='. 884: $iconpath.'quill.gif border="0" name="'.$msg. 885: '" height="22" /></a>'); 886: my $domain=(split(m|/|,$startdir))[2]; 887: my $plainname=&Apache::loncommon::plainname($listname,$domain); 888: $r->print ($listname); 889: if (defined($plainname) && $plainname) { $r->print(" ($plainname) "); } 890: $r->print ('</form>'.$tabtag.'</tr>'."\n"); 891: return OK; 892: } 893: 894: # display file 895: if (($fnptr == 0 and $filecom[3] ne '') or $absolute) { 896: my $filelink = $pathprefix.$filecom[0]; 897: my @file_ext = split (/\./,$listname); 898: my $curfext = $file_ext[-1]; 899: if (@Omit) { 900: foreach (@Omit) { return OK if ($curfext eq $_); } 901: } 902: if (@Only) { 903: my $skip = 1; 904: foreach (@Only) { $skip = 0 if ($curfext eq $_); } 905: return OK if ($skip > 0); 906: } 907: # Set the icon for the file 908: my $iconname = &Apache::loncommon::icon($listname); 909: $r->print("<tr valign='$valign' bgcolor=$fileclr><td nowrap='nowrap' valign='top'>"); 910: 911: if ($env{'form.catalogmode'} eq 'interactive') { 912: my $quotable_filelink = &Apache::loncommon::escape_single($filelink); 913: $r->print("<a href=\"javascript:select_data(\'", 914: $quotable_filelink,"')\">"); 915: $r->print("<img alt=\"\" src='",$iconpath,"select.gif' border='0' /></a>". 916: "\n"); 917: $r->print("</td><td nowrap='nowrap' valign='top'>"); 918: } elsif ($env{'form.catalogmode'} eq 'import') { 919: $r->print("<form name='form$fnum' action=''>\n"); 920: $r->print("<input type='checkbox' name='filelink"."' ". 921: "value='$filelink' onClick='". 922: "javascript:queue(\"form$fnum\")' "); 923: if ($hash{'store_'.$filelink}) { 924: $r->print("checked"); 925: } 926: $r->print(" />\n"); 927: $r->print("</form></td><td nowrap='nowrap' valign='top'>"); 928: $hash{"pre_${fnum}_link"}=$filelink; 929: $fnum++; 930: } 931: # Form to open or close sequences 932: if ($filelink=~/\.(page|sequence)$/) { 933: my $curdir = $startdir.$filecom[0].'/'; 934: my $anchor = $curdir; 935: $anchor =~ s/\///g; 936: &begin_form($r,$curdir); 937: $indent--; 938: } 939: # General indentation 940: if ($indent > 0 and $indent < 11) { 941: $r->print("<img alt=\"\" src=",$iconpath,"whitespace",$indent, 942: ".gif border='0' />\n"); 943: } elsif ($indent >0) { 944: my $ten = int($indent/10.); 945: my $rem = $indent%10.0; 946: my $count = 0; 947: while ($count < $ten) { 948: $r->print("<img alt=\"\" src=",$iconpath, 949: "whitespace10.gif border='0' />\n"); 950: $count++; 951: } 952: $r->print("<img alt=\"\" src=",$iconpath,"whitespace",$rem, 953: ".gif border='0' />\n") if $rem > 0; 954: } 955: # Sequence open/close icon 956: if ($filelink=~/\.(page|sequence)$/) { 957: my $curdir = $startdir.$filecom[0].'/'; 958: my $anchor = $curdir; 959: $anchor =~ s/\///g; 960: $r->print ('<input type="hidden" name="acts" value="" />'); 961: $r->print ('<a name="'.$anchor.'"></a><input src="'.$iconpath. 962: 'folder_pointer_'.$diropen.'.gif"'); 963: $r->print (' name="'.$msg.'" height="22" type="image" border="0" />'. 964: "\n"); 965: } 966: # Filetype icons 967: $r->print("<img alt=\"\" src='$iconname' border='0' />\n"); 968: my $quotable_filelink = &Apache::loncommon::escape_single($filelink); 969: 970: 971: $r->print (" <a href=\"javascript:openWindow('".$quotable_filelink. 972: "', 'previewfile', '450', '500', 'no', 'yes','yes');\"". 973: " target=\"_self\">$listname</a> "); 974: 975: $r->print (" (<a href=\"javascript:openWindow('".$quotable_filelink. 976: ".meta', 'metadatafile', '500', '550', 'no', 'yes','no');\" ". 977: " target=\"_self\">metadata</a>) "); 978: # Close form to open/close sequence 979: if ($filelink=~/\.(page|sequence)$/) { 980: $r->print('</form>'); 981: } 982: $r->print("</td>\n"); 983: if ($hash{'display_attrs_0'} == 1) { 984: my $title = &Apache::lonnet::gettitle($filelink,'title'); 985: $r->print('<td> '.($title eq '' ? ' ' : $title). 986: ' </td>'."\n"); 987: } 988: $r->print('<td align=right> ', 989: $filecom[8]," </td>\n") 990: if $hash{'display_attrs_1'} == 1; 991: $r->print('<td> '. 992: (localtime($filecom[9]))." </td>\n") 993: if $hash{'display_attrs_2'} == 1; 994: $r->print('<td> '. 995: (localtime($filecom[10]))." </td>\n") 996: if $hash{'display_attrs_3'} == 1; 997: 998: if ($hash{'display_attrs_4'} == 1) { 999: my $author = &Apache::lonnet::metadata($filelink,'author'); 1000: $r->print('<td> '.($author eq '' ? ' ' : $author). 1001: " </td>\n"); 1002: } 1003: if ($hash{'display_attrs_5'} == 1) { 1004: my $keywords = &Apache::lonnet::metadata($filelink,'keywords'); 1005: # $keywords = ' ' if (!$keywords); 1006: $r->print('<td> '.($keywords eq '' ? ' ' : $keywords). 1007: " </td>\n"); 1008: } 1009: #' 1010: 1011: if ($hash{'display_attrs_6'} == 1) { 1012: my $lang = &Apache::lonnet::metadata($filelink,'language'); 1013: $lang = &Apache::loncommon::languagedescription($lang); 1014: $r->print('<td> '.($lang eq '' ? ' ' : $lang). 1015: " </td>\n"); 1016: } 1017: if ($hash{'display_attrs_8'} == 1) { 1018: # statistics 1019: &dynmetaread($filelink); 1020: $r->print("<td>"); 1021: &dynmetaprint($r,$filelink,'count'); 1022: &dynmetaprint($r,$filelink,'course'); 1023: &dynmetaprint($r,$filelink,'stdno'); 1024: &dynmetaprint($r,$filelink,'avetries'); 1025: &dynmetaprint($r,$filelink,'difficulty'); 1026: &dynmetaprint($r,$filelink,'disc'); 1027: &dynmetaprint($r,$filelink,'clear'); 1028: &dynmetaprint($r,$filelink,'technical'); 1029: &dynmetaprint($r,$filelink,'correct'); 1030: &dynmetaprint($r,$filelink,'helpful'); 1031: &dynmetaprint($r,$filelink,'depth'); 1032: $r->print(" </td>\n"); 1033: 1034: } 1035: if ($hash{'display_attrs_10'} == 1) { 1036: my $source = &Apache::lonnet::metadata($filelink,'sourceavail'); 1037: if($source eq 'open') { 1038: my $sourcelink = &Apache::lonsource::make_link($filelink,$listname); 1039: my $quotable_sourcelink = &Apache::loncommon::escape_single($sourcelink); 1040: $r->print('<td>'."<a href=\"javascript:openWindow('" 1041: .$quotable_sourcelink. 1042: "', 'previewsource', '700', '700', 'no', 'yes','yes');\"". 1043: " target=\"_self\">Yes</a> "."</td>\n"); 1044: } else { #A cuddled else. :P 1045: $r->print("<td> </td>\n"); 1046: } 1047: } 1048: if ($hash{'display_attrs_11'} == 1) { 1049: # links 1050: &dynmetaread($filelink); 1051: $r->print('<td>'); 1052: &coursecontext($r,$filelink); 1053: &dynmetaprint($r,$filelink,'goto_list'); 1054: &dynmetaprint($r,$filelink,'comefrom_list'); 1055: &dynmetaprint($r,$filelink,'sequsage_list'); 1056: &dynmetaprint($r,$filelink,'dependencies'); 1057: &dynmetaprint($r,$filelink,'course_list'); 1058: $r->print('</td>'); 1059: } 1060: if ($hash{'display_attrs_7'} == 1) { 1061: # Show resource 1062: my $output=&showpreview($filelink); 1063: $r->print('<td> '.($output eq '' ? ' ':$output). 1064: " </td>\n"); 1065: } 1066: $r->print("</tr>\n"); 1067: } 1068: 1069: # -- display directory 1070: if ($fnptr == $dirptr) { 1071: my $curdir = $startdir.$filecom[0].'/'; 1072: my $anchor = $curdir; 1073: $anchor =~ s/\///g; 1074: $r->print("<tr bgcolor=$fileclr>$extrafield<td valign=$valign>"); 1075: &begin_form ($r,$curdir); 1076: my $indentm1 = $indent-1; 1077: if ($indentm1 < 11 and $indentm1 > 0) { 1078: $r->print("<img alt=\"\" src=",$iconpath,"whitespace",$indentm1, 1079: ".gif border='0' />\n"); 1080: } else { 1081: my $ten = int($indentm1/10.); 1082: my $rem = $indentm1%10.0; 1083: my $count = 0; 1084: while ($count < $ten) { 1085: $r->print ("<img alt=\"\" src=",$iconpath 1086: ,"whitespace10.gif border='0' />\n"); 1087: $count++; 1088: } 1089: $r->print ("<img alt=\"\" src=",$iconpath,"whitespace",$rem, 1090: ".gif border='0' />\n") if $rem > 0; 1091: } 1092: $r->print ('<input type="hidden" name="acts" value="" />'); 1093: $r->print ('<a name="'.$anchor.'"></a><input src="'.$iconpath. 1094: 'folder_pointer_'.$diropen.'.gif"'); 1095: $r->print (' name="'.$msg.'" height="22" type="image" border="0" />'. 1096: "\n"); 1097: my $quotable_curdir = &Apache::loncommon::escape_single($curdir); 1098: $r->print ('<a href="javascript:gothere(\'' 1099: .$quotable_curdir.'\')">' 1100: .'<img alt="'.&mt('Open Folder').'"src="'. 1101: $iconpath.'folder_'.$diropen.'.gif" border="0" /></a>'. 1102: "\n"); 1103: $r->print ("$listname</form></td>\n"); 1104: # Attributes 1105: my $filelink = $startdir.$filecom[0].'/default'; 1106: 1107: if ($hash{'display_attrs_0'} == 1) { 1108: my $title = &Apache::lonnet::gettitle($filelink,'title'); 1109: $r->print('<td> '.($title eq '' ? ' ' : $title). 1110: ' </td>'."\n"); 1111: } 1112: $r->print('<td align=right> ', 1113: $filecom[8]," </td>\n") 1114: if $hash{'display_attrs_1'} == 1; 1115: $r->print('<td> '. 1116: (localtime($filecom[9]))." </td>\n") 1117: if $hash{'display_attrs_2'} == 1; 1118: $r->print('<td> '. 1119: (localtime($filecom[10]))." </td>\n") 1120: if $hash{'display_attrs_3'} == 1; 1121: 1122: if ($hash{'display_attrs_4'} == 1) { 1123: my $author = &Apache::lonnet::metadata($filelink,'author'); 1124: $r->print('<td> '.($author eq '' ? ' ' : $author). 1125: " </td>\n"); 1126: } 1127: if ($hash{'display_attrs_5'} == 1) { 1128: my $keywords = &Apache::lonnet::metadata($filelink,'keywords'); 1129: # $keywords = ' ' if (!$keywords); 1130: $r->print('<td> '.($keywords eq '' ? ' ' : $keywords). 1131: " </td>\n"); 1132: } 1133: if ($hash{'display_attrs_6'} == 1) { 1134: my $lang = &Apache::lonnet::metadata($filelink,'language'); 1135: $lang = &Apache::loncommon::languagedescription($lang); 1136: $r->print('<td> '.($lang eq '' ? ' ' : $lang). 1137: " </td>\n"); 1138: } 1139: if ($hash{'display_attrs_8'} == 1) { 1140: $r->print('<td> </td>'); 1141: } 1142: if ($hash{'display_attrs_10'} == 1) { 1143: $r->print('<td> </td>'); 1144: } 1145: if ($hash{'display_attrs_11'} == 1) { 1146: $r->print('<td> </td>'); 1147: } 1148: if ($hash{'display_attrs_7'} == 1) { 1149: $r->print('<td> </td>'); 1150: } 1151: $r->print('</tr>'); 1152: } 1153: 1154: } 1155: 1156: sub coursecontext { 1157: my ($r,$filelink)=@_; 1158: my $filesymb=&Apache::lonnet::symbread($filelink); 1159: if ($filesymb) { 1160: my ($map,$index,$resource)=&Apache::lonnet::decode_symb($filesymb); 1161: $r->print(&mt('Already in this course:<br />[_1] in folder/map [_2].<br />', 1162: &Apache::lonnet::gettitle($resource), 1163: &Apache::lonnet::gettitle($map))); 1164: } 1165: } 1166: 1167: sub showpreview { 1168: my ($filelink)=@_; 1169: if ($filelink=~m-^(/ext/|http://)-) { 1170: return &mt('External Resource, preview not enabled'); 1171: } 1172: my ($curfext)=($filelink=~/\.(\w+)$/); 1173: my $output=''; 1174: my $embstyle=&Apache::loncommon::fileembstyle($curfext); 1175: if ($embstyle eq 'ssi') { 1176: my $cache=$Apache::lonnet::perlvar{'lonDocRoot'}.$filelink. 1177: '.tmp'; 1178: if ((!$env{'form.updatedisplay'}) && 1179: (-e $cache)) { 1180: open(FH,$cache); 1181: $output=join("\n",<FH>); 1182: close(FH); 1183: } else { 1184: # In update display mode, remove old cache. This is done to retroactively 1185: # clean up course context renderings. 1186: if (-e $cache) { 1187: unlink($cache); 1188: } 1189: $output=&Apache::lonnet::ssi_body($filelink); 1190: # Is access denied? Don't render, don't store 1191: if ($output=~/LONCAPAACCESSCONTROLERRORSCREEN/s) { 1192: $output=''; 1193: # Was this rendered in course content? Don't store 1194: } elsif (!&Apache::lonnet::symbread($filelink)) { 1195: open(FH,">$cache"); 1196: print FH $output; 1197: close(FH); 1198: } 1199: } 1200: $output='<font size="-2">'.$output.'</font>'; 1201: } elsif ($embstyle eq 'img') { 1202: $output='<img alt="'.&mt('Preview').'" src="'.$filelink.'" />'; 1203: } elsif ($filelink=~m{^/res/($match_domain)/($match_username)/}) { 1204: $output='<img alt="'.&mt('Preview').'" src="http://'. 1205: $Apache::lonnet::hostname{&Apache::lonnet::homeserver($2,$1)}. 1206: '/cgi-bin/thumbnail.gif?url='.$filelink.'" />'; 1207: } 1208: return $output; 1209: } 1210: 1211: sub dynmetaprint { 1212: my ($r,$filelink,$item)=@_; 1213: if ($dynhash{$filelink}->{$item}) { 1214: $r->print("\n<br />".$fieldnames{$item}.': '. 1215: &Apache::lonmeta::prettyprint($item, 1216: $dynhash{$filelink}->{$item}, 1217: (($env{'form.catalogmode'} ne 'import')?'preview':''), 1218: '', 1219: (($env{'form.catalogmode'} eq 'import')?'document.forms.fileattr':''),1)); 1220: } 1221: } 1222: 1223: # ------------------- prints the beginning of a form for directory or file link 1224: sub begin_form { 1225: my ($r,$uri) = @_; 1226: my $anchor = $uri; 1227: $anchor =~ s/\///g; 1228: $r->print ('<form method="post" name="dirpath'.$dnum.'" action="'.$uri. 1229: '#'.$anchor. 1230: '" onSubmit="return rep_dirpath(\''.$dnum.'\''. 1231: ',document.forms.fileattr.acts.value)" '. 1232: 'enctype="application/x-www-form-urlencoded">'."\n"); 1233: $r->print ('<input type="hidden" name="openuri" value="'.$uri.'" />'. 1234: "\n"); 1235: $r->print ('<input type="hidden" name="dirPointer" value="on" />'."\n"); 1236: $dnum++; 1237: } 1238: 1239: # --------- settings whenever the user causes the indexer window to be launched 1240: sub start_fresh_session { 1241: my ($hash) = @_; 1242: delete $hash->{'form.catalogmode'}; 1243: delete $hash->{'form.mode'}; 1244: delete $hash->{'form.form'}; 1245: delete $hash->{'form.element'}; 1246: delete $hash->{'form.omit'}; 1247: delete $hash->{'form.only'}; 1248: foreach (keys %{$hash}) { 1249: delete $hash->{$_} if (/^(pre_|store)/); 1250: } 1251: } 1252: 1253: # ------------------------------------------------------------------- setvalues 1254: sub setvalues { 1255: # setvalues is used in registerurl to synchronize the database 1256: # hash and environment hashes 1257: my ($H1,$h1key,$H2,$h2key) =@_; 1258: # 1259: if (exists $H2->{$h2key}) { 1260: $H1->{$h1key} = $H2->{$h2key}; 1261: } elsif (exists $H1->{$h1key}) { 1262: $H2->{$h2key} = $H1->{$h1key}; 1263: } 1264: } 1265: 1266: 1; 1267: 1268: sub cleanup { 1269: if (tied(%hash)){ 1270: &Apache::lonnet::logthis('Cleanup indexer: hash'); 1271: } 1272: return OK; 1273: } 1274: 1275: 1276: 1277: 1278: 1279: =head1 NAME 1280: 1281: Apache::lonindexer - mod_perl module for cross server filesystem browsing 1282: 1283: =head1 SYNOPSIS 1284: 1285: Invoked by /etc/httpd/conf/srm.conf: 1286: 1287: <LocationMatch "^/res.*/$"> 1288: SetHandler perl-script 1289: PerlHandler Apache::lonindexer 1290: </LocationMatch> 1291: 1292: =head1 INTRODUCTION 1293: 1294: This module enables a scheme of browsing across a cross server. 1295: 1296: This is part of the LearningOnline Network with CAPA project 1297: described at http://www.lon-capa.org. 1298: 1299: =head1 BEGIN SUBROUTINE 1300: 1301: This routine is only run once after compilation. 1302: 1303: =over 4 1304: 1305: =item * 1306: 1307: Initializes %language hash table. 1308: 1309: =back 1310: 1311: =head1 HANDLER SUBROUTINE 1312: 1313: This routine is called by Apache and mod_perl. 1314: 1315: =over 4 1316: 1317: =item * 1318: 1319: read in machine configuration variables 1320: 1321: =item * 1322: 1323: see if called from an interactive mode 1324: 1325: =item * 1326: 1327: refresh environment with user database values (in %hash) 1328: 1329: =item * 1330: 1331: define extra fields and buttons in case of special mode 1332: 1333: =item * 1334: 1335: set catalogmodefunctions to have extra needed javascript functionality 1336: 1337: =item * 1338: 1339: print header 1340: 1341: =item * 1342: 1343: evaluate actions from previous page (both cumulatively and chronologically) 1344: 1345: =item * 1346: 1347: output title 1348: 1349: =item * 1350: 1351: get state of file attributes to be showing 1352: 1353: =item * 1354: 1355: output state of file attributes to be showing 1356: 1357: =item * 1358: 1359: output starting row to the indexed file/directory hierarchy 1360: 1361: =item * 1362: 1363: read in what directories have previously been set to "open" 1364: 1365: =item * 1366: 1367: if not at top level, provide an uplink arrow 1368: 1369: =item * 1370: 1371: recursively go through all the directories and output as appropriate 1372: 1373: =item * 1374: 1375: information useful for group import 1376: 1377: =item * 1378: 1379: end the tables 1380: 1381: =item * 1382: 1383: end the output and return 1384: 1385: =back 1386: 1387: =head1 OTHER SUBROUTINES 1388: 1389: =over 4 1390: 1391: =item * 1392: 1393: scanDir - recursive scan of a directory 1394: 1395: =item * 1396: 1397: get_list - get complete matched list based on the uri (returns an array) 1398: 1399: =item * 1400: 1401: match_ext - filters out files based on extensions (returns an array) 1402: 1403: =item * 1404: 1405: display_line - displays one line in appropriate table format 1406: 1407: =item * 1408: 1409: begin_form - prints the beginning of a form for directory or file link 1410: 1411: =item * 1412: 1413: start_fresh_session - settings whenever the user causes the indexer window 1414: to be launched 1415: 1416: =back 1417: 1418: =cut