phparraystrimhtml-entitiessanitize

Can't sanitize all array values in PHP (using trim/htmlentities)


I have created a PHP function that sanitizes all array values by using trim and htmlentities, except for those values whose keys are present in $ignore array.

function htmlentities_recursive( $input, $ignore ) {
    if( is_array( $input ) || is_object( $input ) ) {
        foreach ($input as $key => &$c) {
            if( !in_array( $key, $ignore ) ) {
                $c = htmlentities_recursive( $c, $ignore );
            }
        }
        return $input;
    }
    return htmlentities( trim( $input ) );
}

The function works fine for the most part except for the first values of the array. For example it works for all values of $movies array except for the first value "Rear Window&" (does not sanitize this value), and ignores all values with key 'director' as it should.

$movies = array(
    array(
      "title" => "Rear Window&",
      "director" => "Alfred Hitc<hcock&",
      "year" => 1954
    ),
    array(
      "title" => "                            Full >Metal Jacket",
      "director" => "Sta<nley Kubrick&",
      "year" => 1987
    ),
    array(
      "title" => "Mean Stree&ts",
      "director" => "Ma>rtin S<corsese",
      "year" => 1973
    )
);
$testIgnore = ['foo','director','two'];

print_r(htmlentities_recursive($movies, $testIgnore));

The result is-

    Array
(
    [0] => Array
        (
            [title] => Rear Window&
            [director] => Alfred Hitc<hcock&
            [year] => 1954
        )

    [1] => Array
        (
            [title] => Full &gt;Metal Jacket
            [director] => Sta<nley Kubrick&
            [year] => 1987
        )

    [2] => Array
        (
            [title] => Mean Stree&amp;ts
            [director] => Ma>rtin S<corsese
            [year] => 1973
        )

)

How can I make it to sanitize the first value as well ?


Solution

  • It's a strict comparison issue on the call to in_array.

    https://secure.php.net/manual/en/function.in-array.php

    function htmlentities_recursive( $input, $ignore ) {
        if( is_array( $input ) || is_object( $input ) ) {
            foreach ($input as $key => &$c) {
                if( !in_array( $key, $ignore, true ) ) {
                    $c = htmlentities_recursive( $c, $ignore );
                }
            }
            return $input;
        }
        return htmlentities( trim( $input ) );
    }
    

    The zero index on the outer array is causing the entire first inner array to be skipped. Apparently in_array(0, ['hello', 'world']) returns true, but in_array(1, ['hello', 'world']) returns false. Interestingly, in_array(0, []) is false.