Parse PHP Session in Javascript - php

I have recently gone into extending my site using node.js and have come to realisation I need a session handler for my PHP sessions. Now everything was cool and dandy and node.js reads the php sessions and can propogate it's own session with the php ones. I am using database sessions so the session data gets saved into a field in the database.
I have however found a slight problem. I am attempting to read the session data into node.js and it's really quite a strange string. I have been able to get the strucutre of each session variable down to:
'field_name'|'type':'length':'value';
Now on certain strings the value field can be missing on other strings the length can be missing (when a variable is Null). The type can also be more than b, s, i; it can also be N (NULL).
I had originally thought up of a huge translator for JS but this just somehow seems a very wrong way to do it.
Has anyone here tried to extract php session variables in JS before and is there any kind of script that could help? Maybe there is a formatting thing I can use on PHP side to make my life a lot easier in node.js?
Edit: the Schema looks like:
{ _id: { id: 'L:\u00c1\u009d\u008e\u00ad\u000e}<\u0002\u0000\u0000' }
, session_id: 'a2clfnjhopv1srs5k5elgbfjv5'
, user_id: 0
, session_data: 'logged|b:0;uid|i:0;server_key|N;AUTH_TIER2|b:0;email|s:0:"";cheese|s:6:"cheese";'
, active: 1
, expires: 1278920567
}
This is the mongo db record for a user session. The field needing to be translated is session_data. There is some kind of formatting error when pasting it in since stackoverflow wont format that as code when I try and make it for some reason.
I tried to JSONfy the field before but it lost it's types and didn't read Null entries etc so I stopped that
Thanks,

I'm relatively sure PHP uses the serialize and unserialize functions to handle session data.
There is a JavaScript implementation of unserialize in PHP.JS, you can find it here: http://phpjs.org/functions/unserialize

Here is a session_decode function based on the unserialize function of phpjs:
https://github.com/vianneyb/phpjs/blob/master/functions/var/session_decode.js
works for me!

Just to reply with the way I've found: force PHP to use JSON instead :
Use the class below, with session_set_save_handler to store data as JSON and let PHP still using his own system.
Link this class using this function at the beginning of each script you use session :
http://php.net/manual/ru/function.session-set-save-handler.php
PS : here the class use memcache to store JSON resulting object, on Node.JS, use a memcache object, and retrieve like this :
get the PHPSESSID from cookies
use that characters string to bring a key from memcached with "sessions/id" where id is the key and session just the string (see class below).
Now you should have only JSON in memcache, so it's becoming a simple game with Node.JS to work with.
PS : of course you can work with/improve this, you can also use this not only with memcache (a db for example)
<?php
/**
* This class is used to store session data with memcache, it store in json the session to be used more easily in Node.JS
*/
class memcacheSessionHandler{
private static $lifetime = 0;
private static $memcache = null;
public function __construct(){
self::$memcache = new Memcache();
self::$memcache->addServer('localhost', 11211);
}
public function __destruct(){
session_write_close();
self::$memcache->close();
self::$memcache = null;
}
public static function open(){
self::$lifetime = ini_get('session.gc_maxlifetime');
return true;
}
public static function read($id){
$tmp = $_SESSION;
$_SESSION = json_decode(self::$memcache->get("sessions/{$id}"), true);
$new_data = session_encode();
$_SESSION = $tmp;
return $new_data;
}
public static function write($id, $data){
$tmp = $_SESSION;
session_decode($data);
$new_data = $_SESSION;
$_SESSION = $tmp;
return self::$memcache->set("sessions/{$id}", json_encode($new_data), 0, self::$lifetime);
}
public static function destroy($id){
return self::$memcache->delete("sessions/{$id}");
}
public static function gc(){
return true;
}
public static function close(){
return true;
}
}
?>

I had the same problem. I needed to integrate php with node.js. I used js-php-unserialize to do this. The use is pretty straightforward.
var PHPUnserialize = require('php-unserialize');
console.log(PHPUnserialize.unserializeSession(yourData));
For example if you
var yourData = 'A|s:1:"B";userID|s:24:"53d620475e746b37648b4567";';
you will get this result:
{
A: 'B',
userID: '53d620475e746b37648b4567'
}

Related

PHP- One php page will receive GET data in 4 second interval and another page will display the updated data by refreshing itself

The question is one page will receive the GET data in 4 second interval and i have to display the parameter value in another page with updated value.It is just for display and no need to store the value.
I have tried it with the following code:datareceiver.php
<?php
require 'localStore.php';
if(isset($_REQUEST['name'])){
localStore::setData($_REQUEST['name']);
}
?>
localStore.php
<?php
class localStore{
private static $dataVal = "";
public static function setData($data){
self::$dataVal = $data;
}
public static function getData(){
return self::$dataVal;
}
}
?>
display.php
<?php
require 'localStore.php';
header("Refresh:2");
echo localStore::getData();
?>
How i can show the data in 'display.php' page, because the above 'display.php' prints blank on the page. I tried also the global keyword concept and the PHP magic _construct(), _get() and _set() by searching in google and going through stackoverflow. but it was difficult to understand since i am not a PHP guy. t was terrible for me to use these _get(),_set() and _construct().
PHP doesn't work like this. You have to store your data somewhere anyway. Script2 knows nothing about data recieved by script1. When you construct your localStore object it doesn't have access to properties of another object constructed by another execution, cause your datareciever object was destructed immediately after script end. You can check it usind __destruct() method
So, you need some storage to keep recieved by script1 data until script2 wants to display it. Most commonly used ways are: mysql DB, file and queue, say Rabbit.
The simpliest solution is
const FILE_NAME = 'tmp/anyname';
public static function setData($data){
return file_put_contents(self::FILE_NAME, serialize($data));
}
public static function getData(){
$str = file_get_contents(self::FILE_NAME);
return unserialize($str);
}

Fill PHP Sessions with default data

I'm currently building a little website from scratch. I use a custom SessionHandler to store my sessions in the database which seems to work fine. So as soon as the user logs in I can store the relevant information (for example language) in the session data.
However I would also like to store certain data for users that are not logged in (yet) - again mainly the selected language but also some other stuff. To keep things clean I'd like to set all these standard values in one place, as soon as there is a session without a valid login.
The best place should obviously be my handler, however I'm not sure which function to use and how to get my data in there. I've attached the important parts of the code below.
I'm sure there is a simple solution for it, but so far I haven't gotten there. And it's also a terrible problem to google for ..
Thanks for the help!
public function __construct() {
$this->databaseController = new DatabaseController();
ini_set('session.gc_maxlifetime', SESSION_MAX_LIFETIME);
ini_set('session.gc_probability', 1);
ini_set('session.gc_divisor', 100);
session_set_save_handler(
array($this, "_open"),
array($this, "_close"),
array($this, "_read"),
array($this, "_write"),
array($this, "_destroy"),
array($this, "_gc")
);
}
public function _open() {
return $this->databaseController->check();
}
public function _close() {
return $this->databaseController->close();
}
public function _read($id) {
$result = $this->databaseController->getFirstRow("SELECT sessionData FROM bf1_sessions WHERE sessionID = '".mysql_real_escape_string($id)."'");
if (!empty($result['sessionData'])) {
return $result['sessionData'];
}
else {
return '';
}
}
public function _write($id, $data) {
$access = time();
$result = $this->databaseController->executeQuery("REPLACE INTO bf1_sessions (sessionID, sessionAccess, sessionData) VALUES ('".mysql_real_escape_string($id)."', '".intval($access)."', '".mysql_real_escape_string($data)."')");
return $result;
}
Since I've never really used custom session handlers, I had to read the documentation a bit. This will be more psuedo-code, but it should get you in the right direction. Anytime you start a session, it will first call open() and then read(string $sessionId). You are currently selecting session data from the database and returning the serialized data or a blank string (as you should). Instead of returning the blank string, you should just be able to return a serialized string of your default data.
public function _read($id) {
$result = $this->databaseController->getFirstRow("SELECT sessionData FROM bf1_sessions WHERE sessionID = '".mysql_real_escape_string($id)."'");
if (!empty($result['sessionData'])) {
return $result['sessionData'];
}
else {
return serialize(array(
'foo' => 'bar',
'test' => 123
));
}
}
Please note the above may not work exactly as expected. I am assuming that the serialized data is meant to be a simple array of key/value pairs like in my above example. Also, serialize() may not do exactly what you expect it too due to the following notice on the session_set_save_handler() documentation:
While the data looks similar to serialize() please note it is a different format which is speficied in the session.serialize_handler ini setting.
A final thought: you shouldn't actually need to write this default data to the database, since every time you save/close the session write($sessionId, $data) is called with all of the data (instead of just the changes). So you should be fine to just return default data on read() and save everything anytime write() is called. I'm just mentioning this, because there is a chance something weird happens and you may need to actually INSERT INTO the default data before returning it in your read() function. Please comment if you any problems implementing this.
Links:
session_set_save_handler()
serialize()
session.serialize_handler

Object to Cookie in PHP

I am starting my studies in PHP and I'm having problems with an application:
I need to put information of an object in PHP for a cookie and then receive a cookie to object again on another page.
anyone has any solution to this problem?
The information I want to store in cookie is just some information preferably Customer as background color, size of windows.
<?php
class Client {
private $id;
private $pSize;
private $color;
function __construct($id) {
$this->id = $id;
}
public function getPSize() {
return $this->pSize;
}
public function setPSize($pSize) {
$this->pSize = $pSize;
}
public function getColor() {
return $this->color;
}
public function setColor($color) {
$this->color = $color;
}
}
?>
In a page index.php i have:
<?php
include_once 'Client.class.php';
//Test Preference Client
$client = new Client(1);
$client->setColor("#000000");
$client->setPSize(200);
//using Serialize to put to Cookie
$StringClient = serialize($client);
//Store to Cookie
$_COOKIE['PreferenceClient'] = $StringClient;
?>
In a another page i get the inrofmation:
if(isset($_COOKIE['PreferenceClient'])){
// Unsing Unserialize to Object
$objClient = unserialize($_COOKIE['PreferenceClient']);
//Test data:
echo $objClient->getColor();
//Continue with Performing changes to the client if the information exists...
}
I solved the problem. Thanks to everyone who helped.
before i had tried only get the cookie information without serialize
Guys, this is my first post, I apologize if I did something wrong.
I have to make something up for you?
You could store objects in string (like cookie does) via serialize, unserialize.
setcookie ($name, serialize($object)); // set object
$object = unserialize($_COOKIE[$name]); // get object
But remember that using this approach could be dangerous. PHP Object Injection
You could use json instead of serialization to store stdClass, it would be safe enough.
setcookie ($name, json_encode($object)); // set object stdClass
$object = json_decode($_COOKIE[$name]); // get object stdClass
But it's prefer to use session to store your data. You could even store object without calling serialize, unserialize. But __sleep, __wakeup magic still works.
setcookie, $_COOKIE, serialize, magic with serialization.
The answer is: You don't.
Whenever you take data from the client and use it in your code,
you have to implement security that prevents the case when the user changes his client data and injects something unexpected into your server. The client is easily able to fake and change cookie data, and thus to change your object.
Example:
If we serialize the object from Alma Do's answer and store the values in a cookie, the client/user could see our database auth settings from
public function __sleep() {
return array('server', 'username', 'password', 'db');
}
The client now can change his cookie to use a fake server instead of your server, fake your login / user table and pretend to be admin.
I think this is a case of XY Problem, please let us know what exactly is your goal.
This sounds more then a session function. You shouldn't transfer data over a Cookie. In Cookies you only save short information like a session token or a hash or some settings. To transfer and hold data the PHP session function is much better.
http://www.php.net/manual/de/book.session.php
In your session you can serialize some data if you want or save only an array or a value.
session_start(); // on every page
$_SESSION['test'] = "123123";
echo $_SESSION['test'];
to send serialized object you must use a specified thing like time() to bypass SPAM and control the timeOut!
session_start();
setcookie('myobject',serialize("Myvalue"),(time()+(3600*24*30)));
be sure to get stored on the session :
unset($_SESSION['myobject']);
Store your object
$_SESSION['myobject'] = unserialize($_COOKIE['myobject']);
Restore your Obecjt :
$mySeriaLizedObject = $_SESSION['myobject'];

What kind of serialization uses PHP function session_set_save_handler's write function?

I make use of session_set_save_handler(). It works fine. However, sometimes I need to alter user's session data. I simply expected that the session data passed to write function are internally created like this:
serialize($_SESSION);
But they are not. They have this slightly different format than simple PHP serialized data:
user|a:24:{s:2:"id";s:2:"12";s:5:"email";s:19:...CUT...;}last_activity_time|i:1310535031;logged_everywhere|b:1;
Anybody knows what kind of serialization is internally used for serializing $_SESSION data for write function in session_set_save_handler() ? Or even better, if there is some unserialize and serialize function I can use to work with this data ?
Please take a look at the PHP-Dokumentation for session_decode and session_encode. You will find complete samples for unserializing and serializing session strings in the comments.
here's my 2 cents on this issue with php's internal serializer. it's not really parse-able outside of the user's session. So when I used session_set_save_handler() so I can save my session data to a database, and inside my write method, I can access the $_SESSION object, thus, I can save the serialized $_SESSION object to my database, then read or alter it there. The only drawback is, that if it's altered, it wont be a modification to the internal session data used by php.
This at least gives you parse-able access to the current user's session data, although, not the object.
function _write($id, $data)
{
if ($data == "")
{
return true;
}
global $database_connection;
global $table_prefix;
$clean_data = base64_encode(serialize($_SESSION));
$access = time();
$id = mysql_real_escape_string($id);
$access = mysql_real_escape_string($access);
$data = base64_encode($data);
$sql = "REPLACE
INTO " . $table_prefix . "sessions
VALUES ('$id', '$access', '$data', '$clean_data')";
return mysql_query($sql, $database_connection);
}

Using the $_COOKIE var to keep important data

I'm creating a wordpress plugin. All the functions I'm writing are 'hooked' into certain wordpress events. This means I have a hard time creating variables that I need to use in several functions.
For example:
There's two functions that are hooked in somewhere:
Display_if_facebook_connected() {
if (Check_facebook_connected()) { return 'Yes, connected!' }
return '';
}
Display_if_facebook_connected() {
if (!Check_facebook_connected()) { return 'No, not connected!' }
return '';
}
And they both run a very heavy function:
Check_facebook_connected() { // some heavy facebook connect stuff, return bool }
I'm basically trying to avoid having the heavy function run twice, since it will have the same result.
In this case, would it be safe to do $_COOKIE['check_facebook_connected'] = true; and then read that variable in the Display_if_facebook_connected()?
By safe I mean that the user can't see or change the value. Since the cookie is never actually set, I think/hope it just disappears at the end of the php code.
I wouldn't be surprised if there is some better way, or better var, to do this with, but with my limited understanding of php I can't think of any.
UPDATE:
About sessions: I don't need the values to persist over multiple pages, just one page load. Since Wordpress doesn't use sessions I see no reason to change it.
I experimented a bit and the problem persists:
All of the following code is in the main file of my wordpress plugin. The way I understand it, the plugin file is 'included' at every request, so all code is run everytime I refresh my testpost.
Firstly I create the variable:
$myplugin_connected = false;
Then I hook my function in the right place:
add_shortcode( 'myplugin_notconnected', 'myplugin_notconnected_func' );
This basically hooks the myplugin_notconnected_func() function into the [myplugin_notconnected] shortcode. (A shortcode is text in a wordpress post, some id between [ ]-brackets. Wordpress loads the code associated with the shortcode whenever it appears.)
Here's the myplugin_notconnected_func():
function myplugin_notconnected_func( $atts, $content = null ) {
echo '<p>connected: ' . var_export($myplugin_connected, true) . '</p>';
return '$contents';
}
And here's the result:
connected: NULL
This is why I was trying to use $_COOKIE variables because at least they persist over the whole php instance. I apologize for lack of coherence, I'm learning as I go and I definitely appreciate the help!
Display_if_facebook_connected() {
$result = Check_facebook_connected();
if (!$result) { return 'No, unconnected!' } else { return 'Yes, connected!' }
}
$connected = Display_if_facebook_connected();
Scope
Referring to the updated part of your question:
Defining
$myplugin_connected = false;
and getting NULL as result on a subsequent
var_export($myplugin_connected, true)
could mean, that you either defined $myplugin_connected outside global scope (e.g. in a function instead of main), or you have defined in global scope, but have some unset($myplugin_connected) somewhere before the var_export. In both cases the return value of var_export would be NULL.
In your case I believe the former is more probably. You could use:
$GLOBALS['myplugin_connected'] = false;
and
var_export($GLOBALS['myplugin_connected'], true)
to have the connection state (which already has been determined once by your "heavy" function before) available in your shortcode handler.
Cookie
To answer your origin question:
In this case, would it be safe to do
$_COOKIE['check_facebook_connected'] = true; and then read that
variable in the Display_if_facebook_connected()?
Well, $_COOKIE is a server-side superglobal, so yes, as long as you never actually send/set that cookie on response, the user wouldn't see, nor could change it.
Personally, using $_COOKIE to save a state which is only valid for a single page load, feels just plain wrong to me.
I'd recommend to use at least $GLOBALS over $_COOKIE - or maybe even better use a static variable instead of a superglobal in this case - e.g. something like this:
function isConnected() {
static $bConnected = null;
if ($bConnected === null)
$bConnected = Check_facebook_connected();
return $bConnected;
}
But that's always in the eye of the beholder^^
session_start();
Check_facebook_connected()
{
if(isset($_SESSION["is_facebook_connected"])) return ($_SESSION["is_facebook_connected"] === true);
// if we get here we haven't checked the facebook connection status, so do it
...
}

Categories