File:
[LON-CAPA] /
loncom /
interface /
lonindexer.pm
Revision
1.182:
download - view:
text,
annotated -
select for diffs
Fri Sep 19 08:50:42 2008 UTC (15 years, 11 months ago) by
bisitz
Branches:
MAIN
CVS tags:
HEAD
"Browse Resources" table:
- Now uses LON-CAPA standard table
- Removed hardcoded styles
Note:
Due to the usage of standard sub routines some styles are lost now, e.g. special background color for absolute links and vertical alignment in some cases (which actually needed to be improved anyway). I kept these code lines as comments starting with "#SB".
Another idea is to use a different background color for domain and folder rows.
1: # The LearningOnline Network with CAPA
2: # Directory Indexer
3: #
4: # $Id: lonindexer.pm,v 1.182 2008/09/19 08:50:42 bisitz 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<=11; $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<=11; $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: 'ln' => 'Language',
448: 'sa' => 'Source Available',
449: 'sr' => 'Show resource',
450: 'li' => 'Linked/Related Resources',
451: 'av' => 'All versions',
452: 'ud' => 'Update Display',
453: 'pr' => 'Problems',
454: 'gr' => 'Graphics',
455: 'at' => 'All types'
456: );
457: $r->print(<<END);
458: <form method="post" name="fileattr" action="$uri"
459: enctype="application/x-www-form-urlencoded">
460: <label><input type="checkbox" name="attr9" value="1" $attrchk[9] onClick="this.form.submit();" /> $lt{'av'}</label>
461: <table border="0">
462: <tr>
463: <td><label><input type="checkbox" name="attr0" value="1" $attrchk[0] onClick="this.form.submit();" /> $lt{'ti'}</label></td>
464: <td><label><input type="checkbox" name="attr4" value="1" $attrchk[4] onClick="this.form.submit();" /> $lt{'au'}</label></td>
465: <td><label><input type="checkbox" name="attr5" value="1" $attrchk[5] onClick="this.form.submit();" /> $lt{'kw'}</label></td>
466: <td><label><input type="checkbox" name="attr6" value="1" $attrchk[6] onClick="this.form.submit();" /> $lt{'ln'}</label></td>
467: </tr>
468: <tr>
469: <td><label><input type="checkbox" name="attr1" value="1" $attrchk[1] onClick="this.form.submit();" /> $lt{'si'}</label></td>
470: <td><label><input type="checkbox" name="attr2" value="1" $attrchk[2] onClick="this.form.submit();" /> $lt{'la'}</label></td>
471: <td><label><input type="checkbox" name="attr3" value="1" $attrchk[3] onClick="this.form.submit();" /> $lt{'lm'}</label></td>
472: <td><label><input type="checkbox" name="attr10" value="1" $attrchk[10] onClick="this.form.submit();" /> $lt{'sa'}</label></td>
473: </tr>
474: <tr>
475: <td><label><input type="checkbox" name="attr8" value="1" $attrchk[8] onClick="this.form.submit();" /> $lt{'st'}</label></td>
476: <td><label><input type="checkbox" name="attr11" value="1" $attrchk[11] onClick="this.form.submit();" /> $lt{'li'}</label></td>
477: <td><label><input type="checkbox" name="attr7" value="1" $attrchk[7] onClick="this.form.submit();" /> $lt{'sr'}</label></td>
478: <td> </td>
479: </tr>
480: </table>
481: <input type="hidden" name="attrs" value="1" />
482: END
483: my @file_categories = &Apache::loncommon::filecategories();
484: my %select_file_categories;
485: my @select_form_order = ('');
486: $select_file_categories{''} = &mt('All file types');
487: foreach my $cat (@file_categories) {
488: my $types = join(",",&Apache::loncommon::filecategorytypes($cat));
489: $select_file_categories{$types} = $cat;
490: push(@select_form_order,$types);
491: }
492: $select_file_categories{'select_form_order'} = \@select_form_order;
493: my $type_element=
494: &Apache::loncommon::select_form($typeselect,'only',
495: %select_file_categories);
496: $type_element = '<label>'.&mt('File Type Displayed: [_1]',
497: $type_element).'</label>';
498: $r->print(<<END);
499: $type_element
500: <br />
501: <input type="submit" name="updatedisplay" value="$lt{'ud'}" />
502: <input type="hidden" name="acts" value="" />
503: $closebutton $groupimportbutton
504: END
505: $r->print(&Apache::loncommon::inhibit_menu_check('input'));
506:
507: # -------------- Filter out sequence containment in crumbs and "recent folders"
508: my $storeuri=$uri;
509: $storeuri='/'.(split(/\.(page|sequence)\/\//,$uri))[-1];
510: $storeuri=~s/\/+/\//g;
511: # ---------------------------------------------------------------- Bread crumbs
512: $r->print(&Apache::lonhtmlcommon::crumbs($storeuri,'','',
513: (($env{'form.catalogmode'} eq 'import')?
514: 'document.forms.fileattr':'')).
515: &Apache::lonhtmlcommon::select_recent('residx','resrecent',
516: '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();'));
517: # -------------------------------------------------------- Resource Home Button
518: my $reshome=$env{'course.'.$env{'request.course.id'}.'.reshome'};
519: if ($reshome) {
520: $r->print("<font size='+2'><a href='");
521: if ($env{'form.catalogmode'} eq 'import') {
522: $r->print('javascript:document.forms.fileattr.action="'.&Apache::loncommon::inhibit_menu_check($reshome).'";document.forms.fileattr.submit();');
523: } else {
524: $r->print($reshome);
525: }
526: $r->print("'>".&mt('Home').'</a></font>');
527: }
528: $r->print('</form>');
529: # ------------------------------------------------------ Remember where we were
530: &Apache::loncommon::storeresurl($storeuri);
531: &Apache::lonhtmlcommon::store_recent('residx',$storeuri,$storeuri);
532: # -------------------------------------------------- Check All and Uncheck all
533: if ($env{'form.catalogmode'} eq 'import') {
534: $r->print('<br /><input type="button" value="'.&mt("Check All").'" id="checkallbutton" onClick="javascript:checkAll()" />');
535: $r->print('<input type="button" value="'.&mt("Uncheck All").'" id="uncheckallbutton" onClick="javascript:uncheckAll()" />');
536: }
537: # ----------------- output starting row to the indexed file/directory hierarchy
538: #$r->print(&initdebug());
539: #$r->print(&writedebug("Omit:@Omit")) if (@Omit);
540: #$r->print(&writedebug("Only:@Only")) if (@Only);
541: $r->print('<br /><br />');
542: $r->print(&Apache::loncommon::start_data_table()
543: .&Apache::loncommon::start_data_table_header_row());
544: $r->print("<th $colspan>".&mt('Name')."</th>\n");
545: $r->print("<th>".&mt('Title')."</th>\n")
546: if ($hash{'display_attrs_0'} == 1);
547: $r->print('<th align="right">'.&mt("Size")." (".&mt("bytes").") ".
548: "</th>\n") if ($hash{'display_attrs_1'} == 1);
549: $r->print("<th>".&mt("Last accessed")."</th>\n")
550: if ($hash{'display_attrs_2'} == 1);
551: $r->print("<th>".&mt("Last modified")."</th>\n")
552: if ($hash{'display_attrs_3'} == 1);
553: $r->print("<th>".&mt("Author(s)")."</th>\n")
554: if ($hash{'display_attrs_4'} == 1);
555: $r->print("<th>".&mt("Keywords")."</th>\n")
556: if ($hash{'display_attrs_5'} == 1);
557: $r->print("<th>".&mt("Language")."</th>\n")
558: if ($hash{'display_attrs_6'} == 1);
559: $r->print("<th>".&mt("Usage Statistics")." <br />(".
560: &mt("Courses/Network Hits").") ".&mt('updated periodically')."</th>\n")
561: if ($hash{'display_attrs_8'} == 1);
562: $r->print("<th>".&mt("Source Available")."</th>\n")
563: if ($hash{'display_attrs_10'} == 1);
564: $r->print("<th>".&mt("Linked/Related Resources")."</th>\n")
565: if ($hash{'display_attrs_11'} == 1);
566: $r->print("<th>".&mt("Resource")."</th>\n")
567: if ($hash{'display_attrs_7'} == 1);
568: $r->print(&Apache::loncommon::end_data_table_header_row());
569:
570: # ----------------- read in what directories have previously been set to "open"
571: foreach (keys %hash) {
572: if ($_ =~ /^diropen_status_/) {
573: my $key = $_;
574: $key =~ s/^diropen_status_//;
575: $dirs{$key} = $hash{$_};
576: }
577: }
578:
579: if ($env{'form.openuri'}) { # take care of review and refresh options
580: my $uri=$env{'form.openuri'};
581: if (exists($hash{'diropen_status_'.$uri})) {
582: my $cursta = $hash{'diropen_status_'.$uri};
583: $dirs{$uri} = 'open';
584: $hash{'diropen_status_'.$uri} = 'open';
585: if ($cursta eq 'open') {
586: $dirs{$uri} = 'closed';
587: $hash{'diropen_status_'.$uri} = 'closed';
588: }
589: } else {
590: $hash{'diropen_status_'.$uri} = 'open';
591: $dirs{$uri} = 'open';
592: }
593: }
594:
595: my $toplevel;
596: my $indent = 0;
597: $uri = $uri.'/' if $uri !~ /.*\/$/;
598:
599: if ($env{'form.dirPointer'} ne 'on') {
600: $hash{'top.level'} = $uri;
601: $toplevel = $uri;
602: } else {
603: $toplevel = $hash{'top.level'};
604: }
605:
606: # -------------------------------- if not at top level, provide an uplink arrow
607: if ($toplevel ne '/res/'){
608: my (@uri_com) = split(/\//,$uri);
609: pop @uri_com;
610: my $upone = join('/',@uri_com);
611: my @list = qw (0);
612: &display_line ($r,'opened',$upone.'&viewOneUp',0,$upone,@list);
613: $indent = 1;
614: }
615:
616: # -------- recursively go through all the directories and output as appropriate
617: &scanDir ($r,$toplevel,$indent,\%hash);
618:
619: # -------------------------------------------------------------- end the tables
620: $r->print(&Apache::loncommon::end_data_table());
621:
622: # ---------------------------- embed hidden information useful for group import
623: $r->print("<form name='fnum' action=''>");
624: $r->print("<input type='hidden' name='fnum' value='$fnum' /></form>");
625:
626: # --------------------------------------------------- end the output and return
627: $r->print(&Apache::loncommon::end_page()."\n");
628: }
629: if(! $c->aborted()) {
630: # write back into the temporary file
631: my %dbfile;
632: if (tie(%dbfile,'GDBM_File',$diropendb,&GDBM_NEWDB(),0640)) {
633: while (my($key,$value) = each(%hash)) {
634: $dbfile{$key}=$value;
635: }
636: untie(%dbfile);
637: }
638: }
639:
640: return OK;
641: }
642:
643: # ----------------------------------------------- recursive scan of a directory
644: sub scanDir {
645: my ($r,$startdir,$indent,$hashref)=@_;
646: my $c = $r->connection();
647: my ($compuri,$curdir);
648: my $dirptr=16384;
649: my $obs;
650: $indent++;
651: my %dupdirs = %dirs;
652: my @list=&get_list($r,$startdir);
653: foreach my $line (@list) {
654: return if ($c->aborted());
655: #This is a kludge, sorry aboot this
656: my ($strip,$dom,undef,$testdir,undef,undef,undef,undef,undef,undef,undef,undef,undef,undef,$obs,undef)=split(/\&/,$line,16);
657: next if($strip =~ /.*\.meta$/ | $obs eq '1');
658: my (@fileparts) = split(/\./,$strip);
659: if ($hash{'display_attrs_9'} != 1) {
660: # if not all versions to be shown
661: if (scalar(@fileparts) >= 3) {
662: my $fext = pop @fileparts;
663: my $ov = pop @fileparts;
664: my $fname = join ('.',@fileparts,$fext);
665: next if (grep /\Q$fname\E/,@list and $ov =~ /^\d+$/);
666: }
667: }
668:
669: if ($dom eq 'domain') {
670: # dom list has full path /res/<domain name>/ already
671: $curdir='';
672: $compuri = (split(/\&/,$line))[0];
673: } else {
674: # user, dir & file have name only, i.e., w/o path
675: $compuri = join('',$startdir,$strip,'/');
676: $curdir = $startdir;
677: }
678: my $diropen = 'closed';
679: if (($dirptr&$testdir) or ($dom =~ /^(domain|user)$/) or ($compuri=~/\.(sequence|page)\/$/)) {
680: while (my ($key,$val)= each %dupdirs) {
681: if ($key eq $compuri and $val eq "open") {
682: $diropen = "opened";
683: delete($dupdirs{$key});
684: delete($dirs{$key});
685: }
686: }
687: }
688: &display_line($r,$diropen,$line,$indent,$curdir,$hashref,@list);
689: &scanDir ($r,$compuri,$indent) if $diropen eq 'opened';
690: }
691: $indent--;
692: }
693:
694: # --------------- get complete matched list based on the uri (returns an array)
695: sub get_list {
696: my ($r,$uri)=@_;
697: my @list=();
698: (my $luri = $uri) =~ s/\//_/g;
699: if ($env{'form.updatedisplay'}) {
700: foreach (keys %hash) {
701: delete $hash{$_} if ($_ =~ /^dirlist_files_/);
702: delete $hash{$_} if ($_ =~ /^dirlist_timestamp_files_/);
703: }
704: }
705:
706: if (defined($hash{'dirlist_files_'.$luri}) &&
707: $hash{'dirlist_timestamp_files_'.$luri}+600 > (time)) {
708: @list = split(/\n/,$hash{'dirlist_files_'.$luri});
709: } elsif ($uri=~/\.(page|sequence)\/$/) {
710: # is a page or a sequence
711: $uri=~s/\/$//;
712: $uri='/'.(split(/\.(page|sequence)\/\//,$uri))[-1];
713: $uri=~s/\/+/\//g;
714: foreach (&Apache::lonsequence::attemptread(&Apache::lonnet::filelocation('',$uri))) {
715: my @ratpart=split(/\:/,$_);
716: push(@list,&LONCAPA::map::qtescape($ratpart[1]));
717: }
718: $hash{'dirlist_files_'.$luri} = join("\n",@list);
719: } else {
720: # is really a directory
721: @list = &Apache::lonnet::dirlist($uri);
722: $hash{'dirlist_files_'.$luri} = join("\n",@list);
723: $hash{'dirlist_timestamp_files_'.$luri} = time;
724: }
725: return @list=&match_ext($r,@list);
726: }
727:
728: sub dynmetaread {
729: my $uri=shift;
730: if (($hash{'display_attrs_8'}==1) || ($hash{'display_attrs_11'}==1)) {
731: # We don't want the filename
732: $uri=~s/\/[^\/]+$//;
733: # Did we already see this?
734: my $builddir=$uri;
735: while ($builddir) {
736: if ($dynread{$builddir}) {
737: return 0;
738: }
739: $builddir=~s/\/[^\/]+$//;
740: }
741: # Actually get the data
742: %dynhash=
743: (%dynhash,&Apache::lonmeta::get_dynamic_metadata_from_sql($uri.'/'));
744: # Remember that we got it
745: $dynread{$uri}=1;
746: }
747: }
748:
749: sub initdebug {
750: my $start_page=
751: &Apache::loncommon::start_page('Debug',undef,
752: {'only_body' => 1,});
753: $start_page =~ s/\n/ /g;
754: return <<ENDJS;
755: <script type="text/javascript">
756: var debugging = true;
757: if (debugging) {
758: var debuggingWindow = window.open('','Debug','width=400,height=300',true);
759: }
760:
761: function output(text) {
762: if (debugging) {
763: debuggingWindow.document.writeln(text);
764: }
765: }
766: output('$start_page<pre>');
767: </script>
768: ENDJS
769: }
770:
771: sub writedebug {
772: my ($text) = @_;
773: return "<script type=\"text/javascript\">output('$text');</script>";
774: }
775:
776: # -------------------- filters out files based on extensions (returns an array)
777: sub match_ext {
778: my ($r,@packlist)=@_;
779: my @trimlist;
780: my $nextline;
781: my @fileext;
782: my $dirptr=16384;
783:
784: foreach my $line (@packlist) {
785: chomp $line;
786: $line =~ s/^\/home\/httpd\/html//;
787: my @unpackline = split (/\&/,$line);
788: next if ($unpackline[0] eq '.');
789: next if ($unpackline[0] eq '..');
790: my @filecom = split (/\./,$unpackline[0]);
791: my $fext = pop(@filecom);
792: my $fnptr = ($unpackline[3]&$dirptr) || ($fext=~/\.(page|sequence)$/);
793: if ($fnptr == 0 and $unpackline[3] ne "") {
794: my $embstyle = &Apache::loncommon::fileembstyle($fext);
795: push @trimlist,$line if (defined($embstyle) &&
796: ($embstyle ne 'hdn' or $fext eq 'meta'));
797: } else {
798: push @trimlist,$line;
799: }
800: }
801: @trimlist = sort {uc($a) cmp uc($b)} (@trimlist);
802: return @trimlist;
803: }
804:
805: # ------------------------------- displays one line in appropriate table format
806: sub display_line {
807: my ($r,$diropen,$line,$indent,$startdir,$hashref,@list)=@_;
808: my (@pathfn, $fndir);
809: # there could be relative paths (files actually belonging into this directory)
810: # or absolute paths (for example, from sequences)
811: my $absolute;
812: my $pathprefix;
813: if ($line=~m|^/res/| && $startdir ne '') {
814: $absolute=1;
815: $pathprefix='';
816: } else {
817: $absolute=0;
818: $pathprefix=$startdir;
819: }
820: my $dirptr=16384;
821: #SB my $fileclr="#ffffe6";
822: my $iconpath= $r->dir_config('lonIconsURL') . '/';
823:
824: my @filecom = split (/\&/,$line);
825: my @pathcom = split (/\//,$filecom[0]);
826: my $listname = $pathcom[scalar(@pathcom)-1];
827: my $fnptr = $filecom[3]&$dirptr;
828: my $msg = &mt('View').' '.$filecom[0].' '.&mt('resources');
829: $msg = &mt('Close').' '.$filecom[0].' '.&mt('directory') if $diropen eq 'opened';
830:
831: my $tabtag='</td>';
832: my $i=0;
833: while ($i<=11) {
834: $tabtag=join('',$tabtag,"<td> </td>")
835: if ($i != 9 &&
836: $hash{'display_attrs_'.$i} == 1);
837: $i++;
838: }
839: my $valign = ($hash{'display_attrs_7'} == 1 ? 'top' : 'bottom');
840:
841: # display uplink arrow
842: if ($filecom[1] eq 'viewOneUp') {
843: my $updir=$startdir;
844: # -------------- Filter out sequence containment in crumbs and "recent folders"
845: $updir='/'.(split(/\.(page|sequence)\/\//,$startdir))[-1];
846: $updir=~s/\/+/\//g;
847:
848: #SB $r->print("<tr valign='$valign' bgcolor=\"$fileclr\">$extrafield");
849: $r->print(&Apache::loncommon::start_data_table_row()); # valign="$valign" ?!?
850: $r->print($extrafield);
851: $r->print("<td>\n");
852: $r->print ('<form method="post" name="dirpathUP" action="'.$updir.
853: '/" '.
854: 'onSubmit="return rep_dirpath(\'UP\','.
855: 'document.forms.fileattr.acts.value)" '.
856: 'enctype="application/x-www-form-urlencoded"'.
857: '>'."\n");
858: $r->print(&Apache::loncommon::inhibit_menu_check('input'));
859: $r->print ('<input type=hidden name=openuri value="'.
860: $startdir.'" />'."\n");
861: $r->print ('<input type="hidden" name="acts" value="" />'."\n");
862: $r->print ('<input src="'.$iconpath.'arrow_up.gif"');
863: $r->print (' name="'.$msg.'" type="image" class="LC_indexer_icon" />'.
864: "\n");
865: $r->print(&mt("Up")."</form>$tabtag");
866: $r->print(&Apache::loncommon::end_data_table_row());
867: return OK;
868: }
869: # Do we have permission to look at this?
870:
871: if($filecom[15] ne '1') { return OK if (!&Apache::lonnet::allowed('bre',$pathprefix.$filecom[0])); }
872:
873: # make absolute links appear on different background
874: #SB if ($absolute) { $fileclr='#ccdd99'; }
875:
876: # display domain
877: if ($filecom[1] eq 'domain') {
878: $r->print ('<input type="hidden" name="dirPointer" value="on" />'."\n")
879: if ($env{'form.dirPointer'} eq "on");
880: #SB $r->print("<tr valign='$valign' bgcolor=\"$fileclr\">$extrafield");
881: $r->print(&Apache::loncommon::start_data_table_row()); # valign="$valign" ?!?"
882: $r->print($extrafield);
883: $r->print("<td>");
884: &begin_form ($r,$filecom[0]);
885: my $anchor = $filecom[0];
886: $anchor =~ s/\W//g;
887: $r->print ('<a name="'.$anchor.'"></a>');
888: $r->print ('<input type="hidden" name="acts" value="" />');
889: $r->print ('<input src="'.$iconpath.'folder_pointer_'.
890: $diropen.'.gif"');
891: $r->print (' name="'.$msg.'" type="image" class="LC_indexer_icon" />'.
892: "\n");
893: my $quotable_filecom = &Apache::loncommon::escape_single($filecom[0]);
894: $r->print ('<a href="javascript:gothere(\''.$quotable_filecom.
895: '\')"><img alt="" src="'.$iconpath.'server.gif"');
896: $r->print (' class="LC_icon" /></a>'."\n");
897: $r->print (&mt("Domain")." - $listname ");
898: if (&Apache::lonnet::domain($listname,'description')) {
899: $r->print("(".&Apache::lonnet::domain($listname,'description').
900: ")");
901: }
902: $r->print("</form>$tabtag");
903: $r->print(&Apache::loncommon::end_data_table_row());
904: return OK;
905:
906: # display user directory
907: }
908: if ($filecom[1] eq 'user') {
909: # $r->print("<tr valign=$valign bgcolor=\"$fileclr\">$extrafield");
910: my $curdir = $startdir.$filecom[0].'/';
911: my $anchor = $curdir;
912: $anchor =~ s/\W//g;
913: #SB $r->print("<tr bgcolor=\"$fileclr\">$extrafield<td valign=$valign>");
914: $r->print(&Apache::loncommon::start_data_table_row()
915: .$extrafield.'<td valign="'.$valign.'">');
916: &begin_form ($r,$curdir);
917: $r->print ('<a name="'.$anchor.'"></a><img alt="" src="'.$iconpath.
918: 'whitespace1.gif" class="LC_icon" />'."\n");
919: $r->print ('<input type="hidden" name="acts" value="" />');
920: $r->print ('<input src="'.$iconpath.'folder_pointer_'.$diropen.
921: '.gif"');
922: $r->print (' name="'.$msg.'" type="image" class="LC_indexer_icon" />'.
923: "\n");
924: my $quotable_curdir = &Apache::loncommon::escape_single($curdir);
925: $r->print ('<a href="javascript:gothere(\''.$quotable_curdir
926: .'\')"><img alt="'.$msg.'" src="'.
927: $iconpath.'quill.gif" class="LC_indexer_icon" /></a>');
928: my $domain=(split(m|/|,$startdir))[2];
929: my $plainname=&Apache::loncommon::plainname($listname,$domain);
930: $r->print ($listname);
931: if (defined($plainname) && $plainname) { $r->print(" ($plainname) "); }
932: $r->print('</form>'.$tabtag);
933: $r->print(&Apache::loncommon::end_data_table_row());
934: return OK;
935: }
936:
937: # display file
938: if (($fnptr == 0 and $filecom[3] ne '') or $absolute) {
939: my $title;
940: my $filelink = $pathprefix.$filecom[0];
941: if ($hash{'display_attrs_0'} == 1) {
942: $title = &Apache::lonnet::gettitle($filelink);
943: }
944: my @file_ext = split (/\./,$listname);
945: my $curfext = $file_ext[-1];
946: if (@Omit) {
947: foreach (@Omit) { return OK if (lc($curfext) eq $_); }
948: }
949: if (@Only) {
950: my $skip = 1;
951: foreach (@Only) { $skip = 0 if (lc($curfext) eq $_); }
952: return OK if ($skip > 0);
953: }
954: # Set the icon for the file
955: my $iconname = &Apache::loncommon::icon($listname);
956: #SB $r->print("<tr valign='$valign' bgcolor=\"$fileclr\"><td nowrap='nowrap' valign='top'>");
957: $r->print(&Apache::loncommon::start_data_table_row()); # valign="$valign" ?!?"
958: $r->print('<td nowrap="nowrap" valign="top">');
959:
960: if ($env{'form.catalogmode'} eq 'interactive') {
961: my $quotable_filelink = &Apache::loncommon::escape_single($filelink);
962: $r->print("<a href=\"javascript:select_data(\'",
963: $quotable_filelink,"')\">");
964: $r->print("<img alt=\"\" src='",$iconpath,"select.gif' class='LC_icon' /></a>".
965: "\n");
966: $r->print("</td><td nowrap='nowrap' valign='top'>");
967: } elsif ($env{'form.catalogmode'} eq 'import') {
968: $r->print("<form name='form$fnum' action=''>\n");
969: $r->print("<input type='checkbox' name='filelink"."' ".
970: "value='$filelink' onClick='".
971: "javascript:queue(\"form$fnum\")' ");
972: if ($hash{'store_'.$filelink}) {
973: $r->print("checked");
974: }
975: $r->print(" />\n");
976: $r->print("</form></td><td nowrap='nowrap' valign='top'>");
977: $hash{"pre_${fnum}_link"}=$filelink;
978: $hash{"pre_${fnum}_title"}=$title;
979: if (!$hash{"pre_${fnum}_title"}) {
980: $hash{"pre_${fnum}_title"} = 'Not_retrieved';
981: }
982: $fnum++;
983: }
984: # Form to open or close sequences
985: if ($filelink=~/\.(page|sequence)$/) {
986: my $curdir = $startdir.$filecom[0].'/';
987: &begin_form($r,$curdir);
988: $indent--;
989: }
990: # General indentation
991: if ($indent > 0 and $indent < 11) {
992: $r->print("<img alt=\"\" src='",$iconpath,"whitespace",$indent,
993: ".gif' class='LC_icon' />\n");
994: } elsif ($indent >0) {
995: my $ten = int($indent/10.);
996: my $rem = $indent%10.0;
997: my $count = 0;
998: while ($count < $ten) {
999: $r->print("<img alt=\"\" src=".$iconpath.
1000: "whitespace10.gif class='LC_icon' />\n");
1001: $count++;
1002: }
1003: $r->print("<img alt=\"\" src=",$iconpath,"whitespace",$rem,
1004: ".gif class='LC_icon' />\n") if $rem > 0;
1005: }
1006: # Sequence open/close icon
1007: if ($filelink=~/\.(page|sequence)$/) {
1008: my $curdir = $startdir.$filecom[0].'/';
1009: my $anchor = $curdir;
1010: $anchor =~ s/\W//g;
1011: $r->print ('<input type="hidden" name="acts" value="" />');
1012: $r->print ('<a name="'.$anchor.'"></a><input src="'.$iconpath.
1013: 'folder_pointer_'.$diropen.'.gif"');
1014: $r->print (' name="'.$msg.'" type="image" class="LC_indexer_icon" />'.
1015: "\n");
1016: }
1017: # Filetype icons
1018: $r->print("<img alt=\"\" src='$iconname' class='LC_icon' />\n");
1019: my $quotable_filelink = &Apache::loncommon::escape_single($filelink);
1020:
1021: $r->print (" <a href=\"javascript:openWindow('".$quotable_filelink.
1022: "?inhibitmenu=yes','previewfile','450','500','no','yes','yes');\"".
1023: " target=\"_self\">$listname</a> ");
1024: $quotable_filelink = &Apache::loncommon::escape_single($filelink.'.meta');
1025: &Apache::loncommon::inhibit_menu_check(\$quotable_filelink);
1026: $r->print (" (<a href=\"javascript:openWindow('".$quotable_filelink.
1027: "?inhibitmenu=yes','metadatafile','500','550','no','yes','no');\" ".
1028: " target=\"_self\">".&mt('metadata')."</a>) ");
1029: # Close form to open/close sequence
1030: if ($filelink=~/\.(page|sequence)$/) {
1031: $r->print('</form>');
1032: }
1033: $r->print("</td>\n");
1034: if ($hash{'display_attrs_0'} == 1) {
1035: $r->print('<td> '.($title eq '' ? ' ' : $title).
1036: ' </td>'."\n");
1037: }
1038: $r->print('<td align=right> ',
1039: $filecom[8]," </td>\n")
1040: if $hash{'display_attrs_1'} == 1;
1041: $r->print('<td> '.
1042: (&Apache::lonlocal::locallocaltime($filecom[9]))." </td>\n")
1043: if $hash{'display_attrs_2'} == 1;
1044: $r->print('<td> '.
1045: (&Apache::lonlocal::locallocaltime($filecom[10]))." </td>\n")
1046: if $hash{'display_attrs_3'} == 1;
1047:
1048: if ($hash{'display_attrs_4'} == 1) {
1049: my $author = &Apache::lonnet::metadata($filelink,'author');
1050: $r->print('<td> '.($author eq '' ? ' ' : $author).
1051: " </td>\n");
1052: }
1053: if ($hash{'display_attrs_5'} == 1) {
1054: my $keywords = &Apache::lonnet::metadata($filelink,'keywords');
1055: # $keywords = ' ' if (!$keywords);
1056: $r->print('<td> '.($keywords eq '' ? ' ' : $keywords).
1057: " </td>\n");
1058: }
1059: #'
1060:
1061: if ($hash{'display_attrs_6'} == 1) {
1062: my $lang = &Apache::lonnet::metadata($filelink,'language');
1063: $lang = &Apache::loncommon::languagedescription($lang);
1064: $r->print('<td> '.($lang eq '' ? ' ' : $lang).
1065: " </td>\n");
1066: }
1067: if ($hash{'display_attrs_8'} == 1) {
1068: # statistics
1069: &dynmetaread($filelink);
1070: $r->print("<td>");
1071: &dynmetaprint($r,$filelink,'count');
1072: &dynmetaprint($r,$filelink,'course');
1073: &dynmetaprint($r,$filelink,'stdno');
1074: &dynmetaprint($r,$filelink,'avetries');
1075: &dynmetaprint($r,$filelink,'difficulty');
1076: &dynmetaprint($r,$filelink,'disc');
1077: &dynmetaprint($r,$filelink,'clear');
1078: &dynmetaprint($r,$filelink,'technical');
1079: &dynmetaprint($r,$filelink,'correct');
1080: &dynmetaprint($r,$filelink,'helpful');
1081: &dynmetaprint($r,$filelink,'depth');
1082: $r->print(" </td>\n");
1083:
1084: }
1085: if ($hash{'display_attrs_10'} == 1) {
1086: my $source = &Apache::lonnet::metadata($filelink,'sourceavail');
1087: if($source eq 'open') {
1088: my $sourcelink = &Apache::lonsource::make_link($filelink,$listname);
1089: my $quotable_sourcelink = &Apache::loncommon::escape_single($sourcelink);
1090: &Apache::loncommon::inhibit_menu_check(\$quotable_sourcelink);
1091: $r->print('<td>'."<a href=\"javascript:openWindow('"
1092: .$quotable_sourcelink.
1093: "', 'previewsource', '700', '700', 'no', 'yes','yes');\"".
1094: " target=\"_self\">".&mt('Source Code')."</a> "."</td>\n");
1095: } else { #A cuddled else. :P
1096: $r->print("<td> </td>\n");
1097: }
1098: }
1099: if ($hash{'display_attrs_11'} == 1) {
1100: # links
1101: &dynmetaread($filelink);
1102: $r->print('<td>');
1103: &coursecontext($r,$filelink);
1104: &dynmetaprint($r,$filelink,'goto_list');
1105: &dynmetaprint($r,$filelink,'comefrom_list');
1106: &dynmetaprint($r,$filelink,'sequsage_list');
1107: &dynmetaprint($r,$filelink,'dependencies');
1108: &dynmetaprint($r,$filelink,'course_list');
1109: $r->print('</td>');
1110: }
1111: if ($hash{'display_attrs_7'} == 1) {
1112: # Show resource
1113: my $output=&showpreview($filelink);
1114: $r->print('<td> '.($output eq '' ? ' ':$output).
1115: " </td>\n");
1116: }
1117: $r->print(&Apache::loncommon::end_data_table_row());
1118: }
1119:
1120: # -- display directory
1121: if ($fnptr == $dirptr) {
1122: my $curdir = $startdir.$filecom[0].'/';
1123: my $anchor = $curdir;
1124: $anchor =~ s/\W//g;
1125: #SB $r->print("<tr bgcolor=\"$fileclr\">$extrafield<td valign=$valign>");
1126: $r->print(&Apache::loncommon::start_data_table_row()); # SB: bgcolor suggestion: darkgrey ("LC_info_row"?!?)
1127: # $r->print('<tr class="LC_info_row">');
1128: $r->print($extrafield.'<td valign="'.$valign.'">');
1129: &begin_form ($r,$curdir);
1130: my $indentm1 = $indent-1;
1131: if ($indentm1 < 11 and $indentm1 > 0) {
1132: $r->print("<img alt=\"\" src=",$iconpath,"whitespace",$indentm1,
1133: ".gif class='LC_icon' />\n");
1134: } else {
1135: my $ten = int($indentm1/10.);
1136: my $rem = $indentm1%10.0;
1137: my $count = 0;
1138: while ($count < $ten) {
1139: $r->print ("<img alt=\"\" src=",$iconpath
1140: ,"whitespace10.gif class='LC_icon' />\n");
1141: $count++;
1142: }
1143: $r->print ("<img alt=\"\" src=",$iconpath,"whitespace",$rem,
1144: ".gif class='LC_icon' />\n") if $rem > 0;
1145: }
1146: $r->print ('<input type="hidden" name="acts" value="" />');
1147: $r->print ('<a name="'.$anchor.'"></a><input src="'.$iconpath.
1148: 'folder_pointer_'.$diropen.'.gif"');
1149: $r->print (' name="'.$msg.'" type="image" class="LC_indexer_icon" />'.
1150: "\n");
1151: my $quotable_curdir = &Apache::loncommon::escape_single($curdir);
1152: $r->print ('<a href="javascript:gothere(\''
1153: .$quotable_curdir.'\')">'
1154: .'<img alt="'.&mt('Open Folder').'"src="'.
1155: $iconpath.'folder_'.$diropen.'.gif" class="LC_icon" /></a>'.
1156: "\n");
1157: $r->print ("$listname</form></td>\n");
1158: # Attributes
1159: my $filelink = $startdir.$filecom[0].'/default';
1160:
1161: if ($hash{'display_attrs_0'} == 1) {
1162: my $title = &Apache::lonnet::gettitle($filelink);
1163: $r->print('<td> '.($title eq '' ? ' ' : $title).
1164: ' </td>'."\n");
1165: }
1166: $r->print('<td align="right"> ',
1167: $filecom[8]," </td>\n")
1168: if $hash{'display_attrs_1'} == 1;
1169: $r->print('<td> '.
1170: (&Apache::lonlocal::locallocaltime($filecom[9]))." </td>\n")
1171: if $hash{'display_attrs_2'} == 1;
1172: $r->print('<td> '.
1173: (&Apache::lonlocal::locallocaltime($filecom[10]))." </td>\n")
1174: if $hash{'display_attrs_3'} == 1;
1175:
1176: if ($hash{'display_attrs_4'} == 1) {
1177: my $author = &Apache::lonnet::metadata($filelink,'author');
1178: $r->print('<td> '.($author eq '' ? ' ' : $author).
1179: " </td>\n");
1180: }
1181: if ($hash{'display_attrs_5'} == 1) {
1182: my $keywords = &Apache::lonnet::metadata($filelink,'keywords');
1183: # $keywords = ' ' if (!$keywords);
1184: $r->print('<td> '.($keywords eq '' ? ' ' : $keywords).
1185: " </td>\n");
1186: }
1187: if ($hash{'display_attrs_6'} == 1) {
1188: my $lang = &Apache::lonnet::metadata($filelink,'language');
1189: $lang = &Apache::loncommon::languagedescription($lang);
1190: $r->print('<td> '.($lang eq '' ? ' ' : $lang).
1191: " </td>\n");
1192: }
1193: if ($hash{'display_attrs_8'} == 1) {
1194: $r->print('<td> </td>');
1195: }
1196: if ($hash{'display_attrs_10'} == 1) {
1197: $r->print('<td> </td>');
1198: }
1199: if ($hash{'display_attrs_11'} == 1) {
1200: $r->print('<td> </td>');
1201: }
1202: if ($hash{'display_attrs_7'} == 1) {
1203: $r->print('<td> </td>');
1204: }
1205: $r->print(&Apache::loncommon::end_data_table_row());
1206: }
1207:
1208: }
1209:
1210: sub coursecontext {
1211: my ($r,$filelink)=@_;
1212: my $filesymb=&Apache::lonnet::symbread($filelink);
1213: if ($filesymb) {
1214: my ($map,$index,$resource)=&Apache::lonnet::decode_symb($filesymb);
1215: $r->print(&mt('Already in this course:<br />[_1] in folder/map [_2].<br />',
1216: &Apache::lonnet::gettitle($resource),
1217: &Apache::lonnet::gettitle($map)));
1218: }
1219: }
1220:
1221: sub showpreview {
1222: my ($filelink)=@_;
1223: if ($filelink=~m-^(/ext/|http://)-) {
1224: return &mt('External Resource, preview not enabled');
1225: }
1226: my ($curfext)=($filelink=~/\.(\w+)$/);
1227: my $output='';
1228: my $embstyle=&Apache::loncommon::fileembstyle($curfext);
1229: if ($embstyle eq 'ssi') {
1230: my $cache=$Apache::lonnet::perlvar{'lonDocRoot'}.$filelink.
1231: '.tmp';
1232: if ((!$env{'form.updatedisplay'}) &&
1233: (-e $cache)) {
1234: open(FH,$cache);
1235: $output=join("\n",<FH>);
1236: close(FH);
1237: } else {
1238: # In update display mode, remove old cache. This is done to retroactively
1239: # clean up course context renderings.
1240: if (-e $cache) {
1241: unlink($cache);
1242: }
1243: $output=&Apache::lonnet::ssi_body($filelink);
1244: # Is access denied? Don't render, don't store
1245: if ($output=~/LONCAPAACCESSCONTROLERRORSCREEN/s) {
1246: $output='';
1247: # Was this rendered in course content? Don't store
1248: } elsif (!&Apache::lonnet::symbread($filelink)) {
1249: open(FH,">$cache");
1250: print FH $output;
1251: close(FH);
1252: }
1253: }
1254: $output='<font size="-2">'.$output.'</font>';
1255: } elsif ($embstyle eq 'img') {
1256: $output='<img alt="'.&mt('Preview').'" src="'.$filelink.'" />';
1257: } elsif ($filelink=~m{^/res/($match_domain)/($match_username)/}) {
1258: $output='<img alt="'.&mt('Preview').'" src="http://'.
1259: &Apache::lonnet::hostname(&Apache::lonnet::homeserver($2,$1)).
1260: '/cgi-bin/thumbnail.gif?url='.$filelink.'" />';
1261: }
1262: return $output;
1263: }
1264:
1265: sub dynmetaprint {
1266: my ($r,$filelink,$item)=@_;
1267: if ($dynhash{$filelink}->{$item}) {
1268: $r->print("\n<br />".$fieldnames{$item}.': '.
1269: &Apache::lonmeta::prettyprint($item,
1270: $dynhash{$filelink}->{$item},
1271: (($env{'form.catalogmode'} ne 'import')?'preview':''),
1272: '',
1273: (($env{'form.catalogmode'} eq 'import')?'document.forms.fileattr':''),1));
1274: }
1275: }
1276:
1277: # ------------------- prints the beginning of a form for directory or file link
1278: sub begin_form {
1279: my ($r,$uri) = @_;
1280: my $anchor = $uri;
1281: $anchor =~ s/\W//g;
1282: $uri=&Apache::loncommon::escape_single($uri);
1283: $r->print ('<form method="post" name="dirpath'.$dnum.'" action="'.$uri.
1284: '#'.$anchor.
1285: '" onSubmit="return rep_dirpath(\''.$dnum.'\''.
1286: ',document.forms.fileattr.acts.value)" '.
1287: 'enctype="application/x-www-form-urlencoded">'."\n");
1288: $r->print ('<input type="hidden" name="openuri" value="'.$uri.'" />'.
1289: "\n");
1290: $r->print ('<input type="hidden" name="dirPointer" value="on" />'."\n");
1291: $r->print(&Apache::loncommon::inhibit_menu_check('input'));
1292: $dnum++;
1293: }
1294:
1295: # --------- settings whenever the user causes the indexer window to be launched
1296: sub start_fresh_session {
1297: my ($hash) = @_;
1298: delete $hash->{'form.catalogmode'};
1299: delete $hash->{'form.mode'};
1300: delete $hash->{'form.form'};
1301: delete $hash->{'form.element'};
1302: delete $hash->{'form.omit'};
1303: delete $hash->{'form.only'};
1304: foreach (keys %{$hash}) {
1305: delete $hash->{$_} if (/^(pre_|store)/);
1306: }
1307: }
1308:
1309: # ------------------------------------------------------------------- setvalues
1310: sub setvalues {
1311: # setvalues is used in registerurl to synchronize the database
1312: # hash and environment hashes
1313: my ($H1,$h1key,$H2,$h2key) =@_;
1314: #
1315: if (exists $H2->{$h2key}) {
1316: $H1->{$h1key} = $H2->{$h2key};
1317: } elsif (exists $H1->{$h1key}) {
1318: $H2->{$h2key} = $H1->{$h1key};
1319: }
1320: }
1321:
1322: 1;
1323:
1324: sub cleanup {
1325: if (tied(%hash)){
1326: &Apache::lonnet::logthis('Cleanup indexer: hash');
1327: }
1328: return OK;
1329: }
1330:
1331:
1332:
1333:
1334:
1335: =head1 NAME
1336:
1337: Apache::lonindexer - mod_perl module for cross server filesystem browsing
1338:
1339: =head1 SYNOPSIS
1340:
1341: Invoked by /etc/httpd/conf/srm.conf:
1342:
1343: <LocationMatch "^/res.*/$">
1344: SetHandler perl-script
1345: PerlHandler Apache::lonindexer
1346: </LocationMatch>
1347:
1348: =head1 INTRODUCTION
1349:
1350: This module enables a scheme of browsing across a cross server.
1351:
1352: This is part of the LearningOnline Network with CAPA project
1353: described at http://www.lon-capa.org.
1354:
1355: =head1 BEGIN SUBROUTINE
1356:
1357: This routine is only run once after compilation.
1358:
1359: =over 4
1360:
1361: =item *
1362:
1363: Initializes %language hash table.
1364:
1365: =back
1366:
1367: =head1 HANDLER SUBROUTINE
1368:
1369: This routine is called by Apache and mod_perl.
1370:
1371: =over 4
1372:
1373: =item *
1374:
1375: read in machine configuration variables
1376:
1377: =item *
1378:
1379: see if called from an interactive mode
1380:
1381: =item *
1382:
1383: refresh environment with user database values (in %hash)
1384:
1385: =item *
1386:
1387: define extra fields and buttons in case of special mode
1388:
1389: =item *
1390:
1391: set catalogmodefunctions to have extra needed javascript functionality
1392:
1393: =item *
1394:
1395: print header
1396:
1397: =item *
1398:
1399: evaluate actions from previous page (both cumulatively and chronologically)
1400:
1401: =item *
1402:
1403: output title
1404:
1405: =item *
1406:
1407: get state of file attributes to be showing
1408:
1409: =item *
1410:
1411: output state of file attributes to be showing
1412:
1413: =item *
1414:
1415: output starting row to the indexed file/directory hierarchy
1416:
1417: =item *
1418:
1419: read in what directories have previously been set to "open"
1420:
1421: =item *
1422:
1423: if not at top level, provide an uplink arrow
1424:
1425: =item *
1426:
1427: recursively go through all the directories and output as appropriate
1428:
1429: =item *
1430:
1431: information useful for group import
1432:
1433: =item *
1434:
1435: end the tables
1436:
1437: =item *
1438:
1439: end the output and return
1440:
1441: =back
1442:
1443: =head1 OTHER SUBROUTINES
1444:
1445: =over 4
1446:
1447: =item *
1448:
1449: scanDir - recursive scan of a directory
1450:
1451: =item *
1452:
1453: get_list - get complete matched list based on the uri (returns an array)
1454:
1455: =item *
1456:
1457: match_ext - filters out files based on extensions (returns an array)
1458:
1459: =item *
1460:
1461: display_line - displays one line in appropriate table format
1462:
1463: =item *
1464:
1465: begin_form - prints the beginning of a form for directory or file link
1466:
1467: =item *
1468:
1469: start_fresh_session - settings whenever the user causes the indexer window
1470: to be launched
1471:
1472: =back
1473:
1474: =cut
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>