diff --git a/lib/PGcore.pm b/lib/PGcore.pm
index 93b9fbb025..dd67cda465 100644
--- a/lib/PGcore.pm
+++ b/lib/PGcore.pm
@@ -936,4 +936,4 @@ sub surePathToTmpFile {
}
-1;
\ No newline at end of file
+1;
diff --git a/lib/Parser/Context/Constants.pm b/lib/Parser/Context/Constants.pm
index 2fcd96ba0c..344bfea00e 100644
--- a/lib/Parser/Context/Constants.pm
+++ b/lib/Parser/Context/Constants.pm
@@ -11,7 +11,7 @@ sub init {
$self->{dataName} = 'constants';
$self->{name} = 'constant';
$self->{Name} = 'Constant';
- $self->{namePattern} = qr/[a-zA-Z][a-zA-Z0-9]*|_blank_/;
+ $self->{namePattern} = qr/[a-zA-Z][a-zA-Z0-9]*|_blank_|_0/;
$self->{tokenType} = 'const';
}
diff --git a/lib/Parser/Context/Default.pm b/lib/Parser/Context/Default.pm
index 775f20483e..694609d569 100644
--- a/lib/Parser/Context/Default.pm
+++ b/lib/Parser/Context/Default.pm
@@ -133,10 +133,11 @@ $lists = {
$constants = {
'e' => exp(1),
- 'pi' => 4*atan2(1,1),
- 'i' => Value::Complex->new(0,1),
- 'j' => Value::Vector->new(0,1,0)->with(ijk=>1),
- 'k' => Value::Vector->new(0,0,1)->with(ijk=>1),
+ 'pi' => {value => 4*atan2(1,1), TeX => '\pi ', perl => "pi"},
+ 'i' => {value => Value::Complex->new(0,1), isConstant => 1, string => "i", perl => "i"},
+ 'j' => {value => Value::Vector->new(0,1,0)->with(ijk=>1), TeX => '\boldsymbol{j}', string => "j", perl => "j"},
+ 'k' => {value => Value::Vector->new(0,0,1)->with(ijk=>1), TeX => '\boldsymbol{k}', string => "k", perl => "k"},
+ '_0' => {value => Value::Vector->new(0,0,0), hidden => 1, TeX => '\boldsymbol{0}', string => "0"},
'_blank_' => {value => 0, hidden => 1, string => "", TeX => ""},
};
@@ -264,13 +265,6 @@ $context = $context{Full} = new Parser::Context(
reduction => $Parser::reduce,
);
-$context->constants->set(
- pi => {TeX => '\pi ', perl => 'pi'},
- i => {isConstant => 1, perl => 'i'},
- j => {TeX => '\boldsymbol{j}', perl => 'j'},
- k => {TeX => '\boldsymbol{k}', perl => 'k'},
-);
-
$context->usePrecedence('Standard');
$context->{name} = "Full";
@@ -296,18 +290,16 @@ $context->{name} = "Numeric";
$context = $context{Vector} = $context{Full}->copy;
$context->variables->are(x=>'Real',y=>'Real',z=>'Real');
$context->functions->undefine('arg','mod','Re','Im','conj');
-$context->constants->replace(i=>Value::Vector->new(1,0,0)->with(ijk=>1));
-$context->constants->set(i=>{TeX=>'\boldsymbol{i}', perl=>'i'});
+$context->constants->set(
+ i => {value => Value::Vector->new(1,0,0)->with(ijk=>1), TeX => '\boldsymbol{i}'},
+);
$context->parens->set('(' => {formMatrix => 0});
$context = $context{Vector2D} = $context{Vector}->copy;
-$context->constants->replace(
- i => Value::Vector->new(1,0)->with(ijk=>1),
- j => Value::Vector->new(0,1)->with(ijk=>1),
-);
$context->constants->set(
- i => {TeX=>'\boldsymbol{i}', perl=>'i'},
- j => {TeX=>'\boldsymbol{j}', perl=>'j'}
+ i => {value => Value::Vector->new(1,0)->with(ijk=>1)},
+ j => {value => Value::Vector->new(0,1)->with(ijk=>1)},
+ '_0' => {value => Value::Vector->new(0,0)},
);
$context->constants->remove("k");
$context->{name} = "Vector2D";
@@ -318,7 +310,7 @@ $context->{name} = "Vector2D";
$context = $context{Point} = $context{Vector}->copy;
$context->operators->undefine("><",".");
$context->functions->undefine('norm','unit');
-$context->constants->remove('i','j','k');
+$context->constants->remove('i','j','k','_0');
$context->parens->remove("<");
$context->{name} = "Point";
diff --git a/lib/Parser/List/Vector.pm b/lib/Parser/List/Vector.pm
index e76c40c7ee..23d2a96cb5 100644
--- a/lib/Parser/List/Vector.pm
+++ b/lib/Parser/List/Vector.pm
@@ -24,40 +24,42 @@ sub _check {
}
}
-my $ijk_string = ['i','j','k','0'];
-my $ijk_TeX = ['\boldsymbol{i}','\boldsymbol{j}','\boldsymbol{k}','\boldsymbol(0)'];
-
sub ijk {
- my $self = shift;
- my $method = shift || 'TeX'; my $ijk = shift || $ijk_TeX;
+ my $self = shift; my $method = shift || 'string';
my @coords = @{$self->{coords}};
$self->Error("Method 'ijk' can only be used on vectors in three-space")
unless (scalar(@coords) <= 3);
+ my @ijk = (); my $constants = $self->context->{constants};
+ foreach my $x ('i','j','k','_0') {
+ my $v = (split(//,$x))[-1];
+ push(@ijk,($constants->{$x}||{string=>$v,TeX=>"\\boldsymbol{$v}"})->{$method});
+ }
my $prec = $self->{equation}{context}->operators->get('*')->{precedence};
my $string = ''; my $n; my $term;
foreach $n (0..scalar(@coords)-1) {
$term = $coords[$n]->$method($prec);
if ($term ne '0') {
+ $term =~ s/\((-(\d+(\.\d*)?|\.\d+))\)/\1/;
$term = '' if $term eq '1'; $term = '-' if $term eq '-1';
$term = '+' . $term unless $string eq '' or $term =~ m/^-/;
- $string .= $term . $ijk->[$n];
+ $string .= $term . $ijk[$n];
}
}
- $string = $ijk->[3] if $string eq '';
+ $string = $ijk[3] if $string eq '';
return $string;
}
sub TeX {
my $self = shift;
- if ($self->{ijk} || $self->{equation}{ijk} || $self->{equation}{context}->flag("ijk"))
- {return $self->ijk}
+ return $self->ijk("TeX")
+ if $self->{ijk} || $self->{equation}{ijk} || $self->{equation}{context}->flag("ijk");
return $self->SUPER::TeX;
}
sub string {
my $self = shift;
- if ($self->{ijk} || $self->{equation}{ijk} || $self->{equation}{context}->flag("ijk"))
- {return $self->ijk('string',$ijk_string)}
+ return $self->ijk("string")
+ if $self->{ijk} || $self->{equation}{ijk} || $self->{equation}{context}->flag("ijk");
return $self->SUPER::string;
}
diff --git a/lib/Parser/Value.pm b/lib/Parser/Value.pm
index e1a391074e..dc7efb4a80 100644
--- a/lib/Parser/Value.pm
+++ b/lib/Parser/Value.pm
@@ -33,6 +33,7 @@ sub new {
$type = $context->Package($type), $value = $type->new($context,@{$value}) unless $type eq 'value';
$type = $value->typeRef;
+ $value->inContext($context); # force context to be the equation's context
my $c = bless {
value => $value, type => $type, isConstant => 1,
ref => $ref, equation => $equation,
diff --git a/lib/Value/Vector.pm b/lib/Value/Vector.pm
index 40b4000a6b..1d4d97add7 100644
--- a/lib/Value/Vector.pm
+++ b/lib/Value/Vector.pm
@@ -236,15 +236,6 @@ sub areParallel {(shift)->isParallel(@_)}
# Generate the various output formats
#
-my $ijk_string = ['i','j','k','0'];
-my $ijk_TeX = ['\boldsymbol{i}','\boldsymbol{j}','\boldsymbol{k}','\boldsymbol{0}'];
-
-sub string {
- my $self = shift; my $equation = shift;
- return $self->ijk($ijk_string) if $self->getFlag("ijk") && !$self->{ColumnVector};
- return $self->SUPER::string($equation,@_);
-}
-
sub pdot {
my $self = shift;
my $string = $self->string;
@@ -253,6 +244,12 @@ sub pdot {
return $string;
}
+sub string {
+ my $self = shift; my $equation = shift;
+ return $self->ijk("string") if $self->getFlag("ijk") && !$self->{ColumnVector};
+ return $self->SUPER::string($equation,@_);
+}
+
sub TeX {
my $self = shift; my $equation = shift;
if ($self->{ColumnVector}) {
@@ -270,21 +267,20 @@ sub TeX {
}
return $open.'\begin{array}{c}'.join('\\\\',@coords).'\\\\\end{array}'.$close;
}
- return $self->ijk if $self->getFlag("ijk");
+ return $self->ijk("TeX") if $self->getFlag("ijk");
return $self->SUPER::TeX($equation,@_);
}
sub ijk {
- my $self = shift; my $ijk = shift;
- if (!$ijk) {
- my $context = $self->context;
- $ijk = []; $ijk->[3] = $ijk_TeX->[3];
- foreach my $i (0,1,2)
- {$ijk->[$i] = $context->{constants}{$ijk_string->[$i]}{TeX} || $ijk_TeX->[$i]}
- }
+ my $self = shift; my $type = shift || "string";
my @coords = @{$self->data};
Value::Error("Method 'ijk' can only be used on Vectors in 3-space")
unless (scalar(@coords) <= 3);
+ my @ijk = (); my $constants = $self->context->{constants};
+ foreach my $x ('i','j','k','_0') {
+ my $v = (split(//,$x))[-1];
+ push(@ijk,($constants->{$x}||{string=>$v,TeX=>"\\boldsymbol{$v}"})->{$type});
+ }
my $string = ''; my $n; my $term;
foreach $n (0..scalar(@coords)-1) {
$term = $coords[$n]; $term = (Value::isValue($term))? $term->string : "$term";
@@ -292,10 +288,10 @@ sub ijk {
$term = '' if $term eq '1'; $term = '-' if $term eq '-1';
$term = '('.$term.')' if $term =~ m/e/i;
$term = '+' . $term unless $string eq '' or $term =~ m/^-/;
- $string .= $term . $ijk->[$n];
+ $string .= $term . $ijk[$n];
}
}
- $string = $ijk->[3] if $string eq '';
+ $string = $ijk[3] if $string eq '';
return $string;
}
diff --git a/macros/PGbasicmacros.pl b/macros/PGbasicmacros.pl
index cf4b40e11b..df27b776c2 100644
--- a/macros/PGbasicmacros.pl
+++ b/macros/PGbasicmacros.pl
@@ -29,7 +29,10 @@ =head1 DESCRIPTION
=cut
-# this is equivalent to use strict, but can be used within the Safe compartment.
+sub _PGbasicmacros_init { }
+
+# this is equivalent to use strict, but can be used within the Safe compartmen
+
BEGIN{
be_strict;
}
@@ -353,6 +356,9 @@ sub NAMED_ANS_RULE {
# end of addition for dragmath
+ # try to escape HTML entities to deal with xss stuff
+ $answer_value = HTML::Entities::encode_entities($answer_value);
+
MODES(
TeX => "\\mbox{\\parbox[t]{${tcol}ex}{\\hrulefill}}",
Latex2HTML => qq!\\begin{rawhtml}\\end{rawhtml}!,
@@ -443,6 +449,8 @@ sub ANS_RULE { #deprecated
$name = RECORD_ANS_NAME($name, $answer_value);
$answer_value =~ tr/\\$@`//d; #`## make sure student answers can not be interpolated by e.g. EV3
#INSERT_RESPONSE($name,$name,$answer_value); # no longer needed?
+ # try to escape HTML entities to deal with xss stuff
+ $answer_value = HTML::Entities::encode_entities($answer_value);
my $out = MODES(
TeX => qq!\\vskip $height in \\hrulefill\\quad !,
Latex2HTML => qq!\\begin{rawhtml}