inkd
inkd

Reputation: 1509

Sanitize & desanitize multidimensional array

I have the following class I wrote:

class Sanitizer {

    public function sanitizeSingle ($string) {  
        if (get_magic_quotes_gpc()) {
            $string = stripslashes($string);
        }

        return trim(htmlspecialchars($string, ENT_QUOTES)); 
    }

    public function sanitize ($string) {
        if (is_array($string)) {
            foreach ($string as $k => $v) {
                $string[$k] = $this->sanitizeSingle($v);
            }
        }
        else {
            $string = $this->sanitizeSingle($string);
        }

        return $string;
    }

    public function desanitize ($string) {
        return trim(htmlspecialchars_decode($string, ENT_QUOTES));
    }

}

The problem is that while it works on strings and one-dimensional arrays, I get the following error with multidimensional arrays:

Warning: htmlspecialchars() expects parameter 1 to be string, array given in C:\wamp\www\classes\Sanitizer.php on line 10

How do I fix this? Any help would be greatly appreciated.

Upvotes: 1

Views: 1979

Answers (2)

mickmackusa
mickmackusa

Reputation: 47894

With some minor adjustments, you can leverage a native recursive function to sanitize scalar values at any level in your array.

array_walk_recursive($data, [$this, 'sanitizeSingle']);

Code: (Demo)

class Sanitizer {
    public function sanitizeSingle(&$string) {  
        if (function_exists("get_magic_quotes_gpc") && get_magic_quotes_gpc()) {
            $string = stripslashes($string);
        }
        $string = trim(htmlspecialchars($string, ENT_QUOTES)); 
    }

    public function sanitize($data) {
        if (is_array($data)) {
            array_walk_recursive($data, [$this, 'sanitizeSingle']);  // replace your loop with this line
        } else {
            $this->sanitizeSingle($data);
        }
        return $data;
    }
}

$array = ['one' => ['a ', ' b ', ' c'], 'two' => " <a href='test'>Test</a>"];
$string = ' another "test"';

$sanitizer = new Sanitizer();
var_export($sanitizer->sanitize($array));
echo "\n---\n";
var_export($sanitizer->sanitize($string));

Output:

array (
  'one' => 
  array (
    0 => 'a',
    1 => 'b',
    2 => 'c',
  ),
  'two' => '&lt;a href=&#039;test&#039;&gt;Test&lt;/a&gt;',
)
---
'another &quot;test&quot;'

sanitizeSingle() modifies the input string by reference so any adjustments are declared upon the variable and there is no return value.

sanitize() does not modify by reference; the modified data is returned.

Upvotes: 1

viral
viral

Reputation: 3743

Your code was not evaluating array in $v Modify your foreach block like this, this modification will sanitize any level of nested array,

 foreach ($string as $k => $v) {
        if(is_array($v))
        {
            $string[$k] = $this->sanitize($v);
        }
        else
        {
            $string[$k] = $this->sanitizeSingle($v);
        }
 }

Upvotes: 3

Related Questions