Forum Moderators: coopster

Message Too Old, No Replies

session set save handler is using some wacky kind of serialization

         

httpwebwitch

8:56 pm on Feb 25, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I'm using session_set_save_handler [ca2.php.net] to reroute session handling into my mysql db.

It's working. Now, when I write something into $_SESSION, it shows up in my database.

here's a sample of my session data, as output by print_r($_SESSION):

Array ( [var1] => value1 [var2] => value2 ) 

But this is weird: PHP is using a strange kind of serialization when it constructs the session string. I'm not doing anything fancy - the "write" portion of session_set_save_handler [ca2.php.net] takes two arguments, $sessID and $sessData. The string below is what PHP is giving me as the $sessData.

here's what it writes in my database:

var1¦s:6:"value1";var2¦s:6:"value2";

I can see the syntax clearly enough... semicolons, pipes, colons, yadda yadda. it looks *almost* like serialization. But not quite. When I run this string through unserialize(), I get FALSE and an E_NOTICE warning.

Firstly I'm a little confused why PHP5 would use an unorthodox serialization syntax. That's just weird. But then I wanna know, 1) is this some alternative flavour of serialization that I should be familiar with, and 2) is there a built-in parser for this?

httpwebwitch

9:45 pm on Feb 25, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



this does a quick job of it

[pre]function deserializesession($str){
$outsess = array();
$items = explode(";",$str);
foreach($items as $item){
$parts = explode("¦",$item);
$name = $parts[0];
$valueparts = $parts[1];
$valuesplit = explode(":",$valueparts);
$value = substr($valuesplit[2],1,-1);
$outsess[$name] = $value;
}
return $outsess;
}[/pre]

coopster

10:38 pm on Feb 25, 2009 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



Note: The "write" handler is not executed until after the output stream is closed. Thus, output from debugging statements in the "write" handler will never be seen in the browser. If debugging output is necessary, it is suggested that the debug output be written to a file instead.

I would dump the $sessData variable right before the script ends or objects are destroyed to see what value is contained in that variable. It looks to me like it is being serialized before written to the database. Also, does the session data contain any object properties?

httpwebwitch

4:27 pm on Feb 26, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I get $sessData dumped directly into my database by the "write" handler. it looks just like I quoted above

var1¦s:6:"value1";var2¦s:6:"value2";

except note that the pipe characters are actually vertical bars ¦ ¦ ¦ ¦ ¦. WebmasterWorld changes those

It appears that since PHP 4.x or somewhere, the seralization of data that takes place for sessions changed. It used to export human readable text much like serialize() does, however it appears that now the session data is further encoded - quite possibly to hinder session data tampering on the local filesystem. Just mentioning this if you used to view session data to see what was being saved.
source [ca2.php.net]

I've solved the problem in my app... IMHO it's weird that I can't use deserialize() on the session data, I had to roll my own function to do it.

coopster

4:51 pm on Feb 26, 2009 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



I get $sessData dumped directly into my database by the "write" handler. it looks just like I quoted above

var1¦s:6:"value1";var2¦s:6:"value2";

Understood, but that is not session data, that is session data after it has been serialized (at what ever point in the process). What I am asking is if you can determine the format of the session data right before the data is written. This means you need to dump it out right before the "write" handler as that does not occur until after the output stream is closed.

I guess what I'm asking you to discover is at what point the data appears formatted differently.

httpwebwitch

5:17 pm on Feb 26, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



oooooh, ok i understand what you're asking now

I'll do some experiments tonight if I get a chance. I'm not sure where else I'll be able to hook into the session handlers (yet)

coopster

6:17 pm on Feb 26, 2009 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



LOL!
After reading through this from the beginning again ... there is nothing wrong here. Are you trying to bypass your custom session handler when reading the session back from the database table? If so, then you should be using session_decode [php.net].

httpwebwitch

7:39 pm on Feb 26, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



aw, coop you had me excited there for a minute.

I am bypassing the session handler, and reading the serialized session string straight out of the database. It's unorthodox, but I have one situation where I need to go straight in and grab it, without actually "starting" a session or using $_SESSION.

here's another sample string

var1¦s:9:"727738279";anothervar¦N;userid¦s:1:"1";

from the description in the PHP manual, session_decode() sounds like the solution.
but it doesn't work! it returns FALSE... ugh

coopster

7:51 pm on Feb 26, 2009 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



TRUE on success, FALSE on failure.

session_decode() decodes the session data in data, setting variables stored in the session.

My emphasis added

Looks like it is going to try to populate variables in your $_SESSION and I'm guessing the function is failing because you are not starting a session.

coopster

7:53 pm on Feb 26, 2009 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



Yep, bingo. A user-contributed comment on that manual page ...

Seems like there was a change in the behavior of this function somewhere between 4.1.2 and 4.3.3. In 4.1.2 session_decode() didn't care whether the session was started, and would just decode the string into the _SESSION array. In my 4.3.3 install, session_decode() wouldn't work unless I explicitly started the session with session_start().