ID:               20449
 Comment by:       [EMAIL PROTECTED]
 Reported By:      [EMAIL PROTECTED]
 Status:           Feedback
 Bug Type:         Session related
 Operating System: redhat 7.3
 PHP Version:      4.4.0-dev
 New Comment:

Ok.  I will fix my handler using your suggestions.  I'll get back to
you after a few hours of letting it work.

Josh


Previous Comments:
------------------------------------------------------------------------

[2002-11-17 12:40:32] [EMAIL PROTECTED]

I'm trying to provide as much as I can.

Here is a sample session from the dbase.

cart|a:1:{s:9:"161-00084";s:14:"White-Medium|1";}affiliatename|s:0:"";cartposted|s:10:"addProduct";


A quick thought.  I use the | as a delimiter to seperate the color-size
and quantity.  Would my delimiter potentially screw up the unserialize
or serialize functions? 

For multiple products here is a sample session.

cart|a:2:{s:9:"117-00717";s:20:"Black-Small_Medium|1";s:9:"117-00875";s:15:"Yellow-Medium|1";}affiliatename|s:0:"";cartposted|s:10:"addProduct";

------------------------------------------------------------------------

[2002-11-17 12:36:34] [EMAIL PROTECTED]

Missed a couple of words in the above.  "will randomly be deleted" I
meant to write.

------------------------------------------------------------------------

[2002-11-17 12:35:37] [EMAIL PROTECTED]

Your handler isn't very good.  As far as I can tell you never update
the expiry value which means that your sessions will randomly (because
the gc hook is called on a probability) after 5400 seconds (90 minutes)
after initial creation.  A quick fix would be to never expire sessions
by setting:
session.gc_probability = 0
In your php.ini file.  Or, better yet, fix your handler to update the
expiry time when writing to a session.  This expiry time is supposed to
be idle session time, not an absolute the way you have it.

I would suggest letting MySQL handle the timestamp and using a schema
that looks like this:

    id char(32) NOT NULL,
    data text,
    ts timestamp,
    PRIMARY KEY (id)

And instead of that ugly INSERT/UPDATE thing you have for your write
hook, use:

    $data = addslashes($data);
    mysql_query("replace into $table (id,data) values('$id','$data')")
        or error_log("write:
".mysql_error()."\n",3,"/tmp/errors.log");

The gc hook would just be:

function gc($max_time) {
    global $table;
    mysql_query(
      "delete from $table where
UNIX_TIMESTAMP(ts)<UNIX_TIMESTAMP()-$max_time")
      or error_log("gc: ".mysql_error()."\n",3,"/tmp/errors.log");
    return true;
}

But try setting gc_probability to 0 just to verify that this is indeed
the cause of the lost sessions.  If it is, then you need to slap
yourself hard as the code is doing exactly what you told it to do.

------------------------------------------------------------------------

[2002-11-17 12:19:36] [EMAIL PROTECTED]

I'm reopening this bug as I've provided more feedback.

Please yell at me if I'm not doing this right :)

------------------------------------------------------------------------

[2002-11-17 12:17:39] [EMAIL PROTECTED]

here is my session save handler.  Pretty much taken from phpbuilder.com
article.

Important to note that I have never seen a mysql error in my php_errors
log.

<?
$GLOBALS["SESS_DBHOST"] = "not shown";      /* database server hostname
*/
$GLOBALS["SESS_DBNAME"] = "not shown";     /* database name */
$GLOBALS["SESS_DBUSER"] = "not shown";   /* database user */
$GLOBALS["SESS_DBPASS"] = "not shown";   /* database password */

$GLOBALS["SESS_DBH"] = "";

$GLOBALS["SESS_LIFE"] = 5400;

function sess_open($save_path, $session_name) 
  {
    if (!$GLOBALS["SESS_DBH"] = mysql_pconnect($GLOBALS["SESS_DBHOST"],
$GLOBALS["SESS_DBUSER"], $GLOBALS["SESS_DBPASS"])) 
      {
        echo "<li>Can't connect to " . $GLOBALS["SESS_DBHOST"] . " as "
. $GLOBALS["SESS_DBUSER"];
        echo "<li>MySQL Error: ", mysql_error();
        die;
      }

    if (! mysql_select_db($GLOBALS["SESS_DBNAME"],
$GLOBALS["SESS_DBH"]))
      {
        echo "<li>Unable to select database " .
$GLOBALS["SESS_DBNAME"];
        die;
      }

    return true;
  }

function sess_close() 
  {
    return true;
  }

function sess_read($key) 
  {
    $qry = "SELECT value FROM sessions WHERE sesskey = '$key' AND
expiry > " . time();
    $qid = mysql_query($qry, $GLOBALS["SESS_DBH"]);

    if (list($value) = mysql_fetch_row($qid)) 
      {
        return $value;
      }

    return "";
  }

function sess_write($key, $val) 
  {
    $expiry = time() + $GLOBALS["SESS_LIFE"];
    $value = addslashes($val);

    $qry = "INSERT INTO sessions VALUES ('$key', $expiry, '$value')";
    $qid = mysql_query($qry, $GLOBALS["SESS_DBH"]);

    if (! $qid) 
      {
        $qry = "UPDATE sessions SET expiry = $expiry, value = '$value'
WHERE sesskey = '$key' AND expiry > " . time();
        $qid = mysql_query($qry, $GLOBALS["SESS_DBH"]);
      }

    return $qid;
  }

function sess_destroy($key) 
  {
    $qry = "DELETE FROM sessions WHERE sesskey = '$key'";
    $qid = mysql_query($qry, $GLOBALS["SESS_DBH"]);

    return $qid;
  }

function sess_gc($maxlifetime) 
  {
    $qry = "DELETE FROM sessions WHERE expiry < " . time();
    $qid = mysql_query($qry, $GLOBALS["SESS_DBH"]);

    return mysql_affected_rows($GLOBALS["SESS_DBH"]);
  }

//now that we have defined everything, set the save handler
session_set_save_handler(
  "sess_open",
  "sess_close",
  "sess_read",
  "sess_write",
  "sess_destroy",
  "sess_gc");
?>

------------------------------------------------------------------------

The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at
    http://bugs.php.net/20449

-- 
Edit this bug report at http://bugs.php.net/?id=20449&edit=1

Reply via email to