[LON-CAPA-cvs] cvs: loncom /interface loncommon.pm londocs.pm portfolio.pm /publisher lonupload.pm testbankimport.pm
raeburn
raeburn@source.lon-capa.org
Sun, 28 Nov 2010 00:04:11 -0000
This is a MIME encoded message
--raeburn1290902651
Content-Type: text/plain
raeburn Sun Nov 28 00:04:11 2010 EDT
Modified files:
/loncom/interface portfolio.pm loncommon.pm londocs.pm
/loncom/publisher testbankimport.pm lonupload.pm
Log:
- Work on upload of HTML file with references to embedded objects etc.
- Replace &process_secondary_uploads() in londocs with general purpose routines
in loncommon.pm.
- More comprehensive feedback on reference detection.
- Reference updates in HTML file for changed paths originally only available
for upload of HTML file in course, now available for uploads in all contexts.
- Directory traversal in original HTML file via ../ etc. accommodated.
--raeburn1290902651
Content-Type: text/plain
Content-Disposition: attachment; filename="raeburn-20101128000411.txt"
Index: loncom/interface/portfolio.pm
diff -u loncom/interface/portfolio.pm:1.230 loncom/interface/portfolio.pm:1.231
--- loncom/interface/portfolio.pm:1.230 Thu Nov 11 23:58:05 2010
+++ loncom/interface/portfolio.pm Sun Nov 28 00:04:05 2010
@@ -1,7 +1,7 @@
# The LearningOnline Network
# portfolio browser
#
-# $Id: portfolio.pm,v 1.230 2010/11/11 23:58:05 raeburn Exp $
+# $Id: portfolio.pm,v 1.231 2010/11/28 00:04:05 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -1964,7 +1964,7 @@
return;
}
- my (%allfiles,%codebase,$mode);
+ my (%allfiles,%codebase,$mode,$mimetype);
if ($env{'form.'.$formname.'.filename'} =~ m/(\.htm|\.html|\.shtml)$/i) {
if ($env{'form.parserflag'}) {
$mode = 'parse';
@@ -1974,10 +1974,12 @@
if ($state eq 'existingfile') {
$context = $state;
}
+ my $subdir = $port_path.$env{'form.currentpath'};
+ $subdir =~ s{(/)$}{};
my ($result,$timestamp) =
- &Apache::lonnet::userfileupload($formname,$context,
- $port_path.$env{'form.currentpath'},
- $mode,\%allfiles,\%codebase);
+ &Apache::lonnet::userfileupload($formname,$context,$subdir,
+ $mode,\%allfiles,\%codebase,undef,undef,
+ undef,undef,undef,undef,\$mimetype);
if ($state eq 'existingfile') {
my $group_elem;
my $rootdir = $r->dir_config('lonDaemons').'/tmp/overwrites';
@@ -2063,14 +2065,20 @@
,$result,&display_file(undef,$fname)).'</span><br />');
$r->print(&done('Back',$url));
} else {
- if (%allfiles) {
- if (!&suppress_embed_prompt()) {
- &print_dependency_form($r,$url,\%allfiles,\%codebase);
+ if (!&suppress_embed_prompt()) {
+ if ($mimetype eq 'text/html') {
+ if (keys(%allfiles) > 0) {
+ &print_dependency_form($r,$url,\%allfiles,\%codebase,$result);
+ return;
+ } else {
+ $r->print('<p>'.&mt('Completed upload of the file.').'<br />'.
+ &mt('No embedded items identified.').'</p>');
+ }
}
- } else {
- $r->print(&done(undef,$url));
- }
+ }
+ $r->print(&done(undef,$url));
}
+ return;
}
sub hidden_elems {
@@ -2088,25 +2096,28 @@
}
sub print_dependency_form {
- my ($r,$url,$allfiles,$codebase) = @_;
- my $state = <<STATE;
- <input type="hidden" name="action" value="upload_embedded" />
- <input type="hidden" name="currentpath" value="$env{'form.currentpath'}" />
- <input type="hidden" name="fieldname" value="$env{'form.fieldname'}" />
- <input type="hidden" name="mode" value="$env{'form.mode'}" />
-STATE
- if ($env{'form.group'} ne '') {
- $state .= '<input type="hidden" name="group" value="'.$env{'form.group'}.'" />'."\n";
- }
- my $embedded = &Apache::loncommon::ask_for_embedded_content($url,$state,$allfiles,$codebase,
+ my ($r,$url,$allfiles,$codebase,$result) = @_;
+ my $container = &HTML::Entities::encode($result,'<>"&');
+ my $state = &embedded_form_elems($container);
+ my ($embedded,$num,$pathchg) = &Apache::loncommon::ask_for_embedded_content($url,$state,$allfiles,$codebase,
{'error_on_invalid_names' => 1,
'ignore_remote_references' => 1,});
if ($embedded) {
- $r->print('<h2>'.&mt("Reference Warning").'</h2>'.
- '<p>'.&mt("Completed upload of the file. This file contained references to other files. You must upload the referenced files or else the uploaded file may not work properly.").'</p>'.
- '<p>'.&mt("Please select the locations from which the referenced files are to be uploaded.").'</p>'.
- $embedded.
- '<p>Or '.&done('Return to directory',$url).'</p>');
+ if ($num || $pathchg) {
+ $r->print('<h3>'.&mt("Reference Warning").'</h3>');
+ } else {
+ $r->print('<h3>'.&mt("Reference Information").'</h3>');
+ }
+ if ($num) {
+ $r->print('<p>'.&mt("Completed upload of the file. This file contained references to other files. You must upload the referenced files or else the uploaded file may not work properly.").'</p>'.
+ '<p>'.&mt("Please select the locations from which the referenced files are to be uploaded.").'</p>'.
+ $embedded.
+ '<p>'.&mt('or').'</p>'.&done('Return to directory',$url));
+ } else {
+ $r->print('<p>'.&mt("Completed upload of the file. This file contained references to other files.").'</p>'.
+ $embedded.
+ '<p>'.&done('Return to directory',$url).'</p>');
+ }
} else {
$r->print(&done(undef,$url));
}
@@ -2118,7 +2129,8 @@
my $formname = 'existingfile';
my $port_path = &get_port_path();
my $fname = &Apache::lonnet::clean_filename($env{'form.filename'});
- my (%allfiles,%codebase,$mode);
+ my (%allfiles,%codebase,$mode,$mimetype);
+ my $mode;
unless (&suppress_embed_prompt()) {
if ($env{'form.parserflag'}) {
if ($fname =~ /\.s?html?$/i) {
@@ -2134,24 +2146,29 @@
return;
}
$env{'form.'.$formname.'.filename'} = $fname;
+ my $subdir = $port_path.$env{'form.currentpath'};
+ $subdir =~ s{(/)$}{};
my $result=
- &Apache::lonnet::userfileupload($formname,'overwrite',
- $port_path.$env{'form.currentpath'},
- $mode,\%allfiles,\%codebase);
+ &Apache::lonnet::userfileupload($formname,'overwrite',$subdir,$mode,
+ \%allfiles,\%codebase,undef,undef,undef,
+ undef,undef,undef,\$mimetype);
if ($result !~ m|^/uploaded/|) {
$r->print('<span class="LC_error">'.&mt('An error occurred ([_1]) while trying to overwrite [_2].'
,$result,&display_file(undef,$fname)).'</span><br />');
$r->print(&after_overwrite(&mt('Back'),$url));
} else {
- if (%allfiles) {
- if (!&suppress_embed_prompt()) {
- &print_dependency_form($r,$url,\%allfiles,\%codebase);
- } else {
- $r->print(&after_overwrite(undef,$url));
+ if ($mode eq 'parse') {
+ if ($mimetype eq 'text/html') {
+ if (keys(%allfiles) > 0) {
+ &print_dependency_form($r,$url,\%allfiles,\%codebase,$result);
+ return;
+ } else {
+ $r->print('<p>'.&mt('Overwriting completed.').'<br />'.
+ &mt('No embedded items identified.').'</p>');
+ }
}
- } else {
- $r->print(&after_overwrite(undef,$url));
}
+ $r->print(&after_overwrite(undef,$url));
}
return;
}
@@ -2427,6 +2444,19 @@
return $suppress_prompt;
}
+sub embedded_form_elems {
+ my ($container) = @_;
+ my $state = <<STATE;
+ <input type="hidden" name="currentpath" value="$env{'form.currentpath'}" />
+ <input type="hidden" name="fieldname" value="$env{'form.fieldname'}" />
+ <input type="hidden" name="mode" value="$env{'form.mode'}" />
+ <input type="hidden" name="container" value="$container" />
+STATE
+ if ($env{'form.group'} ne '') {
+ $state .= '<input type="hidden" name="group" value="'.$env{'form.group'}.'" />'."\n";
+ }
+ return $state;
+}
sub handler {
# this handles file management
@@ -2573,10 +2603,20 @@
my $getpropath = 1;
my $current_disk_usage =
&Apache::lonnet::diskusage($udom,$uname,$portfolio_root,$getpropath);
- $r->print(
+ my $container = &HTML::Entities::encode($env{'form.container'},'<>&"');
+ my $state = &embedded_form_elems($container).
+ '<input type="hidden" name="action" value="modify_orightml" />';
+ my ($result,$flag) =
&Apache::loncommon::upload_embedded('portfolio',$port_path,$uname,$udom,
- $group,$portfolio_root,$group,$disk_quota,$current_disk_usage));
- $r->print(&done(undef,$url));
+ $group,$portfolio_root,$group,$disk_quota,$current_disk_usage,$state,$url);
+ $r->print($result.&done('Return to directory',$url));
+ } else {
+ &missing_priv($r,$url,'upload');
+ }
+ } elsif ($env{'form.action'} eq 'modify_orightml') {
+ if ($can_upload) {
+ $r->print(&Apache::loncommon::modify_html_refs('portfolio',$port_path,$uname,$udom,$group,$portfolio_root,$group));
+ $r->print(&done('Return to directory',$url));
} else {
&missing_priv($r,$url,'upload');
}
@@ -2651,8 +2691,9 @@
my $formname = 'existingfile';
my $fname = &Apache::lonnet::clean_filename($env{'form.filename'});
$env{'form.'.$formname.'.filename'} = $fname;
- &Apache::lonnet::userfileupload($formname,'canceloverwrite',
- $port_path.$env{'form.currentpath'});
+ my $subdir = $port_path.$env{'form.currentpath'};
+ $subdir =~ s{(/)$}{};
+ &Apache::lonnet::userfileupload($formname,'canceloverwrite',$subdir);
}
}
my $current_path='/';
Index: loncom/interface/loncommon.pm
diff -u loncom/interface/loncommon.pm:1.986 loncom/interface/loncommon.pm:1.987
--- loncom/interface/loncommon.pm:1.986 Sun Nov 14 18:53:51 2010
+++ loncom/interface/loncommon.pm Sun Nov 28 00:04:05 2010
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# a pile of common routines
#
-# $Id: loncommon.pm,v 1.986 2010/11/14 18:53:51 raeburn Exp $
+# $Id: loncommon.pm,v 1.987 2010/11/28 00:04:05 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -8300,21 +8300,13 @@
sub ask_for_embedded_content {
my ($actionurl,$state,$allfiles,$codebase,$args)=@_;
- my (%subdependencies,%dependencies,%newfiles);
+ my (%subdependencies,%dependencies,%mapping,%existing,%newfiles,%pathchanges);
my $num = 0;
- my $upload_output;
- foreach my $embed_file (keys(%{$allfiles})) {
- unless ($embed_file =~ m{^\w+://} || $embed_file =~ m{^/}) {
- my ($relpath,$fname);
- if ($embed_file =~ m{/}) {
- my ($path,$fname) = ($embed_file =~ m{^(.+)/([^/]*)$});
- $subdependencies{$path}{$fname} = 1;
- } else {
- $dependencies{$embed_file} = 1;
- }
- }
- }
- my ($url,$udom,$uname,$getpropath);
+ my $numremref = 0;
+ my $numinvalid = 0;
+ my $numpathchg = 0;
+ my $numexisting = 0;
+ my ($output,$upload_output,$toplevel,$url,$udom,$uname,$getpropath);
if (($actionurl eq '/adm/portfolio') || ($actionurl eq '/adm/coursegrp_portfolio')) {
my $current_path='/';
if ($env{'form.currentpath'}) {
@@ -8329,13 +8321,57 @@
$uname = $env{'user.name'};
$url = '/userfiles/portfolio';
}
+ $toplevel = $url.'/';
$url .= $current_path;
$getpropath = 1;
- } elsif ($actionurl eq '/adm/upload') {
+ } elsif (($actionurl eq '/adm/upload') || ($actionurl eq '/adm/testbank') ||
+ ($actionurl eq '/adm/imsimport')) {
($uname,my $rest) = ($args->{'current_path'} =~ m{/priv/($match_username)/?(.*)$});
- $url = '/home/'.$uname.'/public_html';
+ $url = '/home/'.$uname.'/public_html/';
+ $toplevel = $url;
if ($rest ne '') {
- $url .= '/'.$rest;
+ $url .= $rest;
+ }
+ } elsif ($actionurl eq '/adm/coursedocs') {
+ if (ref($args) eq 'HASH') {
+ $url = $args->{'docs_url'};
+ $toplevel = $url;
+ }
+ }
+ my $now = time();
+ foreach my $embed_file (keys(%{$allfiles})) {
+ my $absolutepath;
+ if ($embed_file =~ m{^\w+://}) {
+ $newfiles{$embed_file} = 1;
+ $mapping{$embed_file} = $embed_file;
+ } else {
+ if ($embed_file =~ m{^/}) {
+ $absolutepath = $embed_file;
+ $embed_file =~ s{^(/+)}{};
+ }
+ if ($embed_file =~ m{/}) {
+ my ($path,$fname) = ($embed_file =~ m{^(.+)/([^/]*)$});
+ $path = &check_for_traversal($path,$url,$toplevel);
+ my $item = $fname;
+ if ($path ne '') {
+ $item = $path.'/'.$fname;
+ $subdependencies{$path}{$fname} = 1;
+ } else {
+ $dependencies{$item} = 1;
+ }
+ if ($absolutepath) {
+ $mapping{$item} = $absolutepath;
+ } else {
+ $mapping{$item} = $embed_file;
+ }
+ } else {
+ $dependencies{$embed_file} = 1;
+ if ($absolutepath) {
+ $mapping{$embed_file} = $absolutepath;
+ } else {
+ $mapping{$embed_file} = $embed_file;
+ }
+ }
}
}
foreach my $path (keys(%subdependencies)) {
@@ -8346,98 +8382,225 @@
my ($file_name,$rest) = split(/\&/,$line,2);
$currsubfile{$file_name} = 1;
}
- } elsif ($actionurl eq '/adm/upload') {
+ } elsif (($actionurl eq '/adm/upload') || ($actionurl eq '/adm/testbank')) {
if (opendir(my $dir,$url.'/'.$path)) {
my @subdir_list = grep(!/^\./,readdir($dir));
map {$currsubfile{$_} = 1;} @subdir_list;
}
}
foreach my $file (keys(%{$subdependencies{$path}})) {
- unless ($currsubfile{$file}) {
- $newfiles{$path.'/'.$file} = 1;
+ if ($currsubfile{$file}) {
+ my $item = $path.'/'.$file;
+ unless ($mapping{$item} eq $item) {
+ $pathchanges{$item} = 1;
+ }
+ $existing{$item} = 1;
+ $numexisting ++;
+ } else {
+ $newfiles{$path.'/'.$file} = 1;
}
}
}
- my (@dir_list,%currfile);
+ my %currfile;
if (($actionurl eq '/adm/portfolio') || ($actionurl eq '/adm/coursegrp_portfolio')) {
my @dir_list = &Apache::lonnet::dirlist($url,$udom,$uname,$getpropath);
foreach my $line (@dir_list) {
my ($file_name,$rest) = split(/\&/,$line,2);
$currfile{$file_name} = 1;
}
- } elsif ($actionurl eq '/adm/upload') {
+ } elsif (($actionurl eq '/adm/upload') || ($actionurl eq '/adm/testbank')) {
if (opendir(my $dir,$url)) {
- @dir_list = grep(!/^\./,readdir($dir));
+ my @dir_list = grep(!/^\./,readdir($dir));
map {$currfile{$_} = 1;} @dir_list;
}
}
foreach my $file (keys(%dependencies)) {
- unless ($currfile{$file}) {
+ if ($currfile{$file}) {
+ unless ($mapping{$file} eq $file) {
+ $pathchanges{$file} = 1;
+ }
+ $existing{$file} = 1;
+ $numexisting ++;
+ } else {
$newfiles{$file} = 1;
}
}
foreach my $embed_file (sort {lc($a) cmp lc($b)} keys(%newfiles)) {
$upload_output .= &start_data_table_row().
- '<td>'.$embed_file.'</td><td>';
+ '<td><span class="LC_filename">'.$embed_file.'</span>';
+ unless ($mapping{$embed_file} eq $embed_file) {
+ $upload_output .= '<br /><span class="LC_info" style="font-size:smaller;">'.&mt('changed from: [_1]',$mapping{$embed_file}).'</span>';
+ }
+ $upload_output .= '</td><td>';
if ($args->{'ignore_remote_references'}
&& $embed_file =~ m{^\w+://}) {
$upload_output.='<span class="LC_warning">'.&mt("URL points to other server.").'</span>';
+ $numremref++;
} elsif ($args->{'error_on_invalid_names'}
&& $embed_file ne &Apache::lonnet::clean_filename($embed_file,{'keep_path' => 1,})) {
- $upload_output.='<span class="LC_warning">'.&mt("Invalid characters").'</span>';
-
+ $upload_output.='<span class="LC_warning">'.&mt('Invalid characters').'</span>';
+ $numinvalid++;
} else {
- $upload_output .='
- <input name="embedded_item_'.$num.'" type="file" value="" />
- <input name="embedded_orig_'.$num.'" type="hidden" value="'.&escape($embed_file).'" />';
- my $attrib = join(':',@{$$allfiles{$embed_file}});
- $upload_output .=
- "\n\t\t".
- '<input name="embedded_attrib_'.$num.'" type="hidden" value="'.
- $attrib.'" />';
- if (exists($$codebase{$embed_file})) {
- $upload_output .=
- "\n\t\t".
- '<input name="codebase_'.$num.'" type="hidden" value="'.
- &escape($$codebase{$embed_file}).'" />';
- }
+ $upload_output .= &embedded_file_element('upload_embedded',$num,
+ $embed_file,\%mapping,
+ $allfiles,$codebase);
+ $num++;
}
$upload_output .= '</td>'.&Apache::loncommon::end_data_table_row()."\n";
- $num++;
}
- if ($num) {
- $upload_output = '<form name="upload_embedded" action="'.$actionurl.'"'.
- ' method="post" enctype="multipart/form-data">'."\n".
- $state.
- '<b>Upload embedded files</b>:<br />'.&start_data_table().
+ foreach my $embed_file (sort {lc($a) cmp lc($b)} keys(%existing)) {
+ $upload_output .= &start_data_table_row().
+ '<td><span class="LC_filename">'.$embed_file.'</span></td>'.
+ '<td><span class="LC_warning">'.&mt('Already exists').'</span></td>'.
+ &Apache::loncommon::end_data_table_row()."\n";
+ }
+ if ($upload_output) {
+ $upload_output = &start_data_table().
$upload_output.
- &Apache::loncommon::end_data_table().'<br />'."\n".
- '<input type ="hidden" name="number_embedded_items" value="'.$num.'" />'."\n".
- '<input type ="submit" value="'.&mt('Upload Listed Files').'" />'."\n".
- &mt('(only files for which a location has been provided will be uploaded)')."\n".
- '</form>';
+ &end_data_table()."\n";
+ }
+ my $applies = 0;
+ if ($numremref) {
+ $applies ++;
+ }
+ if ($numinvalid) {
+ $applies ++;
+ }
+ if ($numexisting) {
+ $applies ++;
+ }
+ if ($num) {
+ $output = '<form name="upload_embedded" action="'.$actionurl.'"'.
+ ' method="post" enctype="multipart/form-data">'."\n".
+ $state.
+ '<h3>'.&mt('Upload embedded files').
+ ':</h3>'.$upload_output.'<br />'."\n".
+ '<input type ="hidden" name="number_embedded_items" value="'.
+ $num.'" />'."\n";
+ if ($actionurl eq '') {
+ $output .= '<input type="hidden" name="phase" value="three" />';
+ }
+ } elsif ($applies) {
+ $output = '<b>'.&mt('Referenced files').'</b>:<br />';
+ if ($applies > 1) {
+ $output .=
+ &mt('No files need to be uploaded, as one of the following applies to each reference:').'<ul>';
+ if ($numremref) {
+ $output .= '<li>'.&mt('reference is to a URL which points to another server').'</li>'."\n";
+ }
+ if ($numinvalid) {
+ $output .= '<li>'.&mt('reference is to file with a name containing invalid characters').'</li>'."\n";
+ }
+ if ($numexisting) {
+ $output .= '<li>'.&mt('reference is to an existing file at the specified location').'</li>'."\n";
+ }
+ $output .= '</ul><br />';
+ } elsif ($numremref) {
+ $output .= '<p>'.&mt('None to upload, as all references are to URLs pointing to another server.').'</p>';
+ } elsif ($numinvalid) {
+ $output .= '<p>'.&mt('None to upload, as all references are to files with names containing invalid characters.').'</p>';
+ } elsif ($numexisting) {
+ $output .= '<p>'.&mt('None to upload, as all references are to existing files.').'</p>';
+ }
+ $output .= $upload_output.'<br />';
+ }
+ my ($pathchange_output,$chgcount);
+ $chgcount = $num;
+ if (keys(%pathchanges) > 0) {
+ foreach my $embed_file (sort {lc($a) cmp lc($b)} keys(%pathchanges)) {
+ if ($num) {
+ $output .= &embedded_file_element('pathchange',$chgcount,
+ $embed_file,\%mapping,
+ $allfiles,$codebase);
+ } else {
+ $pathchange_output .=
+ &start_data_table_row().
+ '<td><input type ="checkbox" name="namechange" value="'.
+ $chgcount.'" checked="checked" /></td>'.
+ '<td>'.$mapping{$embed_file}.'</td>'.
+ '<td>'.$embed_file.
+ &embedded_file_element('pathchange',$numpathchg,$embed_file,
+ \%mapping,$allfiles,$codebase).
+ '</td>'.&end_data_table_row();
+ }
+ $numpathchg ++;
+ $chgcount ++;
+ }
+ }
+ if ($num) {
+ if ($numpathchg) {
+ $output .= '<input type ="hidden" name="number_pathchange_items" value="'.
+ $numpathchg.'" />'."\n";
+ }
+ if (($actionurl eq '/adm/upload') || ($actionurl eq '/adm/testbank') ||
+ ($actionurl eq '/adm/imsimport')) {
+ $output .= '<input type="hidden" name="phase" value="three" />'."\n";
+ } elsif ($actionurl eq '/adm/portfolio' || $actionurl eq '/adm/coursegrp_portfolio') {
+ $output .= '<input type="hidden" name="action" value="upload_embedded" />';
+ }
+ $output .= '<input type ="submit" value="'.&mt('Upload Listed Files').'" />'."\n".
+ &mt('(only files for which a location has been provided will be uploaded)').'</form>'."\n";
+ } elsif ($numpathchg) {
+ my %pathchange = ();
+ $output .= &modify_html_form('pathchange',$actionurl,$state,\%pathchange,$pathchange_output);
+ if (($actionurl eq '/adm/portfolio') || ($actionurl eq '/adm/coursegrp_portfolio')) {
+ $output .= '<p>'.&mt('or').'</p>';
+ }
}
- return $upload_output;
+ return ($output,$num,$numpathchg);
+}
+
+sub embedded_file_element {
+ my ($context,$num,$embed_file,$mapping,$allfiles,$codebase) = @_;
+ return unless ((ref($mapping) eq 'HASH') && (ref($allfiles) eq 'HASH') &&
+ (ref($codebase) eq 'HASH'));
+ my $output;
+ if ($context eq 'upload_embedded') {
+ $output = '<input name="embedded_item_'.$num.'" type="file" value="" />'."\n";
+ }
+ $output .= '<input name="embedded_orig_'.$num.'" type="hidden" value="'.
+ &escape($embed_file).'" />';
+ unless (($context eq 'upload_embedded') &&
+ ($mapping->{$embed_file} eq $embed_file)) {
+ $output .='
+ <input name="embedded_ref_'.$num.'" type="hidden" value="'.&escape($mapping->{$embed_file}).'" />';
+ }
+ my $attrib;
+ if (ref($allfiles->{$mapping->{$embed_file}}) eq 'ARRAY') {
+ $attrib = &escape(join(':',@{$allfiles->{$mapping->{$embed_file}}}));
+ }
+ $output .=
+ "\n\t\t".
+ '<input name="embedded_attrib_'.$num.'" type="hidden" value="'.
+ $attrib.'" />';
+ if (exists($codebase->{$mapping->{$embed_file}})) {
+ $output .=
+ "\n\t\t".
+ '<input name="codebase_'.$num.'" type="hidden" value="'.
+ &escape($codebase->{$mapping->{$embed_file}}).'" />';
+ }
+ return $output;
}
sub upload_embedded {
my ($context,$dirpath,$uname,$udom,$dir_root,$url_root,$group,$disk_quota,
- $current_disk_usage) = @_;
- my $output;
+ $current_disk_usage,$hiddenstate,$actionurl) = @_;
+ my (%pathchange,$output,$modifyform,$footer,$returnflag);
for (my $i=0; $i<$env{'form.number_embedded_items'}; $i++) {
next if (!exists($env{'form.embedded_item_'.$i.'.filename'}));
my $orig_uploaded_filename =
$env{'form.embedded_item_'.$i.'.filename'};
-
- $env{'form.embedded_orig_'.$i} =
- &unescape($env{'form.embedded_orig_'.$i});
+ foreach my $type ('orig','ref','attrib','codebase') {
+ if ($env{'form.embedded_'.$type.'_'.$i} ne '') {
+ $env{'form.embedded_'.$type.'_'.$i} =
+ &unescape($env{'form.embedded_'.$type.'_'.$i});
+ }
+ }
my ($path,$fname) =
($env{'form.embedded_orig_'.$i} =~ m{(.*/)([^/]*)});
# no path, whole string is fname
if (!$fname) { $fname = $env{'form.embedded_orig_'.$i} };
-
- $path = $env{'form.currentpath'}.$path;
$fname = &Apache::lonnet::clean_filename($fname);
# See if there is anything left
next if ($fname eq '');
@@ -8449,7 +8612,8 @@
if ($group ne '') {
$port_path = "groups/$group/$port_path";
}
- ($state,$msg) = &check_for_upload($path,$fname,$group,'embedded_item_'.$i,
+ ($state,$msg) = &check_for_upload($env{'form.currentpath'}.$path,
+ $fname,$group,'embedded_item_'.$i,
$dir_root,$port_path,$disk_quota,
$current_disk_usage,$uname,$udom);
if ($state eq 'will_exceed_quota'
@@ -8467,14 +8631,14 @@
# Check if extension is valid
if (($fname =~ /\.(\w+)$/) &&
(&Apache::loncommon::fileembstyle($1) eq 'hdn')) {
- $output .= &mt('Invalid file extension ([_1]) - reserved for LONCAPA use - rename the file with a different extension and re-upload. ',$1);
+ $output .= &mt('Invalid file extension ([_1]) - reserved for LONCAPA use - rename the file with a different extension and re-upload. ',$1).'<br />';
next;
} elsif (($fname =~ /\.(\w+)$/) &&
(!defined(&Apache::loncommon::fileembstyle($1)))) {
- $output .= &mt('Unrecognized file extension ([_1]) - rename the file with a proper extension and re-upload.',$1);
+ $output .= &mt('Unrecognized file extension ([_1]) - rename the file with a proper extension and re-upload.',$1).'<br />';
next;
} elsif ($fname=~/\.(\d+)\.(\w+)$/) {
- $output .= &mt('File name not allowed - rename the file to remove the number immediately before the file extension([_1]) and re-upload.',$2);
+ $output .= &mt('File name not allowed - rename the file to remove the number immediately before the file extension([_1]) and re-upload.',$2).'<br />';
next;
}
@@ -8484,11 +8648,12 @@
if ($state eq 'existingfile') {
$result=
&Apache::lonnet::userfileupload('embedded_item_'.$i,'existingfile',
- $dirpath.$path,);
+ $dirpath.$env{'form.currentpath'}.$path);
} else {
$result=
&Apache::lonnet::userfileupload('embedded_item_'.$i,'',
- $dirpath.$path);
+ $dirpath.
+ $env{'form.currentpath'}.$path);
if ($result !~ m|^/uploaded/|) {
$output .= '<span class="LC_error">'
.&mt('An error occurred ([_1]) while trying to upload [_2] for embedded element [_3].'
@@ -8496,10 +8661,24 @@
.'</span><br />';
next;
} else {
- $output .= '<p>'.&mt('Uploaded [_1]','<span class="LC_filename">'.
- $path.$fname.'</span>').'</p>';
+ $output .= &mt('Uploaded [_1]','<span class="LC_filename">'.
+ $path.$fname.'</span>').'<br />';
}
}
+ } elsif ($context eq 'coursedoc') {
+ my $result =
+ &Apache::lonnet::userfileupload('embedded_item_'.$i,'coursedoc',
+ $dirpath.'/'.$path);
+ if ($result !~ m|^/uploaded/|) {
+ $output .= '<span class="LC_error">'
+ .&mt('An error occurred ([_1]) while trying to upload [_2] for embedded element [_3].'
+ ,$result,$orig_uploaded_filename,$env{'form.embedded_orig_'.$i})
+ .'</span><br />';
+ next;
+ } else {
+ $output .= &mt('Uploaded [_1]','<span class="LC_filename">'.
+ $path.$fname.'</span>').'<br />';
+ }
} else {
# Save the file
my $target = $env{'form.embedded_item_'.$i};
@@ -8528,19 +8707,190 @@
&mt('An error occurred while writing the file [_1] for embedded element [_2].',$orig_uploaded_filename,$env{'form.embedded_orig_'.$i}).
'</span><br />';
} else {
- if ($context eq 'testbank') {
- $output .= &mt('Embedded file uploaded successfully:').
- ' <a href="'.$url.'">'.
- $orig_uploaded_filename.'</a><br />';
- } else {
- $output .= '<span class=\"LC_fontsize_large\">'.
- &mt('View embedded file: [_1]','<a href="'.$url.'">'.
- $orig_uploaded_filename.'</a>').'</span><br />';
+ $output .= &mt('Uploaded [_1]','<span class="LC_filename">'.
+ $url.'</span>').'<br />';
+ unless ($context eq 'testbank') {
+ $footer .= &mt('View embedded file: [_1]',
+ '<a href="'.$url.'">'.$fname.'</a>').'<br />';
}
}
close($fh);
}
}
+ if ($env{'form.embedded_ref_'.$i}) {
+ $pathchange{$i} = 1;
+ }
+ }
+ if ($output) {
+ $output = '<p>'.$output.'</p>';
+ }
+ $output .= &modify_html_form('upload_embedded',$actionurl,$hiddenstate,\%pathchange);
+ $returnflag = 'ok';
+ if (keys(%pathchange) > 0) {
+ if ($context eq 'portfolio') {
+ $output .= '<p>'.&mt('or').'</p>';
+ } elsif ($context eq 'testbank') {
+ $output .= '<p>'.&mt('Or [_1]continue[_2] the testbank import without modifying the references(s).','<a href="javascript:document.testbankForm.submit();">','</a>').'</p>';
+ $returnflag = 'modify_orightml';
+ }
+ }
+ return ($output.$footer,$returnflag);
+}
+
+sub modify_html_form {
+ my ($context,$actionurl,$hiddenstate,$pathchange,$pathchgtable) = @_;
+ my $end = 0;
+ my $modifyform;
+ if ($context eq 'upload_embedded') {
+ return unless (ref($pathchange) eq 'HASH');
+ if ($env{'form.number_embedded_items'}) {
+ $end += $env{'form.number_embedded_items'};
+ }
+ if ($env{'form.number_pathchange_items'}) {
+ $end += $env{'form.number_pathchange_items'};
+ }
+ if ($end) {
+ for (my $i=0; $i<$end; $i++) {
+ if ($i < $env{'form.number_embedded_items'}) {
+ next unless($pathchange->{$i});
+ }
+ $modifyform .=
+ &start_data_table_row().
+ '<td><input type ="checkbox" name="namechange" value="'.$i.'" '.
+ 'checked="checked" /></td>'.
+ '<td>'.$env{'form.embedded_ref_'.$i}.
+ '<input type="hidden" name="embedded_ref_'.$i.'" value="'.
+ &escape($env{'form.embedded_ref_'.$i}).'" />'.
+ '<input type="hidden" name="embedded_codebase_'.$i.'" value="'.
+ &escape($env{'form.embedded_codebase_'.$i}).'" />'.
+ '<input type="hidden" name="embedded_attrib_'.$i.'" value="'.
+ &escape($env{'form.embedded_attrib_'.$i}).'" /></td>'.
+ '<td>'.$env{'form.embedded_orig_'.$i}.
+ '<input type="hidden" name="embedded_orig_'.$i.'" value="'.
+ &escape($env{'form.embedded_orig_'.$i}).'" /></td>'.
+ &end_data_table_row();
+ }
+ }
+ } else {
+ $modifyform = $pathchgtable;
+ if (($actionurl eq '/adm/upload') || ($actionurl eq '/adm/testbank')) {
+ $hiddenstate .= '<input type="hidden" name="phase" value="four" />';
+ } elsif (($actionurl eq '/adm/portfolio') || ($actionurl eq '/adm/coursegrp_portfolio')) {
+ $hiddenstate .= '<input type="hidden" name="action" value="modify_orightml" />';
+ }
+ }
+ if ($modifyform) {
+ return '<h3>'.&mt('Changes in content of HTML file required').'</h3>'."\n".
+ '<p>'.&mt('Changes need to be made to the reference(s) used for one or more of the dependencies, if your HTML file is to work correctly:').'<ol>'."\n".
+ '<li>'.&mt('For consistency between the reference(s) and the location of the corresponding stored file within LON-CAPA.').'</li>'."\n".
+ '<li>'.&mt('To change absolute paths to relative paths, or replace directory traversal via "../" within the original reference.').'</li>'."\n".
+ '</ol></p>'."\n".'<p>'.
+ &mt('LON-CAPA can make the required changes to your HTML file.').'</p>'."\n".
+ '<form method="post" name="refchanger" action="'.$actionurl.'">'.
+ &start_data_table()."\n".
+ &start_data_table_header_row().
+ '<th>'.&mt('Change?').'</th>'.
+ '<th>'.&mt('Current reference').'</th>'.
+ '<th>'.&mt('Required reference').'</th>'.
+ &end_data_table_header_row()."\n".
+ $modifyform.
+ &end_data_table().'<br />'."\n".$hiddenstate.
+ '<input type="submit" name="pathchanges" value="'.&mt('Modify HTML file').'" />'.
+ '</form>'."\n";
+ }
+ return;
+}
+
+sub modify_html_refs {
+ my ($context,$dirpath,$uname,$udom,$dir_root) = @_;
+ my $container;
+ if ($context eq 'portfolio') {
+ $container = $env{'form.container'};
+ } elsif ($context eq 'coursedoc') {
+ $container = $env{'form.primaryurl'};
+ } else {
+ $container = $env{'form.filename'};
+ $container =~ s{^/priv/(\Q$uname\E)/(.*)}{/home/$1/public_html/$2};
+ }
+ my (%allfiles,%codebase,$output,$content);
+ my @changes = &get_env_multiple('form.namechange');
+ return unless (@changes > 0);
+ if (($context eq 'portfolio') || ($context eq 'coursedoc')) {
+ return unless ($container =~ m{^/uploaded/\Q$udom\E/\Q$uname\E/});
+ $content = &Apache::lonnet::getfile($container);
+ return if ($content eq '-1');
+ } else {
+ return unless ($container =~ /^\Q$dir_root\E/);
+ if (open(my $fh,"<$container")) {
+ $content = join('', <$fh>);
+ close($fh);
+ } else {
+ return;
+ }
+ }
+ my ($count,$codebasecount) = (0,0);
+ my $mm = new File::MMagic;
+ my $mime_type = $mm->checktype_contents($content);
+ if ($mime_type eq 'text/html') {
+ my $parse_result =
+ &Apache::lonnet::extract_embedded_items($container,\%allfiles,
+ \%codebase,\$content);
+ if ($parse_result eq 'ok') {
+ foreach my $i (@changes) {
+ my $orig = &unescape($env{'form.embedded_orig_'.$i});
+ my $ref = &unescape($env{'form.embedded_ref_'.$i});
+ if ($allfiles{$ref}) {
+ my $newname = $orig;
+ my ($attrib_regexp,$codebase);
+ my $attrib_regexp = &unescape($env{'form.embedded_attrib_'.$i});
+ if ($attrib_regexp =~ /:/) {
+ $attrib_regexp =~ s/\:/|/g;
+ }
+ if ($content =~ m{($attrib_regexp\s*=\s*['"]?)\Q$ref\E(['"]?)}) {
+ my $numchg = ($content =~ s{($attrib_regexp\s*=\s*['"]?)\Q$ref\E(['"]?)}{$1$newname$2}gi);
+ $count += $numchg;
+ }
+ if ($env{'form.embedded_codebase_'.$i} ne '') {
+ my $codebase = &unescape($env{'form.embedded_codebase_'.$i});
+ my $numchg = ($content =~ s/(codebase\s*=\s*["']?)\Q$codebase\E(["']?)/$1.$2/i); #' stupid emacs
+ $codebasecount ++;
+ }
+ }
+ }
+ if ($count || $codebasecount) {
+ my $saveresult;
+ if ($context eq 'portfolio' || $context eq 'coursedoc') {
+ my $url = &Apache::lonnet::store_edited_file($container,$content,$udom,$uname,\$saveresult);
+ if ($url eq $container) {
+ my ($fname) = ($container =~ m{/([^/]+)$});
+ $output = '<p>'.&mt('Updated [quant,_1,reference] in [_2].',
+ $count,'<span class="LC_filename">'.
+ $fname.'</span>').'</p>';
+ } else {
+ $output = '<p class="LC_error">'.
+ &mt('Error: update failed for: [_1].',
+ '<span class="LC_filename">'.
+ $container.'</span>').'</p>';
+ }
+ } else {
+ if (open(my $fh,">$container")) {
+ print $fh $content;
+ close($fh);
+ $output = '<p>'.&mt('Updated [quant,_1,reference] in [_2].',
+ $count,'<span class="LC_filename">'.
+ $container.'</span>').'</p>';
+ } else {
+ $output = '<p class="LC_error">'.
+ &mt('Error: could not update [_1].',
+ '<span class="LC_filename">'.
+ $container.'</span>').'</p>';
+ }
+ }
+ }
+ } else {
+ &logthis('Failed to parse '.$container.
+ ' to modify references: '.$parse_result);
+ }
}
return $output;
}
@@ -8628,6 +8978,48 @@
}
}
+sub check_for_traversal {
+ my ($path,$url,$toplevel) = @_;
+ my @parts=split(/\//,$path);
+ my $cleanpath;
+ my $fullpath = $url;
+ for (my $i=0;$i<@parts;$i++) {
+ next if ($parts[$i] eq '.');
+ if ($parts[$i] eq '..') {
+ $fullpath =~ s{([^/]+/)$}{};
+ } else {
+ $fullpath .= $parts[$i].'/';
+ }
+ }
+ if ($fullpath =~ /^\Q$url\E(.*)$/) {
+ $cleanpath = $1;
+ } elsif ($fullpath =~ /^\Q$toplevel\E(.*)$/) {
+ my $curr_toprel = $1;
+ my @parts = split(/\//,$curr_toprel);
+ my ($url_toprel) = ($url =~ /^\Q$toplevel\E(.*)$/);
+ my @urlparts = split(/\//,$url_toprel);
+ my $doubledots;
+ my $startdiff = -1;
+ for (my $i=0; $i<@urlparts; $i++) {
+ if ($startdiff == -1) {
+ unless ($urlparts[$i] eq $parts[$i]) {
+ $startdiff = $i;
+ $doubledots .= '../';
+ }
+ } else {
+ $doubledots .= '../';
+ }
+ }
+ if ($startdiff > -1) {
+ $cleanpath = $doubledots;
+ for (my $i=$startdiff; $i<@parts; $i++) {
+ $cleanpath .= $parts[$i].'/';
+ }
+ }
+ }
+ $cleanpath =~ s{(/)$}{};
+ return $cleanpath;
+}
=pod
Index: loncom/interface/londocs.pm
diff -u loncom/interface/londocs.pm:1.439 loncom/interface/londocs.pm:1.440
--- loncom/interface/londocs.pm:1.439 Wed Oct 27 01:00:38 2010
+++ loncom/interface/londocs.pm Sun Nov 28 00:04:05 2010
@@ -1,7 +1,7 @@
# The LearningOnline Network
# Documents
#
-# $Id: londocs.pm,v 1.439 2010/10/27 01:00:38 raeburn Exp $
+# $Id: londocs.pm,v 1.440 2010/11/28 00:04:05 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -1682,11 +1682,10 @@
sub process_file_upload {
my ($upload_output,$coursenum,$coursedom,$allfiles,$codebase,$uploadcmd) = @_;
# upload a file, if present
- my $parseaction;
- if ($env{'form.parserflag'}) {
+ my ($parseaction,$showupload,$nextphase,$mimetype);
+ if ($env{'form.parserflag'}) {
$parseaction = 'parse';
}
- my $phase_status;
my $folder=$env{'form.folder'};
if ($folder eq '') {
$folder='default';
@@ -1705,7 +1704,8 @@
$LONCAPA::map::resources[1]='';
}
if ($fatal) {
- return 'failed';
+ $$upload_output = '<p><span class="LC_error">'.&mt('The uploaded file has not been stored as an error occurred reading the contents of the current folder.').'</span></p>';
+ return;
}
my $destination = 'docs/';
if ($folder =~ /^supplemental/) {
@@ -1716,13 +1716,23 @@
} elsif ($folder =~ /^(default|supplemental)_(\d+)$/) {
$destination .= $2.'/';
}
-# this is for a course, not a user, so set coursedoc flag
-# probably the only place in the system where this should be "1"
+# this is for a course, not a user, so set context to coursedoc.
my $newidx=&LONCAPA::map::getresidx();
$destination .= $newidx;
my $url=&Apache::lonnet::userfileupload('uploaddoc','coursedoc',$destination,
$parseaction,$allfiles,
- $codebase);
+ $codebase,undef,undef,undef,undef,
+ undef,undef,\$mimetype);
+ if ($url =~ m{^/uploaded/\Q$coursedom\E/\Q$coursenum\E.*/([^/]+)$}) {
+ my $stored = $1;
+ $showupload = '<p>'.&mt('Uploaded [_1]','<span class="LC_filename">'.
+ $stored.'</span>').'</p>';
+ } else {
+ my ($filename) = ($env{'form.uploaddoc.filename'} =~ m{([^/]+)$});
+
+ $$upload_output = '<p><span class="LC_error">'.&mt('Unable to save file [_1].','<span class="LC_filename">'.$filename.'</span>').'</span></p>';
+ return;
+ }
my $ext='false';
if ($url=~m{^http://}) { $ext='true'; }
$url = &LONCAPA::map::qtunescape($url);
@@ -1739,51 +1749,37 @@
($errtext,$fatal)=&storemap($coursenum,$coursedom,
$folder.'.'.$container);
if ($fatal) {
- $$upload_output .= '<p><span class="LC_error">'.$errtext.'</span></p>';
- return 'failed';
+ $$upload_output = '<p><span class="LC_error">'.$errtext.'</span></p>';
+ return;
} else {
- if ($parseaction eq 'parse') {
+ if ($parseaction eq 'parse' && $mimetype eq 'text/html') {
+ $$upload_output = $showupload;
my $total_embedded = scalar(keys(%{$allfiles}));
if ($total_embedded > 0) {
- my $num = 0;
- my $state = '
- <input type="hidden" name="folderpath" value="'.&HTML::Entities::encode($env{'form.folderpath'},'<>&"').'" />
- <input type="hidden" name="cmd" value="upload_embedded" />
- <input type="hidden" name="newidx" value="'.$newidx.'" />
- <input type="hidden" name="primaryurl" value="'.&escape($url).'" />
- <input type="hidden" name="phasetwo" value="'.$total_embedded.'" />';
- $phase_status = 'phasetwo';
-
- $$upload_output .=
- 'This file contains embedded multimedia objects, which need to be uploaded to LON-CAPA.<br />'.
- &Apache::loncommon::ask_for_embedded_content(
- '/adm/coursedocs',$state,$allfiles,$codebase);
+ my $uploadphase = 'upload_embedded';
+ my $primaryurl = &HTML::Entities::encode($url,'<>&"');
+ my $state = &embedded_form_elems($uploadphase,$primaryurl,$newidx);
+ my ($embedded,$num) =
+ &Apache::loncommon::ask_for_embedded_content(
+ '/adm/coursedocs',$state,$allfiles,$codebase,{'docs_url' => $url});
+ if ($embedded) {
+ if ($num) {
+ $$upload_output .=
+ '<p>'.&mt('This file contains embedded multimedia objects, which need to be uploaded.').'</p>'.$embedded;
+ $nextphase = $uploadphase;
+ } else {
+ $$upload_output .= $embedded;
+ }
+ } else {
+ $$upload_output .= &mt('Embedded item(s) already present, so no additional upload(s) required').'<br />';
+ }
} else {
- $$upload_output .= 'No embedded items identified<br />';
+ $$upload_output .= &mt('No embedded items identified').'<br />';
}
}
}
}
- return $phase_status;
-}
-
-sub process_secondary_uploads {
- my ($upload_output,$coursedom,$coursenum,$formname,$num,$newidx) = @_;
- my $folder=$env{'form.folder'};
- my $destination = 'docs/';
- if ($folder =~ /^supplemental/) {
- $destination = 'supplemental/';
- }
- if (($folder eq 'default') || ($folder eq 'supplemental')) {
- $destination .= 'default/';
- } elsif ($folder =~ /^(default|supplemental)_(\d+)$/) {
- $destination .= $2.'/';
- }
- $destination .= $newidx;
- my ($url,$filename);
- $url=&Apache::lonnet::userfileupload($formname.$num,'coursedoc',$destination);
- ($filename) = ($url =~ m{^/uploaded/\Q$coursedom\E/\Q$coursenum\E/\Q$destination\E/(.+)$});
- return $filename;
+ return $nextphase;
}
sub is_supplemental_title {
@@ -1848,7 +1844,7 @@
}
if ($env{'form.pagepath'}) {
$type = $container = 'page';
- $esc_path=&escape($path = $env{'form.pagepath'});
+ $esc_path=&escape($env{'form.pagepath'});
$path = &HTML::Entities::encode($env{'form.pagepath'},'<>&"');
$symb=&escape($env{'form.pagesymb'});
}
@@ -2825,92 +2821,49 @@
my %allfiles = ();
my %codebase = ();
- my ($upload_result,$upload_output);
+ my ($upload_result,$upload_output,$uploadphase);
if ($allowed) {
if (($env{'form.uploaddoc.filename'}) &&
($env{'form.cmd'}=~/^upload_(\w+)/)) {
-# Process file upload - phase one - upload and parse primary file.
+ my $context = $1;
+ # Process file upload - phase one - upload and parse primary file.
undef($hadchanges);
- $upload_result = &process_file_upload(\$upload_output,$coursenum,
- $coursedom,\%allfiles,
- \%codebase,$1);
+ $uploadphase = &process_file_upload(\$upload_output,$coursenum,$coursedom,
+ \%allfiles,\%codebase,$context);
if ($hadchanges) {
&mark_hash_old();
}
- if ($upload_result eq 'phasetwo') {
- $r->print($upload_output);
- }
- } elsif ($env{'form.phasetwo'}) {
- my %newname = ();
- my %origname = ();
- my %attribs = ();
- my $updateflag = 0;
- my $residx = $env{'form.newidx'};
- my $primary_url = &unescape($env{'form.primaryurl'});
-# Process file upload - phase two - gather secondary files.
- for (my $i=0; $i<$env{'form.phasetwo'}; $i++) {
- if ($env{'form.embedded_item_'.$i.'.filename'}) {
- my $javacodebase;
- $newname{$i} = &process_secondary_uploads(\$upload_output,$coursedom,$coursenum,'embedded_item_',$i,$residx);
- $origname{$i} = &unescape($env{'form.embedded_orig_'.$i});
- if (exists($env{'form.embedded_codebase_'.$i})) {
- $javacodebase = &unescape($env{'form.embedded_codebase_'.$i});
- $origname{$i} =~ s#^\Q$javacodebase\E/##;
- }
- my @attributes = ();
- if ($env{'form.embedded_attrib_'.$i} =~ /:/) {
- @attributes = split(/:/,$env{'form.embedded_attrib_'.$i});
- } else {
- @attributes = ($env{'form.embedded_attrib_'.$i});
- }
- foreach my $attr (@attributes) {
- push(@{$attribs{$i}},&unescape($attr));
- }
- if ($javacodebase) {
- $codebase{$i} = $javacodebase;
- $codebase{$i} =~ s#/$##;
- $updateflag = 1;
- }
- }
- unless ($newname{$i} eq $origname{$i}) {
- $updateflag = 1;
- }
- }
-# Process file upload - phase three - modify primary file
- if ($updateflag) {
- my ($content,$rtncode);
- my $updateflag = 0;
- my $getstatus = &Apache::lonnet::getuploaded('GET',$primary_url,$coursedom,$coursenum,\$content,\$rtncode);
- if ($getstatus eq 'ok') {
- foreach my $item (keys(%newname)) {
- if ($newname{$item} ne $origname{$item}) {
- my $attrib_regexp = '';
- if (@{$attribs{$item}} > 1) {
- $attrib_regexp = join('|',@{$attribs{$item}});
- } else {
- $attrib_regexp = $attribs{$item}[0];
- }
- if ($content =~ m#($attrib_regexp\s*=\s*['"]?)\Q$origname{$item}\E(['"]?)#) {
- }
- $content =~ s#($attrib_regexp\s*=\s*['"]?)\Q$origname{$item}\E(['"]?)#$1$newname{$item}$2#gi;
- }
- if (exists($codebase{$item})) {
- $content =~ s/(codebase\s*=\s*["']?)\Q$codebase{$item}\E(["']?)/$1.$2/i; #' stupid emacs
- }
- }
-# Save edited file.
- my $saveresult;
- my $docuname=$env{'course.'.$env{'request.course.id'}.'.num'};
- my $docudom=$env{'course.'.$env{'request.course.id'}.'.domain'};
- my $url = &Apache::lonnet::store_edited_file($primary_url,$content,$docudom,$docuname,\$saveresult);
- } else {
- &Apache::lonnet::logthis('retrieval of uploaded file - '.$primary_url.' - for editing, failed: '.$getstatus);
- }
- }
+ $r->print($upload_output);
+ } elsif ($env{'form.phase'} eq 'upload_embedded') {
+ # Process file upload - phase two - upload embedded objects
+ $uploadphase = 'check_embedded';
+ my $primaryurl = &HTML::Entities::encode($env{'form.primaryurl'},'<>&"');
+ my $state = &embedded_form_elems($uploadphase,$primaryurl,
+ $env{'form.newidx'});
+ my $docuname=$env{'course.'.$env{'request.course.id'}.'.num'};
+ my $docudom=$env{'course.'.$env{'request.course.id'}.'.domain'};
+ my ($destination,$dir_root) = &embedded_destination();
+ my $url_root = '/uploaded/'.$docudom.'/'.$docuname;
+ my $actionurl = '/adm/coursedocs';
+ my ($result,$flag) =
+ &Apache::loncommon::upload_embedded('coursedoc',$destination,
+ $docuname,$docudom,$dir_root,$url_root,undef,undef,undef,$state,
+ $actionurl);
+ $r->print($result.&return_to_editor());
+ } elsif ($env{'form.phase'} eq 'check_embedded') {
+ # Process file upload - phase three - modify references in HTML file
+ $uploadphase = 'modified_orightml';
+ my $docuname=$env{'course.'.$env{'request.course.id'}.'.num'};
+ my $docudom=$env{'course.'.$env{'request.course.id'}.'.domain'};
+ my ($destination,$dir_root) = &embedded_destination();
+ $r->print(&Apache::loncommon::modify_html_refs('coursedoc',$destination,
+ $docuname,$docudom,undef,
+ $dir_root).
+ &return_to_editor());
}
}
- unless ($showdoc || $upload_result eq 'phasetwo') {
+ unless ($showdoc || $uploadphase) {
# -----------------------------------------------------------------------------
my %lt=&Apache::lonlocal::texthash(
'uplm' => 'Upload a new main '.lc($crstype).' document',
@@ -3468,7 +3421,7 @@
</form>');
}
} else {
- unless ($upload_result eq 'phasetwo') {
+ unless ($uploadphase) {
# -------------------------------------------------------- This is showdoc mode
$r->print("<h1>".&mt('Uploaded Document').' - '.
&Apache::lonnet::gettitle($r->uri).'</h1><p>'.
@@ -3481,6 +3434,42 @@
return OK;
}
+sub embedded_form_elems {
+ my ($phase,$primaryurl,$newidx) = @_;
+ my $folderpath = &HTML::Entities::encode($env{'form.folderpath'},'<>&"');
+ return <<STATE;
+ <input type="hidden" name="folderpath" value="$folderpath" />
+ <input type="hidden" name="cmd" value="upload_embedded" />
+ <input type="hidden" name="newidx" value="$newidx" />
+ <input type="hidden" name="phase" value="$phase" />
+ <input type="hidden" name="primaryurl" value="$primaryurl" />
+STATE
+}
+
+sub embedded_destination {
+ my $folder=$env{'form.folder'};
+ my $destination = 'docs/';
+ if ($folder =~ /^supplemental/) {
+ $destination = 'supplemental/';
+ }
+ if (($folder eq 'default') || ($folder eq 'supplemental')) {
+ $destination .= 'default/';
+ } elsif ($folder =~ /^(default|supplemental)_(\d+)$/) {
+ $destination .= $2.'/';
+ }
+ $destination .= $env{'form.newidx'};
+ my $dir_root = '/userfiles';
+ return ($destination,$dir_root);
+}
+
+sub return_to_editor {
+ my $actionurl = '/adm/coursedocs';
+ return '<p><form name="backtoeditor" method="post" action="'.$actionurl.'" />'."\n".
+ '<input type="hidden" name="folderpath" value="'.&HTML::Entities::encode($env{'form.folderpath'},'<>&"').'" /></form>'."\n".
+ '<a href="javascript:document.backtoeditor.submit();">'.&mt('Return to Editor').
+ '</a></p>';
+}
+
sub generate_admin_options {
my ($help_ref,$env_ref) = @_;
my %lt=&Apache::lonlocal::texthash(
Index: loncom/publisher/testbankimport.pm
diff -u loncom/publisher/testbankimport.pm:1.26 loncom/publisher/testbankimport.pm:1.27
--- loncom/publisher/testbankimport.pm:1.26 Sat Nov 27 22:43:32 2010
+++ loncom/publisher/testbankimport.pm Sun Nov 28 00:04:10 2010
@@ -1,5 +1,5 @@
# Handler for parsing text upload problem descriptions into .problems
-# $Id: testbankimport.pm,v 1.26 2010/11/27 22:43:32 raeburn Exp $
+# $Id: testbankimport.pm,v 1.27 2010/11/28 00:04:10 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -1906,15 +1906,32 @@
}
$r->print(&print_header($uname,$udom,$javascript,\%loadentries,$title,
- $current_page,\@pages,\%names));
+ $current_page,\@pages,\%names));
- if ($env{'form.phase'} eq 'three') {
- if ($env{'form.action'} eq 'upload_embedded') {
- $r->print(&Apache::lonupload::phasethree($r,$fn,$uname,$udom,'testbank'));
+ if (($env{'form.phase'} eq 'four') || ($env{'form.phase'} eq 'three')) {
+ if ($env{'form.phase'} eq 'four') {
+ $r->print(&Apache::lonupload::phasefour($r,$fn,$uname,$udom,'testbank'));
+ my $current_page = 0;
+ my $js;
+ &jscript_zero($webpath,\$js);
+ $js = '<script type="text/javascript">'."\n$js\n".'</script>';
+ $r->print($js);
+ &display_zero($r,$uname,$fn,$current_page,$webpath);
+ } elsif ($env{'form.phase'} eq 'three') {
+ if ($env{'form.action'} eq 'upload_embedded') {
+ my ($result,$flag) =
+ &Apache::lonupload::phasethree($r,$fn,$uname,$udom,'testbank');
+ $r->print($result);
+ if ($flag eq 'modify_orightml') {
+ undef($page_name);
+ $r->print('<form name="testbankForm" method="post" action="/adm/testbank">'.
+ &page_footer('',$uname,$fn).'</form>');
+ }
+ }
}
if ($badfile) {
&file_error($r,$uname,$fn,$current_page,$webpath,$res);
- } else {
+ } else {
&display_zero ($r,$uname,$fn,$current_page,$webpath) if $page_name eq 'Welcome';
&display_one ($r,$uname,$fn,$current_page,$textref,$header) if $page_name eq 'Blocks';
&display_two ($r,$uname,$fn,$current_page,$textref,$header,$qcount) if $page_name eq 'Format';
@@ -1925,7 +1942,6 @@
my ($result,$flag) = &Apache::lonupload::phasetwo($r,$fn,$uname,$udom,'testbank');
$r->print($result);
if ($flag eq 'ok') {
- my $current_page = 0;
my $js;
&jscript_zero($webpath,\$js);
$js = '<script type="text/javascript">'."\n$js\n".'</script>';
Index: loncom/publisher/lonupload.pm
diff -u loncom/publisher/lonupload.pm:1.50 loncom/publisher/lonupload.pm:1.51
--- loncom/publisher/lonupload.pm:1.50 Wed Oct 27 01:04:15 2010
+++ loncom/publisher/lonupload.pm Sun Nov 28 00:04:10 2010
@@ -2,7 +2,7 @@
# The LearningOnline Network with CAPA
# Handler to upload files into construction space
#
-# $Id: lonupload.pm,v 1.50 2010/10/27 01:04:15 raeburn Exp $
+# $Id: lonupload.pm,v 1.51 2010/11/28 00:04:10 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -70,7 +70,7 @@
=item *
-output relevant interface phase (phaseone or phasetwo or phasethree)
+output relevant interface phase (phaseone, phasetwo, phasethree or phasefour)
=item *
@@ -99,6 +99,11 @@
Interface for handling secondary uploads of embedded objects
in an html file.
+=item phasefour()
+
+Interface for handling optional renaming of links to embedded
+objects.
+
=item upfile_store()
Store contents of uploaded file into temporary space. Invoked
@@ -351,25 +356,32 @@
&Apache::lonnet::extract_embedded_items($target,\%allfiles,\%codebase);
if (keys(%allfiles) > 0) {
my ($currentpath) = ($url =~ m{^(.+)/[^/]+$});
- my $state = <<STATE;
- <input type="hidden" name="action" value="upload_embedded" />
- <input type="hidden" name="mode" value="$mode" />
- <input type="hidden" name="phase" value="three" />
- <input type="hidden" name="filename" value="$url" />
-STATE
- my $embedded = &Apache::loncommon::ask_for_embedded_content($action,$state,\%allfiles,\%codebase,
- {'error_on_invalid_names' => 1,
- 'ignore_remote_references' => 1,
- 'current_path' => $currentpath});
+ my $state = &embedded_form_elems('upload_embedded',$url,$mode);
+ my ($embedded,$num,$pathchg) =
+ &Apache::loncommon::ask_for_embedded_content($action,$state,\%allfiles,
+ \%codebase,
+ {'error_on_invalid_names' => 1,
+ 'ignore_remote_references' => 1,
+ 'current_path' => $currentpath});
if ($embedded) {
- $result .= '<h3>'.&mt('Reference Warning').'</h3>'.
- '<p>'.&mt('Completed upload of the file. This file contained references to other files.').'</p>'.
- '<p>'.&mt('Please select the locations from which the referenced files are to be uploaded.').'</p>'.
- $embedded;
- }
- if ($mode eq 'testbank') {
- $returnflag = 'embedded';
- $result .= '<p>'.&mt('Or [_1]continue[_2] the testbank import without these files','<a href="javascript:document.testbankForm.submit();">','</a>').'</p>';
+ $result .= '<h3>'.&mt('Reference Warning').'</h3>';
+ if ($num) {
+ $result .= '<p>'.&mt('Completed upload of the file.').' '.&mt('This file contained references to other files.').'</p>'.
+ '<p>'.&mt('Please select the locations from which the referenced files are to be uploaded.').'</p>'.
+ $embedded;
+ if ($mode eq 'testbank') {
+ $returnflag = 'embedded';
+ $result .= '<p>'.&mt('Or [_1]continue[_2] the testbank import without these files.','<a href="javascript:document.testbankForm.submit();">','</a>').'</p>';
+ }
+ } else {
+ $result .= '<p>'.&mt('Completed upload of the file.').'</p>'.$embedded;
+ if ($pathchg) {
+ if ($mode eq 'testbank') {
+ $returnflag = 'embedded';
+ $result .= '<p>'.&mt('Or [_1]continue[_2] the testbank import without modifying the references(s).','<a href="javascript:document.testbankForm.submit();">','</a>').'</p>';
+ }
+ }
+ }
}
}
}
@@ -389,18 +401,59 @@
sub phasethree {
my ($r,$fn,$uname,$udom,$mode) = @_;
+ my $action = '/adm/upload';
+ if ($mode eq 'testbank') {
+ $action = '/adm/testbank';
+ } elsif ($mode eq 'imsimport') {
+ $action = '/adm/imsimport';
+ }
+ my $dir_root = '/home/'.$uname.'/public_html';
+ my $url_root = '/priv/'.$uname;
+ my $path = &File::Basename::dirname($fn);
+ my $filename = &HTML::Entities::encode($env{'form.filename'},'<>&"');
+ my $state = &embedded_form_elems('modify_orightml',$filename,$mode).
+ '<input type="hidden" name="phase" value="four" />';
+ my ($result,$returnflag) =
+ &Apache::loncommon::upload_embedded($mode,$path,$uname,$udom,
+ $dir_root,$url_root,undef,
+ undef,undef,$state,$action);
+ if ($mode ne 'imsimport' && $mode ne 'testbank') {
+ $result .= '<br /><h3><a href="'.$url_root.$fn.'">'.
+ &mt('View main file').'</a></h3>'.
+ '<h3><a href="'.$url_root.$path.'">'.
+ &mt('Back to Directory').'</a></h3><br />';
+ }
+ return ($result,$returnflag);
+}
+
+sub embedded_form_elems {
+ my ($action,$filename,$mode) = @_;
+ return <<STATE;
+ <input type="hidden" name="action" value="$action" />
+ <input type="hidden" name="mode" value="$mode" />
+ <input type="hidden" name="filename" value="$filename" />
+STATE
+}
+
+sub phasefour {
+ my ($r,$fn,$uname,$udom,$mode) = @_;
+ my $action = '/adm/upload';
+ if ($mode eq 'testbank') {
+ $action = '/adm/testbank';
+ } elsif ($mode eq 'imsimport') {
+ $action = '/adm/imsimport';
+ }
my $result;
my $dir_root = '/home/'.$uname.'/public_html';
my $url_root = '/priv/'.$uname;
- my $base = &File::Basename::basename($fn);
my $path = &File::Basename::dirname($fn);
- $result = &Apache::loncommon::upload_embedded($mode,$path,$uname,$udom,
- $dir_root,$url_root);
+ $result .= &Apache::loncommon::modify_html_refs($mode,$path,
+ $uname,$udom,$dir_root);
if ($mode ne 'imsimport' && $mode ne 'testbank') {
- $result = '<br /><font size="+2"><a href="'.$url_root.$fn.'">'.
- &mt('View main file').'</a></font>'.
- '<br /><font size="+2"><a href="'.$url_root.$path.'">'.
- &mt('Back to Directory').'</a></font><br />';
+ $result .= '<br /><h3><a href="'.$url_root.$fn.'">'.
+ &mt('View main file').'</a></h3>'.
+ '<h3><a href="'.$url_root.$path.'">'.
+ &mt('Back to Directory').'</a></h3><br />';
}
return $result;
}
@@ -490,8 +543,10 @@
.'</p>'
);
}
-
- if ($env{'form.phase'} eq 'three') {
+ if ($env{'form.phase'} eq 'four') {
+ my $output = &phasefour($r,$fn,$uname,$udom,'author');
+ $r->print($output);
+ } elsif ($env{'form.phase'} eq 'three') {
my $output = &phasethree($r,$fn,$uname,$udom,'author');
$r->print($output);
} elsif ($env{'form.phase'} eq 'two') {
--raeburn1290902651--