Skip to content

Commit 5991462

Browse files
authored
Merge pull request #1684 from codeigniter4/sessions
Updating session id cleanup for filehandler. Fixes #1681 Fixes #1565
2 parents 9d5929e + a7d3d76 commit 5991462

2 files changed

Lines changed: 68 additions & 12 deletions

File tree

system/Session/Handlers/BaseHandler.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,5 +209,4 @@ protected function fail()
209209

210210
return false;
211211
}
212-
213212
}

system/Session/Handlers/FileHandler.php

Lines changed: 68 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,16 @@ class FileHandler extends BaseHandler implements \SessionHandlerInterface
7373
*/
7474
protected $fileNew;
7575

76+
/**
77+
* @var boolean
78+
*/
79+
protected $matchIP = false;
80+
81+
/**
82+
* @var string
83+
*/
84+
protected $sessionIDRegex;
85+
7686
//--------------------------------------------------------------------
7787

7888
/**
@@ -91,14 +101,19 @@ public function __construct($config, string $ipAddress)
91101
}
92102
else
93103
{
94-
$sessionPath = rtrim(ini_get('session.save_path'), '/\\');
104+
$sessionPath = rtrim(ini_get('session.save_path'), '/\\');
105+
95106
if (! $sessionPath)
96-
{
107+
{
97108
$sessionPath = WRITEPATH . 'session';
98109
}
99110

100-
$this->savePath = $sessionPath;
111+
$this->savePath = $sessionPath;
101112
}
113+
114+
$this->matchIP = $config->sessionMatchIP;
115+
116+
$this->configureSessionIDRegex();
102117
}
103118

104119
//--------------------------------------------------------------------
@@ -130,8 +145,8 @@ public function open($savePath, $name): bool
130145

131146
$this->savePath = $savePath;
132147
$this->filePath = $this->savePath . '/'
133-
. $name // we'll use the session cookie name as a prefix to avoid collisions
134-
. ($this->matchIP ? md5($this->ipAddress) : '');
148+
. $name // we'll use the session cookie name as a prefix to avoid collisions
149+
. ($this->matchIP ? md5($this->ipAddress) : '');
135150

136151
return true;
137152
}
@@ -219,7 +234,7 @@ public function write($sessionID, $sessionData): bool
219234
{
220235
// If the two IDs don't match, we have a session_regenerate_id() call
221236
// and we need to close the old handle and open a new one
222-
if ($sessionID !== $this->sessionID && ( ! $this->close() || $this->read($sessionID) === false))
237+
if ($sessionID !== $this->sessionID && (! $this->close() || $this->read($sessionID) === false))
223238
{
224239
return false;
225240
}
@@ -302,13 +317,15 @@ public function destroy($session_id): bool
302317
{
303318
if ($this->close())
304319
{
305-
return is_file($this->filePath . $session_id) ? (unlink($this->filePath . $session_id) && $this->destroyCookie()) : true;
320+
return is_file($this->filePath . $session_id)
321+
? (unlink($this->filePath . $session_id) && $this->destroyCookie()) : true;
306322
}
307323
elseif ($this->filePath !== null)
308324
{
309325
clearstatcache();
310326

311-
return is_file($this->filePath . $session_id) ? (unlink($this->filePath . $session_id) && $this->destroyCookie()) : true;
327+
return is_file($this->filePath . $session_id)
328+
? (unlink($this->filePath . $session_id) && $this->destroyCookie()) : true;
312329
}
313330

314331
return false;
@@ -336,20 +353,28 @@ public function gc($maxlifetime): bool
336353

337354
$ts = time() - $maxlifetime;
338355

356+
$pattern = $this->matchIP === true
357+
? '[0-9a-f]{32}'
358+
: '';
359+
339360
$pattern = sprintf(
340-
'/^%s[0-9a-f]{%d}$/', preg_quote($this->cookieName, '/'), ($this->matchIP === true ? 72 : 40)
361+
'#\A%s' . $pattern . $this->sessionIDRegex . '\z#',
362+
preg_quote($this->cookieName)
341363
);
342364

343365
while (($file = readdir($directory)) !== false)
344366
{
345367
// If the filename doesn't match this pattern, it's either not a session file or is not ours
346-
if (! preg_match($pattern, $file) || ! is_file($this->savePath . '/' . $file) || ($mtime = filemtime($this->savePath . '/' . $file)) === false || $mtime > $ts
368+
if (! preg_match($pattern, $file)
369+
|| ! is_file($this->savePath . DIRECTORY_SEPARATOR . $file)
370+
|| ($mtime = filemtime($this->savePath . DIRECTORY_SEPARATOR . $file)) === false
371+
|| $mtime > $ts
347372
)
348373
{
349374
continue;
350375
}
351376

352-
unlink($this->savePath . '/' . $file);
377+
unlink($this->savePath . DIRECTORY_SEPARATOR . $file);
353378
}
354379

355380
closedir($directory);
@@ -358,4 +383,36 @@ public function gc($maxlifetime): bool
358383
}
359384

360385
//--------------------------------------------------------------------
386+
387+
/**
388+
* Configure Session ID regular expression
389+
*/
390+
protected function configureSessionIDRegex()
391+
{
392+
$bitsPerCharacter = (int)ini_get('session.sid_bits_per_character');
393+
$SIDLength = (int)ini_get('session.sid_length');
394+
395+
if (($bits = $SIDLength * $bitsPerCharacter) < 160)
396+
{
397+
// Add as many more characters as necessary to reach at least 160 bits
398+
$SIDLength += (int)ceil((160 % $bits) / $bitsPerCharacter);
399+
ini_set('session.sid_length', $SIDLength);
400+
}
401+
402+
// Yes, 4,5,6 are the only known possible values as of 2016-10-27
403+
switch ($bitsPerCharacter)
404+
{
405+
case 4:
406+
$this->sessionIDRegex = '[0-9a-f]';
407+
break;
408+
case 5:
409+
$this->sessionIDRegex = '[0-9a-v]';
410+
break;
411+
case 6:
412+
$this->sessionIDRegex = '[0-9a-zA-Z,-]';
413+
break;
414+
}
415+
416+
$this->sessionIDRegex .= '{' . $SIDLength . '}';
417+
}
361418
}

0 commit comments

Comments
 (0)