--- loncom/homework/daxesave.pm 2023/08/23 20:43:34 1.6 +++ loncom/homework/daxesave.pm 2023/08/28 18:58:44 1.7 @@ -1,7 +1,7 @@ # The LearningOnline Network # Convert and save a problem from Daxe. # -# $Id: daxesave.pm,v 1.6 2023/08/23 20:43:34 raeburn Exp $ +# $Id: daxesave.pm,v 1.7 2023/08/28 18:58:44 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -45,14 +45,15 @@ sub handler { $request->content_type('text/plain'); # path should be in the form "/daxeopen/priv/..." - # or ^/daxeopen/uploaded/[^/]+/[^/]+/.*html?$ + # or "/daxeopen/uploaded/$cdom/$cnum/(docs|supplemental)/(default|\d+)/\d+/" my $path = $env{'form.path'}; $path =~ s/^\/daxeopen//; my $allowed = 0; - if ($path =~ /^\/priv/) { + my ($cdom,$cnum); + if ($path =~ m{^/priv/}) { my ($ownername,$ownerdom,$ownerhome) = - &Apache::lonnet::constructaccess($path, 'setpriv'); + &Apache::lonnet::constructaccess($path); if (($ownername ne '') && ($ownerdom ne '') && ($ownerhome ne '')) { unless ($ownerhome eq 'no_host') { my @hosts = &Apache::lonnet::current_machine_ids(); @@ -61,7 +62,7 @@ sub handler { } } } - } elsif ($path =~ m|^/uploaded/[^/]+/[^/]+/|) { + } elsif ($path =~ m|^/uploaded/|) { if ($env{'user.name'} ne '' && $env{'user.domain'} ne '' && $env{'request.course.id'}) { $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; @@ -79,33 +80,74 @@ sub handler { return OK; } - my $newpath = &Apache::lonnet::filelocation('', $path); - - my $contents = $env{'form.file'}; - - my $mode; - if ($path =~ /\.(task|problem|exam|quiz|assess|survey|library|xml|html|htm|xhtml|xhtm)$/) { - try { - $contents = &Apache::xml_to_loncapa::convert_file($contents); - } catch { - $request->print("error\nconvert failed for $path: $_"); - return OK; - }; - $mode = '>:encoding(UTF-8)'; - } else { - $mode = '>'; - } + if ($path =~ m{^/priv/}) { + my $newpath = &Apache::lonnet::filelocation('', $path); + my $contents = $env{'form.file'}; - my $filebak = $newpath.".bak"; - if (-e $newpath) { - copy($newpath, $filebak); # errors ignored - } - if (open(my $out, $mode, $newpath)) { - print $out $contents; - close $out; - $request->print("ok\n"); - } else { - $request->print("error\nFailed to open file to save $path"); + my $mode; + if ($path =~ /\.(task|problem|exam|quiz|assess|survey|library|xml|html|htm|xhtml|xhtm)$/) { + try { + $contents = &Apache::xml_to_loncapa::convert_file($contents); + } catch { + $request->print("error\nconvert failed for $path: $_"); + return OK; + }; + $mode = '>:encoding(UTF-8)'; + } else { + $mode = '>'; + } + + my $filebak = $newpath.".bak"; + if (-e $newpath) { + copy($newpath, $filebak); # errors ignored + } + if (open(my $out, $mode, $newpath)) { + print $out $contents; + close($out); + $request->print("ok\n"); + } else { + $request->print("error\nFailed to open file to save $path"); + } + } elsif ($path =~ m{^/uploaded/}) { + my ($unauthorized,$unsupported); + if ($path =~ m{^\Q/uploaded/$cdom/$cnum/\E(docs|supplemental)/(default|\d+)/(\d+)/(.+)$}) { + my ($type,$folder,$rid,$fname) = ($1,$2,$3,$4); + my $referrer = $request->headers_in->{'Referer'}; + if ($referrer =~ m{\Qfile=/daxeopen/uploaded/$cdom/$cnum/$type/$folder/$rid/\E}) { + if ($fname =~ /\.(html|htm|xhtml|xhtm)$/) { + try { + $env{'form.file'} = &Apache::xml_to_loncapa::convert_file($env{'form.file'}); + } catch { + $request->print("error\nconvert failed for $fname: $_"); + return OK; + } + } elsif ($fname =~ /\.(task|problem|exam|quiz|assess|survey|library|xml)$/) { + $unsupported = $1; + } + unless ($unsupported) { + my $url = &Apache::lonnet::finishuserfileupload($cnum,$cdom,'file', + "$type/$folder/$rid/$fname"); + if ($url =~ m{^/uploaded/$cdom/$cnum/$type/$folder/$rid/}) { + $request->print("ok\n"); + } else { + $request->print("error\nFailed to save uploaded file: $fname"); + } + } + } else { + $unauthorized = 1; + } + } else { + $unauthorized = 1; + } + if ($unauthorized) { + $request->log_reason("Unauthorized path: $path", $path); + $request->print("error\nUnauthorized path: $path"); + $request->status(403); + } elsif ($unsupported) { + $request->log_reason("File extension: $unsupported -- not allowed for upload to course", $path); + $request->print("error\nFile extension: $unsupported -- not allowed for upload to course"); + $request->status(403); + } } return OK; }