# Handler for parsing text upload problem descriptions into .problems
# $Id: testbankimport.pm,v 1.23 2009/05/06 13:13:00 bisitz Exp $
#
# Copyright Michigan State University Board of Trustees
#
# This file is part of the LearningOnline Network with CAPA (LON-CAPA).
#
# LON-CAPA is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# LON-CAPA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with LON-CAPA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# /home/httpd/html/adm/gpl.txt
#
# http://www.lon-capa.org/
#
package Apache::testbankimport;
use strict;
use Apache::Constants qw(:common :http :methods);
use Apache::loncacc;
use Apache::loncommon();
use Apache::lonnet;
use HTML::Entities();
use Apache::lonlocal;
use Apache::lonupload;
use Apache::londocs;
use File::Basename();
use LONCAPA();
use File::MMagic;
use XML::DOM;
use RTF::HTMLConverter;
use HTML::TokeParser;
# ---------------------------------------------------------------- Display Control
sub display_control {
# figure out what page we're on and where we're heading.
my $page = $env{'form.page'};
my $command = $env{'form.go'};
my $current_page = &calculate_page($page,$command);
return $current_page;
}
# CALCULATE THE CURRENT PAGE
sub calculate_page($$) {
my ($prev,$dir) = @_;
return 0 if $prev eq ''; # start with first page
return $prev + 1 if $dir eq 'NextPage';
return $prev - 1 if $dir eq 'PreviousPage';
return $prev if $dir eq 'ExitPage';
return 0 if $dir eq 'BackToStart';
}
sub jscript_zero {
my ($webpath,$jsref) = @_;
my $start_page =
&Apache::loncommon::start_page('Create Testbank directory',undef,
{'only_body' => 1,
'js_ready' => 1,});
my $end_page =
&Apache::loncommon::end_page({'js_ready' => 1,});
my %lt = &Apache::lonlocal::texthash(
loca => 'Location',
newd => 'New Directory',
ente => 'Enter the name of the new directory where you will save the converted testbank questions',
go => 'Go',
);
$$jsref = <<"END_SCRIPT";
function createWin() {
document.info.newdir.value = "";
newWindow = window.open("","CreateDir","HEIGHT=400,WIDTH=750,scrollbars=yes")
newWindow.document.open()
newWindow.document.write('$start_page')
newWindow.document.write("\\n")
newWindow.document.write("
$lt{'loca'}: $webpath
$lt{'newd'}
\\n")
newWindow.document.write("")
newWindow.document.write('$end_page')
newWindow.document.close()
newWindow.focus()
}
END_SCRIPT
return;
}
# ---------------------------------------------------------------- Jscript One
sub jscript_one {
my $jsref = shift;
$$jsref = <<"END_SCRIPT";
function verify() {
if ((document.forms.display.blocks.value == "") || (!document.forms.display.blocks.value) || (document.forms.display.blocks.value == "0")) {
alert("You must enter the number of blocks of questions of a given question type. This number must be 1 or more.")
return false
}
if (document.forms.display.qnumformat.options[document.forms.display.qnumformat.selectedIndex].value == "-1") {
alert("You must select the format used for the question number, e.g., (1), 1., (1, or 1).")
return false
}
return true
}
function nextPage() {
if (verify()) {
document.forms.display.go.value="NextPage"
document.forms.display.submit()
}
}
function backPage() {
document.forms.display.go.value="PreviousPage"
document.forms.display.submit()
}
function setElements() {
var iter = 0
var selParam = 0
END_SCRIPT
if (exists($env{'form.blocks'}) ) {
$$jsref .= qq|
document.forms.display.blocks.value = $env{'form.blocks'}\n|;
}
if (exists($env{'form.qnumformat'}) ) {
$$jsref .= <<"TO_HERE";
for (iter=0; iter= curmin ) {
alert("The question number range for block "+iter+" overlaps with the question number range for one of the previous blocks - this is not permitted.")
return false
}
}
else {
if (parseInt(poolForm.elements[5*i+1].value) <= curmax) {
for (var j=parseInt(poolForm.elements[5*i+1].value); j<=parseInt(poolForm.elements[5*i+2].value); j++) {
for (var k=0; k= parseInt(poolForm.elements[5*k+1].value)) && (j <= parseInt(poolForm.elements[5*k+2].value))) {
var overlap = k+1
alert("The question number range for block "+iter+" overlaps with the question number range for block "+overlap+" - this is not permitted.")
return false
}
}
}
}
}
if (parseInt(poolForm.elements[5*i+1].value) < curmin) {
curmin = parseInt(poolForm.elements[5*i+1].value)
}
if (parseInt(poolForm.elements[5*i+2].value) > curmax) {
curmax = parseInt(poolForm.elements[5*i+2].value)
}
}
}
if (curmax >$qcount+curmin) {
alert("The last # for one or more of the blocks is too large - the last number of the last block can not be greater than $qcount: the total number of questions in the uploaded file.")
return false
}
var endpt = $qcount + curmin
for (var n=curmin; n= parseInt(poolForm.elements[5*m+1].value)) && (n <= parseInt(poolForm.elements[5*m+2].value))) {
warnFlag = false
}
}
if (warnFlag) {
alert("The question type for question "+n+" could not be identified because it does not fall within the number ranges you have provided for any of the $blocks block(s)")
return false
}
}
return true
}
function nextPage() {
if (verify()) {
document.forms.display.go.value="NextPage"
document.forms.display.submit()
}
}
function backPage() {
document.forms.display.go.value="PreviousPage"
document.forms.display.submit()
}
function colSet(caller) {
var poolForm = document.forms.display
var curVal = poolForm.elements[caller*5+3].options[poolForm.elements[caller*5+3].selectedIndex].value
poolForm.elements[caller*5+4].length = 0
if (poolForm.elements[caller*5+3].options[poolForm.elements[caller*5+3].selectedIndex].value == "-1") {
poolForm.elements[caller*5+4].options[0] = new Option("<--- Set type ","-1",true,true)
}
else {
if ((poolForm.elements[caller*5+3].options[poolForm.elements[caller*5+3].selectedIndex].value == "MC") || (poolForm.elements[caller*5+3].options[poolForm.elements[caller*5+3].selectedIndex].value == "MA") || (poolForm.elements[caller*5+3].options[poolForm.elements[caller*5+3].selectedIndex].value == "Ord")) {
poolForm.elements[caller*5+4].options[0] = new Option("Select","-1",true,true)
poolForm.elements[caller*5+4].options[1] = new Option("a.","lcperiod",false,false)
poolForm.elements[caller*5+4].options[2] = new Option("A.","ucperiod",false,false)
poolForm.elements[caller*5+4].options[3] = new Option("(a)","lcparen",false,false)
poolForm.elements[caller*5+4].options[4] = new Option("(A)","ucparen",false,false)
poolForm.elements[caller*5+4].options[5] = new Option("a)","lconeparen",false,false)
poolForm.elements[caller*5+4].options[6] = new Option("A)","uconeparen",false,false)
poolForm.elements[caller*5+4].options[7] = new Option("a.)","lcdotparen",false,false)
poolForm.elements[caller*5+4].options[8] = new Option("A.)","ucdotparen",false,false)
poolForm.elements[caller*5+4].options[9] = new Option("(i)","romparen",false,false)
poolForm.elements[caller*5+4].options[10] = new Option("i)","romoneparen",false,false)
poolForm.elements[caller*5+4].options[11] = new Option("i.)","romdotparen",false,false)
poolForm.elements[caller*5+4].options[12] = new Option("i.","romperiod",false,false)
poolForm.elements[caller*5+4].selectedIndex = 0
}
else {
poolForm.elements[caller*5+4].options[0] = new Option("Not required","0",true,true)
}
}
poolForm.elements[caller*5+5].length = 0
if (poolForm.elements[caller*5+3].options[poolForm.elements[caller*5+3].selectedIndex].value == "-1") {
poolForm.elements[caller*5+5].options[0] = new Option("<--- Set type ","-1",true,true)
}
else {
if ((poolForm.elements[caller*5+3].options[poolForm.elements[caller*5+3].selectedIndex].value == "MA") || (poolForm.elements[caller*5+3].options[poolForm.elements[caller*5+3].selectedIndex].value == "FIB")) {
poolForm.elements[caller*5+5].options[0] = new Option("Select","-1",true,true)
poolForm.elements[caller*5+5].options[1] = new Option("single answer","single",false,false)
poolForm.elements[caller*5+5].options[2] = new Option("comma","comma",false,false)
poolForm.elements[caller*5+5].options[3] = new Option("space","space",false,false)
poolForm.elements[caller*5+5].options[4] = new Option("new line","line",false,false)
poolForm.elements[caller*5+5].options[5] = new Option("tab","tab",false,false)
}
else {
if (poolForm.elements[caller*5+3].options[poolForm.elements[caller*5+3].selectedIndex].value == "Ord") {
poolForm.elements[caller*5+5].options[0] = new Option("Select","-1",true,true)
poolForm.elements[caller*5+5].options[1] = new Option("comma","comma",false,false)
poolForm.elements[caller*5+5].options[2] = new Option("space","space",false,false)
poolForm.elements[caller*5+5].options[3] = new Option("new line","line",false,false)
poolForm.elements[caller*5+5].options[4] = new Option("tab","tab",false,false)
}
else {
if (poolForm.elements[caller*5+3].options[poolForm.elements[caller*5+3].selectedIndex].value == "TF") {
poolForm.elements[caller*5+5].options[0] = new Option("Select","-1",true,true)
poolForm.elements[caller*5+5].options[1] = new Option("True or False","word",false,false)
poolForm.elements[caller*5+5].options[2] = new Option("true or false","word",false,false)
poolForm.elements[caller*5+5].options[3] = new Option("TRUE or FALSE","word",false,false)
poolForm.elements[caller*5+5].options[4] = new Option("T or F","lett",false,false)
poolForm.elements[caller*5+5].options[5] = new Option("t or f","lett",false,false)
}
else {
poolForm.elements[caller*5+5].options[0] = new Option("Not required","0",true,true)
}
}
}
}
}
function setElements() {
var iter = 0
var selParam = 0
END_SCRIPT
my @names = ("start_","end_","qtype_","foilformat_","ansr_");
for (my $x=0; $x<$blocks; $x++) {
foreach my $name (@names) {
my $parname = $name.$x;
my $value = $env{"form.$parname"};
if ($value ne "") {
if (($name eq "start_") || ($name eq "end_")) {
$$jsref .= qq|
document.forms.display.$parname.value = $value\n|;
} elsif ($name eq "qtype_") {
$$jsref .= qq|
for (iter=0; iter 0) {
my $maxnum = $numitems - 1;
my %lt = &Apache::lonlocal::texthash(
fnmb => 'File names must be unique',
isum => 'is used more than once',
);
$$jsref .= qq|
for (var j=$maxnum; j>0; j--) {
var currname = document.dataForm.elements['probfile_'+j].value;
for (var k=j-1; k>=0; k--) {
var comparename = document.dataForm.elements['probfile_'+k].value;
if (currname == comparename) {
alert("$lt{fnmb} - "+currname+" $lt{isum}");
return false;
}
}
}
|;
}
$$jsref .= '
return true;
}
';
$$jsref .= &Apache::loncommon::check_uncheck_jscript();
return;
}
# ---------------------------------------------------------------- Jscript Four
sub jscript_four {
my ($jsref,$webpath) = @_;
$$jsref = qq|
function backtoStart() {
document.location.href="$webpath"
}
function backPage() {
document.forms.verify.go.value="PreviousPage"
document.forms.verify.submit();
}
|;
}
# ---------------------------------------------------------------- Display Zero
sub display_zero {
my ($r,$uname,$fn,$page,$webpath) = @_;
my $go_default = 'NextPage';
if ($fn eq '') {
$r->print(''.&mt('Incomplete file upload').' '.&mt('Return to the [_1]construction space menu[_2] to upload a file','',''));
}
$r->print(&mt('The Testbank Upload utility can be used by LON-CAPA authors to generate LON-CAPA problem files from a testbank file of questions/answers.').' '.
&mt('The following question types can be converted:').'
'.&mt('multiple choice').'
'.&mt('multiple answer correct').'
'.&mt('fill-in-the-blank').'
'.&mt('ordering/ranking').'
'.&mt('true/false').'
'.&mt('essay').'
'.&mt('The file of questions (in plain text, RTF or HTML format) must meet certain requirements for the conversion process to generate functioning LON-CAPA problems.').&Apache::loncommon::help_open_topic('Testbank_Formatting').' '.
&mt('Five steps are involved in the conversion process.').'
'.&mt('Optionally create a new sub-directory where the converted testbank questions will be saved.').'
'.&mt('Provide information about the question format - i.e., question numbering style, and the number of blocks of questions of each question type.').'
'.&mt('Provide information about the questions in each block, including question type, start and end question numbers for each block, and foil labelling style and answer format where required.').'
'.&mt('Review the identified questions, choose which to convert, and (optionally) override the default filename to be used for each problem file.').'
'.&mt('Complete the import of questions.').'
');
}
# ---------------------------------------------------------------- Display One
sub display_one {
my ($r,$uname,$fn,$page,$textref,$header) = @_;
my %topics;
$topics{2} = &mt('Select the format of the question number - e.g., 1, 1., 1), (1 or (1) - ').'
'."\n";
$topics{3} = &mt('Indicate the number of blocks of different question types in the testbank file.').' ';
$r->print('
'.&mt('Identification of blocks of questions').'
'."\n".
'');
return;
}
# ---------------------------------------------------------------- Display Two
sub display_two {
my ($r,$uname,$fn,$page,$textref,$header,$qcount) = @_;
my $blocks = $env{'form.blocks'};
my $qnumformat = $env{'form.qnumformat'};
my @types = ("MC","MA","TF","Ess","FIB","Ord");
my %typenames = (
MC => "Multiple Choice",
TF => "True/False",
MA => "Multiple Answer",
Ess => "Essay",
FIB => "Fill-in-the-blank",
Ord => "Ranking/ordering",
);
my %qnumtypes = (
number => "1",
period => "1.",
paren => "(1)",
leadparen => "(1",
trailparen => "1)",
);
my $bl1st = '';
my $bl1end = '';
if ($blocks == 1) {
$bl1st = '1';
$bl1end = $qcount;
}
my $steptitle = &mt('Information about question types and formats in each block.');
$r->print('
'.&mt('Classification of blocks').'
'.
'');
return;
}
# ---------------------------------------------------------------- Display Three
sub display_three {
my ($r,$uname,$fn,$page,$textref,$res,$header,$urlpath,$qcount) = @_;
my $qnumformat = $env{'form.qnumformat'};
my $filename = $env{'form.filename'};
my $source = $env{'form.go'};
my $blocks = $env{'form.blocks'};
my ($alphabet,$romans) = &get_constants();
my @start = ();
my @end = ();
my @nums = ();
my @qtype = ();
my @foilformats = ();
my @ansrtypes = ();
my %multparts = ();
my $numitems = 0;
my %lt = &Apache::lonlocal::texthash (
crt => 'Create?',
typ => 'Type',
fnam => 'File Name',
ques => 'Question',
answ => 'Answer',
chka => 'check all',
unch => 'uncheck all',
);
for (my $i=0; $i<$blocks; $i++) {
if (($env{"form.start_$i"} ne '') && ($env{"form.end_$i"} ne '')) {
$start[$i] = $env{"form.start_$i"};
$end[$i] = $env{"form.end_$i"};
$nums[$i] = $end[$i]-$start[$i] +1;
$qtype[$i] = $env{"form.qtype_$i"};
if (($qtype[$i] eq "MC") || ($qtype[$i] eq "MA") || ($qtype[$i] eq "Ord")) {
$foilformats[$i] = $env{"form.foilformat_$i"};
} else {
$foilformats[$i] = '';
}
if (($qtype[$i] eq "MA") || ($qtype[$i] eq "FIB") || ($qtype[$i] eq "TF") || ($qtype[$i] eq "Ord")) {
$ansrtypes[$i] = $env{"form.ansr_$i"};
} else {
$ansrtypes[$i] = '';
}
} else {
$nums[$i] = 0;
}
$numitems += $nums[$i];
}
my ($items,$ids,$footer) = &file_split(\@start,\@end,\@nums,$qnumformat,\@foilformats,$textref,\%multparts,$numitems,\@qtype,$blocks);
my ($showheader,$showcss);
if ($res eq 'application/rtf' || $res eq 'text/html') {
if ($header ne '') {
$showheader = &HTML::Entities::decode($header);
if ($res eq 'text/html') {
$showheader = &build_image_url($urlpath,$showheader);
}
}
}
$r->print('
'.&mt('Review and selection of problems to convert').'
'."\n".
'');
}
# ---------------------------------------------------------------- Final Display
sub final_display {
my ($r,$uname,$fn,$page,$textref,$res,$header,$css,$js,$webpath,$dirpath,$subdir) = @_;
my $qnumformat = $env{'form.qnumformat'};
my $blocks = $env{'form.blocks'};
my $question_id = '';
my @question_title = ();
my @question_status = ();
my @qtype = ();
my @start = ();
my @nums = ();
my @end = ();
my @foilformats = ();
my @ansrtypes = ();
my %multparts = ();
my $numitems = 0;
my @createprobs = &Apache::loncommon::get_env_multiple('form.createprob');
for (my $i=0; $i<$blocks; $i++) {
$start[$i] = $env{"form.start_$i"};
$end[$i] = $env{"form.end_$i"};
if (($end[$i] - $start[$i]) >= 0) {
$nums[$i] = $end[$i] - $start[$i]+1;
} else {
$nums[$i] = 0;
}
$qtype[$i] = $env{"form.qtype_$i"};
if (($qtype[$i] eq "MC") || ($qtype[$i] eq "MA") || ($qtype[$i] eq "Ord")) {
$foilformats[$i] = $env{"form.foilformat_$i"};
} else {
$foilformats[$i] = '';
}
if (($qtype[$i] eq "MA") || ($qtype[$i] eq "FIB") || ($qtype[$i] eq "TF") || ($qtype[$i] eq "Ord")) {
$ansrtypes[$i] = $env{"form.ansr_$i"};
}
$numitems += $nums[$i];
}
my %answers;
my ($items,$ids,$footer) = &file_split(\@start,\@end,\@nums,$qnumformat,\@foilformats,$textref,\%multparts,$numitems,\@qtype,$blocks);
# Converting MC and MA answer to number, and splitting answers for FIB, and ordering for Ord.
my ($alphabet,$romans) = &get_constants();
my %patterns = (
comma => ',',
space => '\s+',
line => '[\r\n\f]+',
tab => '\t+',
);
for (my $i=0; $i<$blocks; $i++) {
if ($nums[$i] > 0) {
if (($qtype[$i] eq "MC") || ($qtype[$i] eq "MA") || ($qtype[$i] eq "FIB") || ($qtype[$i] eq "Ord")) {
for (my $k=$numitems+$start[$i]-1; $k<$numitems+$end[$i]; $k++) {
my $qnum = $k - $numitems;
next if (!grep(/^$qnum$/,@createprobs));
if (($res eq 'application/rtf') || ($res eq 'text/html')) {
$items->[$k] = &HTML::Entities::decode($items->[$k]);
}
@{$answers{$qnum}} = ();
if ($qtype[$i] eq "MC") {
$items->[$k] =~ tr/A-Z/a-z/;
$items->[$k] =~ s/<\/?[^>]+>//g;
$items->[$k] =~ s/\W//g;
if ($foilformats[$i] eq "lcperiod" || $foilformats[$i] eq "lcparen" || $foilformats[$i] eq "lconeparen" || $foilformats[$i] eq "lcdotparen" || $foilformats[$i] eq "ucparen" || $foilformats[$i] eq "ucperiod" || $foilformats[$i] eq "uconeparen" || $foilformats[$i] eq "ucdotparen") {
for (my $j=0; $j<@{$alphabet}; $j++) {
if ($alphabet->[$j] eq $items->[$k]) {
push @{$answers{$qnum}}, $j;
last;
}
}
} elsif (($foilformats[$i] eq "romparen") || ($foilformats[$i] eq "romperiod") || ($foilformats[$i] eq "romoneparen") || ($foilformats[$i] eq "romdotparen")) {
for (my $j=0; $j<@{$romans}; $j++) {
if ($romans->[$j] eq $items->[$k]) {
push @{$answers{$qnum}}, $j;
last;
}
}
}
} elsif (($qtype[$i] eq "MA") || ($qtype[$i] eq "Ord")) {
$items->[$k] =~ tr/A-Z/a-z/;
$items->[$k] =~ s/<\/?[^>]+>//g;
my @corrects = split/$patterns{$ansrtypes[$i]}/,$items->[$k];
foreach my $correct (@corrects) {
my @tied;
if ($qtype[$i] eq "Ord") {
if ($correct =~ /=/) {
@tied = split(/=/,$correct);
for (my $j=0; $j<@tied; $j++) {
$tied[$j] =~ s/\W//g;
}
} else {
$correct =~s/\W//g;
}
} else {
$correct =~s/\W//g;
}
if ($foilformats[$i] eq "lcperiod" || $foilformats[$i] eq "lcparen" || $foilformats[$i] eq "ucparen" || $foilformats[$i] eq "ucperiod") {
if (($qtype[$i] eq "Ord") && (@tied > 0)) {
my @ties;
foreach my $tie (@tied) {
for (my $j=0; $j<@{$alphabet}; $j++) {
if ($alphabet->[$j] eq $tie) {
push(@ties,$j);
last;
}
}
}
my $ans = join('=',@ties);
push(@{$answers{$qnum}},$ans);
} else {
for (my $j=0; $j<@{$alphabet}; $j++) {
if ($alphabet->[$j] eq $correct) {
push @{$answers{$qnum}}, $j;
last;
}
}
}
} elsif (($foilformats[$i] eq "romparen") || ($foilformats[$i] eq "romperiod") || ($foilformats[$i] eq "romoneparen") || ($foilformats[$i] eq "romdotparen")) {
if (($qtype[$i] eq "Ord") && (@tied > 0)) {
my @ties;
foreach my $tie (@tied) {
for (my $j=0; $j<@{$romans}; $j++) {
if ($romans->[$j] eq $tie) {
push(@ties,$j);
last;
}
}
}
push(@{$answers{$qnum}},join('=',@ties));
} else {
for (my $j=0; $j<@{$romans}; $j++) {
if ($romans->[$j] eq $correct) {
push @{$answers{$qnum}}, $j;
last;
}
}
}
}
}
} elsif ($qtype[$i] eq "FIB") {
$items->[$k] =~ s/<\/?[^>]+>//g;
@{$answers{$qnum}} = split/$patterns{$ansrtypes[$i]}/,$items->[$k];
for (my $j=0; $j<@{$answers{$qnum}}; $j++) {
$answers{$qnum}[$j] =~ s/^\s+//;
$answers{$qnum}[$j] =~ s/\s+$//;
if ($j==0) {
$answers{$qnum}[$j] =~ s/^<[^>]+>//;
} elsif ($j == @{$answers{$qnum}}-1) {
$answers{$qnum}[$j] =~ s/<\/[^>]+>$//;
}
}
}
}
}
}
}
my $state;
$r->print('');
} elsif (($destdir ne '') && (-e $destdir)) {
my (@qn_file,@result,@numid);
my $qcount = 0;
my $itemcount = 0;
for (my $i=0; $i<$blocks; $i++) {
if ($nums[$i] > 0) {
if (($qtype[$i] eq "MC") || ($qtype[$i] eq "MA") || ($qtype[$i] eq "FIB") || ($qtype[$i] eq "Ord")) {
for (my $j=$start[$i]-1; $j<$end[$i]; $j++) {
$numid[$qcount] = $ids->[$itemcount];
$itemcount ++;
next if (!grep(/^$qcount$/,@createprobs));
my $libfile = &probfile_name($j);
my $answer = $j + $numitems;
my $numans = scalar(@{$answers{$qcount}});
my $foilcount = 0;
if (($qtype[$i] eq "MC") || ($qtype[$i] eq "MA") || ($qtype[$i] eq "Ord")) {
$foilcount = @{$multparts{$j}};
$foilcount --;
}
($result[$qcount],$qn_file[$qcount]) = &create_mcq($destdir,$subdir,\@{$multparts{$j}},\@{$answers{$qcount}},$qtype[$i],$libfile,$res,$header,$footer,$js,$css);
$qcount ++;
}
} elsif ($qtype[$i] eq "TF") {
for (my $j=$start[$i]-1; $j<$end[$i]; $j++) {
$numid[$qcount] = $ids->[$itemcount];
$itemcount ++;
next if (!grep(/^$qcount$/,@createprobs));
my $libfile = &probfile_name($j);
my $answer = $j + $numitems;
$items->[$answer] =~ s/^\s+//;
$items->[$answer] =~ s/\s+$//;
$items->[$answer] =~ s/\W//g;
$items->[$answer] =~ tr/A-Z/a-z/;
my $answer_id = '';
if ($ansrtypes[$i] eq 'word' ) {
if ($items->[$answer] =~ m/true/) {
$answer_id = 0;
} else {
$answer_id = 1;
}
} elsif ($ansrtypes[$i] eq 'lett') {
if ($items->[$answer] =~ m/^t/) {
$answer_id = 0;
} else {
$answer_id = 1;
}
}
($result[$qcount],$qn_file[$qcount]) = &create_ess($destdir,$subdir,$answer_id,$items->[$j],$items->[$answer],$qtype[$i],$libfile,$res,$header,$footer,$js,$css);
$qcount ++;
}
} elsif ($qtype[$i] eq "Ess") {
for (my $j=$start[$i]-1; $j<$end[$i]; $j++) {
$numid[$qcount] = $ids->[$itemcount];
$itemcount ++;
next if (!grep(/^$qcount$/,@createprobs));
my $libfile = &probfile_name($j);
my $answer = $j + $numitems;
my $answer_id = '';
($result[$qcount],$qn_file[$qcount]) = &create_ess($destdir,$subdir,$answer_id,$items->[$j],$items->[$answer],$qtype[$i],$libfile,$res,$header,$footer,$js,$css);
$qcount ++;
}
}
}
}
my ($successes,$failures,$existing);
for (my $i=0; $i<@qn_file; $i++) {
if ($result[$i] eq 'ok') {
$successes .= ''.$numid[$i].': '.
$qn_file[$i].' '."\n";
} elsif ($result[$i] eq 'failed') {
$failures .= $numid[$i].': '.$qn_file[$i].' '."\n";
} elsif ($result[$i] eq 'exists') {
$existing .= ''.$numid[$i].': '.
$qn_file[$i].' '."\n";
}
}
if ($successes) {
$r->print('
'.&mt('Individual problem files have been created from the following problems included in the testbank file:').' '.$successes.'
'.
&mt('The problems must be published before they can be used in a course').'
');
}
if ($failures) {
$r->print('
'.&mt('An error occurred when opening files for the following problems, so they have not been created:').' '.$failures.'
');
}
if ($existing) {
$r->print('
'.&mt('The following files already existed, and were not overwritten so these problems generated from the testbank have not been saved:').' '.$existing.'
'.&mt('No destination directory was available so import of questions could not proceed.').'
'.
&page_footer($env{'form.newdir'},$uname,$fn,$page,$webpath,$subdir,$state).'');
}
return;
}
sub show_uploaded_data {
my ($textref,$header) = @_;
my $output = '
'.&mt('Testbank data uploaded to the server').'
'."\n".
'
';
return $output;
}
sub page_footer {
my ($newdir,$uname,$fn,$page,$webpath,$subdir,$state) = @_;
my $prevval = &mt('Previous Page');
my $nextval = &mt('Next Page');
my $prevclick = 'javascript:backPage();';
my $nextclick = 'javascript:nextPage();';
my $go = '';
if (($page == 0) || ($state eq 'badfile')) {
$go = 'NextPage';
$prevval = &mt('Exit Now');
$prevclick = 'javascript:location.href='."'$webpath';";
$nextclick = 'javascript:submit();'
} elsif ($page == 3) {
$nextval = &mt('Complete Testbank Conversion');
} elsif ($page == 4) {
if (($state ne 'existing') && ($state ne 'unchecked')) {
my $destdir = $webpath;
if ($subdir ne '') {
$destdir = $webpath.$subdir;
}
$prevval = &mt('Back to Directory');
$prevclick = 'javascript:location.href='."'$destdir';";
}
}
my $output = '
';
if ($page ne '') {
$output .= '
';
if (($page < 4) && ($state ne 'badfile')) {
$output .= '
';
}
$output .= '
';
}
return $output;
}
sub question_count {
my ($qnumformat,$textref) = @_;
my $text_in = join "\n", @{$textref};
$text_in = "\n ".$text_in;
my $qpattern ='';
if ($qnumformat eq "period") {
$qpattern = '\d{1,}\.';
} elsif ($qnumformat eq "paren") {
$qpattern = '\(\d{1,}\)';
} elsif ($qnumformat eq "number") {
$qpattern = '\d{1,}';
} elsif ($qnumformat eq "leadparen") {
$qpattern = '\(\d{1,}';
} elsif ($qnumformat eq "trailparen") {
$qpattern = '\d{1,}\)';
}
my @questions = split/[\r\n\f]+\s?$qpattern\s?/,$text_in;
my $qcount = scalar(@questions);
$qcount = $qcount/2;
$qcount = int($qcount);
return $qcount;
}
sub get_constants {
my @alphabet = ("a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z");
my @romans = ("i","ii","iii","iv","v","vi","vii","viii","ix","x","xi","xii","xiii","xiv","xv","xvi","xvii","xviii","xix","xx","xxi","xxii","xxiii","xxiv","xxv","xxvi");
return (\@alphabet,\@romans);
}
sub file_split {
my ($startsref,$endsref,$numsref,$qnumformat,$foilsref,$textref,$multpartsref,$numitems,$qtyperef,$blocks) = @_;
my $text_in = join "\n", @{$textref};
$text_in = "\n ".$text_in;
my $dignum = length($numitems);
my ($qpatst,$qpatend,$numpat,@questions,@qids);
my $numpat = '\d{1';
if ($dignum > 1) {
$numpat .= ','.$dignum.'}';
} else {
$numpat .= '}';
}
if ($qnumformat eq "period") {
$qpatend = '\.';
} elsif ($qnumformat eq "paren") {
$qpatst = '\(';
$qpatend = '\)';
} elsif ($qnumformat eq "leadparen") {
$qpatst = '\(';
} elsif ($qnumformat eq "trailparen") {
$qpatend = '\)';
}
my @lines = split/[\r\n\f]+\s*$qpatst($numpat)$qpatend\s*/,$text_in;
# my @questions = split/\n\s\d{1,3}\.\s/,$text_in;
shift(@lines);
for (my $i=0; $i<@lines; $i++) {
if ($i%2) {
push(@questions,$lines[$i]);
} else {
push(@qids,$lines[$i]);
}
}
my %multparts = ();
for (my $i=0; $i<$blocks; $i++) {
if (${$numsref}[$i] > 0) {
if ((${$qtyperef}[$i] eq "MC") || (${$qtyperef}[$i] eq "MA") || (${$qtyperef}[$i] eq "Ord")) {
my $splitstr = '';
if (${$foilsref}[$i] eq "lcperiod") {
$splitstr = '[a-z]\.';
} elsif (${$foilsref}[$i] eq "lcparen") {
$splitstr = '\([a-z]\)';
} elsif (${$foilsref}[$i] eq "lconeparen") {
$splitstr = '[a-z]\)';
} elsif (${$foilsref}[$i] eq "lcdotparen") {
$splitstr = '[a-z]\.\)';
} elsif (${$foilsref}[$i] eq "ucperiod") {
$splitstr = '[A-Z]\.';
} elsif (${$foilsref}[$i] eq "ucparen") {
$splitstr = '\([A-Z]\)';
} elsif (${$foilsref}[$i] eq "uconeparen") {
$splitstr = '[A-Z]\)';
} elsif (${$foilsref}[$i] eq "ucdotparen") {
$splitstr = '[A-Z]\.\)';
} elsif (${$foilsref}[$i] eq "romperiod") {
$splitstr = '[ivx]+\.';
} elsif (${$foilsref}[$i] eq "romparen") {
$splitstr = '\([ivx]+\)';
} elsif (${$foilsref}[$i] eq "romoneparen") {
$splitstr = '[ivx]+\)';
} elsif (${$foilsref}[$i] eq "romdotparen") {
$splitstr = '[ivx]+\.\)';
}
for (my $j=${$startsref}[$i]-1; $j<${$endsref}[$i]; $j++) {
@{$multparts{$j}} = split/[\r\n\f]+\s*$splitstr\s*/,$questions[$j];
chomp(@{$multparts{$j}});
}
} elsif (${$qtyperef}[$i] eq "FIB") {
for (my $j=${$startsref}[$i]-1; $j<${$endsref}[$i]; $j++) {
@{$multparts{$j}} = ("$questions[$j]");
}
}
}
}
my ($lastanswer,$footer) = ($questions[-1] =~ /^([,\r\n\f\t\s().A-Za-z]+)(.+)$/);
if ($footer ne '') {
$questions[-1] = $lastanswer;
}
%{$multpartsref} = %multparts;
return (\@questions,\@qids,$footer);
}
# create_mcq builds an MC, MA, Ord or FIB question
sub create_mcq {
my ($destdir,$subdir,$qstnref,$answerref,$qtype,$libfile,$res,$header,$footer,$js,$css) = @_;
my $qstn = ${$qstnref}[0];
my $numfoils = scalar(@{$qstnref}) - 1;
my $datestamp = localtime;
my $numansrs = scalar(@{$answerref});
my $output = '';
if ($res eq 'application/rtf' || $res eq 'text/html') {
if ($header ne '') {
$output .= &HTML::Entities::decode($header);
}
if ($js ne '') {
$output .= &HTML::Entities::decode($js);
}
if ($css ne '') {
$output .= &HTML::Entities::decode($css);
}
$qstn = &HTML::Entities::decode($qstn);
}
$output .= $qstn.''."\n";
if ($qtype eq "MA") {
$output .= qq|
|;
for (my $k=0; $k<@{$qstnref}-1; $k++) {
$output .= " |;
}
if ($qtype eq "MC") {
$output .= qq|
|;
for (my $k=0; $k<@{$qstnref}-1; $k++) {
$output .= " |;
}
if ($qtype eq "Ord") {
$output .= qq|
|;
for (my $k=0; $k<@{$qstnref}-1; $k++) {
my $ansval;
my $num = 0;
for (my $i=0; $i<@{$answerref}; $i++) {
if ($$answerref[$i] =~ /=/) {
my @tied = split(/=/,$$answerref[$i]);
foreach my $tie (@tied) {
if ($k == $tie) {
$ansval = $num + 1;
last;
}
}
$num += scalar(@tied);
} elsif ($k == $$answerref[$i]) {
$ansval = $num + 1;
last;
} else {
$num ++;
}
}
my $showfoil = ${$qstnref}[$k+1];
if ($res eq 'application/rtf' || $res eq 'text/html') {
$showfoil = &HTML::Entities::decode($showfoil);
}
$output .= " $showfoil\n";
}
chomp($output);
$output .= qq|
|;
}
if ($qtype eq "FIB") {
my $numerical = 1;
for (my $i=0; $i<@{$answerref}; $i++) {
if (${$answerref}[$i] =~ m/([^\d\.]|\.\.)/) {
$numerical = 0;
}
}
if ($numerical) {
my $numans;
my $tol;
if (@{$answerref} == 1) {
$tol = 5;
$numans = $$answerref[0];
} else {
my $min = $$answerref[0];
my $max = $$answerref[0];
for (my $i=1; $i<@{$answerref}; $i++) {
if ($$answerref[$i]<=$min) {
$min = $$answerref[$i];
} elsif ($$answerref[$i] >= $max) {
$max = $$answerref[$i];
}
}
$numans = ($max + $min)/2;
$tol = 100*($max - $min)/($numans*2);
}
$output .= qq|
|;
} else {
if (@{$answerref} == 1) {
$output .= qq|
|;
} else {
for (my $i=0; $i<@{$answerref}; $i++) {
${$answerref}[$i] =~ s/\|/\|/g;
}
my $regexpans = join('|',@{$answerref});
$regexpans = '/('.$regexpans.')/';
$output .= qq|
|;
}
}
}
if ($footer ne '') {
$output .= ''.&HTML::Entities::decode($footer).'';
}
$output .= qq|
|;
my $result;
if (-e $destdir.$libfile) {
$result = 'exists';
} else {
if (open(PROB,">$destdir$libfile")) {
print PROB $output;
close(PROB);
$result = 'ok';
} else {
$result = 'failed';
}
}
return ($result,$subdir.$libfile);
}
# create_ess builds an essay or True/False question
sub create_ess {
my ($destdir,$subdir,$answer_id,$qstn,$answertxt,$qtype,$libfile,$res,$header,
$footer,$js,$css) = @_;
my $output = '';
if ($res eq 'application/rtf' || $res eq 'text/html') {
if ($header ne '') {
$output .= &HTML::Entities::decode($header);
}
if ($js ne '') {
$output .= &HTML::Entities::decode($js);
}
if ($css ne '') {
$output .= &HTML::Entities::decode($css);
}
$qstn = &HTML::Entities::decode($qstn);
$answertxt = &HTML::Entities::decode($answertxt);
}
$output .= $qstn.'';
my $answer = '';
my $answerlog = '';
if ($qtype eq "Ess") {
$output .= '
'.$answertxt
.'';
} elsif ($qtype eq "TF") {
$answer = $answer_id;
$output .= qq|
|;
$output .= " ";
if ($answer_id) {
$output .= "False";
} else {
$output .= "True";
}
$output .= "\n";
$output .= " ";
if ($answer_id) {
$output .= "True";
} else {
$output .= "False";
}
$output .= '';
}
if ($footer ne '') {
$output .= '
'.&HTML::Entities::decode($footer).'';
}
$output .= '
';
my $result;
if (-e $destdir.$libfile) {
$result = 'exists';
} else {
if (open(PROB,">$destdir$libfile")) {
print PROB $output;
close(PROB);
} else {
$result = 'failed';
}
}
return ($result,$subdir.$libfile);
}
sub probfile_name {
my ($j) = @_;
my $libfile = &HTML::Entities::decode($env{'form.probfile_'.$j});
my $qnum = $j + 1;
if ($libfile eq '') {
if (length($qnum) == 1) {
$qnum = "00".$qnum;
} elsif (length($qnum) == 2) {
$qnum = "0".$qnum;
}
$libfile = 'testbank_question_'.$qnum;
$libfile .= '.problem';
}
return $libfile;
}
sub file_error {
my ($r,$uname,$fn,$current_page,$webpath,$res) = @_;
$r->print('');
return;
}
sub parse_datafile {
my ($r,$uname,$filename,$pathname,$dirpath,$urlpath,$page_name,$subdir,$timestamp) = @_;
my ($badfile,$res,%allfiles,%codebase);
my $mm = new File::MMagic;
my ($text,$header,$css,$js);
if (-e "$dirpath") {
$res = $mm->checktype_filename($dirpath.$filename);
if ($env{'form.phase'} eq 'three') {
if ($res eq 'text/plain') {
open(TESTBANK,"<$dirpath$filename");
@{$text} = ;
close(TESTBANK);
} elsif ($res eq 'application/rtf') {
my $html = '';
my $image_uri = $timestamp;
if ($page_name eq 'Target') {
$image_uri = $urlpath.'/'.$timestamp;
}
my $image_dir;
if ($page_name eq 'Blocks') {
$image_dir = $dirpath;
$image_dir =~ s/\/$//;
$image_dir .= '/'.$timestamp;
if (!-e $image_dir) {
mkdir($image_dir,0755);
}
} else {
$image_dir = $r->dir_config('lonDaemons').'/tmp/'.
$env{'user.name'}.'_'.$env{'user.domain'}.
'_rtfupload_'.$filename.'_'.time.'_'.$$;
if (!-e $image_dir) {
mkdir($image_dir,0755);
}
}
my $parser = RTF::HTMLConverter->new (
in => $dirpath.$filename,
out => \$html,
DOMImplementation => 'XML::DOM',
image_uri => $image_uri,
image_dir => $image_dir,
);
$parser->parse();
utf8::decode($html);
($text,$header,$css,$js) =
&parse_htmlcontent($res,$subdir,$html,undef,$page_name);
} elsif ($res eq 'text/html') {
($text,$header,$css,$js) =
&parse_htmlcontent($res,$subdir,undef,$dirpath.$filename,$page_name);
} else {
$badfile = 1;
}
}
}
return ($res,$badfile,$text,$header,$css,$js,\%allfiles,\%codebase);
}
sub parse_htmlcontent {
my ($res,$subdir,$html,$fullpath,$page_name) = @_;
my ($p,$fh);
if ($res eq 'application/rtf') {
$p = HTML::TokeParser->new( \$html );
} elsif ($res eq 'text/html') {
open($fh, "<:utf8", $fullpath);
$p = HTML::TokeParser->new( $fh );
}
my ($current_tag,$line,@text,$header,$css,$js,$have_header,$delayed);
while (my $token = $p->get_token) {
if (ref($token) eq 'ARRAY') {
if ($token->[0] eq 'S') {
if ($delayed ne '') {
$line.= $delayed;
$delayed = '';
}
$current_tag = $token->[1];
next if ($token->[1] eq 'html' || $token->[1] eq 'head' || $token->[1] eq 'body' || $token->[1] eq 'meta' || $token->[1] eq 'title');
if ($token->[1] eq 'p') {
$line =~ s/^[\s\240]*(.*?)[\s\240]*$/$1/;
if (!$have_header) {
$header = $line;
if ($header ne '') {
$header =~ s/\s*[\n\r\f]+/\n/gs;
}
$have_header = 1;
} else {
push(@text,$line);
}
$line = '';
} elsif ($current_tag eq 'style') {
$css .= $token->[4];
} elsif ($current_tag eq 'script') {
$js .= $token->[4];
} else {
my $contents = $token->[4];
if ($subdir ne '') {
if (($token->[1] eq 'img') && ($token->[2]->{'src'} ne '')) {
if (($res eq 'text/html') ||
($res eq 'application/rtf') && ($page_name ne 'Target')) {
$contents =~ s/(src=\s*["']?)/$1..\//i;
}
}
}
if (($line eq '') && ($current_tag eq 'font')) {
$delayed = &HTML::Entities::encode($contents,'<>&"');
} else {
$line .= &HTML::Entities::encode($contents,'<>&"');
}
}
} elsif ($token->[0] eq 'T') {
if ($current_tag ne 'html' && $current_tag ne 'head' && $current_tag ne 'body' && $current_tag ne 'meta' && $current_tag ne 'title') {
if ($current_tag eq 'style') {
$css .= $token->[1];
} elsif ($current_tag eq 'script') {
$js .= $token->[1];
} else {
if ($delayed ne '') {
my ($id,$rest) = ($token->[1] =~ /^(\s*\(*[A-Za-z0-9]+\)*\.*\s+)(.+)$/s);
if ($id ne '') {
$line .= $id.$delayed.$rest;
} else {
$line .= $token->[1].$delayed;
}
$delayed = '';
} else {
$line .= $token->[1];
}
}
}
} elsif ($token->[0] eq 'E') {
next if ($token->[1] eq 'html' || $token->[1] eq 'head' || $token->[1] eq 'body' || $token->[1] eq 'meta' || $token->[1] eq 'title' || $token->[1] eq 'p');
if ($token->[1] eq 'style') {
$css .= $token->[2];
} elsif ($token->[1] eq 'script') {
$js .= $token->[2];
} else {
$line .= &HTML::Entities::encode($token->[2],'<>&"');
}
$current_tag = '';
}
}
}
if ($line ne '') {
if ($line ne '') {
$line =~ s/\s*[\n\r\f]+/\n/gs;
}
$line =~ s/^[\s\240]*(.*?)[\s\240]*$/$1/;
push(@text,$line);
}
if ($res eq 'text/html') {
close($fh);
}
return (\@text,$header,$css,$js);
}
sub build_image_url {
my ($urlpath,$item) = @_;
$item =~ s/(]+src=["']?\s*)(\.?\.?\/?)/$1$urlpath/gsi;
return $item;
}
sub print_header {
my ($uname,$udom,$javascript,$loadentries,$title) = @_;
my $output = &Apache::loncommon::start_page($title,$javascript,
{'add_entries' => $loadentries});
if (($uname ne $env{'user.name'}) || ($udom ne $env{'user.domain'})) {
$output .= '
'
.&mt('Co-Author [_1]:[_2]',$uname,$udom)
.'
';
}
return $output;
}
sub topic_bar {
my ($imgnum,$title) = @_;
my $output = '
'.$title.'
';
return $output;
}
# ---------------------------------------------------------------- Main Handler
sub handler {
my $r=shift;
my $uname;
my $udom;
my $javascript = '';
my $page_name = '';
my $current_page = '';
my $qcount = '';
my $title = 'Upload testbank questions to Construction Space';
if ($env{'form.uploaduname'}) {
$env{'form.filename'}='/priv/'.$env{'form.uploaduname'}.'/'.
$env{'form.filename'};
}
($uname,$udom)=
&Apache::loncacc::constructaccess($env{'form.filename'},
$r->dir_config('lonDefDomain'));
unless (($uname) && ($udom)) {
$r->log_reason($uname.':'.$udom.' trying to convert testbank file '.
$env{'form.filename'}.' - not authorized',$r->filename);
return HTTP_NOT_ACCEPTABLE;
}
my ($fn,$filename);
if ($env{'form.filename'}) {
$fn=$env{'form.filename'};
$fn=~s/^https?\:\/\/[^\/]+\///;
$fn=~s/^\///;
$fn=~s{(~|priv/)($LONCAPA::username_re)}{};
$fn=~s/\/+/\//g;
} else {
$r->log_reason($env{'user.name'}.' at '.$env{'user.domain'}.
' unspecified filename for upload', $r->filename);
return HTTP_NOT_FOUND;
}
# ----------------------------------------------------------- Start page output
&Apache::loncommon::content_type($r,'text/html');
$r->send_http_header;
my ($filename,$pathname) = &File::Basename::fileparse($fn);
my $webpath = '/priv/'.$uname.$pathname;
my $urlpath = '/~'.$uname.$pathname;
my $dirpath = '/home/'.$uname.'/public_html'.$pathname;
my ($res,$subdir,$badfile,$textref,$header,$css,$js,%loadentries);
if ($env{'form.phase'} eq 'three') {
$current_page = &display_control();
my @pages = ('Welcome','Blocks','Format','Target','Confirmation');
$page_name = $pages[$current_page];
if ($env{'form.timestamp'} eq '') {
$env{'form.timestamp'} = time;
}
if ($env{'form.newdir'} ne '') {
if ($env{'form.newdir'} =~ /^\Q$dirpath\E(.+)$/) {
$subdir = $1;
}
}
($res,$badfile,$textref,$header,$css,$js) =
&parse_datafile($r,$uname,$filename,$pathname,$dirpath,$urlpath,
$page_name,$subdir,$env{'form.timestamp'});
if ($page_name eq 'Welcome') {
&jscript_zero($webpath,\$javascript);
} elsif ($page_name eq 'Blocks') {
if ($env{'form.go'} eq "PreviousPage") {
$loadentries{'onload'} = "setElements()";
}
&jscript_one(\$javascript);
} elsif ($page_name eq 'Format') {
if ($env{'form.go'} eq "PreviousPage") {
$loadentries{'onload'} = "setElements()";
}
$qcount = question_count($env{'form.qnumformat'},$textref);
&jscript_two(\$javascript,$qcount);
} elsif ($page_name eq 'Target') {
if ($env{'form.go'} eq "PreviousPage") {
$loadentries{'onload'} = "setElements()";
}
&jscript_three($webpath,\$javascript);
} elsif ($page_name eq 'Confirmation') {
&jscript_four(\$javascript,$webpath);
}
$javascript = "\n";
if ($res eq 'application/rtf' || $res eq 'text/html') {
if ($page_name eq 'Target') {
$javascript .= $js.$css;
}
}
}
$r->print(&print_header($uname,$udom,$javascript,\%loadentries,$title));
if ($env{'form.phase'} eq 'three') {
if ($env{'form.action'} eq 'upload_embedded') {
$r->print(&Apache::lonupload::phasethree($r,$fn,$uname,$udom,'testbank'));
}
if ($badfile) {
&file_error($r,$uname,$fn,$current_page,$webpath,$res);
} 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';
&display_three ($r,$uname,$fn,$current_page,$textref,$res,$header,$urlpath,$qcount) if $page_name eq 'Target';
&final_display ($r,$uname,$fn,$current_page,$textref,$res,$header,$css,$js,$webpath,$dirpath,$subdir) if $page_name eq 'Confirmation';
}
} elsif ($env{'form.phase'} eq 'two') {
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 = '';
$r->print($js);
&display_zero($r,$uname,$fn,$current_page,$webpath);
} elsif ($flag eq 'embedded') {
$r->print($js.'');
}
} else {
&Apache::lonupload::phaseone($r,$fn,$uname,$udom,'testbank');
}
$r->print(&Apache::loncommon::end_page());
return OK;
}
1;
__END__
500 Internal Server Error
Internal Server Error
The server encountered an internal error or
misconfiguration and was unable to complete
your request.
Please contact the server administrator at
root@localhost to inform them of the time this error occurred,
and the actions you performed just before this error.
More information about this error may be available
in the server error log.