Ars Longa, Vita Brevis

Mar 6, 2008

Сессии PHP и unserialize()

Рубрика: PHP
Tags: , , ,
Vladimir @ 06:23
RSS 2.0

Как прочитать данные из сохранённой сессии

Иногда случаются ситуации, когда сессии приходится хранить в базе данных и, что еще хуже, иногда приходится читать данные из сериализованной сессии.
Начнём с того, что сессии в PHP сохраняются не с помощью serialize(). Точнее, у сохранённой сессии несколько другой формат, так как PHP приходится хранить еще и имя переменной.

В общем виде это выглядит так:
name|value;name|value

Например:
a|i:1;b|i:2;
“транслируется” в

[-]
View Code PHP
    $_SESSION['a'] = 1;
    $_SESSION['b'] = 2;

И вот, иногда случается, что необходимо извлечь данные из сохранённой сессии. Соблазн использовать unserialize() достаточно велик, так как в этом случае не придётся изобретать велосипед заново и писать код, выполняющий ту же самую функцию.
На php.net (и других сайтах) я неоднократно встречал код, предназначенный для для разбора сессий. Но что удивительно, все авторы просто разбивают строку по символу ‘|’: слева — имя переменной, справа  — её сериализованное значение. Но что меня удивляет: никто из авторов не подумал, что строковые данные тоже могут содержать вертикальную черту! Да, вероятность этого, признаю, небольшая, но последствия могут быть не очень хорошими :-)

Года два назад я написал функцию, которая разбирает сессию. Хотя код не очень удачный (смесь автоматной модели с хардкодингом), сбоев еще не было.

[-]
View Code PHP
    function unserialize_session($s)
    {
        static $tt = array(
            /*                 0  1  2 */
            /*   |    */ array(3, 1, 1),
            /*   "    */ array(1, 0, 1),
            /*   \    */ array(0, 2, 1),
            /* (rest) */ array(0, 1, 1),
        );

        static $chars = '|"\\';
        $result = array();

        $len   = strlen($s);<br