--- rat/lonratedt.pm 2002/09/04 16:54:44 1.36 +++ rat/lonratedt.pm 2005/06/08 16:10:01 1.68 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Edit Handler for RAT Maps # -# $Id: lonratedt.pm,v 1.36 2002/09/04 16:54:44 www Exp $ +# $Id: lonratedt.pm,v 1.68 2005/06/08 16:10:01 www Exp $ # # Copyright Michigan State University Board of Trustees # @@ -25,22 +25,155 @@ # # http://www.lon-capa.org/ # -# (TeX Content Handler -# -# 05/29/00,05/30 Gerd Kortemeyer) -# 7/1,6/30 Gerd Kortemeyer + package Apache::lonratedt; +=pod + +=head1 NAME + +Apache::lonratedt: advanced resource assembly tool + +=head1 SYNOPSIS + +lonratedt provides the routines and the handler for the Advanced + Resource Assembly Tool (RAT), and ties the various pieces together + with Javascript. + +=head1 OVERVIEW + +=head2 Map Representation + +=begin latex + +% +\begin{figure} +\begin{center}\includegraphics[% + width=0.55\paperwidth,bb = 0 0 200 100, draft, type=eps]{Map_Example}\end{center} + + +\caption{\label{Map_In_Advanced_Editor}Example of a Map in the Advanced Editor} +\end{figure} +% +\begin{figure} +\begin{lyxcode} + + +~~ + +~~~~ + +~~ + +~~~~ + +~~ + +~~~~ + +~~ + +~~~~ + +~~ + +~~~~ + +~~ + +~~~~ + +~~ + +~~ + +~~ + +~~ + +~~ +\end{lyxcode} + +\caption{\label{XML}XML for Map in Figure \ref{Map_In_Advanced_Editor}} +\end{figure} + +=end latex + +Fig. "XML for Map in Figure" shows the XML representation of the +resource map shown in Fig. "Example of a Map in the Advanced Editor", +which is the format in which maps are stored. In the figure, however, +additional graphical map layout information generated by the Advanced +Resource Assembly Tool is not displayed. This graphical information is +optional to re-generate the same graphical layout when the map is +brought up again in the Resource Assembly Tool, and is not needed for +any other system functionality. + +Maps can be generated by tools other than the Resource Assembly +Tool. In particular, an author might have some other representation of +a course sequence, which can be converted into a map using scripts. If +this map then were to be brought up in the Resource Assembly Tool, the +Tool would automatically generate a graphical layout for it. Each +entry of the map (resources, conditions and links) is stored in a +separate tag. + +Resources and conditionsX have to have unique ID +numbers. These numbers are automatically generated by the Resource +Assembly Tool when the entry is first created, or added to the entries +when a map generated outside the Resource Assembly Tool is first +retrieved. They can also be assigned by custom scripts or added in by +hand. + +In the XML example, entry 1 is the start resource of the map. When +this map is accessed, the source (src) URL of this tag will be the +first resource rendered. Entry 2 is the finish resource of this +map. This resource will be the last resource in the sequence of +resources. Entry 6 is a problem resource with the given URL and title, +as well as the priority "mandatory". Entry 19 is a condition, which is +used by the link between entries 6, the problem, and 9, a +sequence. I + +=cut + use strict; use Apache::Constants qw(:common); use Apache::lonnet; use Apache::lonratsrv; use Apache::lonsequence; use Apache::loncommon; +use Apache::lonlocal; use File::Copy; -use vars qw(@order @resources); +use vars qw(@order @resources @resparms @zombies %revzombies); # Mapread read maps into global arrays @links and @resources, determines status @@ -54,8 +187,15 @@ sub mapread { undef @links; undef @resources; undef @order; + undef @resparms; + undef @zombies; + undef %revzombies; + @resources=(''); @order=(); + @resparms=(); + @zombies=(); + %revzombies=(); my ($outtext,$errtext)=&Apache::lonratsrv::loadmap($fn,''); if ($errtext) { return ($errtext,2); } @@ -64,13 +204,23 @@ sub mapread { foreach (split(/\<\&\>/,$outtext)) { my ($command,$number,$content)=split(/\<\:\>/,$_); if ($command eq 'objcont') { - $resources[$number]=$content; + my ($title,$src,$ext,$type)=split(/\:/,$content); + if ($type ne 'zombie') { + $resources[$number]=$content; + } else { + $zombies[$number]=$content; + $revzombies{$src}=$number; + } } if ($command eq 'objlinks') { $links[$number]=$content; } if ($command eq 'objparms') { - return('Map has resource parameters. Use advanced editor.',1); + if ($resparms[$number]) { + $resparms[$number].='&&&'.$content; + } else { + $resparms[$number]=$content; + } } } # ------------------------------------------------------- Is this a linear map? @@ -84,13 +234,13 @@ sub mapread { my ($start,$end,$cond)=split(/\:/,$_); if ((defined($starters[$start])) || (defined($endings[$end]))) { return - ('Map has branchings. Use advanced editor.',1); + (&mt('Map has branchings. Use advanced editor.'),1); } $starters[$start]=1; $endings[$end]=1; if ($cond) { return - ('Map has conditions. Use advanced editor.',1); + (&mt('Map has conditions. Use advanced editor.'),1); } } @@ -99,11 +249,16 @@ sub mapread { if (defined($resources[$i])) { unless (($starters[$i]) || ($endings[$i])) { return - ('Map has unconnected resources. Use advanced editor.',1); + (&mt('Map has unconnected resources. Use advanced editor.'),1); } } } - +# ---------------------------------------------- Did we just read an empty map? + if ($#resources<1) { + undef $resources[0]; + $resources[1]=':::start'; + $resources[2]=':::finish'; + } # -------------------------------------------------- This is a linear map, sort my $startidx=0; @@ -152,7 +307,10 @@ sub attemptread { foreach (split(/\<\&\>/,$outtext)) { my ($command,$number,$content)=split(/\<\:\>/,$_); if ($command eq 'objcont') { - $theseres[$number]=$content; + my ($title,$src,$ext,$type)=split(/\:/,$content); + unless ($type eq 'zombie') { + $theseres[$number]=$content; + } } if ($command eq 'objlinks') { $links[$number]=$content; @@ -249,6 +407,10 @@ sub attemptread { # --------------------------------------------------------- Build up RAT screen sub ratedt { my ($r,$url)=@_; + my $frameset = ''; + if ($env{'environment.remote'} eq 'off') { + $frameset = ''; + } $r->print(< @@ -257,9 +419,9 @@ sub ratedt { var flag=0; - +$frameset - + @@ -273,16 +435,25 @@ sub buttons { my $adv=shift; my $output='
'; if ($adv==1) { - $output.=''; + $output.=''. + &Apache::loncommon::help_open_topic('Sequence_Advanced_Editor_Creation');; } else { unless ($adv==2) { - $output.=''; + $output.=''. + &Apache::loncommon::help_open_topic('Sequence_Simple_Editor_Creation'); } - $output.=''; + $output.=''. + &Apache::loncommon::help_open_topic('Sequence_Advanced_Editor_Creation'); } return $output.'

'; } +# ----------------------------------------------------- Get an unused res index + +sub unusedindex { + return 1+($#resources>$#zombies?$#resources:$#zombies); +} + # ----------------------------------------------------------- Paste into target # modifies @order, @resources @@ -295,11 +466,12 @@ sub pastetarget { $name=&Apache::lonnet::unescape($name); $url=&Apache::lonnet::unescape($url); if ($url) { - my $idx=$#resources+1; + my $idx=&unusedindex(); $insertorder[$#insertorder+1]=$idx; my $ext='false'; if ($url=~/^http\:\/\//) { $ext='true'; } $url=~s/\:/\:/g; + $name=~s/\:/\:/g; $resources[$idx]=$name.':'.$url.':'.$ext.':normal:res'; } } @@ -312,18 +484,39 @@ sub pastetarget { # modifies @resources sub startfinish { +# Remove all start and finish foreach (@order) { my ($name,$url,$ext)=split(/\:/,$resources[$_]); if ($url=~/http\&colon\:\/\//) { $ext='true'; } $resources[$_]=$name.':'.$url.':'.$ext.':normal:res'; } +# Garbage collection + my $stillchange=1; + while (($#order>1) && ($stillchange)) { + $stillchange=0; + for (my $i=0;$i<=$#order;$i++) { + my ($name,$url,$ext)=split(/\:/,$resources[$order[$i]]); + unless ($url) { +# Take out empty resource + for (my $j=$i+1;$j<=$#order;$j++) { + $order[$j-1]=$order[$j]; + } + $#order--; + $stillchange=1; + last; + } + } + } +# Put in a start resource my ($name,$url,$ext)=split(/\:/,$resources[$order[0]]); $resources[$order[0]]=$name.':'.$url.':'.$ext.':start:res'; +# Make sure this has at least start and finish if ($#order==0) { - $resources[$#resources+1]='::false'; + $resources[&unusedindex()]='::false'; $order[1]=$#resources; } - my ($name,$url,$ext)=split(/\:/,$resources[$order[$#order]]); +# Make the last one a finish resource + ($name,$url,$ext)=split(/\:/,$resources[$order[$#order]]); $resources[$order[$#order]]=$name.':'.$url.':'.$ext.':finish:res'; } @@ -348,6 +541,13 @@ sub storemap { if (defined($resources[$order[$i]])) { $output.='<&>objcont<:>'.$order[$i].'<:>'.$resources[$order[$i]]; } + if (defined($resparms[$order[$i]])) { + foreach (split('&&&',$resparms[$order[$i]])) { + if ($_) { + $output.='<&>objparms<:>'.$order[$i].'<:>'.$_; + } + } + } if (defined($order[$i+1])) { if (defined($resources[$order[$i+1]])) { $output.='<&>objlinks<:>'.$k.'<:>'. @@ -357,13 +557,66 @@ sub storemap { } } $output=~s/http\&colon\;\/\///g; - $ENV{'form.output'}=$output; + $env{'form.output'}=$output; return &Apache::lonratsrv::loadmap($fn,&Apache::lonratsrv::savemap($fn,'')); } +# ------------------------------------------ Store and get parameters in global + +sub storeparameter { + my ($to,$name,$value,$ptype)=@_; + my $newentry=''; + my $nametype=''; + foreach (split('&&&',$resparms[$to])) { + my ($thistype,$thisname,$thisvalue)=split('___',$_); + if ($thisname) { + unless ($thisname eq $name) { + $newentry.=$_.'&&&'; + } else { + $nametype=$thistype; + } + } + } + unless ($ptype) { $ptype=$nametype; } + unless ($ptype) { $ptype='string'; } + $newentry.=$ptype.'___'.$name.'___'.$value; + $resparms[$to]=$newentry; +} + +sub delparameter { + my ($to,$name)=@_; + my $newentry=''; + my $nametype=''; + foreach (split('&&&',$resparms[$to])) { + my ($thistype,$thisname,$thisvalue)=split('___',$_); + if ($thisname) { + unless ($thisname eq $name) { + $newentry.=$_.'&&&'; + } + } + } + $resparms[$to]=$newentry; +} + +sub getparameter { + my ($to,$name)=@_; + my $value=undef; + my $ptype=undef; + foreach (split('&&&',$resparms[$to])) { + my ($thistype,$thisname,$thisvalue)=split('___',$_); + if ($thisname eq $name) { + $value=$thisvalue; + $ptype=$thistype; + } + } + return ($value,$ptype); +} + +# ----------------------------------------------------------------- Edit script sub editscript { my $mode=shift; + my $resurl=&Apache::loncommon::lastresurl(); return(<
'; + } else { + $targetmsg=''.&mt('An error occured while saving.').'
'; + } } - if ($ENV{'form.revert'}) { - $targetmsg='Reverting ...
'; + if ($env{'form.revert'}) { + $targetmsg=''.&mt('Reverted.').'
'; unlink($tmpfn); my ($errtext,$fatal)= &mapread(&Apache::lonnet::filelocation('',$url),''); } if (-e $tmpfn) { $targetmsg= - 'You are working with an unsaved version of your map.
'; + ''.&mt('You are working with an unsaved version of your map.').'
'; my ($errtext,$fatal)=&mapread($tmpfn,''); } # ---------------------------------------------------------- Process form input - my @importselect=(); - my @targetselect=(); - undef @importselect; - undef @targetselect; - if (defined($ENV{'form.importsel'})) { - if (ref($ENV{'form.importsel'})) { - @importselect=sort(@{$ENV{'form.importsel'}}); - } else { - @importselect=($ENV{'form.importsel'}); - } - } - if (defined($ENV{'form.target'})) { - if (ref($ENV{'form.target'})) { - @targetselect=sort(@{$ENV{'form.target'}}); - } else { - @targetselect=($ENV{'form.target'}); - } - } + my @importselect=&Apache::loncommon::get_env_multiple('form.importsel'); + my @targetselect=&Apache::loncommon::get_env_multiple('form.target'); # ============================================================ Process commands - my $targetdetail=$ENV{'form.targetdetail'}; - my $importdetail=$ENV{'form.curimpdetail'}; + my $targetdetail=$env{'form.targetdetail'}; + my $importdetail=$env{'form.curimpdetail'}; # ---------------------------------------------------- Importing from groupsort - if (($ENV{'form.importdetail'}) && (!$ENV{'form.impfortarget'})) { + if (($env{'form.importdetail'}) && (!$env{'form.impfortarget'})) { $importdetail=''; - my @curimport=split(/\&/,$ENV{'form.curimpdetail'}); + my @curimport=split(/\&/,$env{'form.curimpdetail'}); my $lastsel; @@ -540,7 +781,7 @@ sub smpedt { } } - $importdetail.='&'.$ENV{'form.importdetail'}; + $importdetail.='&'.$env{'form.importdetail'}; for (my $i=$lastsel+1;$i<=$#curimport;$i++) { my ($name,$url)=split(/\=/,$curimport[$i]); @@ -552,12 +793,12 @@ sub smpedt { $importdetail=~s/^\&//; # ------------------------------------------------------------------- Clear all - } elsif ($ENV{'form.clear'}) { + } elsif ($env{'form.clear'}) { $importdetail=''; # ------------------------------------------------------------ Discard selected - } elsif ($ENV{'form.discard'}) { + } elsif ($env{'form.discard'}) { $importdetail=''; - my @curimport=split(/\&/,$ENV{'form.curimpdetail'}); + my @curimport=split(/\&/,$env{'form.curimpdetail'}); foreach (@importselect) { $curimport[$_]=''; } @@ -568,9 +809,9 @@ sub smpedt { } } # --------------------------------------------------------- Loading another map - } elsif ($ENV{'form.loadmap'}) { + } elsif ($env{'form.loadmap'}) { $importdetail=''; - my @curimport=split(/\&/,$ENV{'form.curimpdetail'}); + my @curimport=split(/\&/,$env{'form.curimpdetail'}); my $lastsel; @@ -588,7 +829,7 @@ sub smpedt { } foreach ( - &Apache::lonsequence::attemptread(&Apache::lonnet::filelocation('',$ENV{'form.importmap'}))) { + &Apache::lonsequence::attemptread(&Apache::lonnet::filelocation('',$env{'form.importmap'}))) { my ($name,$url)=split(/\:/,$_); if ($url) { $importdetail.='&'.&Apache::lonnet::escape($name).'='. @@ -606,19 +847,19 @@ sub smpedt { $importdetail=~s/^\&//; # ------------------------------------------------ Groupimport/search to target - } elsif ($ENV{'form.importdetail'}) { + } elsif ($env{'form.importdetail'}) { my $lastsel; if (defined($targetselect[-1])) { $lastsel=$targetselect[-1]; } else { $lastsel=$#order+1; } - &pastetarget($lastsel,split(/\&/,$ENV{'form.importdetail'})); + &pastetarget($lastsel,split(/\&/,$env{'form.importdetail'})); &storemap(&Apache::lonnet::filelocation('',$url)); # ------------------------------------------------------------------------- Cut - } elsif (($ENV{'form.cut'}) || ($ENV{'form.copy'})) { + } elsif (($env{'form.cut'}) || ($env{'form.copy'})) { $importdetail=''; - my @curimport=split(/\&/,$ENV{'form.curimpdetail'}); + my @curimport=split(/\&/,$env{'form.curimpdetail'}); my $lastsel; @@ -652,7 +893,7 @@ sub smpedt { $importdetail=~s/\&+/\&/g; $importdetail=~s/^\&//; - if ($ENV{'form.cut'}) { + if ($env{'form.cut'}) { my @neworder=(); for (my $i=0;$i<=$#order;$i++) { my $include=1; @@ -666,7 +907,7 @@ sub smpedt { } # ----------------------------------------------------------------------- Paste - } elsif ($ENV{'form.paste'}) { + } elsif ($env{'form.paste'}) { my $lastsel; if (defined($targetselect[-1])) { $lastsel=$targetselect[-1]; @@ -674,13 +915,40 @@ sub smpedt { $lastsel=$#order+1; } my @newsequence; - my @curimport=split(/\&/,$ENV{'form.curimpdetail'}); + my @curimport=split(/\&/,$env{'form.curimpdetail'}); foreach (@importselect) { $newsequence[$#newsequence+1]=$curimport[$_]; } &pastetarget($lastsel,@newsequence); &storemap(&Apache::lonnet::filelocation('',$url)); -# ------------------------------------------------ +# -------------------------------------------------------------------- Move up + } elsif ($env{'form.moveup'}) { + foreach (sort @targetselect) { + if ($_-1>0) { + my $movethis=$order[$_-1]; + $order[$_-1]=$order[$_-2]; + $order[$_-2]=$movethis; + } + } + &storemap(&Apache::lonnet::filelocation('',$url)); +# ------------------------------------------------------------------ Move down + } elsif ($env{'form.movedown'}) { + foreach (reverse sort @targetselect) { + if ($_-1<$#order) { + my $movethis=$order[$_-1]; + $order[$_-1]=$order[$_]; + $order[$_]=$movethis; + } + } + &storemap(&Apache::lonnet::filelocation('',$url)); +# --------------------------------------------------------------------- Rename + } elsif ($env{'form.renameres'}) { + my $residx=$Apache::lonratedt::order[$env{'form.renameidx'}-1]; + my ($name,@resrest)=split(/\:/,$Apache::lonratedt::resources[$residx]); + $name=$env{'form.renametitle'}; + $name=~s/\:/\&colon\;/g; + $Apache::lonratedt::resources[$residx]=$name.':'.join(':',@resrest); + &storemap(&Apache::lonnet::filelocation('',$url)); } # ------------------------------------------------------------ Assemble windows @@ -688,7 +956,7 @@ sub smpedt { $importdetail='&'.$importdetail; $importdetail=~s/^\&+/\&/; my $importwindow= - ''. + ''. join("\n",map { $idx++; if ($_) { @@ -701,8 +969,9 @@ sub smpedt { } split(/\&/,$importdetail)); $idx=0; + $targetdetail=''; my $targetwindow= - ''. + ''. join("\n",map { my ($name,$url)=split(/\:/,$resources[$_]); unless ($name) { $name=(split(/\//,$url))[-1]; } @@ -710,12 +979,35 @@ sub smpedt { $targetdetail.='&'.&Apache::lonnet::escape($name).'='. &Apache::lonnet::escape($url); $idx++; + $name=~s/\:/\:/g; ''; } @order); # ----------------------------------------------------- Start simple RAT screen my $editscript=&editscript('simple'); - my $bodytag=&Apache::loncommon::bodytag(undef,undef,undef,1); + my $bodytag=&Apache::loncommon::bodytag(undef,undef,undef, + ($env{'environment.remote'} ne 'off')). + &Apache::loncommon::help_open_menu('','Sequence_Simple_Editor_Creation','Sequence_Simple_Editor_Creation','',6,'RAT'); + my %lt=&Apache::lonlocal::texthash( + 'sa' => 'Save', + 'nt' => 'New Title', + 'se' => 'Search', + 'im' => 'Import', + 'vi' => 'View', + 'lm' => 'Load Map', + 'ds' => 'Discard Selected', + 'ca' => 'Clear All', + 'ta' => 'Temporary Assembly Workspace', + 'rv' => 'Revert to Last Saved', + 'sa' => 'Save', + 'mu' => 'Move Up', + 'md' => 'Move Down', + 're' => 'Rename', + 'as' => 'after selected', + 'cs' => 'Cut selected', + 'ps' => 'Copy selected', + 'pas' => 'Paste after selected', + ); $r->print(< @@ -741,42 +1033,68 @@ sub smpedt { [document.forms.simpleedit.importsel.selectedIndex]); } + function renametarget() { + var selidx=document.forms.simpleedit.target.selectedIndex; + var entry=(document.forms.simpleedit.targetdetail.value.split('&')) + [selidx]; + var oldname=unescape((entry.split('='))[0]); + var nameparts=oldname.split(':'); + oldname=unescape(nameparts.join(':')); + nameparts=oldname.split('"'); + oldname=unescape(nameparts.join('"')); + nameparts=oldname.split('''); + oldname=unescape(nameparts.join("'")); + newtitle=prompt('$lt{'nt'}',oldname); + if (newtitle) { + document.forms.simpleedit.renameres.value=1; + document.forms.simpleedit.renameidx.value=selidx; + document.forms.simpleedit.renametitle.value=newtitle; + document.forms.simpleedit.submit(); + } + } + $bodytag $buttons $errtext -

$url

+ + + - + - +
Import
$lt{'ta'}  Target
File: $url
- - -after selected + + +$lt{'as'}

- - - +value="Select Map">
+ + +
  +"javascript:impfortarget.value=1;groupsearch()" value="$lt{'se'}"> -after selected +"javascript:impfortarget.value=1;groupimport();" value="$lt{'im'}"> +$lt{'as'} +
+ + +
$targetmsg - - - + + +
-Cut selected
+$lt{'cs'}


-Copy selected
+$lt{'ps'}


-Paste after selected
+$lt{'pas'}
'. + ''. + ''. + ''. + ''. + ''. + ''); + my @backgroundColors = ("#FFFFFF", "#F6F6F6"); foreach (&attemptread(&Apache::lonnet::filelocation('',$url))) { if (defined($_)) { $idx++; - my ($title,$url)=split(/\:/,$_); + my ($title,$url,$cond)=split(/\:/,$_); + if ($cond eq 'cond') { next; } $title=~s/\&colon\;/\:/g; $url=~s/\&colon\;/\:/g; unless ($title) { $title=(split(/\//,$url))[-1] }; - unless ($title) { $title='Empty'; } + unless ($title) { $title=''.&mt('Empty').''; } + my $resurl = &Apache::lonratsrv::qtescape($url); + my $resfilepath = $Apache::lonnet::perlvar{'lonDocRoot'}.$resurl; + my $filename; + if ($resurl =~ m#/([^/]+)$#) { + $filename = $1; + } + my $cstrurl = $resurl; + $cstrurl =~ s#^/res/[^/]+/([^/]+)/#/priv/$1/#; + my $bgcol = $idx%2; + $r->print(''."\n"); } } + $r->print('
'.&mt('Type').''.&mt('Title in map').''.&mt('Filename of resource').''.&mt('Link to published resource').''.&mt('Link to resource in Construction Space').'
'. + ''.&Apache::lonratsrv::qtescape($title). + ''.$filename.''); + if ($url) { + $r->print(''.&mt('Resource space').''); + } + $r->print(''); if ($url) { - $r->print(''); + $r->print(''. + &mt('Construction space').''); } - $r->print(&Apache::lonratsrv::qtescape($title)); - if ($url) { $r->print(''); } - $r->print('
'); + $r->print('
'); $r->print(''); } @@ -854,11 +1202,17 @@ sub viewmap { sub handler { my $r=shift; - $r->content_type('text/html'); + &Apache::loncommon::content_type($r,'text/html'); $r->send_http_header; return OK if $r->header_only; - + my $target = $env{'form.grade_target'}; + if ($target eq 'meta') { + &Apache::loncommon::content_type($r,'text/html'); + $r->send_http_header; + return OK; + } + my $url=$r->uri; my $fn=&Apache::lonnet::filelocation('',$url); @@ -871,8 +1225,8 @@ sub handler { # ------------------------------------------- Determine which tools can be used my $adv=0; - unless ($ENV{'form.forcesmp'}) { - if ($ENV{'form.forceadv'}) { + unless ($env{'form.forcesmp'}) { + if ($env{'form.forceadv'}) { $adv=1; } elsif (my $fh=Apache::File->new($fn)) { my $allmap=join('',<$fh>); @@ -890,9 +1244,9 @@ sub handler { # ----------------------------------- adv==1 now means "graphical MUST be used" - if ($ENV{'form.forceadv'}) { + if ($env{'form.forceadv'}) { &ratedt($r,$url); - } elsif ($ENV{'form.forcesmp'}) { + } elsif ($env{'form.forcesmp'}) { &smpedt($r,$url,$errtext); } else { &viewmap($r,$url,$adv,$errtext); 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.