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