Skip to content
Permalink
Browse files

Make stash() use clone of sql class (#4499)

* Make stash() use clone of sql class

When using `stash()` while the query builder is not finished with an sql, there would either be errors or false results since the Session class uses the singleton Gdn::sql().

The `stash()` method (and its helper method `_getStashSession()`) are the only two methods using db queries in Session. So I've not set $this->sql in `__construct()` but only in `stash()` since it wouldn't be needed elsewhere.

This solves issue #4391

* Make $sql protected, clone only once

* Update class.session.php

* Clone sql object in stash() and pass it to sub procedures

Several additional changes:
1. removed dash from private method name
2. added documentation to getStashSession()
3. changed casening of variables in getStashSession()
4. changed array syntax from array() to [] in getStashSession()
5. replaced serialize($session->Attributes) in stash() with dbencode(...)

* Correct variable $domain case

* Remove $valueToStash set to '' as default
  • Loading branch information...
R-J authored and tburry committed Sep 29, 2016
1 parent b21f20d commit a5711dea4ff72c9251dc2aff090c2ce1a84695db
Showing with 52 additions and 42 deletions.
  1. +52 −42 library/core/class.session.php
@@ -656,13 +656,17 @@ public function stash($name = '', $value = '', $unsetOnRetrieve = true) {
return;
}
// Grab the user's session
$session = $this->_getStashSession($value);
// Create a fresh copy of the Sql object to avoid pollution.
$sql = clone Gdn::sql();
$sql->reset();
// Grab the user's session.
$session = $this->getStashSession($sql, $value);
if (!$session) {
return;
}
// Stash or unstash the value depending on inputs
// Stash or unstash the value depending on inputs.
if ($value != '') {
$session->Attributes[$name] = $value;
} else {
@@ -671,85 +675,91 @@ public function stash($name = '', $value = '', $unsetOnRetrieve = true) {
unset($session->Attributes[$name]);
}
}
// Update the attributes
Gdn::SQL()->put(
// Update the attributes.
$sql->put(
'Session',
[
'DateUpdated' => Gdn_Format::toDateTime(),
'Attributes' => serialize($session->Attributes)
'Attributes' => dbencode($session->Attributes)
],
['SessionID' => $session->SessionID]
);
return $value;
}
/**
* Used by $this->Stash() to create & manage sessions for users & guests.
* Used by $this->stash() to create & manage sessions for users & guests.
*
* This is a stop-gap solution until full session management for users &
* guests can be imlemented.
* guests can be implemented.
*
* @param Gdn_SQLDriver $sql Local clone of the sql driver.
* @param string $valueToStash The value of the stash to set.
*
* @return bool|Gdn_DataSet Current session.
*/
private function _getStashSession($ValueToStash) {
$CookieName = c('Garden.Cookie.Name', 'Vanilla');
$Name = $CookieName.'-sid';
private function getStashSession($sql, $valueToStash) {
$cookieName = c('Garden.Cookie.Name', 'Vanilla');
$name = $cookieName.'-sid';
// Grab the entire session record
$SessionID = val($Name, $_COOKIE, '');
// Grab the entire session record.
$sessionID = val($name, $_COOKIE, '');
// If there is no session, and no value for saving, return;
if ($SessionID == '' && $ValueToStash == '') {
// If there is no session, and no value for saving, return.
if ($sessionID == '' && $valueToStash == '') {
return false;
}
$Session = Gdn::SQL()
$session = $sql
->select()
->from('Session')
->where('SessionID', $SessionID)
->where('SessionID', $sessionID)
->get()
->firstRow();
if (!$Session) {
$SessionID = betterRandomString(32);
$TransientKey = substr(md5(mt_rand()), 0, 11).'!';
if (!$session) {
$sessionID = betterRandomString(32);
$transientKey = substr(md5(mt_rand()), 0, 11).'!';
// Save the session information to the database.
Gdn::SQL()->insert(
$sql->insert(
'Session',
array(
'SessionID' => $SessionID,
[
'SessionID' => $sessionID,
'UserID' => Gdn::session()->UserID,
'TransientKey' => $TransientKey,
'TransientKey' => $transientKey,
'DateInserted' => Gdn_Format::toDateTime(),
'DateUpdated' => Gdn_Format::toDateTime()
)
]
);
Trace("Inserting session stash $SessionID");
trace("Inserting session stash $sessionID");
$Session = Gdn::SQL()
$session = $sql
->select()
->from('Session')
->where('SessionID', $SessionID)
->where('SessionID', $sessionID)
->get()
->firstRow();
// Save a session cookie
$Path = c('Garden.Cookie.Path', '/');
$Domain = c('Garden.Cookie.Domain', '');
$Expire = 0;
// Save a session cookie.
$path = c('Garden.Cookie.Path', '/');
$domain = c('Garden.Cookie.Domain', '');
$expire = 0;
// If the domain being set is completely incompatible with the current domain then make the domain work.
$CurrentHost = Gdn::request()->host();
if (!stringEndsWith($CurrentHost, trim($Domain, '.'))) {
$Domain = '';
// If the domain being set is completely incompatible with the
// current domain then make the domain work.
$currentHost = Gdn::request()->host();
if (!stringEndsWith($currentHost, trim($domain, '.'))) {
$domain = '';
}
safeCookie($Name, $SessionID, $Expire, $Path, $Domain);
$_COOKIE[$Name] = $SessionID;
safeCookie($name, $sessionID, $expire, $path, $domain);
$_COOKIE[$name] = $sessionID;
}
$Session->Attributes = dbdecode($Session->Attributes);
if (!$Session->Attributes) {
$Session->Attributes = array();
$session->Attributes = dbdecode($session->Attributes);
if (!$session->Attributes) {
$session->Attributes = [];
}
return $Session;
return $session;
}
}

0 comments on commit a5711de

Please sign in to comment.
You can’t perform that action at this time.