[horde] horde 3.0.5, postgresql session handler fails

Chris Stromsoe cbs+horde at cts.ucla.edu
Sat Oct 8 14:13:02 PDT 2005


I can't get session handling working with the postgresql session handler with 
horde 3.0.5.  After authenticating, I'm returned to the login page. If I use 
the default "none" / php files-based handler, sessions seem to work fine.

Looking at the query logs and comparing against the SQL for mysql, it looks 
like read()/write() are broken for the postgres handler.

On the initial page load -- before authenticating -- read() gets called with a 
session id, starts a transaction, then selects on the session id FOR UPDATE to 
lock the row.  If the query doesn't return any information, it does an INSERT, 
then re-selects the row.  It then calls write() with the same session id, which 
does an UPDATE on the session id and commits the transaction.

After passing in authentication credentials, read() gets called with a session 
id as above, starts a transaction, and selects on the sesion id FOR UPDATE to 
lock it.  In login.php on line 71 Horde::getCleanSession() is called, 
generating a new session id.  write() gets called with the new session id, 
which does an UPDATE which fails because there is no row in the table with the 
new session id.

Compounding the problem, the failure is not detected.  From 
lib/Horde/SessionHanderl/pgsql.php:

         /* Build the SQL query. */
         $query = sprintf('UPDATE %s SET session_lastmodified = %s, 
session_data= %s WHERE session_id = %s; COMMIT;',
                          $this->_params['table'],
                          time(),
                          $this->quote($session_data),
                          $this->quote($id));

         /* Log the query at a DEBUG log level. */
         Horde::logMessage(sprintf('SQL Query by SessionHandler_pgsql::write(): 
query = "%s"', $query),
                           __FILE__, __LINE__, PEAR_LOG_DEBUG);

         $result = @pg_query($this->_db, $query);
         $success = (pg_affected_rows($result) == 0);
         pg_free_result($result);

Because the update query includes the COMMIT, I'm pretty sure that 
pg_affected_rows() will return the result of the COMMIT not the result of the 
UPDATE, which means that the test for pg_affected_rows() == 0 will always be 
true.  Testing to see if the UPDATE was succesful should probably be testing 
for pg_affected_rows() == 1.


-Chris


More information about the horde mailing list