Skip to content

Commit

Permalink
adds configurable masking of array/object properties
Browse files Browse the repository at this point in the history
  • Loading branch information
thinkingmedia committed Oct 22, 2016
1 parent 752d0fe commit 24c74f9
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 3 deletions.
44 changes: 41 additions & 3 deletions src/Error/Debugger.php
Expand Up @@ -14,6 +14,7 @@
*/
namespace Cake\Error;

use Cake\Core\InstanceConfigTrait;
use Cake\Log\Log;
use Cake\Utility\Hash;
use Cake\Utility\Security;
Expand All @@ -32,6 +33,16 @@
*/
class Debugger
{
use InstanceConfigTrait;

/**
* Default configuration
*
* @var array
*/
protected $_defaultConfig = [
'mask' => []
];

/**
* A list of errors generated by the application.
Expand Down Expand Up @@ -152,7 +163,7 @@ public function __construct()
* Returns a reference to the Debugger singleton object instance.
*
* @param string|null $class Class name.
* @return object
* @return object|Debugger
*/
public static function getInstance($class = null)
{
Expand All @@ -169,6 +180,24 @@ public static function getInstance($class = null)
return $instance[0];
}

/**
* Read or write configuration options for the Debugger instance.
*
* @param string|array|null $key The key to get/set, or a complete array of configs.
* @param mixed|null $value The value to set.
* @param bool $merge Whether to recursively merge or overwrite existing config, defaults to true.
* @return mixed Config value being read, or the object itself on write operations.
* @throws \Cake\Core\Exception\Exception When trying to set a key that is invalid.
*/
public static function configInstance($key = null, $value = null, $merge = true)
{
if (is_array($key) || func_num_args() >= 2) {
return static::getInstance()->config($key, $value, $merge);
}

return static::getInstance()->config($key);
}

/**
* Recursively formats and outputs the contents of the supplied variable.
*
Expand Down Expand Up @@ -505,10 +534,13 @@ protected static function _array(array $var, $depth, $indent)
$vars = [];

if ($depth >= 0) {
$mask = (array)static::configInstance('mask');
foreach ($var as $key => $val) {
// Sniff for globals as !== explodes in < 5.4
if ($key === 'GLOBALS' && is_array($val) && isset($val['GLOBALS'])) {
$val = '[recursion]';
} elseif (array_key_exists($key, $mask)) {
$val = (string)$mask[$key];
} elseif ($val !== $var) {
$val = static::_export($val, $depth, $indent);
}
Expand Down Expand Up @@ -555,9 +587,10 @@ protected static function _object($var, $depth, $indent)
}

if ($depth > 0) {
$mask = (array)static::configInstance('mask');
$objectVars = get_object_vars($var);
foreach ($objectVars as $key => $value) {
$value = static::_export($value, $depth - 1, $indent);
$value = array_key_exists($key, $mask) ? $mask[$key] : static::_export($value, $depth - 1, $indent);
$props[] = "$key => " . $value;
}

Expand All @@ -575,7 +608,12 @@ protected static function _object($var, $depth, $indent)

$value = static::_export($property, $depth - 1, $indent);
$key = $reflectionProperty->name;
$props[] = sprintf('[%s] %s => %s', $visibility, $key, $value);
$props[] = sprintf(
'[%s] %s => %s',
$visibility,
$key,
array_key_exists($key, $mask) ? $mask[$key] : $value
);
}
}

Expand Down
32 changes: 32 additions & 0 deletions tests/TestCase/Error/DebuggerTest.php
Expand Up @@ -36,6 +36,11 @@ public function __debugInfo()
}
}

class SecurityThing
{
public $password = 'pass1234';
}

/**
* DebuggerTest class
*
Expand Down Expand Up @@ -561,4 +566,31 @@ public function testDebugInfo()
eos;
$this->assertEquals($expected, $result);
}

/**
* Tests the masking of an array key.
*
* @return void
*/
public function testMaskArray()
{
Debugger::configInstance('mask', ['password' => '[**********]']);
$result = Debugger::exportVar(['password' => 'pass1234']);
$expected = "['password'=>[**********]]";
$this->assertEquals($expected, preg_replace('/\s+/', '', $result));
}

/**
* Tests the masking of an array key.
*
* @return void
*/
public function testMaskObject()
{
Debugger::configInstance('mask', ['password' => '[**********]']);
$object = new SecurityThing();
$result = Debugger::exportVar($object);
$expected = "object(Cake\\Test\\TestCase\\Error\\SecurityThing){password=>[**********]}";
$this->assertEquals($expected, preg_replace('/\s+/', '', $result));
}
}

0 comments on commit 24c74f9

Please sign in to comment.