Backport(バックポート) #3816 » 0001-changed-opPDODatabaseSessionStorage-write-to-replace.patch
lib/user/opPDODatabaseSessionStorage.class.php | ||
---|---|---|
return parent::sessionOpen($path, $name);
|
||
}
|
||
/**
|
||
* Writes data to this storage replacing 4 byte utf8 characters.
|
||
*
|
||
* @param string $key A unique key identifying your data
|
||
* @param mixed $data Data associated with your key
|
||
*
|
||
* @see sfSessionStorage
|
||
*/
|
||
public function write($key, $data)
|
||
{
|
||
// "utf8", a type of character set in MySQL, can't handle 4 bytes utf8 characters
|
||
// so we replace such a character to "U+FFFD" (A unicode "REPLACEMENT CHARACTER").
|
||
if (!$this->isReadyFor4BytesUtf8())
|
||
{
|
||
$data = $this->replace4BytesUtf8Characters($data);
|
||
}
|
||
parent::write($key, $data);
|
||
}
|
||
protected function replace4BytesUtf8Characters($value)
|
||
{
|
||
if (is_array($value))
|
||
{
|
||
$result = array();
|
||
foreach ($value as $k => $v)
|
||
{
|
||
$result[$this->replace4BytesUtf8Characters($k)] = $this->replace4BytesUtf8Characters($v);
|
||
}
|
||
return $result;
|
||
}
|
||
elseif (!is_string($value))
|
||
{
|
||
return $value;
|
||
}
|
||
// See: RFC 3629 (section 4, Syntax of UTF-8 Byte Sequences)
|
||
// http://tools.ietf.org/html/rfc3629#section-4
|
||
return preg_replace('/(
|
||
\xF0[\x90-\xBF][\x80-\xBF]{2}| # %xF0 %x90-BF 2( UTF8-tail )
|
||
[\xF1-\xF3][\x80-\xBF]{3}| # %xF1-F3 3( UTF8-tail )
|
||
\xF4[\x80-\x8F][\x80-\xBF]{2} # %xF4 %x80-8F 2( UTF8-tail )
|
||
)/x', "\xEF\xBF\xBD", $value);
|
||
}
|
||
protected function isReadyFor4BytesUtf8()
|
||
{
|
||
return 'mysql' !== $this->db->getAttribute(PDO::ATTR_DRIVER_NAME);
|
||
}
|
||
}
|
test/unit/user/opPDODatabaseSessionStrageTest.class.php | ||
---|---|---|
<?php
|
||
require_once(dirname(__FILE__).'/../../bootstrap/unit.php');
|
||
$_app = 'pc_frontend';
|
||
$_end = 'test';
|
||
$configuration = ProjectConfiguration::getApplicationConfiguration($_app, $_env, true);
|
||
sfContext::createInstance($configuration);
|
||
new sfDatabaseManager($configuration);
|
||
$t = new lime_test(2 + 2, new lime_output_color());
|
||
$storage = new opPDODatabaseSessionStorage(array(
|
||
'db_table' => 'session',
|
||
'database' => 'doctrine',
|
||
'db_id_col' => 'id',
|
||
'db_data_col' => 'session_data',
|
||
'db_time_col' => 'time',
|
||
));
|
||
$t->ok($storage instanceof sfStorage, 'sfPDOSessionStorage is an instance of sfStorage');
|
||
$t->ok($storage instanceof sfDatabaseSessionStorage, 'sfPDOSessionStorage is an instance of sfDatabaseSessionStorage');
|
||
$storage->sessionOpen();
|
||
// main test
|
||
$sessionId = '1';
|
||
$newSessionData = 'foo:bar:baz';
|
||
$storage->write($sessionId, $newSessionData);
|
||
$t->is($storage->read($sessionId), $newSessionData, 'session data can get data correctly');
|
||
$sessionId = '1';
|
||
$newSessionData = 'testⓉⒺⓈⓉテスト🅃🄴🅂🅃てすと';
|
||
$strConverted = 'testⓉⒺⓈⓉテスト����てすと';
|
||
$storage->write($sessionId, $newSessionData);
|
||
$t->is($storage->read($sessionId), $strConverted, 'session data using 4 byte utf characters can get data correctly');
|