Annotation of loncom/interface/londependencies.pm, revision 1.5
1.1 raeburn 1: # The LearningOnline Network with CAPA
2: # Handler to manage dependencies for HTML files uploaded directly
3: # to a course.
4: #
1.5 ! raeburn 5: # $Id: londependencies.pm,v 1.4 2013/05/03 21:57:13 raeburn Exp $
1.1 raeburn 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: # /home/httpd/html/adm/gpl.txt
25: #
26: # http://www.lon-capa.org/
27: #
28: #
29: ###############################################################
30: ##############################################################
31:
32: =pod
33:
34: =head1 NAME
35:
36: londependencies- Handler to manage dependencies for HTML files
37: uploaded directly to a course.
38:
39: =head1 SYNOPSIS
40:
41: londependencies provides an interface for uploading, replacing
42: and deleting files which are dependencies for an HTML page
43: uploaded directly to a course.
44:
45: =head1 DESCRIPTION
46:
47: This module is used when editing a web page uploaded to a course,
48: in course context.
49:
50: =head1 INTERNAL SUBROUTINES
51:
52: =over
53:
54: =item process_changes()
55:
56: =item display_dependencies()
57:
58: =back
59:
60: =cut
61:
62: package Apache::londependencies;
63:
64: use strict;
65: use Apache::Constants qw(:common :http);
66: use Apache::lonnet;
67: use Apache::loncommon();
68: use Apache::lonhtmlcommon();
69: use Apache::lonlocal;
70: use LONCAPA qw(:DEFAULT :match);
71: use File::MMagic;
72:
73: sub handler {
74: my $r=shift;
75: if ($r->header_only) {
76: &Apache::loncommon::content_type($r,'text/html');
77: $r->send_http_header;
78: return OK;
79: }
80: my ($allowed,$cnum,$cdom,$chome);
81: if ($env{'request.course.id'}) {
82: $allowed = &Apache::lonnet::allowed('mdc',$env{'request.course.id'});
83: }
84: if (!$env{'request.course.fn'} || !$allowed) {
85: # Not in a course, or no mdc priv in course
86: $env{'user.error.msg'}="/adm/dependencies:mdc:0:0:Cannot display dependencies for page uploaded to course";
87: return HTTP_NOT_ACCEPTABLE;
88: } else {
89: $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
90: $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
91: $chome = $env{'course.'.$env{'request.course.id'}.'.home'};
92: }
93: &Apache::loncommon::content_type($r,'text/html');
94: $r->send_http_header;
95:
96: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
1.3 raeburn 97: ['action','symb','title','url','folderpath']);
1.1 raeburn 98: my $action = $env{'form.action'};
99: my $symb = $env{'form.symb'};
100: my $docs_title = $env{'form.title'};
1.2 raeburn 101: my $docs_url = $env{'form.url'};
1.3 raeburn 102: my $folderpath = &unescape($env{'form.folderpath'});
1.2 raeburn 103: my ($mimetype,$numpathchgs,$numrefchanges,%allfiles,%codebase,$url);
1.5 ! raeburn 104: my $earlyout;
1.2 raeburn 105: if ($symb) {
106: (undef,undef,$url) = &Apache::lonnet::decode_symb($symb);
1.5 ! raeburn 107: unless (&Apache::lonnet::is_on_map($url)) {
! 108: $earlyout = 1;
! 109: }
1.4 raeburn 110: } elsif (($docs_url) && (($env{'httpref.'.$docs_url} ne '') ||
111: ($docs_url =~ m{^\Q/uploaded/$cdom/$cnum/\E(portfolio/syllabus)/}))) {
1.2 raeburn 112: $url = $docs_url;
113: $url =~ s{^/}{};
114: }
1.1 raeburn 115: my $title = &mt('Manage Dependencies');
116: my $state = '<input type="hidden" name="symb" value="'.$symb.'" />'."\n".
1.3 raeburn 117: '<input type="hidden" name="folderpath" value="'.$env{'form.folderpath'}.'" />'."\n".
1.2 raeburn 118: '<input type="hidden" name="title" value="'.$docs_title.'" />'."\n".
119: '<input type="hidden" name="url" value="'.$docs_url.'" />'."\n";
1.1 raeburn 120: my $dir_root = '/userfiles';
1.4 raeburn 121: my ($destination,$context);
122: if ($url =~ m{^\Quploaded/$cdom/$cnum/\E(portfolio/syllabus)/}) {
123: $destination = $1;
124: $context = 'syllabus';
125: } else {
126: ($destination) =
127: ($url =~ m{^\Quploaded/$cdom/$cnum/\E((?:docs|supplemental)/(?:default|\d+)/\d+)/});
128: $context = 'coursedoc';
1.5 ! raeburn 129: if ($destination eq '') {
! 130: $earlyout = 1;
! 131: }
1.4 raeburn 132: }
1.1 raeburn 133: my $js = &Apache::loncommon::ask_embedded_js();
134: my $output = &Apache::loncommon::start_page($title,$js,
135: {'only_body' => 1});
1.5 ! raeburn 136: if ($earlyout) {
! 137: $r->print($output.&mt('Cannot display dependency information - invalid file: [_1].',$url).
! 138: &Apache::loncommon::end_page());
! 139: return OK;
! 140: }
1.1 raeburn 141: if ($action eq 'modifyhrefs') {
142: my ($result,$count,$codebasecount) =
143: &Apache::loncommon::modify_html_refs('manage_dependencies',$destination,
144: $cnum,$cdom,$dir_root);
145: $output .= $result;
146: $numrefchanges = $count + $codebasecount;
147: } elsif ($action eq 'process_changes') {
148: (my $result,$numpathchgs) =
1.4 raeburn 149: &process_changes($cdom,$cnum,$chome,$url,$destination,$dir_root,$state,$context);
1.1 raeburn 150: $output .= $result;
151: }
152: unless ((($action eq 'process_changes') && ($numpathchgs > 0)) ||
153: (($action eq 'modifyhrefs') && ($numrefchanges > 0))) {
154: if ($url =~ m{^\Quploaded/$cdom/$cnum/\E}) {
155: $output .= &display_dependencies($url,$state,$docs_title);
156: } else {
157: $output .= &mt('Cannot display dependency information - invalid file: [_1].',$url);
158: }
159: $output .= '<p><a href="javascript:window.close()">'.&mt('Close window').'</a>';
160: }
161: if (($action eq 'modifyhrefs') && ($numrefchanges > 0)) {
162: $output .= '<p><a href="javascript:window.opener.location.reload(true);javascript:window.close();">'.
163: &mt('Close pop-up window and reload page').'</a>';
164: }
165: $output .= &Apache::loncommon::end_page();
166: $r->print($output);
167: return OK;
168: }
169:
170: sub process_changes {
1.4 raeburn 171: my ($cdom,$cnum,$chome,$url,$destination,$dir_root,$state,$context) = @_;
1.1 raeburn 172: my ($output,$numpathchgs);
173: my ($numnew,$numtodelete,$numtomod) = (0,0,0);
174: my $url_root = "/uploaded/$cdom/$cnum";
175: if ($destination ne '') {
176: my $actionurl = '/adm/dependencies';
177: my @deletions = &Apache::loncommon::get_env_multiple('form.del_upload_dep');
178: my @modifications = &Apache::loncommon::get_env_multiple('form.mod_upload_dep');
179: $numtodelete = scalar(@deletions);
180: $numtomod = scalar(@modifications);
181: $numnew = $env{'form.number_newemb_items'};
182: if ($numtodelete > 0) {
183: my ($outcome,$error);
184: my @ids=&Apache::lonnet::current_machine_ids();
185: my $dir;
186: if (grep(/^\Q$chome\E$/,@ids)) {
187: $dir = &LONCAPA::propath($cdom,$cnum)."$dir_root/$destination";
188: }
189: foreach my $todelete (@deletions) {
190: my $item = &unescape($env{'form.embedded_orig_'.$todelete});
191: if ($dir eq '') {
192: my $result =
193: &Apache::lonnet::removeuploadedurl("$url_root/$destination/$item");
194: if ($result eq 'ok') {
195: $outcome .= '<li><span class="LC_filename">'.$item.'</li>';
196: } else {
197: $error .= &mt('Error: [_1] occurred when removing [_2]',$result,$item).'<br />';
198: }
199: } else {
200: if (-e "$dir/$item") {
201: if (unlink("$dir/$item")) {
202: $outcome .= '<li><span class="LC_filename">'.$item.'</li>';
203: } else {
204: $error .= &mt('Removal failed for [_1].',$item).'<br />';
205: }
206: } else {
207: $error .= &mt('File: [_1] not found when attempting removal.',$item).'<br />';
208: }
209: }
210: }
211: if ($outcome ne '') {
212: $output .= '<h4>'.&mt('Deleted unused files').'</h4>'.
213: '<ul>'.$outcome.'</ul>';
214: }
215: if ($error ne '') {
216: $output .= '<h4>'.&mt('Error(s) deleting unused files').'</h4>'.
217: '<p class="LC_warning">'.$error.'</p>';
218: }
219: }
220: if ((@modifications > 0) || ($numnew > 0)) {
221: (my $result,my $flag,$numpathchgs) =
1.4 raeburn 222: &Apache::loncommon::upload_embedded($context,$destination,$cnum,$cdom,
1.1 raeburn 223: $dir_root,$url_root,undef,undef,undef,
224: $state,'/adm/dependencies');
225: $output .= '<h4>'.&mt('Uploaded files').'</h4>'.
226: $result;
1.4 raeburn 227: unless ($numpathchgs) {
228: if ($context eq 'syllabus') {
229: my $modres =
230: &Apache::loncommon::modify_html_refs($context,'portfolio/syllabus',
231: $cnum,$cdom,
232: '/userfiles',"/$url");
233: $result .= $modres;
234: }
235: }
1.1 raeburn 236: }
237: } else {
238: $output .= '<span class="LC_warning">'.
239: &mt('Unable to process any requested dependency changes - invalid file: [_1].',$url).
240: '</span>';
241: }
242: if (!$numtodelete && !$numtomod && !$numnew) {
243: $output .= '<h4>'.&mt('No changes made.').'</h4>';
244: }
245: unless ($numpathchgs) {
246: $output .= '<hr />';
247: }
248: return ($output,$numpathchgs);
249: }
250:
251: sub display_dependencies {
252: my ($url,$state,$docs_title) = @_;
253: my ($mimetype,%allfiles,%codebase);
254: my $output;
255: if (&Apache::lonnet::repcopy_userfile("/$url") eq 'ok') {
256: my $file=&Apache::lonnet::filelocation("","/$url");
257: my $mm = new File::MMagic;
258: $mimetype = $mm->checktype_filename($file);
259: if ($mimetype eq 'text/html') {
260: my $parse_result = &Apache::lonnet::extract_embedded_items($file,\%allfiles,\%codebase);
261: if ($parse_result eq 'ok') {
262: my ($embedded,$num,$delnum) =
263: &Apache::loncommon::ask_for_embedded_content(
264: '/adm/dependencies',$state,\%allfiles,\%codebase,
265: {'error_on_invalid_names' => 1,
266: 'ignore_remote_references' => 1,
267: 'docs_url' => $url,
268: 'docs_title' => $docs_title});
269: if ($embedded) {
270: $output .= $embedded;
271: } else {
272: $output .= &mt('This file has no dependencies.').'<br />';
273: }
274: } else {
275: $output .= '<span class="LC_warning">'.
276: &mt('Could not parse HTML file: [_1] to identify existing dependencies.',"/$url").
277: '</span>';
278: }
279: } else {
280: $output .= '<span class="LC_warning">'.
281: &mt('File: [_1] does not appear to be an HTML file.',"/$url").
282: '</span>';
283: }
284: } else {
285: $output .= '<span class="LC_warning">'.
286: &mt('Failed to access HTML file: [_1] to identify existing dependencies.',
287: "/$url");
288: }
289: return $output;
290: }
291:
292: 1;
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>