--- loncom/xml/lonxml.pm 2003/09/27 04:15:26 1.266.2.2 +++ loncom/xml/lonxml.pm 2003/09/14 23:57:18 1.276 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # XML Parser Module # -# $Id: lonxml.pm,v 1.266.2.2 2003/09/27 04:15:26 albertel Exp $ +# $Id: lonxml.pm,v 1.276 2003/09/14 23:57:18 www Exp $ # # Copyright Michigan State University Board of Trustees # @@ -69,6 +69,7 @@ use Safe::Hole(); use Math::Cephes(); use Math::Random(); use Opcode(); +use POSIX qw(strftime); sub register { @@ -158,9 +159,6 @@ $Apache::lonxml::usestyle=1; $Apache::lonxml::style_values=''; $Apache::lonxml::style_end_values=''; -#array of ssi calls that need to occur after we are done parsing -@Apache::lonxml::ssi_info=(); - sub xmlbegin { my $output=''; if ($ENV{'browser.mathml'}) { @@ -185,103 +183,8 @@ sub xmlend { $crs.='_'.$ENV{'request.course.sec'}; } $crs=~s/\_/\//g; - my $seeid=&Apache::lonnet::allowed('rin',$crs); - unless ($symb) { - $symb=&Apache::lonnet::symbread(); - } - if ($symb) { - my %contrib=&Apache::lonnet::restore($symb,$ENV{'request.course.id'}, - $ENV{'course.'.$ENV{'request.course.id'}.'.domain'}, - $ENV{'course.'.$ENV{'request.course.id'}.'.num'}); - if ($contrib{'version'}) { - unless ($discussiononly) { - $discussion.= - '

'; - } - my $idx; - for ($idx=1;$idx<=$contrib{'version'};$idx++) { - my $hidden=($contrib{'hidden'}=~/\.$idx\./); - my $deleted=($contrib{'deleted'}=~/\.$idx\./); - unless ((($hidden) && (!$seeid)) || ($deleted)) { - my $message=$contrib{$idx.':message'}; - $message=~s/\n/\
/g; - $message=&Apache::lontexconvert::msgtexconverted($message); - if ($contrib{$idx.':attachmenturl'}) { - my ($fname,$ft) - =($contrib{$idx.':attachmenturl'}=~/\/(\w+)\.(\w+)$/); - $message.='

Attachment: '.$fname.'.'.$ft.''; - } - if ($message) { - if ($hidden) { - $message=''.$message.''; - } - my $screenname=&Apache::loncommon::screenname( - $contrib{$idx.':sendername'}, - $contrib{$idx.':senderdomain'}); - my $plainname=&Apache::loncommon::nickname( - $contrib{$idx.':sendername'}, - $contrib{$idx.':senderdomain'}); - - my $sender='Anonymous'; - if ((!$contrib{$idx.':anonymous'}) || ($seeid)) { - $sender=&Apache::loncommon::aboutmewrapper( - $plainname, - $contrib{$idx.':sendername'}, - $contrib{$idx.':senderdomain'}).' ('. - $contrib{$idx.':sendername'}.' at '. - $contrib{$idx.':senderdomain'}.')'; - if ($contrib{$idx.':anonymous'}) { - $sender.=' [anonymous] '. - $screenname; - } - if ($seeid) { - if ($hidden) { - $sender.=' Make Visible'; - } else { - $sender.=' Hide'; - } - $sender.=' Delete'; - } - } else { - if ($screenname) { - $sender=''.$screenname.''; - } - } - $discussion.='

'.$sender.' ('. - localtime($contrib{$idx.':timestamp'}). - '):

'.$message. - '

'; - } - } - } - unless ($discussiononly) { - $discussion.='
'; - } - } - if ($discussiononly) { - $discussion.=(< - - - - -
-Note: in anonymous discussion, your name is visible only to -course faculty
- -

-Attachment (128 KB max size): -

- -ENDDISCUSS - $discussion.=&Apache::lonfeedback::generate_preview_button(); - } - } + $discussion=&Apache::lonfeedback::list_discussion + ($crs,$symb,$discussiononly); } return $discussion.($discussiononly?'':''); } @@ -454,7 +357,6 @@ sub xmlparse { if ($ENV{'request.uri'}) { &writeallows($ENV{'request.uri'}); } - &do_registered_ssi(); if ($Apache::lonxml::counter_changed) { &store_counter() } return $finaloutput; } @@ -481,23 +383,25 @@ sub htmlclean { } sub latex_special_symbols { - my ($current_token,$stack,$parstack,$where)=@_; + my ($string,$where)=@_; if ($where eq 'header') { - $current_token =~ s/(\\|_|\^)/ /g; - $current_token =~ s/(\$|%|\#|&|\{|\})/\\$1/g; + $string =~ s/(\\|_|\^)/ /g; + $string =~ s/(\$|%|\#|&|\{|\})/\\$1/g; + $string =~ s/_/ /g; } else { - $current_token=~s/\\ /\\char92 /g; - $current_token=~s/\^/\\char94 /g; - $current_token=~s/\~/\\char126 /g; - $current_token=~s/(&[^A-Za-z\#])/\\$1/g; - $current_token=~s/([^&])\#/$1\\#/g; - $current_token=~s/(\$|_|{|})/\\$1/g; - $current_token=~s/\\char92 /\\texttt{\\char92}/g; - $current_token=~s/(>|<)/\$$1\$/g; #more or less - if ($current_token=~m/\d%/) {$current_token =~ s/(\d)%/$1\\%/g;} #percent after digit - if ($current_token=~m/\s%/) {$current_token =~ s/(\s)%/$1\\%/g;} #persent after space + $string=~s/\\ /\\char92 /g; + $string=~s/\^/\\char94 /g; + $string=~s/\~/\\char126 /g; + $string=~s/(&[^A-Za-z\#])/\\$1/g; + $string=~s/([^&])\#/$1\\#/g; + $string=~s/(\$|_|{|})/\\$1/g; + $string=~s/\\char92 /\\texttt{\\char92}/g; + $string=~s/(>|<)/\$$1\$/g; #more or less + if ($string=~m/\d%/) {$string =~ s/(\d)%/$1\\%/g;} #percent after digit + if ($string=~m/\s%/) {$string =~ s/(\s)%/$1\\%/g;} #percent after space + if ($string eq '%.') {$string = '\%.';} #percent at the end of statement } - return $current_token; + return $string; } sub inner_xmlparse { @@ -587,7 +491,7 @@ sub inner_xmlparse { if (($token->[0] eq 'T') || ($token->[0] eq 'C') || ($token->[0] eq 'D') ) { #Style file definitions should be correct if ($target eq 'tex' && ($Apache::lonxml::usestyle)) { - $result=&latex_special_symbols($result,$stack,$parstack); + $result=&latex_special_symbols($result); } } @@ -703,7 +607,6 @@ sub setup_globals { &init_counter(); @Apache::lonxml::pwd=(); @Apache::lonxml::extlinks=(); - @Apache::lonxml::ssi_info=(); if ($target eq 'meta') { $Apache::lonxml::redirection = 0; $Apache::lonxml::metamode = 1; @@ -956,83 +859,105 @@ sub store_counter { } sub get_all_text { - my($tag,$pars)= @_; - &Apache::lonxml::debug("Got a ".ref($pars)); - my $gotfullstack=1; - if (ref($pars) ne 'ARRAY') { - $gotfullstack=0; - $pars=[$pars]; - } - my $depth=0; - my $token; - my $result=''; - if ( $tag =~ m:^/: ) { - my $tag=substr($tag,1); - #&Apache::lonxml::debug("have:$tag:"); - my $top_empty=0; - while (($depth >=0) && ($#$pars > -1) && (!$top_empty)) { - while (($depth >=0) && ($token = $$pars[-1]->get_token)) { - #&Apache::lonxml::debug("e token:$token->[0]:$depth:$token->[1]:".$#$pars.":".$#Apache::lonxml::pwd); - if (($token->[0] eq 'T')||($token->[0] eq 'C')||($token->[0] eq 'D')) { - $result.=$token->[1]; - } elsif ($token->[0] eq 'PI') { - $result.=$token->[2]; - } elsif ($token->[0] eq 'S') { - if ($token->[1] =~ /^$tag$/i) { $depth++; } - $result.=$token->[4]; - } elsif ($token->[0] eq 'E') { - if ( $token->[1] =~ /^$tag$/i) { $depth--; } - #skip sending back the last end tag - if ($depth > -1) { $result.=$token->[2]; } else { - $$pars[-1]->unget_token($token); - } - } - } - if (($depth >=0) && ($#$pars == 0) ) { $top_empty=1; } - if (($depth >=0) && ($#$pars > 0) ) { - pop(@$pars); - pop(@Apache::lonxml::pwd); - } - } - if ($top_empty && $depth >= 0) { - #never found the end tag ran out of text, throw error send back blank - &error('Never found end tag for <'.$tag.'>'); - if ($gotfullstack) { - my $newstring=''.$result; - &Apache::lonxml::newparser($pars,\$newstring); - } - $result=''; - } - } else { - while ($#$pars > -1) { - while ($token = $$pars[-1]->get_token) { - #&Apache::lonxml::debug("s token:$token->[0]:$depth:$token->[1]"); - if (($token->[0] eq 'T')||($token->[0] eq 'C')|| - ($token->[0] eq 'D')) { - $result.=$token->[1]; - } elsif ($token->[0] eq 'PI') { - $result.=$token->[2]; - } elsif ($token->[0] eq 'S') { - if ( $token->[1] =~ /^$tag$/i) { - $$pars[-1]->unget_token($token); last; - } else { - $result.=$token->[4]; - } - } elsif ($token->[0] eq 'E') { - $result.=$token->[2]; - } - } - if (($#$pars > 0) ) { - pop(@$pars); - pop(@Apache::lonxml::pwd); - } else { last; } - } - } - if ($result =~ m||) { - $Apache::lonxml::usestyle=1; - } - #&Apache::lonxml::debug("Exit:$result:"); - return $result + my($tag,$pars,$style)= @_; + &Apache::lonxml::debug("Got a ".ref($pars)); + my $gotfullstack=1; + if (ref($pars) ne 'ARRAY') { + $gotfullstack=0; + $pars=[$pars]; + } + &Apache::lonxml::debug("Got a ".ref($style)); + if (ref($style) ne 'HASH') { + $style={}; + } else { + &Apache::lonhomework::showhash(%$style); + } + my $depth=0; + my $token; + my $result=''; + if ( $tag =~ m:^/: ) { + my $tag=substr($tag,1); + #&Apache::lonxml::debug("have:$tag:"); + my $top_empty=0; + while (($depth >=0) && ($#$pars > -1) && (!$top_empty)) { + while (($depth >=0) && ($token = $$pars[-1]->get_token)) { + #&Apache::lonxml::debug("e token:$token->[0]:$depth:$token->[1]:".$#$pars.":".$#Apache::lonxml::pwd); + if (($token->[0] eq 'T')||($token->[0] eq 'C')||($token->[0] eq 'D')) { + $result.=$token->[1]; + } elsif ($token->[0] eq 'PI') { + $result.=$token->[2]; + } elsif ($token->[0] eq 'S') { + if ($token->[1] =~ /^$tag$/i) { $depth++; } + if ($token->[1] =~ /^LONCAPA_INTERNAL_TURN_STYLE_ON$/i) { $Apache::lonxml::usestyle=1; } + if ($token->[1] =~ /^LONCAPA_INTERNAL_TURN_STYLE_OFF$/i) { $Apache::lonxml::usestyle=0; } + $result.=$token->[4]; + } elsif ($token->[0] eq 'E') { + if ( $token->[1] =~ /^$tag$/i) { $depth--; } + #skip sending back the last end tag + if ($depth == 0 && exists($$style{'/'.$token->[1]})) { + my $string= + ''. + $$style{'/'.$token->[1]}. + $token->[2]. + ''; + &Apache::lonxml::newparser($pars,\$string); + #&Apache::lonxml::debug("reParsing $string"); + next; + } + if ($depth > -1) { + $result.=$token->[2]; + } else { + $$pars[-1]->unget_token($token); + } + } + } + if (($depth >=0) && ($#$pars == 0) ) { $top_empty=1; } + if (($depth >=0) && ($#$pars > 0) ) { + pop(@$pars); + pop(@Apache::lonxml::pwd); + } + } + if ($top_empty && $depth >= 0) { + #never found the end tag ran out of text, throw error send back blank + &error('Never found end tag for <'.$tag. + '> current string
'.
+		   &HTML::Entities::encode($result).
+		   '
'); + if ($gotfullstack) { + my $newstring=''.$result; + &Apache::lonxml::newparser($pars,\$newstring); + } + $result=''; + } + } else { + while ($#$pars > -1) { + while ($token = $$pars[-1]->get_token) { + #&Apache::lonxml::debug("s token:$token->[0]:$depth:$token->[1]"); + if (($token->[0] eq 'T')||($token->[0] eq 'C')|| + ($token->[0] eq 'D')) { + $result.=$token->[1]; + } elsif ($token->[0] eq 'PI') { + $result.=$token->[2]; + } elsif ($token->[0] eq 'S') { + if ( $token->[1] =~ /^$tag$/i) { + $$pars[-1]->unget_token($token); last; + } else { + $result.=$token->[4]; + } + if ($token->[1] =~ /^LONCAPA_INTERNAL_TURN_STYLE_ON$/i) { $Apache::lonxml::usestyle=1; } + if ($token->[1] =~ /^LONCAPA_INTERNAL_TURN_STYLE_OFF$/i) { $Apache::lonxml::usestyle=0; } + } elsif ($token->[0] eq 'E') { + $result.=$token->[2]; + } + } + if (($#$pars > 0) ) { + pop(@$pars); + pop(@Apache::lonxml::pwd); + } else { last; } + } + } + #&Apache::lonxml::debug("Exit:$result:"); + return $result } sub newparser { @@ -1054,7 +979,7 @@ sub parstring { my $val=$token->[2]->{$_}; $val =~ s/([\%\@\\\"\'])/\\$1/g; #if ($val =~ m/^[\%\@]/) { $val="\\".$val; } - $temp .= "my \$$_=\"$val\";" + $temp .= "my \$$_=\"$val\";"; } } return $temp; @@ -1077,19 +1002,6 @@ sub writeallows { &Apache::lonnet::appenv(%httpref); } -sub register_ssi { - my ($url,%form)=@_; - push (@Apache::lonxml::ssi_info,{'url'=>$url,'form'=>\%form}); - return ''; -} - -sub do_registered_ssi { - foreach my $info (@Apache::lonxml::ssi_info) { - my %form=%{ $info->{'form'}}; - my $url=$info->{'url'}; - &Apache::lonnet::ssi($url,%form); - } -} # # Afterburner handles anchors, highlights and links # @@ -1132,8 +1044,10 @@ sub storefile { if (my $fh=Apache::File->new('>'.$file)) { print $fh $contents; $fh->close(); + return 1; } else { - &warning("Unable to save file $file"); + &warning("Unable to save file $file"); + return 0; } } @@ -1155,16 +1069,35 @@ SIMPLECONTENT return $filecontents; } +sub createnewsty { + my $filecontents=(< + + + + + +SIMPLECONTENT + return $filecontents; +} + sub inserteditinfo { - my ($result,$filecontents)=@_; + my ($result,$filecontents,$filetype)=@_; $filecontents = &HTML::Entities::encode($filecontents); # my $editheader='Edit below
'; - my $xml_help = Apache::loncommon::helpLatexCheatsheet(); + my $xml_help = ''; + if ($filetype eq 'html') { + $xml_help=Apache::loncommon::helpLatexCheatsheet(); + } + my $cleanbut = ''; + if ($filetype eq 'html') { + $cleanbut=''; + } my $titledisplay=&display_title(); my $buttons=(< +$cleanbut BUTTONS @@ -1232,12 +1165,20 @@ sub handler { my $file=&Apache::lonnet::filelocation("",$request->uri); + my $filetype; + if ($file =~ /\.sty$/) { + $filetype='sty'; + } else { + $filetype='html'; + } # # Edit action? Save file. # unless ($ENV{'request.state'} eq 'published') { if (($ENV{'form.savethisfile'}) || ($ENV{'form.attemptclean'})) { - &storefile($file,$ENV{'form.filecont'}); + if (&storefile($file,$ENV{'form.filecont'})) { + $request->print("Updated: ". strftime("%d %b %H:%M:%S",localtime())." "); + } } } my %mystyle; @@ -1256,7 +1197,11 @@ sub handler { ENDNOTFOUND $filecontents=''; if ($ENV{'request.state'} ne 'published') { - $filecontents=&createnewhtml(); + if ($filetype eq 'sty') { + $filecontents=&createnewsty(); + } else { + $filecontents=&createnewhtml(); + } $ENV{'form.editmode'}='Edit'; #force edit mode } } else { @@ -1284,11 +1229,11 @@ ENDNOTFOUND $displayfile=~s/^\/[^\/]*//; $result='

'.$displayfile. '

'; - $result=&inserteditinfo($result,$filecontents); + $result=&inserteditinfo($result,$filecontents,$filetype); } } - - writeallows($request->uri); + if ($filetype eq 'html') { writeallows($request->uri); } + $request->print($result); @@ -1410,7 +1355,7 @@ sub register_insert { my $line = $data[$i]; if ( $line =~ /^\#/ || $line =~ /^\s*\n/) { next; } if ( $line =~ /TABLE/ ) { last; } - my ($tag,$descrip,$color,$function,$show) = split(/,/, $line); + my ($tag,$descrip,$color,$function,$show,$helpfile,$helpdesc) = split(/,/, $line); if ($tag) { $insertlist{"$tagnum.tag"} = $tag; $insertlist{"$tagnum.description"} = $descrip; @@ -1418,6 +1363,8 @@ sub register_insert { $insertlist{"$tagnum.function"} = $function; if (!defined($show)) { $show='yes'; } $insertlist{"$tagnum.show"}= $show; + $insertlist{"$tagnum.helpfile"} = $helpfile; + $insertlist{"$tagnum.helpdesc"} = $helpdesc; $insertlist{"$tag.num"}=$tagnum; $tagnum++; } @@ -1452,6 +1399,20 @@ sub description { return $insertlist{$tagnum.'.description'}; } +# Returns a list containing the help file, and the description +sub helpinfo { + my ($token)=@_; + my $tagnum; + my $tag=$token->[1]; + foreach my $namespace (reverse @Apache::lonxml::namespace) { + my $testtag=$namespace.'::'.$tag; + $tagnum=$insertlist{"$testtag.num"}; + if (defined($tagnum)) { last; } + } + if (!defined ($tagnum)) { $tagnum=$Apache::lonxml::insertlist{"$tag.num"}; } + return ($insertlist{$tagnum.'.helpfile'}, $insertlist{$tagnum.'.helpdesc'}); +} + # ----------------------------------------------------------------- whichuser # returns a list of $symb, $courseid, $domain, $name that is correct for # calls to lonnet functions for this setup.