Annotation of loncom/publisher/lonpubdir.pm, revision 1.49
1.1 www 1: # The LearningOnline Network with CAPA
1.32 www 2: # Construction Space Directory Lister
1.16 albertel 3: #
1.49 ! www 4: # $Id: lonpubdir.pm,v 1.48 2003/12/22 19:30:25 www Exp $
1.16 albertel 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/
1.1 www 27: #
1.17 harris41 28: ###
1.1 www 29:
30: package Apache::lonpubdir;
31:
32: use strict;
33: use Apache::File;
34: use File::Copy;
35: use Apache::Constants qw(:common :http :methods);
1.6 www 36: use Apache::loncacc;
1.17 harris41 37: use Apache::loncommon();
1.48 www 38: use Apache::lonhtmlcommon();
1.39 www 39: use Apache::lonlocal;
1.1 www 40:
41: sub handler {
42:
43: my $r=shift;
44:
45: my $fn;
46:
1.23 foxr 47:
48:
49: $fn = getEffectiveUrl($r);
50:
51: # Validate access to the construction space and get username@domain.
1.6 www 52:
53: my $uname;
54: my $udom;
55:
1.9 www 56: ($uname,$udom)=
1.6 www 57: &Apache::loncacc::constructaccess(
1.9 www 58: $fn,$r->dir_config('lonDefDomain'));
59: unless (($uname) && ($udom)) {
1.6 www 60: $r->log_reason($uname.' at '.$udom.
1.32 www 61: ' trying to list directory '.$ENV{'form.filename'}.
1.6 www 62: ' ('.$fn.') - not authorized',
63: $r->filename);
64: return HTTP_NOT_ACCEPTABLE;
65: }
1.23 foxr 66:
1.32 www 67: # Remove trailing / from directory name.
1.23 foxr 68:
1.3 www 69: $fn=~s/\/$//;
1.1 www 70:
71: unless ($fn) {
72: $r->log_reason($ENV{'user.name'}.' at '.$ENV{'user.domain'}.
1.2 www 73: ' trying to list empty directory', $r->filename);
1.1 www 74: return HTTP_NOT_FOUND;
75: }
76:
77: # ----------------------------------------------------------- Start page output
78:
1.23 foxr 79: my $thisdisfn=$fn;
80: $thisdisfn=~s/^\/home\/$uname\/public_html//; # subdirectory part of
81: # construction space.
82: my $docroot=$r->dir_config('lonDocRoot'); # Apache londocument root.
1.1 www 83:
1.23 foxr 84: my $resdir=$docroot.'/res/'.$udom.'/'.$uname.$thisdisfn; # Resource directory
85: my $targetdir=$udom.'/'.$uname.$thisdisfn; # Publiction target directory.
1.25 www 86: my $linkdir='/priv/'.$uname.$thisdisfn; # Full URL name of constr space.
1.1 www 87:
88:
89:
1.26 www 90: &startpage($r, $uname, $udom, $thisdisfn); # Put out the start of page.
1.6 www 91:
1.23 foxr 92: # Start off the diretory table.
1.1 www 93:
1.2 www 94: $r->print('<table border=2>'.
1.39 www 95: '<tr><th>'.&mt('Actions').'</th><th>'.&mt('Name').'</th><th>'.
96: &mt('Title').'</th>'.
97: '<th>'.&mt('Status').'</th><th>'.&mt('Last Modified').
98: '</th></tr>');
1.1 www 99:
1.2 www 100: my $filename;
1.23 foxr 101: my $dirptr=16384; # Mask indicating a directory in stat.cmode.
1.1 www 102:
1.2 www 103: opendir(DIR,$fn);
1.44 albertel 104: my @files=sort {uc($a) cmp uc($b)} (readdir(DIR));
1.11 albertel 105: foreach my $filename (@files) {
1.2 www 106: my ($cdev,$cino,$cmode,$cnlink,
107: $cuid,$cgid,$crdev,$csize,
108: $catime,$cmtime,$cctime,
109: $cblksize,$cblocks)=stat($fn.'/'.$filename);
1.12 www 110:
1.10 albertel 111: my $extension='';
112: if ($filename=~/\.(\w+)$/) { $extension=$1; }
1.15 matthew 113: if ($cmode&$dirptr) {
1.21 foxr 114: putdirectory($r, $thisdisfn, $linkdir, $filename, $cmtime);
1.17 harris41 115: } elsif (&Apache::loncommon::fileembstyle($extension) ne 'hdn') {
1.22 foxr 116: putresource($r, $uname, $filename, $thisdisfn, $resdir,
117: $targetdir, $linkdir, $cmtime);
1.14 albertel 118: } else {
1.15 matthew 119: # "hidden" extension and not a directory, so hide it away.
1.2 www 120: }
121: }
122: closedir(DIR);
123:
124: $r->print('</table></body></html>');
1.1 www 125: return OK;
126: }
1.21 foxr 127: #
1.23 foxr 128: # Gets the effective URL of the request and returns it:
129: # $effn = getEffectiveUrl($r);
130: # $r - The Apache Request object.
131: sub getEffectiveUrl {
132: my $r = shift;
133: my $fn;
134:
135: if ($ENV{'form.filename'}) { # If a form filename is defined.
136: $fn=$ENV{'form.filename'};
137: #
138: # Replace the ~username of the URL with /home/username/public_html
139: # so that we don't have to worry about ~ expansion internally.
140: #
1.32 www 141: $fn=~s/^http\:\/\/[^\/]+\///;
142: $fn=~s/^\///;
143: $fn=~s/\~(\w+)/\/home\/$1\/public_html/;
1.23 foxr 144:
145: # Remove trailing / strings (?)
146:
147: $fn=~s/\/[^\/]+$//;
1.24 albertel 148: } else {
149: # If no form is defined, use request filename.
150: $fn = $r->filename();
151: my $lonDocRoot=$r->dir_config('lonDocRoot');
152: if ( $fn =~ /$lonDocRoot/ ) {
153: #internal authentication, needs fixup.
154: $fn = $r->uri(); # non users do not get the full path request
155: # through SCRIPT_FILENAME
156: $fn=~s|^/~(\w+)|/home/$1/public_html|;
157: }
1.23 foxr 158: }
1.37 www 159: $fn=~s/\/+/\//g;
1.23 foxr 160: return $fn;
161: }
162: #
163: # Output the header of the page. This includes:
164: # - The HTML header
165: # - The H1/H3 stuff which includes the directory.
166: #
167: # startpage($r, $uame, $udom, $thisdisfn);
168: # $r - The apache request object.
169: # $uname - User name.
170: # $udom - Domain name the user is logged in under.
171: # $thisdisfn - Displayable version of the filename.
1.26 www 172:
1.23 foxr 173: sub startpage {
174: my ($r, $uname, $udom, $thisdisfn) = @_;
175:
1.39 www 176: &Apache::loncommon::content_type($r,'text/html');
1.23 foxr 177: $r->send_http_header;
178:
179: $r->print('<html><head><title>LON-CAPA Construction Space</title></head>');
180:
1.26 www 181: $r->print(&Apache::loncommon::bodytag(undef,undef,undef,1));
1.29 www 182: my $pubdirscript=(<<ENDPUBDIRSCRIPT);
183: <script>
1.37 www 184: // Store directory location for menu bar to find
185:
186: parent.lastknownpriv='/~$uname/$thisdisfn/';
187:
188: // Confirmation dialogues
189:
1.29 www 190: function pubdir(theform) {
191: if (confirm('Publish complete directory?')) {
192: theform.submit();
193: }
194: }
195: function pubrecdir(theform) {
196: if (confirm('Publish directory and all subdirectories?')) {
197: theform.pubrec.value='1';
198: theform.submit();
199: }
200: }
201: </script>
202: ENDPUBDIRSCRIPT
203:
1.48 www 204: $r->print('<h2>'.&mt('Construction Space Directory').'</h2>'.
1.31 albertel 205: '<script type="text/javascript">top.document.title = \''.
206: $thisdisfn.'/ - LON-CAPA Construction Space\';</script>'.
207: $pubdirscript.
1.26 www 208: '<form method="post" action="/adm/publish" target="_parent">'.
1.35 www 209: '<table><tr><td><input type="hidden" name="filename" value="/~'.
1.26 www 210: $uname.$thisdisfn.'/" />'.
1.40 www 211: '<input type="button" onClick="pubdir(this.form);" value="'.
212: &mt('Publish Directory').'" />'.
1.29 www 213: '<input type="hidden" name="pubrec" value="" />'.
1.40 www 214: '<input type="button" onClick="pubrecdir(this.form);" value="'.
215: &mt('Publish Directory and Sub Directories').'" /></td><td>'.
1.28 www 216: '<input type="button" onClick="window.location='."'/~".
1.40 www 217: $uname.$thisdisfn."/default.meta'".'" value="'.
218: &mt('Edit Directory Catalog Information').'" /></td></tr><tr><td><input type="checkbox" name="forcerepub" /> '.&mt('Force publication of unmodified files').'.</td><td> </td></tr></table></form>');
1.23 foxr 219:
220: if (($uname ne $ENV{'user.name'}) || ($udom ne $ENV{'user.domain'})) {
1.39 www 221: $r->print('<h3>'.&mt('Co-Author').': '.$uname.' at '.$udom.
1.23 foxr 222: '</h3>');
223: }
1.48 www 224: $r->print(
1.49 ! www 225: &Apache::lonhtmlcommon::crumbs($thisdisfn.'/','_top','/priv/'.$uname));
1.23 foxr 226: }
227:
228: #
229: # Get the title string or "[untitled]" if the file has no title metadata:
230: # Without the latter substitution, it's impossible to examine metadata for
231: # untitled resources. Resources may be legitimately untitled, to prevent
232: # searches from locating them.
233: #
234: # $str = getTitleString($fullname);
235: # $fullname - Fully qualified filename to check.
236: #
237: sub getTitleString {
238: my $fullname = shift;
239: my $title = &Apache::lonnet::metadata($fullname, 'title');
240:
241: unless ($title) {
1.40 www 242: $title = "[".&mt('untitled')."]";
1.23 foxr 243: }
244: return $title;
245: }
246:
247:
248: #
1.21 foxr 249: # Put out a directory table row:
250: # putdirectory(r, base, here, dirname, modtime)
251: # r - Apache request object.
252: # reqfile - File in request.
253: # here - Where we are in directory tree.
254: # dirname - Name of directory special file.
255: # modtime - Encoded modification time.
256: #
257: sub putdirectory {
258: my ($r, $reqfile, $here, $dirname, $modtime) = @_;
259:
260: # construct the display filename: the directory name unless ..:
261:
262: my $disfilename = $dirname;
263: if ($dirname eq '..') {
1.39 www 264: $disfilename = '<i>'.&mt('Parent Directory').'</i>';
1.21 foxr 265: }
266: unless (( ($dirname eq '..') && ($reqfile eq '')) ||
267: ($dirname eq '.')) {
1.25 www 268: $r->print('<tr bgcolor="#CCCCFF">'.
1.47 sakharuk 269: '<td>'.&mt('Go to ...').'</td>'.
1.25 www 270: '<td><a href="'.$here.'/'.$dirname.'/" target="_top">'.
1.21 foxr 271: $disfilename.'</a></td>'.
272: '<td> </td>'.
273: '<td> </td>'.
1.42 www 274: '<td>'.&Apache::lonlocal::locallocaltime($modtime).'</td>'.
1.25 www 275: "</tr>\n");
1.21 foxr 276: }
277: return OK;
278: }
1.22 foxr 279: #
280: # Put a table row for a file resource.
281: #
282: sub putresource {
283: my ($r, $uname, $filename, $thisdisfn,
284: $resdir, $targetdir, $linkdir,
285: $cmtime) = @_;
286:
1.47 sakharuk 287: my $status=&mt('Unpublished');
1.25 www 288: my $bgcolor='#FFCCCC';
1.22 foxr 289: my $title=' ';
290: if (-e $resdir.'/'.$filename) {
291: my ($rdev,$rino,$rmode,$rnlink,
292: $ruid,$rgid,$rrdev,$rsize,
293: $ratime,$rmtime,$rctime,
294: $rblksize,$rblocks)=stat($resdir.'/'.$filename);
295: if ($rmtime>=$cmtime) {
1.41 www 296: $status=&mt('Published');
1.25 www 297: $bgcolor='#CCFFCC';
1.40 www 298: if (&Apache::lonnet::metadata($targetdir.'/'.$filename,'obsolete')) {
1.41 www 299: $status=&mt('Obsolete');
1.40 www 300: $bgcolor='#AAAAAA';
301: }
1.23 foxr 302: $title='<a href="/res/'.$targetdir.'/'.$filename.
303: '.meta" target=cat>'.
304: getTitleString($targetdir.'/'.$filename, 'title').'</a>';
1.22 foxr 305: } else {
1.41 www 306: $status=&mt('Modified');
1.25 www 307: $bgcolor='#FFFFCC';
1.22 foxr 308: $title='<a href="/res/'.$targetdir.'/'.$filename.'.meta" target=cat>'.
1.25 www 309: getTitleString($targetdir.'/'.$filename,'title').'</a>';
1.22 foxr 310: if (&Apache::loncommon::fileembstyle(($filename=~/\.(\w+)$/)) eq 'ssi') {
311: $status.='<br><a href="/adm/diff?filename=/~'.$uname.
312: $thisdisfn.'/'.$filename.
1.41 www 313: '&versiontwo=priv" target=cat>'.&mt('Diffs').'</a>';
1.22 foxr 314: }
315: }
316: $status.='<br><a href="/adm/retrieve?filename=/~'.$uname.
1.41 www 317: $thisdisfn.'/'.$filename.'" target=cat>'.&mt('Retrieve').'</a>';
1.22 foxr 318: }
1.33 www 319: my $editlink='';
1.38 taceyjo1 320: my $editlink2='';
1.36 www 321: if ($filename=~/\.(xml|html|htm|xhtml|xhtm|sty)$/) {
1.39 www 322: $editlink=' (<a href="'.$linkdir.'/'.$filename.'?forceedit=1" target="_top">'.&mt('Edit').'</a>)';
1.34 www 323: }
324: if ($filename=~/\.(problem|exam|quiz|assess|survey|form|library)$/) {
1.39 www 325: $editlink=' (<a href="'.$linkdir.'/'.$filename.'?forceedit=1" target="_top">'.&mt('EditXML').'</a>)';
326: $editlink2=' (<a href="'.$linkdir.'/'.$filename.'?forceColoredit=1" target="_top">'.&mt('Edit').'</a>)';
1.43 taceyjo1 327: }
328: if ($filename=~/\.(zip|tar|bz2|gz|tar.gz|tar.bz2|tgz)$/) {
1.46 taceyjo1 329: $editlink=' (<a target="_parent" href="/adm/cfile?decompress=/~'.
330: $uname.$thisdisfn.'/'.$filename.'">'.&mt('Decompress').'</a>)';
1.33 www 331: }
1.25 www 332: $r->print('<tr bgcolor="'.$bgcolor.'">'.
1.22 foxr 333: '<td><a target="_parent" href="/adm/publish?filename=/~'.
1.40 www 334: $uname.$thisdisfn.'/'.$filename.'">'.&mt('Publish').'</a>'.
1.22 foxr 335: '</td>'.
336: '<td>'.
1.25 www 337: '<a href="'.$linkdir.'/'.$filename.'" target="_top">'.
1.38 taceyjo1 338: $filename.'</a>'.$editlink2.$editlink.
1.22 foxr 339: '</td>'.
340: '<td>'.$title.'</td>'.
1.41 www 341: '<td>'.$status.'</td>'.
1.42 www 342: '<td>'.&Apache::lonlocal::locallocaltime($cmtime).'</td>'.
1.25 www 343: "</tr>\n");
1.22 foxr 344: return OK;
1.23 foxr 345: }
346: #
347: # Categorize files in the directory.
348: # For each file in a list of files in a file directory,
349: # the file categorized as one of:
350: # - directory
351: # - sequence
352: # - problem
353: # - Other resource.
354: #
355: # For each file the modification date is determined as well.
356: # Returned is a list of sublists:
357: # (directories, sequences, problems, other)
358: # each of the sublists contains entries of the following form (sorted by
359: # filename):
360: # (filename, typecode, lastmodtime)
361: #
362: # $list = CategorizeFiles($location, $files)
363: # $location - Directory in which the files live (relative to our
364: # execution.
365: # $files - list of files.
366: #
367: sub CategorizeFiles {
368: my $location = shift;
369: my $files = shift;
1.22 foxr 370: }
371:
1.4 www 372: 1;
373: __END__
1.17 harris41 374:
375: =head1 NAME
376:
1.32 www 377: Apache::lonpubdir - Construction space directory lister
1.17 harris41 378:
379: =head1 SYNOPSIS
380:
381: Invoked (for various locations) by /etc/httpd/conf/srm.conf:
382:
1.18 harris41 383: <LocationMatch "^/\~.*/$">
384: PerlAccessHandler Apache::loncacc
385: SetHandler perl-script
386: PerlHandler Apache::lonpubdir
387: ErrorDocument 403 /adm/login
388: ErrorDocument 404 /adm/notfound.html
389: ErrorDocument 406 /adm/unauthorized.html
390: ErrorDocument 500 /adm/errorhandler
391: </LocationMatch>
392:
393: <Location /adm/pubdir>
394: PerlAccessHandler Apache::lonacc
395: SetHandler perl-script
396: PerlHandler Apache::lonpubdir
397: ErrorDocument 403 /adm/login
398: ErrorDocument 404 /adm/notfound.html
399: ErrorDocument 406 /adm/unauthorized.html
400: ErrorDocument 500 /adm/errorhandler
401: </Location>
1.17 harris41 402:
403: =head1 INTRODUCTION
404:
1.18 harris41 405: This module publishes a directory of files.
1.17 harris41 406:
407: This is part of the LearningOnline Network with CAPA project
408: described at http://www.lon-capa.org.
409:
410: =head1 HANDLER SUBROUTINE
411:
412: This routine is called by Apache and mod_perl.
413:
414: =over 4
415:
416: =item *
417:
418: read in information
419:
420: =item *
421:
422: start page output
423:
424: =item *
425:
426: run through list of files and attempt to publish unhidden files
427:
428: =back
429:
430: =cut
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>