unserialize () [función.unserialize]: Error en el desplazamiento


Estoy usando Hotaru CMS con el complemento de carga de imágenes, obtengo este error si intento adjuntar una imagen a un mensaje, de lo contrario no hay error.

El código infractor (el error apunta a la línea con**):

/**
     * Retrieve submission step data
     *
     * @param $key - empty when setting
     * @return bool
     */
    public function loadSubmitData($h, $key = '')
    {
        // delete everything in this table older than 30 minutes:
        $this->deleteTempData($h->db);

        if (!$key) { return false; }

        $cleanKey = preg_replace('/[^a-z0-9]+/','',$key);
        if (strcmp($key,$cleanKey) != 0) {
            return false;
        } else {
            $sql = "SELECT tempdata_value FROM " . TABLE_TEMPDATA . " WHERE tempdata_key = %s ORDER BY tempdata_updatedts DESC LIMIT 1";
            $submitted_data = $h->db->get_var($h->db->prepare($sql, $key));
            **if ($submitted_data) { return unserialize($submitted_data); } else { return false; }** 
        }
    }

Datos de la tabla, observe que el bit final tiene la información de la imagen, no soy un experto en PHP, así que me preguntaba qué podrían pensar ustedes/chicas?

Tempdata_value:

a:10:{s:16:"submit_editorial";b:0;s:15:"submit_orig_url";s:13:"www.bbc.co.uk";s:12:"submit_title";s:14:"No title found";s:14:"submit_content";s:12:"dnfsdkfjdfdf";s:15:"submit_category";i:2;s:11:"submit_tags";s:3:"bbc";s:9:"submit_id";b:0;s:16:"submit_subscribe";i:0;s:15:"submit_comments";s:4:"open";s:5:"image";s:19:"C:fakepath100.jpg";}

Editar: Creo que he encontrado el bit serializar...

/**
     * Save submission step data
     *
     * @return bool
     */
    public function saveSubmitData($h)
    {
        // delete everything in this table older than 30 minutes:
        $this->deleteTempData($h->db);

        $sid = preg_replace('/[^a-z0-9]+/i', '', session_id());
        $key = md5(microtime() . $sid . rand());
        $sql = "INSERT INTO " . TABLE_TEMPDATA . " (tempdata_key, tempdata_value, tempdata_updateby) VALUES (%s,%s, %d)";
        $h->db->query($h->db->prepare($sql, $key, serialize($h->vars['submitted_data']), $h->currentUser->id));
        return $key;
    }
Author: user576820, 2012-04-14

14 answers

unserialize() [function.unserialize]: Error at offset fue cuotas a invalid serialization data debido a la longitud no válida

Solución rápida

Lo que puede hacer es recalculating the length de los elementos en matriz serializada

Datos serializados actuales

$data = 'a:10:{s:16:"submit_editorial";b:0;s:15:"submit_orig_url";s:13:"www.bbc.co.uk";s:12:"submit_title";s:14:"No title found";s:14:"submit_content";s:12:"dnfsdkfjdfdf";s:15:"submit_category";i:2;s:11:"submit_tags";s:3:"bbc";s:9:"submit_id";b:0;s:16:"submit_subscribe";i:0;s:15:"submit_comments";s:4:"open";s:5:"image";s:19:"C:fakepath100.jpg";}';

Ejemplo sin nuevo cálculo

var_dump(unserialize($data));

Salida

Notice: unserialize() [function.unserialize]: Error at offset 337 of 338 bytes

Recalculando

$data = preg_replace('!s:(\d+):"(.*?)";!e', "'s:'.strlen('$2').':\"$2\";'", $data);
var_dump(unserialize($data));

Salida

array
  'submit_editorial' => boolean false
  'submit_orig_url' => string 'www.bbc.co.uk' (length=13)
  'submit_title' => string 'No title found' (length=14)
  'submit_content' => string 'dnfsdkfjdfdf' (length=12)
  'submit_category' => int 2
  'submit_tags' => string 'bbc' (length=3)
  'submit_id' => boolean false
  'submit_subscribe' => int 0
  'submit_comments' => string 'open' (length=4)
  'image' => string 'C:fakepath100.jpg' (length=17)

Recomendación .. I

En lugar de usar este tipo de solución rápida ... te aconsejo que actualices la pregunta con

  • Cómo serializa sus datos

  • Cómo lo estás guardando ..

================================ EDITAR 1 ===============================

El Error

El Error se generó debido al uso de comillas dobles " en lugar de comillas simples ' por eso C:\fakepath\100.png se convirtió a C:fakepath100.jpg

Para corregir el error

Es necesario cambiar $h->vars['submitted_data'] De (Tenga en cuenta el chamuscado bastante ')

Sustitúyase

 $h->vars['submitted_data']['image'] = "C:\fakepath\100.png" ;

Con

 $h->vars['submitted_data']['image'] = 'C:\fakepath\100.png' ;

Filtro Adicional

También puede agregar este filtro simple antes de llamar a serialize

function satitize(&$value, $key)
{
    $value = addslashes($value);
}

array_walk($h->vars['submitted_data'], "satitize");

Si tiene caracteres UTF, también puede ejecutar

 $h->vars['submitted_data'] = array_map("utf8_encode",$h->vars['submitted_data']);

Cómo detectar el problema en futuros datos serializados

  findSerializeError ( $data1 ) ;

Salida

Diffrence 9 != 7
    -> ORD number 57 != 55
    -> Line Number = 315
    -> Section Data1  = pen";s:5:"image";s:19:"C:fakepath100.jpg
    -> Section Data2  = pen";s:5:"image";s:17:"C:fakepath100.jpg
                                            ^------- The Error (Element Length)

findSerializeError Función

function findSerializeError($data1) {
    echo "<pre>";
    $data2 = preg_replace ( '!s:(\d+):"(.*?)";!e', "'s:'.strlen('$2').':\"$2\";'",$data1 );
    $max = (strlen ( $data1 ) > strlen ( $data2 )) ? strlen ( $data1 ) : strlen ( $data2 );

    echo $data1 . PHP_EOL;
    echo $data2 . PHP_EOL;

    for($i = 0; $i < $max; $i ++) {

        if (@$data1 {$i} !== @$data2 {$i}) {

            echo "Diffrence ", @$data1 {$i}, " != ", @$data2 {$i}, PHP_EOL;
            echo "\t-> ORD number ", ord ( @$data1 {$i} ), " != ", ord ( @$data2 {$i} ), PHP_EOL;
            echo "\t-> Line Number = $i" . PHP_EOL;

            $start = ($i - 20);
            $start = ($start < 0) ? 0 : $start;
            $length = 40;

            $point = $max - $i;
            if ($point < 20) {
                $rlength = 1;
                $rpoint = - $point;
            } else {
                $rpoint = $length - 20;
                $rlength = 1;
            }

            echo "\t-> Section Data1  = ", substr_replace ( substr ( $data1, $start, $length ), "<b style=\"color:green\">{$data1 {$i}}</b>", $rpoint, $rlength ), PHP_EOL;
            echo "\t-> Section Data2  = ", substr_replace ( substr ( $data2, $start, $length ), "<b style=\"color:red\">{$data2 {$i}}</b>", $rpoint, $rlength ), PHP_EOL;
        }

    }

}

A mejor manera de guardar en la base de datos

$toDatabse = base64_encode(serialize($data));  // Save to database
$fromDatabase = unserialize(base64_decode($data)); //Getting Save Format 
 189
Author: Baba,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-19 00:40:05

No tengo suficiente reputación para comentar, así que espero que esto sea visto por las personas que usan la respuesta "correcta" anterior:

Desde php 5.5 el modificador /e en preg_replace() ha sido obsoleto completamente y el preg_match anterior se producirá un error. La documentación de php recomienda usar preg_match_callback en su lugar.

Por favor, encuentre la siguiente solución como alternativa a la anterior propuesta preg_match.

$fixed_data = preg_replace_callback ( '!s:(\d+):"(.*?)";!', function($match) {      
    return ($match[1] == strlen($match[2])) ? $match[0] : 's:' . strlen($match[2]) . ':"' . $match[2] . '";';
},$bad_data );
 49
Author: r00tAcc3ss,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-27 19:05:02

Hay otra razón por la que unserialize() falló porque puso incorrectamente datos serializados en la base de datos ver Explicación Oficial aquí. Dado que serialize() devuelve datos binarios y a las variables php no les importan los métodos de codificación, por lo que ponerlos en TEXTO, VARCHAR() causará este error.

Solución: almacene los datos serializados en BLOB en su tabla.

 12
Author: Ge Rong,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-27 08:54:54

Solución rápida

Recalculando la longitud de los elementos en el array serializado - pero no use (preg_replace) está obsoleto - mejor use preg_replace_callback:

$data = preg_replace_callback('!s:(\d+):"(.*?)";!', function($m) { return 's:'.mb_strlen($m[2]).':"'.$m[2].'";'; }, $data);
 7
Author: adilbo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-13 09:46:01

Este error se debe a que su conjunto de caracteres es incorrecto.

Establecer charset después de abrir etiqueta:

header('Content-Type: text/html; charset=utf-8');

Y establecer charset utf8 en su base de datos :

mysql_query("SET NAMES 'utf8'");
 4
Author: Will,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-04-24 14:56:19

Función pública unserializeKeySkills (string string) {

    $output = array();
    $string = trim(preg_replace('/\s\s+/', ' ',$string));
    $string = preg_replace_callback('!s:(\d+):"(.*?)";!', function($m) { return 's:'.strlen($m[2]).':"'.$m[2].'";'; }, utf8_encode( trim(preg_replace('/\s\s+/', ' ',$string)) ));
    try {
        $output =  unserialize($string);
    } catch (\Exception $e) {
        \Log::error("unserialize Data : " .print_r($string,true));
    }
    return $output;
}
 4
Author: Pardeep Goyal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-28 09:09:19

Puede arreglar la cadena serializada rota usando la siguiente función, con el manejo del carácter multibyte.

function repairSerializeString($value)
{

    $regex = '/s:([0-9]+):"(.*?)"/';

    return preg_replace_callback(
        $regex, function($match) {
            return "s:".mb_strlen($match[2]).":\"".$match[2]."\""; 
        },
        $value
    );
}
 3
Author: Rajesh Meniya,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-23 12:23:14
$badData = 'a:2:{i:0;s:16:"as:45:"d";
Is \n";i:1;s:19:"as:45:"d";
Is \r\n";}';

No se puede arreglar una cadena de serialización rota usando las expresiones regulares propuestas:

$data = preg_replace('!s:(\d+):"(.*?)";!e', "'s:'.strlen('$2').':\"$2\";'", $badData);
var_dump(@unserialize($data)); // Output: bool(false)

// or

$data = preg_replace_callback(
    '/s:(\d+):"(.*?)";/',
    function($m){
        return 's:' . mb_strlen($m[2]) . ':"' . $m[2] . '";';
    },
    $badData
);
var_dump(@unserialize($data)); // Output: bool(false)

Puede arreglar la cadena serializada rota usando la siguiente expresión regular:

$data = preg_replace_callback(
    '/(?<=^|\{|;)s:(\d+):\"(.*?)\";(?=[asbdiO]\:\d|N;|\}|$)/s',
    function($m){
        return 's:' . mb_strlen($m[2]) . ':"' . $m[2] . '";';
    },
    $badData
);

var_dump(@unserialize($data));

Salida

array(2) {
  [0] =>
  string(17) "as:45:"d";
Is \n"
  [1] =>
  string(19) "as:45:"d";
Is \r\n"
}

O

array(2) {
  [0] =>
  string(16) "as:45:"d";
Is \n"
  [1] =>
  string(18) "as:45:"d";
Is \r\n"
}
 3
Author: Даниил Путилин,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-29 12:27:53

Los documentos oficiales dicen que debe devolver false y establecer E_NOTICE

Pero ya que tiene error, el informe de errores está configurado para ser activado por E_NOTICE

Aquí hay una solución que le permite detectar false devuelto por unserialize

$old_err=error_reporting(); 
error_reporting($old_err & ~E_NOTICE);
$object = unserialize($serialized_data);
error_reporting($old_err);

Es posible que desee considerar el uso base64 codificar / decodificar

$string=base64_encode(serialize($obj));
unserialize(base64_decode($string));
 2
Author: muayyad alsadi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-19 15:18:24

En mi caso, estaba almacenando datos serializados en el campo BLOB de la base de datos MySQL que aparentemente no era lo suficientemente grande como para contener todo el valor y truncarlo. Obviamente, tal cadena no podía ser sin serializada.
Una vez convertido ese campo a MEDIUMBLOB el problema se disipó. También puede ser necesario cambiar las opciones de la tabla ROW_FORMAT a DYNAMIC o COMPRESSED.

 1
Author: Adam Bubela,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-16 16:17:55

Después de haber probado algunas cosas en esta página sin éxito, eché un vistazo a la fuente de la página y remarcé que todas las comillas en la cadena serializada han sido reemplazadas por entidades html. Decodificar estas entidades ayuda a evitar mucho dolor de cabeza:

$myVar = html_entity_decode($myVar);
 1
Author: David,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-14 13:08:56

Tendrá que cambiar el tipo de intercalación a utf8_unicode_ci y el problema se solucionará.

 0
Author: Ankit Vishwakarma,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-16 13:54:06

Otra razón de este problema puede ser el tipo de columna de la tabla de sesiones "payload". Si tiene grandes datos en la sesión, una columna de texto no sería suficiente. Necesitarás MEDIUMTEXT o incluso LONGTEXT.

 0
Author: GarryOne,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-17 15:51:27

Me enfrenté al mismo problema al no serializar datos. Descubrió que si hay un",',:, or ; en cualquiera de los valores de la matriz, la serialización se corrompe. Tenía un: en mi matriz, así que lo quité y se arregló.

Espero que ayude a alguien.

 0
Author: Sajal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-09 19:02:22