1:
2: # The LearningOnline Network with CAPA
3: # Handler to upload files into construction space
4: #
5: # $Id: lonupload.pm,v 1.21 2003/11/08 10:58:30 albertel Exp $
6: #
7: # Copyright Michigan State University Board of Trustees
8: #
9: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
10: #
11: # LON-CAPA is free software; you can redistribute it and/or modify
12: # it under the terms of the GNU General Public License as published by
13: # the Free Software Foundation; either version 2 of the License, or
14: # (at your option) any later version.
15: #
16: # LON-CAPA is distributed in the hope that it will be useful,
17: # but WITHOUT ANY WARRANTY; without even the implied warranty of
18: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19: # GNU General Public License for more details.
20: #
21: # You should have received a copy of the GNU General Public License
22: # along with LON-CAPA; if not, write to the Free Software
23: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24: #
25: # /home/httpd/html/adm/gpl.txt
26: #
27: # http://www.lon-capa.org/
28: #
29: ###
30:
31: package Apache::lonupload;
32:
33: use strict;
34: use Apache::File;
35: use File::Copy;
36: use File::Basename;
37: use Apache::Constants qw(:common :http :methods);
38: use Apache::loncacc;
39: use Apache::loncommon();
40: use Apache::Log();
41: use Apache::lonnet;
42: use HTML::Entities();
43: use Apache::lonlocal;
44:
45: my $DEBUG=0;
46:
47: sub Debug {
48:
49: # Marshall the parameters.
50:
51: my $r = shift;
52: my $log = $r->log;
53: my $message = shift;
54:
55: # Put out the indicated message butonly if DEBUG is false.
56:
57: if ($DEBUG) {
58: $log->debug($message);
59: }
60: }
61:
62: sub upfile_store {
63: my $r=shift;
64:
65: my $fname=$ENV{'form.upfile.filename'};
66: $fname=~s/\W//g;
67:
68: chomp($ENV{'form.upfile'});
69:
70: my $datatoken=$ENV{'user.name'}.'_'.$ENV{'user.domain'}.
71: '_upload_'.$fname.'_'.time.'_'.$$;
72: {
73: my $fh=Apache::File->new('>'.$r->dir_config('lonDaemons').
74: '/tmp/'.$datatoken.'.tmp');
75: print $fh $ENV{'form.upfile'};
76: }
77: return $datatoken;
78: }
79:
80:
81: sub phaseone {
82: my ($r,$fn,$uname,$udom)=@_;
83: $ENV{'form.upfile.filename'}=~s/\\/\//g;
84: $ENV{'form.upfile.filename'}=~s/^.*\/([^\/]+)$/$1/;
85: if ($ENV{'form.upfile.filename'}) {
86: $fn=~s/\/[^\/]+$//;
87: $fn=~s/([^\/])$/$1\//;
88: $fn.=$ENV{'form.upfile.filename'};
89: $fn=~s/^\///;
90: $fn=~s/(\/)+/\//g;
91:
92: # Fn is the full path to the destination filename.
93: #
94:
95: &Debug($r, "Filename for upload: $fn");
96: if (($fn) && ($fn!~/\/$/)) {
97: $r->print(
98: '<form action=/adm/upload method=post>'.
99: '<input type=hidden name=phase value=two>'.
100: '<input type=hidden name=datatoken value="'.&upfile_store.'">'.
101: '<input type=hidden name=uploaduname value="'.$uname.'">'.
102: &mt('Store uploaded file as ')."<tt>/priv/$uname/</tt>".
103: '<input type=text size=50 name=filename value="'.$fn.'"><br>'.
104: '<input type=submit value="'.&mt('Store').'"></form>');
105: # Check for bad extension and warn user
106: if ($fn=~/\.(\w+)$/ &&
107: (&Apache::loncommon::fileembstyle($1) eq 'hdn')) {
108: $r->print(
109: '<font color=red>'.
110: &mt('The extension on this file,').' "'.$1.
111: '"'.&mt(', is reserved internally by LON-CAPA.').' <br \>'.
112: &mt('Please change the extension.').
113: '</font>');
114: } elsif($fn=~/\.(\w+)$/ &&
115: !defined(&Apache::loncommon::fileembstyle($1))) {
116: $r->print(
117: '<font color=red>'.
118: &mt('The extension on this file,').' "'.$1.
119: '"'.&mt(', is not recognized by LON-CAPA.').' <br \>'.
120: &mt('Please change the extension.').
121: '</font>');
122: }
123: } else {
124: $r->print('<font color=red>'.&mt('Illegal filename.').'</font>');
125: }
126: } else {
127: $r->print('<font color=red>'.&mt('No upload file specified.').'</font>');
128: }
129: }
130:
131: sub phasetwo {
132: my ($r,$tfn,$uname,$udom)=@_;
133: my $fn='/priv/'.$uname.'/'.$tfn;
134: $fn=~s/\/+/\//g;
135: &Debug($r, "Filename is ".$tfn);
136: if ($tfn) {
137: &Debug($r, "Filename for tfn = ".$tfn);
138: my $target='/home/'.$uname.'/public_html'.$tfn;
139: &Debug($r, "target -> ".$target);
140: # target is the full filesystem path of the destination file.
141: my $base = &File::Basename::basename($fn);
142: my $path = &File::Basename::dirname($fn);
143: $base = &HTML::Entities::encode($base);
144: my $url = $path."/".$base;
145: &Debug($r, "URL is now ".$url);
146: my $datatoken=$ENV{'form.datatoken'};
147: if (($fn) && ($datatoken)) {
148: if ((-e $target) && ($ENV{'form.override'} ne 'Yes')) {
149: $r->print(
150: '<form action=/adm/upload method=post>'.
151: &mt('File').' <tt>'.$fn.'</tt> '.&mt('exists. Overwrite?').' '.
152: '<input type=hidden name=phase value=two>'.
153: '<input type=hidden name=filename value="'."$url".'">'.
154: '<input type=hidden name=datatoken value="'.$datatoken.'">'.
155: '<input type=submit name=override value="'.&mt('Yes').'"></form>');
156: } else {
157: my $source=$r->dir_config('lonDaemons').
158: '/tmp/'.$datatoken.'.tmp';
159: # Check for bad extension and disallow upload
160: if ($fn=~/\.(\w+)$/ &&
161: (&Apache::loncommon::fileembstyle($1) eq 'hdn')) {
162: $r->print(
163: &mt('File').' <tt>'.$fn.'</tt> '.&mt('could not be copied.').'<br />'.
164: '<font color=red>'.
165: &mt('The extension on this file is reserved internally by LON-CAPA.').
166: '</font>');
167: $r->print('<p><font size=+2><a href="'.$path.
168: '">'.&mt('Back to Directory').'</a></font>');
169: } elsif ($fn=~/\.(\w+)$/ &&
170: !defined(&Apache::loncommon::fileembstyle($1))) {
171: $r->print(
172: &mt('File').' <tt>'.$fn.'</tt> '.&mt('could not be copied.').'<br />'.
173: '<font color=red>'.
174: &mt('The extension on this file is not recognized by LON-CAPA.').
175: '</font>');
176: $r->print('<p><font size=+2><a href="'.$path.
177: '">'.&mt('Back to Directory').'</a></font>');
178: } elsif (-d $target) {
179: $r->print(
180: 'File <tt>'.$fn.'</tt> could not be copied.<br />'.
181: '<font color=red>'.
182: &mt('The target is an existing directory.').
183: '</font>');
184: $r->print('<p><font size=+2><a href="'.$path.
185: '">'.&mt('Back to Directory').'</a></font>');
186: } elsif (copy($source,$target)) {
187: chmod(0660, $target); # Set permissions to rw-rw---.
188: $r->print(&mt('File copied.'));
189: $r->print('<p><font size=+2><a href="'.$url.
190: '">'.&mt('View file').'</a></font>');
191: $r->print('<p><font size=+2><a href="'.$path.
192: '">'.&mt('Back to Directory').'</a></font>');
193: } else {
194: $r->print('Failed to copy: '.$!);
195: $r->print('<p><font size=+2><a href="'.$path.
196: '">'.&mt('Back to Directory').'</a></font>');
197: }
198: }
199: } else {
200: $r->print(
201: '<font size=+1 color=red>'.
202: &mt('Please use browser "Back" button and pick a filename').'</font><p>');
203: }
204: } else {
205: $r->print(
206: '<font size=+1 color=red>'.&mt('Please use browser "Back" button and pick a filename').'</font><p>');
207: }
208: }
209:
210: # ---------------------------------------------------------------- Main Handler
211: sub handler {
212:
213: my $r=shift;
214:
215: my $uname;
216: my $udom;
217: #
218: # phase two: re-attach user
219: #
220: if ($ENV{'form.uploaduname'}) {
221: $ENV{'form.filename'}='/priv/'.$ENV{'form.uploaduname'}.'/'.
222: $ENV{'form.filename'};
223: }
224: #
225:
226: ($uname,$udom)=
227: &Apache::loncacc::constructaccess(
228: $ENV{'form.filename'},$r->dir_config('lonDefDomain'));
229: unless (($uname) && ($udom)) {
230: $r->log_reason($uname.' at '.$udom.
231: ' trying to publish file '.$ENV{'form.filename'}.
232: ' - not authorized',
233: $r->filename);
234: return HTTP_NOT_ACCEPTABLE;
235: }
236:
237: my $fn;
238: if ($ENV{'form.filename'}) {
239: $fn=$ENV{'form.filename'};
240: $fn=~s/^http\:\/\/[^\/]+\///;
241: $fn=~s/^\///;
242: $fn=~s/(\~|priv\/)(\w+)//;
243: $fn=~s/\/+/\//g;
244: } else {
245: $r->log_reason($ENV{'user.name'}.' at '.$ENV{'user.domain'}.
246: ' unspecified filename for upload', $r->filename);
247: return HTTP_NOT_FOUND;
248: }
249:
250: # ----------------------------------------------------------- Start page output
251:
252:
253: &Apache::loncommon::content_type($r,'text/html');
254: $r->send_http_header;
255:
256: $r->print('<html><head><title>LON-CAPA Construction Space</title></head>');
257:
258: $r->print(&Apache::loncommon::bodytag('Upload file to Construction Space'));
259:
260: if (($uname ne $ENV{'user.name'}) || ($udom ne $ENV{'user.domain'})) {
261: $r->print('<h3><font color=red>'.&mt('Co-Author').': '.$uname.
262: &mt(' at ').$udom.'</font></h3>');
263: }
264:
265: if ($ENV{'form.phase'} eq 'two') {
266: &phasetwo($r,$fn,$uname,$udom);
267: } else {
268: &phaseone($r,$fn,$uname,$udom);
269: }
270:
271: $r->print('</body></html>');
272: return OK;
273: }
274:
275: 1;
276: __END__
277:
278: =head1 NAME
279:
280: Apache::lonupload - upload files into construction space
281:
282: =head1 SYNOPSIS
283:
284: Invoked by /etc/httpd/conf/srm.conf:
285:
286: <Location /adm/upload>
287: PerlAccessHandler Apache::lonacc
288: SetHandler perl-script
289: PerlHandler Apache::lonupload
290: ErrorDocument 403 /adm/login
291: ErrorDocument 404 /adm/notfound.html
292: ErrorDocument 406 /adm/unauthorized.html
293: ErrorDocument 500 /adm/errorhandler
294: </Location>
295:
296: =head1 INTRODUCTION
297:
298: This module uploads a file sitting on a client computer into
299: library server construction space.
300:
301: This is part of the LearningOnline Network with CAPA project
302: described at http://www.lon-capa.org.
303:
304: =head1 HANDLER SUBROUTINE
305:
306: This routine is called by Apache and mod_perl.
307:
308: =over 4
309:
310: =item *
311:
312: Initialize variables
313:
314: =item *
315:
316: Start page output
317:
318: =item *
319:
320: output relevant interface phase (phaseone or phasetwo)
321:
322: =item *
323:
324: (phase one is to specify upload file; phase two is to handle conditions
325: subsequent to specification--like overwriting an existing file)
326:
327: =back
328:
329: =head1 OTHER SUBROUTINES
330:
331: =over 4
332:
333: =item *
334:
335: phaseone() : Interface for specifying file to upload.
336:
337: =item *
338:
339: phasetwo() : Interface for handling post-conditions about uploading (such
340: as overwriting an existing file).
341:
342: =item *
343:
344: upfile_store() : Store contents of uploaded file into temporary space. Invoked
345: by phaseone subroutine.
346:
347: =back
348:
349: =cut
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>