web-dev-qa-db-fra.com

Vérifiez pour voir si une chaîne est sérialisée?

Quel est le meilleur moyen de déterminer si une chaîne est le résultat/sortie de la fonction serialize ()?

127
Dang

Je dirais, essayez de unserialize c'est ;-)

Citant le manuel:

Dans le cas où la chaîne transmise n'est pas non sérialisable, FALSE est renvoyé et E_NOTICE est émis.

Donc, vous devez vérifier si la valeur de retour est false ou non (avec === ou !==, pour ne pas avoir de problème avec 0 ou null ou tout ce qui est égal à false, je dirais) .

Méfiez-vous simplement de la remarque: vous voudrez peut-être/devrez utiliser le @ opérateur .

Par exemple :

$str = 'hjkl';
$data = @unserialize($str);
if ($data !== false) {
    echo "ok";
} else {
    echo "not ok";
}

Vous obtiendrez:

not ok


EDIT: Oh, et comme @Peter a dit (merci à lui!), Vous pourriez avoir des ennuis si vous essayez de ne pas sérialiser la représentation d’un booléen faux :-(

Donc, vérifier que votre chaîne sérialisée n’est pas égale à "b:0; "pourrait être utile aussi; quelque chose comme ça devrait faire l'affaire, je suppose:

$data = @unserialize($str);
if ($str === 'b:0;' || $data !== false) {
    echo "ok";
} else {
    echo "not ok";
}

tester ce cas particulier avant d'essayer de désérialiser serait une optimisation - mais probablement pas utile, si vous n'avez pas souvent une fausse valeur sérialisée.

182
Pascal MARTIN

Je n’ai pas écrit ce code, c’est de WordPress en fait. Je pensais l’inclure pour tous les intéressés, c’est peut-être exagéré, mais ça marche :)

<?php
function is_serialized( $data ) {
    // if it isn't a string, it isn't serialized
    if ( !is_string( $data ) )
        return false;
    $data = trim( $data );
    if ( 'N;' == $data )
        return true;
    if ( !preg_match( '/^([adObis]):/', $data, $badions ) )
        return false;
    switch ( $badions[1] ) {
        case 'a' :
        case 'O' :
        case 's' :
            if ( preg_match( "/^{$badions[1]}:[0-9]+:.*[;}]\$/s", $data ) )
                return true;
            break;
        case 'b' :
        case 'i' :
        case 'd' :
            if ( preg_match( "/^{$badions[1]}:[0-9.E-]+;\$/", $data ) )
                return true;
            break;
    }
    return false;
}
53
Brandon Wamboldt

Optimiser la réponse de Pascal MARTIN

/**
 * Check if a string is serialized
 * @param string $string
 */
public static function is_serial($string) {
    return (@unserialize($string) !== false);
}
17
SoN9ne

Si $ string est une valeur sérialisée false, c'est-à-dire $string = 'b:0;' _ La fonction de SoN9ne renvoie false, c'est faux

donc la fonction serait

/**
 * Check if a string is serialized
 * @param string $string
 */
function is_serial($string) {
    return ($string == 'b:0;' || @unserialize($string) !== false);
}
16
Hazem Noor

En dépit de l'excellente réponse de Pascal MARTIN, j'étais curieux de savoir si vous pouviez aborder cette question d'une autre manière. Je l'ai donc fait simplement comme un exercice mental.

<?php

ini_set( 'display_errors', 1 );
ini_set( 'track_errors', 1 );
error_reporting( E_ALL );

$valueToUnserialize = serialize( false );
//$valueToUnserialize = "a"; # uncomment this for another test

$unserialized = @unserialize( $valueToUnserialize );

if ( FALSE === $unserialized && isset( $php_errormsg ) && strpos( $php_errormsg, 'unserialize' ) !== FALSE )
{
  echo 'Value could not be unserialized<br>';
  echo $valueToUnserialize;
} else {
  echo 'Value was unserialized!<br>';
  var_dump( $unserialized );
}

Et cela fonctionne réellement. La seule mise en garde est que cela va probablement casser si vous avez un gestionnaire d'erreurs enregistré à cause de la façon dont $ php_errormsg fonctionne .

13
Peter Bailey
$data = @unserialize($str);
if($data !== false || $str === 'b:0;')
    echo 'ok';
else
    echo "not ok";

Traite correctement le cas de serialize(false). :)

10
chaos

Il y a WordPress: (le détail est ici)

    function is_serialized($data, $strict = true)
    {
        // if it isn't a string, it isn't serialized.
        if (!is_string($data)) {
            return false;
        }
        $data = trim($data);
        if ('N;' == $data) {
            return true;
        }
        if (strlen($data) < 4) {
            return false;
        }
        if (':' !== $data[1]) {
            return false;
        }
        if ($strict) {
            $lastc = substr($data, -1);
            if (';' !== $lastc && '}' !== $lastc) {
                return false;
            }
        } else {
            $semicolon = strpos($data, ';');
            $brace = strpos($data, '}');
            // Either ; or } must exist.
            if (false === $semicolon && false === $brace)
                return false;
            // But neither must be in the first X characters.
            if (false !== $semicolon && $semicolon < 3)
                return false;
            if (false !== $brace && $brace < 4)
                return false;
        }
        $token = $data[0];
        switch ($token) {
            case 's' :
                if ($strict) {
                    if ('"' !== substr($data, -2, 1)) {
                        return false;
                    }
                } elseif (false === strpos($data, '"')) {
                    return false;
                }
            // or else fall through
            case 'a' :
            case 'O' :
                return (bool)preg_match("/^{$token}:[0-9]+:/s", $data);
            case 'b' :
            case 'i' :
            case 'd' :
                $end = $strict ? '$' : '';
                return (bool)preg_match("/^{$token}:[0-9.E-]+;$end/", $data);
        }
        return false;
    }
3
ingenious

intégrer à une fonction

function isSerialized($value)
{
   return preg_match('^([adObis]:|N;)^', $value);
}
3
RossW
/**
 * some people will look down on this little puppy
 */
function isSerialized($s){
if(
    stristr($s, '{' ) != false &&
    stristr($s, '}' ) != false &&
    stristr($s, ';' ) != false &&
    stristr($s, ':' ) != false
    ){
    return true;
}else{
    return false;
}

}
2
Björn3

Cela fonctionne bien pour moi

<?php

function is_serialized($data){
    return (is_string($data) && preg_match("#^((N;)|((a|O|s):[0-9]+:.*[;}])|((b|i|d):[0-9.E-]+;))$#um", $data));
    }

?>
1