When using a custom session handler to save sessions on a postgreSQL server, open a postgres seccond connection and the session will break if any Unicode characters are present!
This is my custom session handler:
class custom_session_handler implements SessionHandlerInterface { protected $nombre_de_sesion, $tiempo_de_vida, $db; public function open($savePath, $sessionName) { $this->db = pg_connect("host=**** port=5432 dbname=**** user=**** password=***") or die('Imposible conectar con la base de datos de sesiones'); $this->gc(time()); $this->nombre_de_sesion = trim($sessionName); $this->tiempo_de_vida = pg_escape_literal(time() + 2500); return (isset($this->nombre_de_sesion) && strlen($this->nombre_de_sesion) > 2) ? true : false; } public function close() { return pg_close($this->db); } public function destroy($session_id) { return pg_affected_rows(pg_query($this->db, 'DELETE FROM "sesiones_soporte" WHERE session_id = ' . pg_escape_literal($session_id) . '')) ? true : false; } public function write($session_id, $session_data) { $escaped_id = pg_escape_literal($session_id); $escaped_session = pg_escape_literal(pg_escape_bytea($session_data)); if (pg_affected_rows(pg_query($this->db, 'UPDATE "sesiones_soporte" SET "session_expira" = ' . $this->tiempo_de_vida . ', "session_byte"=' . $escaped_session . ' WHERE session_id = ' . $escaped_id . ' AND session_expira > ' . (int) time())) == 1) { return true; } else { pg_query($this->db, 'INSERT INTO "sesiones_soporte" ("session_id", "session_expira", "session_byte") VALUES (' . $escaped_id . ', ' . $this->tiempo_de_vida . ', ' . $escaped_session . ' )'); return true; } return false; } public function read($session_id) { $escaped_id = pg_escape_literal($session_id); $sesion = pg_unescape_bytea(pg_fetch_result(pg_query($this->db, 'SELECT session_byte FROM "sesiones_soporte" WHERE session_id = ' . $escaped_id . ' AND session_expira > ' . (int) time() . ' LIMIT 1'), 0, 'session_byte')); !isset($sesion) ? : pg_query($this->db, 'UPDATE "sesiones_soporte" SET "session_expira" = ' . $this->tiempo_de_vida . ' WHERE session_id = ' . $escaped_id . ' AND session_expira > ' . (int) time()); return (isset($sesion) ? $sesion : false); } public function gc($maxlifetime) { return pg_affected_rows(pg_query($this->db, 'DELETE FROM "sesiones_soporte" WHERE session_expira < ' . (int) $maxlifetime)); } }
Start our handler with our session:
$handler = new custom_session_handler(); session_set_save_handler($handler, true); session_name('my_session'); session_start();
And save some data in our session:
$_SESSION['test'] = 'ÑéΓΓ³ΓΊΓ±';
At this point you can var_dump() execute your session and it will work, you can refresh the page and it will contain session information and it will work, but stay with me on this ...
well i need to check the fridge:
$seccond_server = pg_connect("host=#### port=#### dbname=#### user=#### password=######### or die("No bueno on db
Oooh, the session data looks fine, but ... wait ... Now your session is broken!
Reload the page and you will get: PHP Warning: session_start(): Failed to decode session object. Session has been destroyed in some location at some line PHP Warning: session_start(): Failed to decode session object. Session has been destroyed in some location at some line
Reloading the page again will give you: PHP Warning: pg_fetch_result(): Unable to jump to row 0 on PostgreSQL result index something in some path:
You can reproduce comments and uncomment that seccond pg_connect and the session will work until you make this seccond pg_connect
Update:
I forgot to mention that the same code works flawlessly in PHP 5.6.2
I added this problem as a comment to the PHP bug tracking system, as I found something similar: https://bugs.php.net/bug.php?id=70584
I just filled out a PHP error report if someone wants to follow and / or update it: https://bugs.php.net/bug.php?id=71088
Client and server information:
FIRST SERVER (session store): PostgreSQL 9.4.4 on x86_64-unknown-linux-gnu, compiled gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-11), 64-bit
SECCOND SERVER: PostgreSQL 8.4.20 on x86_64-redhat-linux-gnu, compiled GCC gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-11), 64-bit
CLIENT (php): PostgreSQL (libpq) version 9.4.4