Skip to content

Commit

Permalink
HTML escape context variables.
Browse files Browse the repository at this point in the history
When creating HTML or js errors the context should be
escaped, as it is very possible that the context vars will contain
HTML.

Clean up some internals in Debugger::outputError().  There were
a few duplicate data structures, and $$ variables.

Fixes #2884
  • Loading branch information
markstory committed May 17, 2012
1 parent 0faaedf commit c6258fa
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 20 deletions.
9 changes: 5 additions & 4 deletions lib/Cake/Test/Case/Utility/DebuggerTest.php
Expand Up @@ -140,15 +140,16 @@ public function testOutput() {
'a' => array(
'href' => "javascript:void(0);",
'onclick' => "preg:/document\.getElementById\('cakeErr[a-z0-9]+\-trace'\)\.style\.display = " .
"\(document\.getElementById\('cakeErr[a-z0-9]+\-trace'\)\.style\.display == 'none'" .
" \? '' \: 'none'\);/"
"\(document\.getElementById\('cakeErr[a-z0-9]+\-trace'\)\.style\.display == 'none'" .
" \? '' \: 'none'\);/"
),
'b' => array(), 'Notice', '/b', ' (8)',
));

$this->assertRegExp('/Undefined variable:\s+buzz/', $result[1]);
$this->assertRegExp('/<a[^>]+>Code/', $result[1]);
$this->assertRegExp('/<a[^>]+>Context/', $result[2]);
$this->assertContains('$wrong = &#039;&#039;', $result[3], 'Context should be HTML escaped.');
}

/**
Expand All @@ -162,14 +163,14 @@ public function testChangeOutputFormats() {

Debugger::output('js', array(
'traceLine' => '{:reference} - <a href="txmt://open?url=file://{:file}' .
'&line={:line}">{:path}</a>, line {:line}'
'&line={:line}">{:path}</a>, line {:line}'
));
$result = Debugger::trace();
$this->assertRegExp('/' . preg_quote('txmt://open?url=file://', '/') . '(\/|[A-Z]:\\\\)' . '/', $result);

Debugger::output('xml', array(
'error' => '<error><code>{:code}</code><file>{:file}</file><line>{:line}</line>' .
'{:description}</error>',
'{:description}</error>',
'context' => "<context>{:context}</context>",
'trace' => "<stack>{:trace}</stack>",
));
Expand Down
33 changes: 17 additions & 16 deletions lib/Cake/Utility/Debugger.php
Expand Up @@ -63,11 +63,13 @@ class Debugger {
'trace' => '<pre class="stack-trace">{:trace}</pre>',
'code' => '',
'context' => '',
'links' => array()
'links' => array(),
'escapeContext' => true,
),
'html' => array(
'trace' => '<pre class="cake-error trace"><b>Trace</b> <p>{:trace}</p></pre>',
'context' => '<pre class="cake-error context"><b>Context</b> <p>{:context}</p></pre>'
'context' => '<pre class="cake-error context"><b>Context</b> <p>{:context}</p></pre>',
'escapeContext' => true,
),
'txt' => array(
'error' => "{:error}: {:code} :: {:description} on line {:line} of {:path}\n{:info}",
Expand Down Expand Up @@ -716,7 +718,7 @@ public function outputError($data) {
$info = '';

foreach ((array)$data['context'] as $var => $value) {
$context[] = "\${$var}\t=\t" . $this->exportVar($value, 1);
$context[] = "\${$var} = " . $this->exportVar($value, 1);
}

switch ($this->_outputFormat) {
Expand All @@ -731,30 +733,29 @@ public function outputError($data) {
$data['trace'] = $trace;
$data['id'] = 'cakeErr' . uniqid();
$tpl = array_merge($this->_templates['base'], $this->_templates[$this->_outputFormat]);
$insert = array('context' => join("\n", $context)) + $data;

$detect = array('context');

if (isset($tpl['links'])) {
foreach ($tpl['links'] as $key => $val) {
if (in_array($key, $detect) && empty($insert[$key])) {
continue;
}
$links[$key] = String::insert($val, $insert, $insertOpts);
$links[$key] = String::insert($val, $data, $insertOpts);
}
}

foreach (array('code', 'context', 'trace') as $key) {
if (empty($$key) || !isset($tpl[$key])) {
if (!empty($tpl['escapeContext'])) {
$context = h($context);
}

$infoData = compact('code', 'context', 'trace');
foreach ($infoData as $key => $value) {
if (empty($value) || !isset($tpl[$key])) {
continue;
}
if (is_array($$key)) {
$$key = join("\n", $$key);
if (is_array($value)) {
$value = join("\n", $value);
}
$info .= String::insert($tpl[$key], compact($key) + $insert, $insertOpts);
$info .= String::insert($tpl[$key], array($key => $value) + $data, $insertOpts);
}
$links = join(' ', $links);
unset($data['context']);

if (isset($tpl['callback']) && is_callable($tpl['callback'])) {
return call_user_func($tpl['callback'], $data, compact('links', 'info'));
}
Expand Down

0 comments on commit c6258fa

Please sign in to comment.