feature #16317 Rely on iconv and symfony/polyfill-* (nicolas-grekas)
This PR was merged into the 2.8 branch.
Discussion
----------
Rely on iconv and symfony/polyfill-*
| Q | A
| ------------- | ---
| Bug fix? | no
| New feature? | no
| BC breaks? | no
| Deprecations? | yes
| Tests pass? | yes
| Fixed tickets | #16240
| License | MIT
| Doc PR | -
Status: needs work
symfony/polyfill-* packages are not ready yet. Still, review welcomed.
Commits
-------
303f05b
Rely on iconv and symfony/polyfill-*
This commit is contained in:
commit
6557e85faf
@ -21,7 +21,13 @@
|
|||||||
"twig/twig": "~1.20|~2.0",
|
"twig/twig": "~1.20|~2.0",
|
||||||
"psr/log": "~1.0",
|
"psr/log": "~1.0",
|
||||||
"symfony/security-acl": "~2.7",
|
"symfony/security-acl": "~2.7",
|
||||||
"paragonie/random_compat": "~1.0"
|
"symfony/polyfill-intl-icu": "~1.0",
|
||||||
|
"symfony/polyfill-mbstring": "~1.0",
|
||||||
|
"symfony/polyfill-php54": "~1.0",
|
||||||
|
"symfony/polyfill-php55": "~1.0",
|
||||||
|
"symfony/polyfill-php56": "~1.0",
|
||||||
|
"symfony/polyfill-php70": "~1.0",
|
||||||
|
"symfony/polyfill-util": "~1.0"
|
||||||
},
|
},
|
||||||
"replace": {
|
"replace": {
|
||||||
"symfony/asset": "self.version",
|
"symfony/asset": "self.version",
|
||||||
@ -77,7 +83,6 @@
|
|||||||
"doctrine/orm": "~2.4,>=2.4.5",
|
"doctrine/orm": "~2.4,>=2.4.5",
|
||||||
"doctrine/doctrine-bundle": "~1.2",
|
"doctrine/doctrine-bundle": "~1.2",
|
||||||
"monolog/monolog": "~1.11",
|
"monolog/monolog": "~1.11",
|
||||||
"ircmaxell/password-compat": "~1.0",
|
|
||||||
"ocramius/proxy-manager": "~0.4|~1.0",
|
"ocramius/proxy-manager": "~0.4|~1.0",
|
||||||
"egulias/email-validator": "~1.2",
|
"egulias/email-validator": "~1.2",
|
||||||
"phpdocumentor/reflection": "^1.0.7"
|
"phpdocumentor/reflection": "^1.0.7"
|
||||||
@ -96,10 +101,8 @@
|
|||||||
"Symfony\\Component\\": "src/Symfony/Component/"
|
"Symfony\\Component\\": "src/Symfony/Component/"
|
||||||
},
|
},
|
||||||
"classmap": [
|
"classmap": [
|
||||||
"src/Symfony/Component/HttpFoundation/Resources/stubs",
|
|
||||||
"src/Symfony/Component/Intl/Resources/stubs"
|
"src/Symfony/Component/Intl/Resources/stubs"
|
||||||
],
|
]
|
||||||
"files": [ "src/Symfony/Component/Intl/Resources/stubs/functions.php" ]
|
|
||||||
},
|
},
|
||||||
"minimum-stability": "dev",
|
"minimum-stability": "dev",
|
||||||
"extra": {
|
"extra": {
|
||||||
|
@ -99,17 +99,10 @@ class DbalLogger implements SQLLogger
|
|||||||
}
|
}
|
||||||
|
|
||||||
// detect if the too long string must be shorten
|
// detect if the too long string must be shorten
|
||||||
if (function_exists('mb_strlen')) {
|
if (self::MAX_STRING_LENGTH < iconv_strlen($params[$index], 'UTF-8')) {
|
||||||
if (self::MAX_STRING_LENGTH < mb_strlen($params[$index], 'UTF-8')) {
|
$params[$index] = iconv_substr($params[$index], 0, self::MAX_STRING_LENGTH - 6, 'UTF-8').' [...]';
|
||||||
$params[$index] = mb_substr($params[$index], 0, self::MAX_STRING_LENGTH - 6, 'UTF-8').' [...]';
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
if (self::MAX_STRING_LENGTH < strlen($params[$index])) {
|
|
||||||
$params[$index] = substr($params[$index], 0, self::MAX_STRING_LENGTH - 6).' [...]';
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $params;
|
return $params;
|
||||||
|
@ -132,9 +132,6 @@ class DbalLoggerTest extends \PHPUnit_Framework_TestCase
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @requires extension mbstring
|
|
||||||
*/
|
|
||||||
public function testLogUTF8LongString()
|
public function testLogUTF8LongString()
|
||||||
{
|
{
|
||||||
$logger = $this->getMock('Psr\\Log\\LoggerInterface');
|
$logger = $this->getMock('Psr\\Log\\LoggerInterface');
|
||||||
@ -160,7 +157,7 @@ class DbalLoggerTest extends \PHPUnit_Framework_TestCase
|
|||||||
$dbalLogger
|
$dbalLogger
|
||||||
->expects($this->once())
|
->expects($this->once())
|
||||||
->method('log')
|
->method('log')
|
||||||
->with('SQL', array('short' => $shortString, 'long' => mb_substr($longString, 0, DbalLogger::MAX_STRING_LENGTH - 6, mb_detect_encoding($longString)).' [...]'))
|
->with('SQL', array('short' => $shortString, 'long' => iconv_substr($longString, 0, DbalLogger::MAX_STRING_LENGTH - 6, 'UTF-8').' [...]'))
|
||||||
;
|
;
|
||||||
|
|
||||||
$dbalLogger->startQuery('SQL', array(
|
$dbalLogger->startQuery('SQL', array(
|
||||||
|
@ -24,7 +24,6 @@ class SymfonyTestsListener extends \PHPUnit_Framework_BaseTestListener
|
|||||||
private $skippedFile = false;
|
private $skippedFile = false;
|
||||||
private $wasSkipped = array();
|
private $wasSkipped = array();
|
||||||
private $isSkipped = array();
|
private $isSkipped = array();
|
||||||
private $testsStack = array();
|
|
||||||
|
|
||||||
public function __destruct()
|
public function __destruct()
|
||||||
{
|
{
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
"symfony/finder": "~2.3|~3.0.0",
|
"symfony/finder": "~2.3|~3.0.0",
|
||||||
"symfony/form": "~2.8",
|
"symfony/form": "~2.8",
|
||||||
"symfony/http-kernel": "~2.8|~3.0.0",
|
"symfony/http-kernel": "~2.8|~3.0.0",
|
||||||
"symfony/intl": "~2.3|~3.0.0",
|
"symfony/polyfill-intl-icu": "~1.0",
|
||||||
"symfony/routing": "~2.2|~3.0.0",
|
"symfony/routing": "~2.2|~3.0.0",
|
||||||
"symfony/templating": "~2.1|~3.0.0",
|
"symfony/templating": "~2.1|~3.0.0",
|
||||||
"symfony/translation": "~2.7|~3.0.0",
|
"symfony/translation": "~2.7|~3.0.0",
|
||||||
|
@ -240,7 +240,7 @@ EOF
|
|||||||
{
|
{
|
||||||
$string = trim(preg_replace('/\s+/', ' ', $string));
|
$string = trim(preg_replace('/\s+/', ' ', $string));
|
||||||
|
|
||||||
if (function_exists('mb_strlen') && false !== $encoding = mb_detect_encoding($string)) {
|
if (false !== $encoding = mb_detect_encoding($string, null, true)) {
|
||||||
if (mb_strlen($string, $encoding) > $length) {
|
if (mb_strlen($string, $encoding) > $length) {
|
||||||
return mb_substr($string, 0, $length - 3, $encoding).'...';
|
return mb_substr($string, 0, $length - 3, $encoding).'...';
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
"symfony/event-dispatcher": "~2.8|~3.0.0",
|
"symfony/event-dispatcher": "~2.8|~3.0.0",
|
||||||
"symfony/http-foundation": "~2.4.9|~2.5,>=2.5.4|~3.0.0",
|
"symfony/http-foundation": "~2.4.9|~2.5,>=2.5.4|~3.0.0",
|
||||||
"symfony/http-kernel": "~2.8",
|
"symfony/http-kernel": "~2.8",
|
||||||
|
"symfony/polyfill-mbstring": "~1.0",
|
||||||
"symfony/filesystem": "~2.3|~3.0.0",
|
"symfony/filesystem": "~2.3|~3.0.0",
|
||||||
"symfony/routing": "~2.8|~3.0.0",
|
"symfony/routing": "~2.8|~3.0.0",
|
||||||
"symfony/security-core": "~2.6|~3.0.0",
|
"symfony/security-core": "~2.6|~3.0.0",
|
||||||
@ -40,7 +41,7 @@
|
|||||||
"symfony/css-selector": "~2.0,>=2.0.5|~3.0.0",
|
"symfony/css-selector": "~2.0,>=2.0.5|~3.0.0",
|
||||||
"symfony/dom-crawler": "~2.0,>=2.0.5|~3.0.0",
|
"symfony/dom-crawler": "~2.0,>=2.0.5|~3.0.0",
|
||||||
"symfony/finder": "~2.0,>=2.0.5|~3.0.0",
|
"symfony/finder": "~2.0,>=2.0.5|~3.0.0",
|
||||||
"symfony/intl": "~2.3|~3.0.0",
|
"symfony/polyfill-intl-icu": "~1.0",
|
||||||
"symfony/security": "~2.6|~3.0.0",
|
"symfony/security": "~2.6|~3.0.0",
|
||||||
"symfony/form": "~2.8",
|
"symfony/form": "~2.8",
|
||||||
"symfony/expression-language": "~2.6|~3.0.0",
|
"symfony/expression-language": "~2.6|~3.0.0",
|
||||||
|
@ -23,7 +23,6 @@
|
|||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"symfony/browser-kit": "~2.4|~3.0.0",
|
"symfony/browser-kit": "~2.4|~3.0.0",
|
||||||
"symfony/config": "~2.8|~3.0.0",
|
|
||||||
"symfony/console": "~2.7|~3.0.0",
|
"symfony/console": "~2.7|~3.0.0",
|
||||||
"symfony/css-selector": "~2.0,>=2.0.5|~3.0.0",
|
"symfony/css-selector": "~2.0,>=2.0.5|~3.0.0",
|
||||||
"symfony/dom-crawler": "~2.0,>=2.0.5|~3.0.0",
|
"symfony/dom-crawler": "~2.0,>=2.0.5|~3.0.0",
|
||||||
@ -37,8 +36,7 @@
|
|||||||
"symfony/yaml": "~2.0,>=2.0.5|~3.0.0",
|
"symfony/yaml": "~2.0,>=2.0.5|~3.0.0",
|
||||||
"symfony/expression-language": "~2.6|~3.0.0",
|
"symfony/expression-language": "~2.6|~3.0.0",
|
||||||
"doctrine/doctrine-bundle": "~1.2",
|
"doctrine/doctrine-bundle": "~1.2",
|
||||||
"twig/twig": "~1.20|~2.0",
|
"twig/twig": "~1.20|~2.0"
|
||||||
"ircmaxell/password-compat": "~1.0"
|
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": { "Symfony\\Bundle\\SecurityBundle\\": "" }
|
"psr-4": { "Symfony\\Bundle\\SecurityBundle\\": "" }
|
||||||
|
@ -1077,11 +1077,7 @@ class Application
|
|||||||
|
|
||||||
private function stringWidth($string)
|
private function stringWidth($string)
|
||||||
{
|
{
|
||||||
if (!function_exists('mb_strwidth')) {
|
if (false === $encoding = mb_detect_encoding($string, null, true)) {
|
||||||
return strlen($string);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (false === $encoding = mb_detect_encoding($string)) {
|
|
||||||
return strlen($string);
|
return strlen($string);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1094,11 +1090,7 @@ class Application
|
|||||||
// additionally, array_slice() is not enough as some character has doubled width.
|
// additionally, array_slice() is not enough as some character has doubled width.
|
||||||
// we need a function to split string not by character count but by string width
|
// we need a function to split string not by character count but by string width
|
||||||
|
|
||||||
if (!function_exists('mb_strwidth')) {
|
if (false === $encoding = mb_detect_encoding($string, null, true)) {
|
||||||
return str_split($string, $width);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (false === $encoding = mb_detect_encoding($string)) {
|
|
||||||
return str_split($string, $width);
|
return str_split($string, $width);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,11 +51,7 @@ abstract class Helper implements HelperInterface
|
|||||||
*/
|
*/
|
||||||
public static function strlen($string)
|
public static function strlen($string)
|
||||||
{
|
{
|
||||||
if (!function_exists('mb_strwidth')) {
|
if (false === $encoding = mb_detect_encoding($string, null, true)) {
|
||||||
return strlen($string);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (false === $encoding = mb_detect_encoding($string)) {
|
|
||||||
return strlen($string);
|
return strlen($string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -351,7 +351,7 @@ class Table
|
|||||||
}
|
}
|
||||||
|
|
||||||
// str_pad won't work properly with multi-byte strings, we need to fix the padding
|
// str_pad won't work properly with multi-byte strings, we need to fix the padding
|
||||||
if (function_exists('mb_strwidth') && false !== $encoding = mb_detect_encoding($cell)) {
|
if (false !== $encoding = mb_detect_encoding($cell, null, true)) {
|
||||||
$width += strlen($cell) - mb_strwidth($cell, $encoding);
|
$width += strlen($cell) - mb_strwidth($cell, $encoding);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -558,9 +558,6 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception4.txt', $tester->getDisplay(true), '->renderException() wraps messages when they are bigger than the terminal');
|
$this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception4.txt', $tester->getDisplay(true), '->renderException() wraps messages when they are bigger than the terminal');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @requires extension mbstring
|
|
||||||
*/
|
|
||||||
public function testRenderExceptionWithDoubleWidthCharacters()
|
public function testRenderExceptionWithDoubleWidthCharacters()
|
||||||
{
|
{
|
||||||
$application = $this->getMock('Symfony\Component\Console\Application', array('getTerminalWidth'));
|
$application = $this->getMock('Symfony\Component\Console\Application', array('getTerminalWidth'));
|
||||||
|
@ -52,9 +52,6 @@ class FormatterHelperTest extends \PHPUnit_Framework_TestCase
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @requires extension mbstring
|
|
||||||
*/
|
|
||||||
public function testFormatBlockWithDiacriticLetters()
|
public function testFormatBlockWithDiacriticLetters()
|
||||||
{
|
{
|
||||||
$formatter = new FormatterHelper();
|
$formatter = new FormatterHelper();
|
||||||
@ -68,9 +65,6 @@ class FormatterHelperTest extends \PHPUnit_Framework_TestCase
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @requires extension mbstring
|
|
||||||
*/
|
|
||||||
public function testFormatBlockWithDoubleWidthDiacriticLetters()
|
public function testFormatBlockWithDoubleWidthDiacriticLetters()
|
||||||
{
|
{
|
||||||
$formatter = new FormatterHelper();
|
$formatter = new FormatterHelper();
|
||||||
|
@ -155,9 +155,6 @@ class LegacyProgressHelperTest extends \PHPUnit_Framework_TestCase
|
|||||||
$progress->advance(1);
|
$progress->advance(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @requires extension mbstring
|
|
||||||
*/
|
|
||||||
public function testMultiByteSupport()
|
public function testMultiByteSupport()
|
||||||
{
|
{
|
||||||
$progress = new ProgressHelper();
|
$progress = new ProgressHelper();
|
||||||
|
@ -256,9 +256,6 @@ TABLE
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @requires extension mbstring
|
|
||||||
*/
|
|
||||||
public function testRenderMultiByte()
|
public function testRenderMultiByte()
|
||||||
{
|
{
|
||||||
$table = new TableHelper();
|
$table = new TableHelper();
|
||||||
@ -282,9 +279,6 @@ TABLE;
|
|||||||
$this->assertEquals($expected, $this->getOutputContent($output));
|
$this->assertEquals($expected, $this->getOutputContent($output));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @requires extension mbstring
|
|
||||||
*/
|
|
||||||
public function testRenderFullWidthCharacters()
|
public function testRenderFullWidthCharacters()
|
||||||
{
|
{
|
||||||
$table = new TableHelper();
|
$table = new TableHelper();
|
||||||
|
@ -307,9 +307,6 @@ class ProgressBarTest extends \PHPUnit_Framework_TestCase
|
|||||||
$bar->advance(1);
|
$bar->advance(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @requires extension mbstring
|
|
||||||
*/
|
|
||||||
public function testMultiByteSupport()
|
public function testMultiByteSupport()
|
||||||
{
|
{
|
||||||
$bar = new ProgressBar($output = $this->getOutputStream());
|
$bar = new ProgressBar($output = $this->getOutputStream());
|
||||||
@ -541,9 +538,6 @@ class ProgressBarTest extends \PHPUnit_Framework_TestCase
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @requires extension mbstring
|
|
||||||
*/
|
|
||||||
public function testAnsiColorsAndEmojis()
|
public function testAnsiColorsAndEmojis()
|
||||||
{
|
{
|
||||||
$bar = new ProgressBar($output = $this->getOutputStream(), 15);
|
$bar = new ProgressBar($output = $this->getOutputStream(), 15);
|
||||||
|
@ -464,9 +464,6 @@ TABLE
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @requires extension mbstring
|
|
||||||
*/
|
|
||||||
public function testRenderMultiByte()
|
public function testRenderMultiByte()
|
||||||
{
|
{
|
||||||
$table = new Table($output = $this->getOutputStream());
|
$table = new Table($output = $this->getOutputStream());
|
||||||
|
@ -16,7 +16,8 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.3.9"
|
"php": ">=5.3.9",
|
||||||
|
"symfony/polyfill-mbstring": "~1.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"symfony/event-dispatcher": "~2.1|~3.0.0",
|
"symfony/event-dispatcher": "~2.1|~3.0.0",
|
||||||
|
@ -173,34 +173,7 @@ class Crawler extends \SplObjectStorage
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// Convert charset to HTML-entities to work around bugs in DOMDocument::loadHTML()
|
// Convert charset to HTML-entities to work around bugs in DOMDocument::loadHTML()
|
||||||
|
|
||||||
if (function_exists('mb_convert_encoding')) {
|
|
||||||
$content = mb_convert_encoding($content, 'HTML-ENTITIES', $charset);
|
$content = mb_convert_encoding($content, 'HTML-ENTITIES', $charset);
|
||||||
} elseif (function_exists('iconv')) {
|
|
||||||
$content = preg_replace_callback(
|
|
||||||
'/[\x80-\xFF]+/',
|
|
||||||
function ($m) {
|
|
||||||
$m = unpack('C*', $m[0]);
|
|
||||||
$i = 1;
|
|
||||||
$entities = '';
|
|
||||||
|
|
||||||
while (isset($m[$i])) {
|
|
||||||
if (0xF0 <= $m[$i]) {
|
|
||||||
$c = (($m[$i++] - 0xF0) << 18) + (($m[$i++] - 0x80) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
|
|
||||||
} elseif (0xE0 <= $m[$i]) {
|
|
||||||
$c = (($m[$i++] - 0xE0) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
|
|
||||||
} else {
|
|
||||||
$c = (($m[$i++] - 0xC0) << 6) + $m[$i++] - 0x80;
|
|
||||||
}
|
|
||||||
|
|
||||||
$entities .= '&#'.$c.';';
|
|
||||||
}
|
|
||||||
|
|
||||||
return $entities;
|
|
||||||
},
|
|
||||||
iconv($charset, 'UTF-8', $content)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,7 +102,6 @@ class CrawlerTest extends \PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @covers Symfony\Component\DomCrawler\Crawler::addHtmlContent
|
* @covers Symfony\Component\DomCrawler\Crawler::addHtmlContent
|
||||||
* @requires extension mbstring
|
|
||||||
*/
|
*/
|
||||||
public function testAddHtmlContentCharset()
|
public function testAddHtmlContentCharset()
|
||||||
{
|
{
|
||||||
@ -137,7 +136,6 @@ class CrawlerTest extends \PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @covers Symfony\Component\DomCrawler\Crawler::addHtmlContent
|
* @covers Symfony\Component\DomCrawler\Crawler::addHtmlContent
|
||||||
* @requires extension mbstring
|
|
||||||
*/
|
*/
|
||||||
public function testAddHtmlContentCharsetGbk()
|
public function testAddHtmlContentCharsetGbk()
|
||||||
{
|
{
|
||||||
|
@ -16,7 +16,8 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.3.9"
|
"php": ">=5.3.9",
|
||||||
|
"symfony/polyfill-mbstring": "~1.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"symfony/css-selector": "~2.8|~3.0.0"
|
"symfony/css-selector": "~2.8|~3.0.0"
|
||||||
|
@ -197,7 +197,7 @@ class NumberToLocalizedStringTransformer implements DataTransformerInterface
|
|||||||
throw new TransformationFailedException('I don\'t have a clear idea what infinity looks like');
|
throw new TransformationFailedException('I don\'t have a clear idea what infinity looks like');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (function_exists('mb_detect_encoding') && false !== $encoding = mb_detect_encoding($value)) {
|
if (false !== $encoding = mb_detect_encoding($value, null, true)) {
|
||||||
$length = mb_strlen($value, $encoding);
|
$length = mb_strlen($value, $encoding);
|
||||||
$remainder = mb_substr($value, $position, $length, $encoding);
|
$remainder = mb_substr($value, $position, $length, $encoding);
|
||||||
} else {
|
} else {
|
||||||
|
@ -238,8 +238,6 @@ class NumberToLocalizedStringTransformerTest extends \PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @see https://github.com/symfony/symfony/issues/7609
|
* @see https://github.com/symfony/symfony/issues/7609
|
||||||
*
|
|
||||||
* @requires extension mbstring
|
|
||||||
*/
|
*/
|
||||||
public function testReverseTransformWithGroupingAndFixedSpaces()
|
public function testReverseTransformWithGroupingAndFixedSpaces()
|
||||||
{
|
{
|
||||||
@ -583,7 +581,6 @@ class NumberToLocalizedStringTransformerTest extends \PHPUnit_Framework_TestCase
|
|||||||
/**
|
/**
|
||||||
* @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
|
* @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
|
||||||
* @expectedExceptionMessage The number contains unrecognized characters: "foo8"
|
* @expectedExceptionMessage The number contains unrecognized characters: "foo8"
|
||||||
* @requires extension mbstring
|
|
||||||
*/
|
*/
|
||||||
public function testReverseTransformDisallowsCenteredExtraCharactersMultibyte()
|
public function testReverseTransformDisallowsCenteredExtraCharactersMultibyte()
|
||||||
{
|
{
|
||||||
@ -600,7 +597,6 @@ class NumberToLocalizedStringTransformerTest extends \PHPUnit_Framework_TestCase
|
|||||||
/**
|
/**
|
||||||
* @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
|
* @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
|
||||||
* @expectedExceptionMessage The number contains unrecognized characters: "foo8"
|
* @expectedExceptionMessage The number contains unrecognized characters: "foo8"
|
||||||
* @requires extension mbstring
|
|
||||||
*/
|
*/
|
||||||
public function testReverseTransformIgnoresTrailingSpacesInExceptionMessage()
|
public function testReverseTransformIgnoresTrailingSpacesInExceptionMessage()
|
||||||
{
|
{
|
||||||
@ -628,7 +624,6 @@ class NumberToLocalizedStringTransformerTest extends \PHPUnit_Framework_TestCase
|
|||||||
/**
|
/**
|
||||||
* @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
|
* @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
|
||||||
* @expectedExceptionMessage The number contains unrecognized characters: "foo"
|
* @expectedExceptionMessage The number contains unrecognized characters: "foo"
|
||||||
* @requires extension mbstring
|
|
||||||
*/
|
*/
|
||||||
public function testReverseTransformDisallowsTrailingExtraCharactersMultibyte()
|
public function testReverseTransformDisallowsTrailingExtraCharactersMultibyte()
|
||||||
{
|
{
|
||||||
|
@ -24,7 +24,6 @@ class StringUtilTest extends \PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider spaceProvider
|
* @dataProvider spaceProvider
|
||||||
* @requires extension mbstring
|
|
||||||
*/
|
*/
|
||||||
public function testTrimUtf8Separators($hex)
|
public function testTrimUtf8Separators($hex)
|
||||||
{
|
{
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
"symfony/event-dispatcher": "~2.1|~3.0.0",
|
"symfony/event-dispatcher": "~2.1|~3.0.0",
|
||||||
"symfony/intl": "~2.4|~3.0.0",
|
"symfony/intl": "~2.4|~3.0.0",
|
||||||
"symfony/options-resolver": "~2.6",
|
"symfony/options-resolver": "~2.6",
|
||||||
|
"symfony/polyfill-mbstring": "~1.0",
|
||||||
"symfony/property-access": "~2.3|~3.0.0"
|
"symfony/property-access": "~2.3|~3.0.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
|
@ -142,7 +142,7 @@ class JsonResponse extends Response
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (JSON_ERROR_NONE !== json_last_error()) {
|
if (JSON_ERROR_NONE !== json_last_error()) {
|
||||||
throw new \InvalidArgumentException($this->transformJsonError());
|
throw new \InvalidArgumentException(json_last_error_msg());
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->data = $data;
|
$this->data = $data;
|
||||||
@ -196,31 +196,4 @@ class JsonResponse extends Response
|
|||||||
|
|
||||||
return $this->setContent($this->data);
|
return $this->setContent($this->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function transformJsonError()
|
|
||||||
{
|
|
||||||
if (function_exists('json_last_error_msg')) {
|
|
||||||
return json_last_error_msg();
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (json_last_error()) {
|
|
||||||
case JSON_ERROR_DEPTH:
|
|
||||||
return 'Maximum stack depth exceeded.';
|
|
||||||
|
|
||||||
case JSON_ERROR_STATE_MISMATCH:
|
|
||||||
return 'Underflow or the modes mismatch.';
|
|
||||||
|
|
||||||
case JSON_ERROR_CTRL_CHAR:
|
|
||||||
return 'Unexpected control character found.';
|
|
||||||
|
|
||||||
case JSON_ERROR_SYNTAX:
|
|
||||||
return 'Syntax error, malformed JSON.';
|
|
||||||
|
|
||||||
case JSON_ERROR_UTF8:
|
|
||||||
return 'Malformed UTF-8 characters, possibly incorrectly encoded.';
|
|
||||||
|
|
||||||
default:
|
|
||||||
return 'Unknown error.';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -34,18 +34,6 @@ $response->send();
|
|||||||
The Request and the Response classes have many other methods that implement
|
The Request and the Response classes have many other methods that implement
|
||||||
the HTTP specification.
|
the HTTP specification.
|
||||||
|
|
||||||
Loading
|
|
||||||
-------
|
|
||||||
|
|
||||||
If you are not using Composer but are using PHP 5.3.x, you must add the following to your autoloader:
|
|
||||||
|
|
||||||
```php
|
|
||||||
// SessionHandlerInterface
|
|
||||||
if (!interface_exists('SessionHandlerInterface')) {
|
|
||||||
$loader->registerPrefixFallback(__DIR__.'/../vendor/symfony/src/Symfony/Component/HttpFoundation/Resources/stubs');
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Resources
|
Resources
|
||||||
---------
|
---------
|
||||||
|
|
||||||
|
@ -1,102 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of the Symfony package.
|
|
||||||
*
|
|
||||||
* (c) Fabien Potencier <fabien@symfony.com>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SessionHandlerInterface for PHP < 5.4.
|
|
||||||
*
|
|
||||||
* The order in which these methods are invoked by PHP are:
|
|
||||||
* 1. open [session_start]
|
|
||||||
* 2. read
|
|
||||||
* 3. gc [optional depending on probability settings: gc_probability / gc_divisor]
|
|
||||||
* 4. destroy [optional when session_regenerate_id(true) is used]
|
|
||||||
* 5. write [session_write_close] or destroy [session_destroy]
|
|
||||||
* 6. close
|
|
||||||
*
|
|
||||||
* Extensive documentation can be found at php.net, see links:
|
|
||||||
*
|
|
||||||
* @see http://php.net/sessionhandlerinterface
|
|
||||||
* @see http://php.net/session.customhandler
|
|
||||||
* @see http://php.net/session-set-save-handler
|
|
||||||
*
|
|
||||||
* @author Drak <drak@zikula.org>
|
|
||||||
* @author Tobias Schultze <http://tobion.de>
|
|
||||||
*/
|
|
||||||
interface SessionHandlerInterface
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Re-initializes existing session, or creates a new one.
|
|
||||||
*
|
|
||||||
* @see http://php.net/sessionhandlerinterface.open
|
|
||||||
*
|
|
||||||
* @param string $savePath Save path
|
|
||||||
* @param string $sessionName Session name, see http://php.net/function.session-name.php
|
|
||||||
*
|
|
||||||
* @return bool true on success, false on failure
|
|
||||||
*/
|
|
||||||
public function open($savePath, $sessionName);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Closes the current session.
|
|
||||||
*
|
|
||||||
* @see http://php.net/sessionhandlerinterface.close
|
|
||||||
*
|
|
||||||
* @return bool true on success, false on failure
|
|
||||||
*/
|
|
||||||
public function close();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads the session data.
|
|
||||||
*
|
|
||||||
* @see http://php.net/sessionhandlerinterface.read
|
|
||||||
*
|
|
||||||
* @param string $sessionId Session ID, see http://php.net/function.session-id
|
|
||||||
*
|
|
||||||
* @return string Same session data as passed in write() or empty string when non-existent or on failure
|
|
||||||
*/
|
|
||||||
public function read($sessionId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes the session data to the storage.
|
|
||||||
*
|
|
||||||
* Care, the session ID passed to write() can be different from the one previously
|
|
||||||
* received in read() when the session ID changed due to session_regenerate_id().
|
|
||||||
*
|
|
||||||
* @see http://php.net/sessionhandlerinterface.write
|
|
||||||
*
|
|
||||||
* @param string $sessionId Session ID , see http://php.net/function.session-id
|
|
||||||
* @param string $data Serialized session data to save
|
|
||||||
*
|
|
||||||
* @return bool true on success, false on failure
|
|
||||||
*/
|
|
||||||
public function write($sessionId, $data);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destroys a session.
|
|
||||||
*
|
|
||||||
* @see http://php.net/sessionhandlerinterface.destroy
|
|
||||||
*
|
|
||||||
* @param string $sessionId Session ID, see http://php.net/function.session-id
|
|
||||||
*
|
|
||||||
* @return bool true on success, false on failure
|
|
||||||
*/
|
|
||||||
public function destroy($sessionId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cleans up expired sessions (garbage collection).
|
|
||||||
*
|
|
||||||
* @see http://php.net/sessionhandlerinterface.gc
|
|
||||||
*
|
|
||||||
* @param string|int $maxlifetime Sessions that have not updated for the last maxlifetime seconds will be removed
|
|
||||||
*
|
|
||||||
* @return bool true on success, false on failure
|
|
||||||
*/
|
|
||||||
public function gc($maxlifetime);
|
|
||||||
}
|
|
@ -101,11 +101,7 @@ class NativeSessionStorage implements SessionStorageInterface
|
|||||||
session_cache_limiter(''); // disable by default because it's managed by HeaderBag (if used)
|
session_cache_limiter(''); // disable by default because it's managed by HeaderBag (if used)
|
||||||
ini_set('session.use_cookies', 1);
|
ini_set('session.use_cookies', 1);
|
||||||
|
|
||||||
if (PHP_VERSION_ID >= 50400) {
|
|
||||||
session_register_shutdown();
|
session_register_shutdown();
|
||||||
} else {
|
|
||||||
register_shutdown_function('session_write_close');
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->setMetadataBag($metaBag);
|
$this->setMetadataBag($metaBag);
|
||||||
$this->setOptions($options);
|
$this->setOptions($options);
|
||||||
|
@ -16,14 +16,14 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.3.9"
|
"php": ">=5.3.9",
|
||||||
|
"symfony/polyfill-php54": "~1.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"symfony/expression-language": "~2.4|~3.0.0"
|
"symfony/expression-language": "~2.4|~3.0.0"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": { "Symfony\\Component\\HttpFoundation\\": "" },
|
"psr-4": { "Symfony\\Component\\HttpFoundation\\": "" }
|
||||||
"classmap": [ "Resources/stubs" ]
|
|
||||||
},
|
},
|
||||||
"minimum-stability": "dev",
|
"minimum-stability": "dev",
|
||||||
"extra": {
|
"extra": {
|
||||||
|
@ -105,7 +105,7 @@ class MongoDbProfilerStorageTest extends AbstractProfilerStorageTest
|
|||||||
$profile = new Profile('utf8_test_profile');
|
$profile = new Profile('utf8_test_profile');
|
||||||
|
|
||||||
$data = 'HЁʃʃϿ, ϢorЃd!';
|
$data = 'HЁʃʃϿ, ϢorЃd!';
|
||||||
$nonUtf8Data = mb_convert_encoding($data, 'UCS-2');
|
$nonUtf8Data = iconv('UTF-8', 'UCS-2', $data);
|
||||||
|
|
||||||
$collector = new MongoDbProfilerStorageTestDataCollector();
|
$collector = new MongoDbProfilerStorageTestDataCollector();
|
||||||
$collector->setData($nonUtf8Data);
|
$collector->setData($nonUtf8Data);
|
||||||
|
@ -30,6 +30,8 @@ use Symfony\Component\Intl\Locale\Locale;
|
|||||||
*
|
*
|
||||||
* @author Igor Wiedler <igor@wiedler.ch>
|
* @author Igor Wiedler <igor@wiedler.ch>
|
||||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
*/
|
*/
|
||||||
class Collator
|
class Collator
|
||||||
{
|
{
|
||||||
|
@ -53,37 +53,10 @@ class JsonBundleReader implements BundleReaderInterface
|
|||||||
'The resource bundle "%s/%s.json" contains invalid JSON: %s',
|
'The resource bundle "%s/%s.json" contains invalid JSON: %s',
|
||||||
$path,
|
$path,
|
||||||
$locale,
|
$locale,
|
||||||
self::getLastJsonError()
|
json_last_error_msg()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string The last error message created by {@link json_decode()}
|
|
||||||
*
|
|
||||||
* @link http://de2.php.net/manual/en/function.json-last-error-msg.php#113243
|
|
||||||
*/
|
|
||||||
private static function getLastJsonError()
|
|
||||||
{
|
|
||||||
if (function_exists('json_last_error_msg')) {
|
|
||||||
return json_last_error_msg();
|
|
||||||
}
|
|
||||||
|
|
||||||
static $errors = array(
|
|
||||||
JSON_ERROR_NONE => null,
|
|
||||||
JSON_ERROR_DEPTH => 'Maximum stack depth exceeded',
|
|
||||||
JSON_ERROR_STATE_MISMATCH => 'Underflow or the modes mismatch',
|
|
||||||
JSON_ERROR_CTRL_CHAR => 'Unexpected control character found',
|
|
||||||
JSON_ERROR_SYNTAX => 'Syntax error, malformed JSON',
|
|
||||||
JSON_ERROR_UTF8 => 'Malformed UTF-8 characters, possibly incorrectly encoded',
|
|
||||||
);
|
|
||||||
|
|
||||||
$error = json_last_error();
|
|
||||||
|
|
||||||
return array_key_exists($error, $errors)
|
|
||||||
? $errors[$error]
|
|
||||||
: sprintf('Unknown error (%s)', $error);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,8 @@ namespace Symfony\Component\Intl\DateFormatter\DateFormat;
|
|||||||
* Parser and formatter for AM/PM markers format.
|
* Parser and formatter for AM/PM markers format.
|
||||||
*
|
*
|
||||||
* @author Igor Wiedler <igor@wiedler.ch>
|
* @author Igor Wiedler <igor@wiedler.ch>
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
*/
|
*/
|
||||||
class AmPmTransformer extends Transformer
|
class AmPmTransformer extends Transformer
|
||||||
{
|
{
|
||||||
|
@ -15,6 +15,8 @@ namespace Symfony\Component\Intl\DateFormatter\DateFormat;
|
|||||||
* Parser and formatter for day of week format.
|
* Parser and formatter for day of week format.
|
||||||
*
|
*
|
||||||
* @author Igor Wiedler <igor@wiedler.ch>
|
* @author Igor Wiedler <igor@wiedler.ch>
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
*/
|
*/
|
||||||
class DayOfWeekTransformer extends Transformer
|
class DayOfWeekTransformer extends Transformer
|
||||||
{
|
{
|
||||||
|
@ -15,6 +15,8 @@ namespace Symfony\Component\Intl\DateFormatter\DateFormat;
|
|||||||
* Parser and formatter for day of year format.
|
* Parser and formatter for day of year format.
|
||||||
*
|
*
|
||||||
* @author Igor Wiedler <igor@wiedler.ch>
|
* @author Igor Wiedler <igor@wiedler.ch>
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
*/
|
*/
|
||||||
class DayOfYearTransformer extends Transformer
|
class DayOfYearTransformer extends Transformer
|
||||||
{
|
{
|
||||||
|
@ -15,6 +15,8 @@ namespace Symfony\Component\Intl\DateFormatter\DateFormat;
|
|||||||
* Parser and formatter for day format.
|
* Parser and formatter for day format.
|
||||||
*
|
*
|
||||||
* @author Igor Wiedler <igor@wiedler.ch>
|
* @author Igor Wiedler <igor@wiedler.ch>
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
*/
|
*/
|
||||||
class DayTransformer extends Transformer
|
class DayTransformer extends Transformer
|
||||||
{
|
{
|
||||||
|
@ -18,6 +18,8 @@ use Symfony\Component\Intl\Globals\IntlGlobals;
|
|||||||
* Parser and formatter for date formats.
|
* Parser and formatter for date formats.
|
||||||
*
|
*
|
||||||
* @author Igor Wiedler <igor@wiedler.ch>
|
* @author Igor Wiedler <igor@wiedler.ch>
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
*/
|
*/
|
||||||
class FullTransformer
|
class FullTransformer
|
||||||
{
|
{
|
||||||
|
@ -15,6 +15,8 @@ namespace Symfony\Component\Intl\DateFormatter\DateFormat;
|
|||||||
* Parser and formatter for 12 hour format (0-11).
|
* Parser and formatter for 12 hour format (0-11).
|
||||||
*
|
*
|
||||||
* @author Igor Wiedler <igor@wiedler.ch>
|
* @author Igor Wiedler <igor@wiedler.ch>
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
*/
|
*/
|
||||||
class Hour1200Transformer extends HourTransformer
|
class Hour1200Transformer extends HourTransformer
|
||||||
{
|
{
|
||||||
|
@ -15,6 +15,8 @@ namespace Symfony\Component\Intl\DateFormatter\DateFormat;
|
|||||||
* Parser and formatter for 12 hour format (1-12).
|
* Parser and formatter for 12 hour format (1-12).
|
||||||
*
|
*
|
||||||
* @author Igor Wiedler <igor@wiedler.ch>
|
* @author Igor Wiedler <igor@wiedler.ch>
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
*/
|
*/
|
||||||
class Hour1201Transformer extends HourTransformer
|
class Hour1201Transformer extends HourTransformer
|
||||||
{
|
{
|
||||||
|
@ -15,6 +15,8 @@ namespace Symfony\Component\Intl\DateFormatter\DateFormat;
|
|||||||
* Parser and formatter for 24 hour format (0-23).
|
* Parser and formatter for 24 hour format (0-23).
|
||||||
*
|
*
|
||||||
* @author Igor Wiedler <igor@wiedler.ch>
|
* @author Igor Wiedler <igor@wiedler.ch>
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
*/
|
*/
|
||||||
class Hour2400Transformer extends HourTransformer
|
class Hour2400Transformer extends HourTransformer
|
||||||
{
|
{
|
||||||
|
@ -15,6 +15,8 @@ namespace Symfony\Component\Intl\DateFormatter\DateFormat;
|
|||||||
* Parser and formatter for 24 hour format (1-24).
|
* Parser and formatter for 24 hour format (1-24).
|
||||||
*
|
*
|
||||||
* @author Igor Wiedler <igor@wiedler.ch>
|
* @author Igor Wiedler <igor@wiedler.ch>
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
*/
|
*/
|
||||||
class Hour2401Transformer extends HourTransformer
|
class Hour2401Transformer extends HourTransformer
|
||||||
{
|
{
|
||||||
|
@ -15,6 +15,8 @@ namespace Symfony\Component\Intl\DateFormatter\DateFormat;
|
|||||||
* Base class for hour transformers.
|
* Base class for hour transformers.
|
||||||
*
|
*
|
||||||
* @author Eriksen Costa <eriksen.costa@infranology.com.br>
|
* @author Eriksen Costa <eriksen.costa@infranology.com.br>
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
*/
|
*/
|
||||||
abstract class HourTransformer extends Transformer
|
abstract class HourTransformer extends Transformer
|
||||||
{
|
{
|
||||||
|
@ -15,6 +15,8 @@ namespace Symfony\Component\Intl\DateFormatter\DateFormat;
|
|||||||
* Parser and formatter for minute format.
|
* Parser and formatter for minute format.
|
||||||
*
|
*
|
||||||
* @author Igor Wiedler <igor@wiedler.ch>
|
* @author Igor Wiedler <igor@wiedler.ch>
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
*/
|
*/
|
||||||
class MinuteTransformer extends Transformer
|
class MinuteTransformer extends Transformer
|
||||||
{
|
{
|
||||||
|
@ -15,6 +15,8 @@ namespace Symfony\Component\Intl\DateFormatter\DateFormat;
|
|||||||
* Parser and formatter for month format.
|
* Parser and formatter for month format.
|
||||||
*
|
*
|
||||||
* @author Igor Wiedler <igor@wiedler.ch>
|
* @author Igor Wiedler <igor@wiedler.ch>
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
*/
|
*/
|
||||||
class MonthTransformer extends Transformer
|
class MonthTransformer extends Transformer
|
||||||
{
|
{
|
||||||
|
@ -15,6 +15,8 @@ namespace Symfony\Component\Intl\DateFormatter\DateFormat;
|
|||||||
* Parser and formatter for quarter format.
|
* Parser and formatter for quarter format.
|
||||||
*
|
*
|
||||||
* @author Igor Wiedler <igor@wiedler.ch>
|
* @author Igor Wiedler <igor@wiedler.ch>
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
*/
|
*/
|
||||||
class QuarterTransformer extends Transformer
|
class QuarterTransformer extends Transformer
|
||||||
{
|
{
|
||||||
|
@ -15,6 +15,8 @@ namespace Symfony\Component\Intl\DateFormatter\DateFormat;
|
|||||||
* Parser and formatter for the second format.
|
* Parser and formatter for the second format.
|
||||||
*
|
*
|
||||||
* @author Igor Wiedler <igor@wiedler.ch>
|
* @author Igor Wiedler <igor@wiedler.ch>
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
*/
|
*/
|
||||||
class SecondTransformer extends Transformer
|
class SecondTransformer extends Transformer
|
||||||
{
|
{
|
||||||
|
@ -17,6 +17,8 @@ use Symfony\Component\Intl\Exception\NotImplementedException;
|
|||||||
* Parser and formatter for time zone format.
|
* Parser and formatter for time zone format.
|
||||||
*
|
*
|
||||||
* @author Igor Wiedler <igor@wiedler.ch>
|
* @author Igor Wiedler <igor@wiedler.ch>
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
*/
|
*/
|
||||||
class TimeZoneTransformer extends Transformer
|
class TimeZoneTransformer extends Transformer
|
||||||
{
|
{
|
||||||
|
@ -15,6 +15,8 @@ namespace Symfony\Component\Intl\DateFormatter\DateFormat;
|
|||||||
* Parser and formatter for date formats.
|
* Parser and formatter for date formats.
|
||||||
*
|
*
|
||||||
* @author Igor Wiedler <igor@wiedler.ch>
|
* @author Igor Wiedler <igor@wiedler.ch>
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
*/
|
*/
|
||||||
abstract class Transformer
|
abstract class Transformer
|
||||||
{
|
{
|
||||||
|
@ -15,6 +15,8 @@ namespace Symfony\Component\Intl\DateFormatter\DateFormat;
|
|||||||
* Parser and formatter for year format.
|
* Parser and formatter for year format.
|
||||||
*
|
*
|
||||||
* @author Igor Wiedler <igor@wiedler.ch>
|
* @author Igor Wiedler <igor@wiedler.ch>
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
*/
|
*/
|
||||||
class YearTransformer extends Transformer
|
class YearTransformer extends Transformer
|
||||||
{
|
{
|
||||||
|
@ -43,6 +43,8 @@ use Symfony\Component\Intl\Locale\Locale;
|
|||||||
*
|
*
|
||||||
* @author Igor Wiedler <igor@wiedler.ch>
|
* @author Igor Wiedler <igor@wiedler.ch>
|
||||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
*/
|
*/
|
||||||
class IntlDateFormatter
|
class IntlDateFormatter
|
||||||
{
|
{
|
||||||
|
@ -15,6 +15,8 @@ namespace Symfony\Component\Intl\Globals;
|
|||||||
* Provides fake static versions of the global functions in the intl extension.
|
* Provides fake static versions of the global functions in the intl extension.
|
||||||
*
|
*
|
||||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
*/
|
*/
|
||||||
abstract class IntlGlobals
|
abstract class IntlGlobals
|
||||||
{
|
{
|
||||||
|
@ -21,6 +21,8 @@ use Symfony\Component\Intl\Exception\MethodNotImplementedException;
|
|||||||
*
|
*
|
||||||
* @author Eriksen Costa <eriksen.costa@infranology.com.br>
|
* @author Eriksen Costa <eriksen.costa@infranology.com.br>
|
||||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
*/
|
*/
|
||||||
class Locale
|
class Locale
|
||||||
{
|
{
|
||||||
|
@ -37,6 +37,8 @@ use Symfony\Component\Intl\Locale\Locale;
|
|||||||
*
|
*
|
||||||
* @author Eriksen Costa <eriksen.costa@infranology.com.br>
|
* @author Eriksen Costa <eriksen.costa@infranology.com.br>
|
||||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
*/
|
*/
|
||||||
class NumberFormatter
|
class NumberFormatter
|
||||||
{
|
{
|
||||||
|
@ -1,78 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of the Symfony package.
|
|
||||||
*
|
|
||||||
* (c) Fabien Potencier <fabien@symfony.com>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
use Symfony\Component\Intl\Globals\IntlGlobals;
|
|
||||||
|
|
||||||
if (!function_exists('intl_is_failure')) {
|
|
||||||
/**
|
|
||||||
* Stub implementation for the {@link intl_is_failure()} function of the intl
|
|
||||||
* extension.
|
|
||||||
*
|
|
||||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
|
||||||
*
|
|
||||||
* @param int $errorCode The error code returned by intl_get_error_code().
|
|
||||||
*
|
|
||||||
* @return bool Whether the error code indicates an error.
|
|
||||||
*
|
|
||||||
* @see IntlGlobals::isFailure()
|
|
||||||
*/
|
|
||||||
function intl_is_failure($errorCode)
|
|
||||||
{
|
|
||||||
return IntlGlobals::isFailure($errorCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stub implementation for the {@link intl_get_error_code()} function of the
|
|
||||||
* intl extension.
|
|
||||||
*
|
|
||||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
|
||||||
*
|
|
||||||
* @return bool The error code of the last intl function call or
|
|
||||||
* IntlGlobals::U_ZERO_ERROR if no error occurred.
|
|
||||||
*
|
|
||||||
* @see IntlGlobals::getErrorCode()
|
|
||||||
*/
|
|
||||||
function intl_get_error_code()
|
|
||||||
{
|
|
||||||
return IntlGlobals::getErrorCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stub implementation for the {@link intl_get_error_code()} function of the
|
|
||||||
* intl extension.
|
|
||||||
*
|
|
||||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
|
||||||
*
|
|
||||||
* @return bool The error message of the last intl function call or
|
|
||||||
* "U_ZERO_ERROR" if no error occurred.
|
|
||||||
*
|
|
||||||
* @see IntlGlobals::getErrorMessage()
|
|
||||||
*/
|
|
||||||
function intl_get_error_message()
|
|
||||||
{
|
|
||||||
return IntlGlobals::getErrorMessage();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stub implementation for the {@link intl_error_name()} function of the intl
|
|
||||||
* extension.
|
|
||||||
*
|
|
||||||
* @param int $errorCode The error code.
|
|
||||||
*
|
|
||||||
* @return string The name of the error code constant.
|
|
||||||
*
|
|
||||||
* @see IntlGlobals::getErrorName()
|
|
||||||
*/
|
|
||||||
function intl_error_name($errorCode)
|
|
||||||
{
|
|
||||||
return IntlGlobals::getErrorName($errorCode);
|
|
||||||
}
|
|
||||||
}
|
|
@ -24,7 +24,9 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.3.9"
|
"php": ">=5.3.9",
|
||||||
|
"symfony/polyfill-intl-icu": "~1.0",
|
||||||
|
"symfony/polyfill-php54": "~1.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"symfony/filesystem": "~2.1|~3.0.0"
|
"symfony/filesystem": "~2.1|~3.0.0"
|
||||||
@ -34,8 +36,7 @@
|
|||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": { "Symfony\\Component\\Intl\\": "" },
|
"psr-4": { "Symfony\\Component\\Intl\\": "" },
|
||||||
"classmap": [ "Resources/stubs" ],
|
"classmap": [ "Resources/stubs" ]
|
||||||
"files": [ "Resources/stubs/functions.php" ]
|
|
||||||
},
|
},
|
||||||
"minimum-stability": "dev",
|
"minimum-stability": "dev",
|
||||||
"extra": {
|
"extra": {
|
||||||
|
@ -97,13 +97,9 @@ class LdapClient implements LdapClientInterface
|
|||||||
*/
|
*/
|
||||||
public function escape($subject, $ignore = '', $flags = 0)
|
public function escape($subject, $ignore = '', $flags = 0)
|
||||||
{
|
{
|
||||||
if (function_exists('ldap_escape')) {
|
|
||||||
return ldap_escape($subject, $ignore, $flags);
|
return ldap_escape($subject, $ignore, $flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->doEscape($subject, $ignore, $flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function connect()
|
private function connect()
|
||||||
{
|
{
|
||||||
if (!$this->connection) {
|
if (!$this->connection) {
|
||||||
@ -132,98 +128,4 @@ class LdapClient implements LdapClientInterface
|
|||||||
|
|
||||||
$this->connection = null;
|
$this->connection = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Stub implementation of the {@link ldap_escape()} function of the ldap
|
|
||||||
* extension.
|
|
||||||
*
|
|
||||||
* Escape strings for safe use in LDAP filters and DNs.
|
|
||||||
*
|
|
||||||
* @author Chris Wright <ldapi@daverandom.com>
|
|
||||||
*
|
|
||||||
* @param string $subject
|
|
||||||
* @param string $ignore
|
|
||||||
* @param int $flags
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*
|
|
||||||
* @see http://stackoverflow.com/a/8561604
|
|
||||||
*/
|
|
||||||
private function doEscape($subject, $ignore = '', $flags = 0)
|
|
||||||
{
|
|
||||||
$charMaps = $this->getCharmaps();
|
|
||||||
|
|
||||||
// Create the base char map to escape
|
|
||||||
$flags = (int) $flags;
|
|
||||||
$charMap = array();
|
|
||||||
|
|
||||||
if ($flags & self::LDAP_ESCAPE_FILTER) {
|
|
||||||
$charMap += $charMaps[self::LDAP_ESCAPE_FILTER];
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($flags & self::LDAP_ESCAPE_DN) {
|
|
||||||
$charMap += $charMaps[self::LDAP_ESCAPE_DN];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$charMap) {
|
|
||||||
$charMap = $charMaps[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove any chars to ignore from the list
|
|
||||||
$ignore = (string) $ignore;
|
|
||||||
|
|
||||||
for ($i = 0, $l = strlen($ignore); $i < $l; ++$i) {
|
|
||||||
unset($charMap[$ignore[$i]]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do the main replacement
|
|
||||||
$result = strtr($subject, $charMap);
|
|
||||||
|
|
||||||
// Encode leading/trailing spaces if LDAP_ESCAPE_DN is passed
|
|
||||||
if ($flags & self::LDAP_ESCAPE_DN) {
|
|
||||||
if ($result[0] === ' ') {
|
|
||||||
$result = '\\20'.substr($result, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($result[strlen($result) - 1] === ' ') {
|
|
||||||
$result = substr($result, 0, -1).'\\20';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function getCharmaps()
|
|
||||||
{
|
|
||||||
if (null !== $this->charmaps) {
|
|
||||||
return $this->charmaps;
|
|
||||||
}
|
|
||||||
|
|
||||||
$charMaps = array(
|
|
||||||
self::LDAP_ESCAPE_FILTER => array('\\', '*', '(', ')', "\x00"),
|
|
||||||
self::LDAP_ESCAPE_DN => array('\\', ',', '=', '+', '<', '>', ';', '"', '#'),
|
|
||||||
);
|
|
||||||
|
|
||||||
$charMaps[0] = array();
|
|
||||||
|
|
||||||
for ($i = 0; $i < 256; ++$i) {
|
|
||||||
$charMaps[0][chr($i)] = sprintf('\\%02x', $i);
|
|
||||||
}
|
|
||||||
|
|
||||||
for ($i = 0, $l = count($charMaps[self::LDAP_ESCAPE_FILTER]); $i < $l; ++$i) {
|
|
||||||
$chr = $charMaps[self::LDAP_ESCAPE_FILTER][$i];
|
|
||||||
unset($charMaps[self::LDAP_ESCAPE_FILTER][$i]);
|
|
||||||
$charMaps[self::LDAP_ESCAPE_FILTER][$chr] = $charMaps[0][$chr];
|
|
||||||
}
|
|
||||||
|
|
||||||
for ($i = 0, $l = count($charMaps[self::LDAP_ESCAPE_DN]); $i < $l; ++$i) {
|
|
||||||
$chr = $charMaps[self::LDAP_ESCAPE_DN][$i];
|
|
||||||
unset($charMaps[self::LDAP_ESCAPE_DN][$i]);
|
|
||||||
$charMaps[self::LDAP_ESCAPE_DN][$chr] = $charMaps[0][$chr];
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->charmaps = $charMaps;
|
|
||||||
|
|
||||||
return $this->charmaps;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,52 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of the Symfony package.
|
|
||||||
*
|
|
||||||
* (c) Fabien Potencier <fabien@symfony.com>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Symfony\Component\Security\Core\Tests\Authentication\Provider;
|
|
||||||
|
|
||||||
use Symfony\Component\Ldap\LdapClient;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @requires extension ldap
|
|
||||||
*/
|
|
||||||
class LdapClientTest extends \PHPUnit_Framework_TestCase
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @dataProvider provideLdapEscapeValues
|
|
||||||
*/
|
|
||||||
public function testLdapEscape($subject, $ignore, $flags, $expected)
|
|
||||||
{
|
|
||||||
$ldap = new LdapClient();
|
|
||||||
$this->assertSame($expected, $ldap->escape($subject, $ignore, $flags));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides values for the ldap_escape shim. These tests come from the official
|
|
||||||
* extension.
|
|
||||||
*
|
|
||||||
* @see https://github.com/php/php-src/blob/master/ext/ldap/tests/ldap_escape_dn.phpt
|
|
||||||
* @see https://github.com/php/php-src/blob/master/ext/ldap/tests/ldap_escape_all.phpt
|
|
||||||
* @see https://github.com/php/php-src/blob/master/ext/ldap/tests/ldap_escape_both.phpt
|
|
||||||
* @see https://github.com/php/php-src/blob/master/ext/ldap/tests/ldap_escape_filter.phpt
|
|
||||||
* @see https://github.com/php/php-src/blob/master/ext/ldap/tests/ldap_escape_ignore.phpt
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function provideLdapEscapeValues()
|
|
||||||
{
|
|
||||||
return array(
|
|
||||||
array('foo=bar(baz)*', null, LdapClient::LDAP_ESCAPE_DN, 'foo\3dbar(baz)*'),
|
|
||||||
array('foo=bar(baz)*', null, null, '\66\6f\6f\3d\62\61\72\28\62\61\7a\29\2a'),
|
|
||||||
array('foo=bar(baz)*', null, LdapClient::LDAP_ESCAPE_DN | LdapClient::LDAP_ESCAPE_FILTER, 'foo\3dbar\28baz\29\2a'),
|
|
||||||
array('foo=bar(baz)*', null, LdapClient::LDAP_ESCAPE_FILTER, 'foo=bar\28baz\29\2a'),
|
|
||||||
array('foo=bar(baz)*', 'ao', null, '\66oo\3d\62a\72\28\62a\7a\29\2a'),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -17,6 +17,7 @@
|
|||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.3.9",
|
"php": ">=5.3.9",
|
||||||
|
"symfony/polyfill-php56": "~1.0",
|
||||||
"ext-ldap": "*"
|
"ext-ldap": "*"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
@ -34,10 +34,6 @@ class BCryptPasswordEncoder extends BasePasswordEncoder
|
|||||||
*/
|
*/
|
||||||
public function __construct($cost)
|
public function __construct($cost)
|
||||||
{
|
{
|
||||||
if (!function_exists('password_hash')) {
|
|
||||||
throw new \RuntimeException('To use the BCrypt encoder, you need to upgrade to PHP 5.5 or install the "ircmaxell/password-compat" via Composer.');
|
|
||||||
}
|
|
||||||
|
|
||||||
$cost = (int) $cost;
|
$cost = (int) $cost;
|
||||||
if ($cost < 4 || $cost > 31) {
|
if ($cost < 4 || $cost > 31) {
|
||||||
throw new \InvalidArgumentException('Cost must be in the range of 4-31.');
|
throw new \InvalidArgumentException('Cost must be in the range of 4-31.');
|
||||||
|
@ -11,8 +11,6 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\Security\Core\Encoder;
|
namespace Symfony\Component\Security\Core\Encoder;
|
||||||
|
|
||||||
use Symfony\Component\Security\Core\Util\StringUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BasePasswordEncoder is the base class for all password encoders.
|
* BasePasswordEncoder is the base class for all password encoders.
|
||||||
*
|
*
|
||||||
@ -83,7 +81,7 @@ abstract class BasePasswordEncoder implements PasswordEncoderInterface
|
|||||||
*/
|
*/
|
||||||
protected function comparePasswords($password1, $password2)
|
protected function comparePasswords($password1, $password2)
|
||||||
{
|
{
|
||||||
return StringUtils::equals($password1, $password2);
|
return hash_equals($password1, $password2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -64,11 +64,7 @@ class Pbkdf2PasswordEncoder extends BasePasswordEncoder
|
|||||||
throw new \LogicException(sprintf('The algorithm "%s" is not supported.', $this->algorithm));
|
throw new \LogicException(sprintf('The algorithm "%s" is not supported.', $this->algorithm));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (function_exists('hash_pbkdf2')) {
|
|
||||||
$digest = hash_pbkdf2($this->algorithm, $raw, $salt, $this->iterations, $this->length, true);
|
$digest = hash_pbkdf2($this->algorithm, $raw, $salt, $this->iterations, $this->length, true);
|
||||||
} else {
|
|
||||||
$digest = $this->hashPbkdf2($this->algorithm, $raw, $salt, $this->iterations, $this->length);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->encodeHashAsBase64 ? base64_encode($digest) : bin2hex($digest);
|
return $this->encodeHashAsBase64 ? base64_encode($digest) : bin2hex($digest);
|
||||||
}
|
}
|
||||||
@ -80,24 +76,4 @@ class Pbkdf2PasswordEncoder extends BasePasswordEncoder
|
|||||||
{
|
{
|
||||||
return !$this->isPasswordTooLong($raw) && $this->comparePasswords($encoded, $this->encodePassword($raw, $salt));
|
return !$this->isPasswordTooLong($raw) && $this->comparePasswords($encoded, $this->encodePassword($raw, $salt));
|
||||||
}
|
}
|
||||||
|
|
||||||
private function hashPbkdf2($algorithm, $password, $salt, $iterations, $length = 0)
|
|
||||||
{
|
|
||||||
// Number of blocks needed to create the derived key
|
|
||||||
$blocks = ceil($length / strlen(hash($algorithm, null, true)));
|
|
||||||
$digest = '';
|
|
||||||
|
|
||||||
for ($i = 1; $i <= $blocks; ++$i) {
|
|
||||||
$ib = $block = hash_hmac($algorithm, $salt.pack('N', $i), $password, true);
|
|
||||||
|
|
||||||
// Iterations
|
|
||||||
for ($j = 1; $j < $iterations; ++$j) {
|
|
||||||
$ib ^= ($block = hash_hmac($algorithm, $block, $password, true));
|
|
||||||
}
|
|
||||||
|
|
||||||
$digest .= $ib;
|
|
||||||
}
|
|
||||||
|
|
||||||
return substr($digest, 0, $this->length);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,8 @@ use Symfony\Component\Security\Core\Util\StringUtils;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Data from PHP.net's hash_equals tests.
|
* Data from PHP.net's hash_equals tests.
|
||||||
|
*
|
||||||
|
* @group legacy
|
||||||
*/
|
*/
|
||||||
class StringUtilsTest extends \PHPUnit_Framework_TestCase
|
class StringUtilsTest extends \PHPUnit_Framework_TestCase
|
||||||
{
|
{
|
||||||
|
@ -11,10 +11,16 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\Security\Core\Util;
|
namespace Symfony\Component\Security\Core\Util;
|
||||||
|
|
||||||
|
@trigger_error('The '.__NAMESPACE__.'\\StringUtils class is deprecated since version 2.8 and will be removed in 3.0. Use hash_equals() instead.', E_USER_DEPRECATED);
|
||||||
|
|
||||||
|
use Symfony\Component\Polyfill\Util\Binary;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* String utility functions.
|
* String utility functions.
|
||||||
*
|
*
|
||||||
* @author Fabien Potencier <fabien@symfony.com>
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* @deprecated since 2.8, to be removed in 3.0.
|
||||||
*/
|
*/
|
||||||
class StringUtils
|
class StringUtils
|
||||||
{
|
{
|
||||||
@ -47,27 +53,9 @@ class StringUtils
|
|||||||
$userInput = (string) $userInput;
|
$userInput = (string) $userInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (function_exists('hash_equals')) {
|
|
||||||
return hash_equals($knownString, $userInput);
|
return hash_equals($knownString, $userInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
$knownLen = self::safeStrlen($knownString);
|
|
||||||
$userLen = self::safeStrlen($userInput);
|
|
||||||
|
|
||||||
if ($userLen !== $knownLen) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = 0;
|
|
||||||
|
|
||||||
for ($i = 0; $i < $knownLen; ++$i) {
|
|
||||||
$result |= (ord($knownString[$i]) ^ ord($userInput[$i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
// They are only identical strings if $result is exactly 0...
|
|
||||||
return 0 === $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the number of bytes in a string.
|
* Returns the number of bytes in a string.
|
||||||
*
|
*
|
||||||
@ -77,17 +65,6 @@ class StringUtils
|
|||||||
*/
|
*/
|
||||||
public static function safeStrlen($string)
|
public static function safeStrlen($string)
|
||||||
{
|
{
|
||||||
// Premature optimization
|
return Binary::strlen($string);
|
||||||
// Since this cannot be changed at runtime, we can cache it
|
|
||||||
static $funcExists = null;
|
|
||||||
if (null === $funcExists) {
|
|
||||||
$funcExists = function_exists('mb_strlen');
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($funcExists) {
|
|
||||||
return mb_strlen($string, '8bit');
|
|
||||||
}
|
|
||||||
|
|
||||||
return strlen($string);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,25 +17,25 @@
|
|||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.3.9",
|
"php": ">=5.3.9",
|
||||||
"paragonie/random_compat": "~1.0"
|
"symfony/polyfill-php55": "~1.0",
|
||||||
|
"symfony/polyfill-php56": "~1.0",
|
||||||
|
"symfony/polyfill-util": "~1.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"symfony/event-dispatcher": "~2.1|~3.0.0",
|
"symfony/event-dispatcher": "~2.1|~3.0.0",
|
||||||
"symfony/expression-language": "~2.6|~3.0.0",
|
"symfony/expression-language": "~2.6|~3.0.0",
|
||||||
"symfony/http-foundation": "~2.4|~3.0.0",
|
"symfony/http-foundation": "~2.4|~3.0.0",
|
||||||
|
"symfony/ldap": "~2.8|~3.0.0",
|
||||||
"symfony/translation": "~2.0,>=2.0.5|~3.0.0",
|
"symfony/translation": "~2.0,>=2.0.5|~3.0.0",
|
||||||
"symfony/validator": "~2.5,>=2.5.5|~3.0.0",
|
"symfony/validator": "~2.5,>=2.5.5|~3.0.0",
|
||||||
"psr/log": "~1.0",
|
"psr/log": "~1.0"
|
||||||
"ircmaxell/password-compat": "1.0.*",
|
|
||||||
"symfony/ldap": "~2.8|~3.0.0"
|
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
"symfony/event-dispatcher": "",
|
"symfony/event-dispatcher": "",
|
||||||
"symfony/http-foundation": "",
|
"symfony/http-foundation": "",
|
||||||
"symfony/validator": "For using the user password constraint",
|
"symfony/validator": "For using the user password constraint",
|
||||||
"symfony/expression-language": "For using the expression voter",
|
"symfony/expression-language": "For using the expression voter",
|
||||||
"symfony/ldap": "For using LDAP integration",
|
"symfony/ldap": "For using LDAP integration"
|
||||||
"ircmaxell/password-compat": "For using the BCrypt password encoder in PHP <5.5"
|
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": { "Symfony\\Component\\Security\\Core\\": "" }
|
"psr-4": { "Symfony\\Component\\Security\\Core\\": "" }
|
||||||
|
@ -11,7 +11,6 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\Security\Csrf;
|
namespace Symfony\Component\Security\Csrf;
|
||||||
|
|
||||||
use Symfony\Component\Security\Core\Util\StringUtils;
|
|
||||||
use Symfony\Component\Security\Csrf\TokenGenerator\UriSafeTokenGenerator;
|
use Symfony\Component\Security\Csrf\TokenGenerator\UriSafeTokenGenerator;
|
||||||
use Symfony\Component\Security\Csrf\TokenGenerator\TokenGeneratorInterface;
|
use Symfony\Component\Security\Csrf\TokenGenerator\TokenGeneratorInterface;
|
||||||
use Symfony\Component\Security\Csrf\TokenStorage\NativeSessionTokenStorage;
|
use Symfony\Component\Security\Csrf\TokenStorage\NativeSessionTokenStorage;
|
||||||
@ -92,6 +91,6 @@ class CsrfTokenManager implements CsrfTokenManagerInterface
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return StringUtils::equals($this->storage->getToken($token->getId()), $token->getValue());
|
return hash_equals($this->storage->getToken($token->getId()), $token->getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,8 +17,8 @@
|
|||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.3.9",
|
"php": ">=5.3.9",
|
||||||
"symfony/security-core": "~2.4|~3.0.0",
|
"symfony/polyfill-php56": "~1.0",
|
||||||
"paragonie/random_compat": "~1.0"
|
"symfony/security-core": "~2.4|~3.0.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"symfony/http-foundation": "~2.1|~3.0.0"
|
"symfony/http-foundation": "~2.1|~3.0.0"
|
||||||
|
@ -17,7 +17,6 @@ use Symfony\Component\HttpFoundation\Response;
|
|||||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||||
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||||
use Symfony\Component\Security\Core\User\UserInterface;
|
use Symfony\Component\Security\Core\User\UserInterface;
|
||||||
use Symfony\Component\Security\Core\Util\StringUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Concrete implementation of the RememberMeServicesInterface providing
|
* Concrete implementation of the RememberMeServicesInterface providing
|
||||||
@ -54,7 +53,7 @@ class TokenBasedRememberMeServices extends AbstractRememberMeServices
|
|||||||
throw new \RuntimeException(sprintf('The UserProviderInterface implementation must return an instance of UserInterface, but returned "%s".', get_class($user)));
|
throw new \RuntimeException(sprintf('The UserProviderInterface implementation must return an instance of UserInterface, but returned "%s".', get_class($user)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (true !== StringUtils::equals($this->generateCookieHash($class, $username, $expires, $user->getPassword()), $hash)) {
|
if (true !== hash_equals($this->generateCookieHash($class, $username, $expires, $user->getPassword()), $hash)) {
|
||||||
throw new AuthenticationException('The cookie\'s hash is invalid.');
|
throw new AuthenticationException('The cookie\'s hash is invalid.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,8 +21,9 @@
|
|||||||
"symfony/event-dispatcher": "~2.1|~3.0.0",
|
"symfony/event-dispatcher": "~2.1|~3.0.0",
|
||||||
"symfony/http-foundation": "~2.4|~3.0.0",
|
"symfony/http-foundation": "~2.4|~3.0.0",
|
||||||
"symfony/http-kernel": "~2.4|~3.0.0",
|
"symfony/http-kernel": "~2.4|~3.0.0",
|
||||||
"symfony/property-access": "~2.3|~3.0.0",
|
"symfony/polyfill-php56": "~1.0",
|
||||||
"paragonie/random_compat": "~1.0"
|
"symfony/polyfill-php70": "~1.0",
|
||||||
|
"symfony/property-access": "~2.3|~3.0.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"symfony/routing": "~2.2|~3.0.0",
|
"symfony/routing": "~2.2|~3.0.0",
|
||||||
|
@ -21,8 +21,11 @@
|
|||||||
"symfony/event-dispatcher": "~2.2|~3.0.0",
|
"symfony/event-dispatcher": "~2.2|~3.0.0",
|
||||||
"symfony/http-foundation": "~2.1|~3.0.0",
|
"symfony/http-foundation": "~2.1|~3.0.0",
|
||||||
"symfony/http-kernel": "~2.4|~3.0.0",
|
"symfony/http-kernel": "~2.4|~3.0.0",
|
||||||
"symfony/property-access": "~2.3|~3.0.0",
|
"symfony/polyfill-php55": "~1.0",
|
||||||
"paragonie/random_compat": "~1.0"
|
"symfony/polyfill-php56": "~1.0",
|
||||||
|
"symfony/polyfill-php70": "~1.0",
|
||||||
|
"symfony/polyfill-util": "~1.0",
|
||||||
|
"symfony/property-access": "~2.3|~3.0.0"
|
||||||
},
|
},
|
||||||
"replace": {
|
"replace": {
|
||||||
"symfony/security-core": "self.version",
|
"symfony/security-core": "self.version",
|
||||||
@ -32,14 +35,13 @@
|
|||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"symfony/finder": "~2.3|~3.0.0",
|
"symfony/finder": "~2.3|~3.0.0",
|
||||||
"symfony/intl": "~2.3|~3.0.0",
|
"symfony/polyfill-intl-icu": "~1.0",
|
||||||
"symfony/routing": "~2.2|~3.0.0",
|
"symfony/routing": "~2.2|~3.0.0",
|
||||||
"symfony/translation": "~2.0,>=2.0.5|~3.0.0",
|
"symfony/translation": "~2.0,>=2.0.5|~3.0.0",
|
||||||
"symfony/validator": "~2.5,>=2.5.5|~3.0.0",
|
"symfony/validator": "~2.5,>=2.5.5|~3.0.0",
|
||||||
"doctrine/common": "~2.2",
|
"doctrine/common": "~2.2",
|
||||||
"doctrine/dbal": "~2.2",
|
"doctrine/dbal": "~2.2",
|
||||||
"psr/log": "~1.0",
|
"psr/log": "~1.0",
|
||||||
"ircmaxell/password-compat": "~1.0",
|
|
||||||
"symfony/expression-language": "~2.6|~3.0.0",
|
"symfony/expression-language": "~2.6|~3.0.0",
|
||||||
"symfony/ldap": "~2.8|~3.0.0"
|
"symfony/ldap": "~2.8|~3.0.0"
|
||||||
},
|
},
|
||||||
@ -50,7 +52,6 @@
|
|||||||
"symfony/validator": "For using the user password constraint",
|
"symfony/validator": "For using the user password constraint",
|
||||||
"symfony/routing": "For using the HttpUtils class to create sub-requests, redirect the user, and match URLs",
|
"symfony/routing": "For using the HttpUtils class to create sub-requests, redirect the user, and match URLs",
|
||||||
"symfony/expression-language": "For using the expression voter",
|
"symfony/expression-language": "For using the expression voter",
|
||||||
"ircmaxell/password-compat": "For using the BCrypt password encoder in PHP <5.5",
|
|
||||||
"symfony/ldap": "For using the LDAP user and authentication providers"
|
"symfony/ldap": "For using the LDAP user and authentication providers"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
@ -108,7 +108,7 @@ class JsonDecode implements DecoderInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (JSON_ERROR_NONE !== $this->lastError = json_last_error()) {
|
if (JSON_ERROR_NONE !== $this->lastError = json_last_error()) {
|
||||||
throw new UnexpectedValueException(JsonEncoder::getLastErrorMessage());
|
throw new UnexpectedValueException(json_last_error_message());
|
||||||
}
|
}
|
||||||
|
|
||||||
return $decodedData;
|
return $decodedData;
|
||||||
|
@ -56,7 +56,7 @@ class JsonEncode implements EncoderInterface
|
|||||||
$encodedJson = json_encode($data, $context['json_encode_options']);
|
$encodedJson = json_encode($data, $context['json_encode_options']);
|
||||||
|
|
||||||
if (JSON_ERROR_NONE !== $this->lastError = json_last_error()) {
|
if (JSON_ERROR_NONE !== $this->lastError = json_last_error()) {
|
||||||
throw new UnexpectedValueException(JsonEncoder::getLastErrorMessage());
|
throw new UnexpectedValueException(json_last_error_message());
|
||||||
}
|
}
|
||||||
|
|
||||||
return $encodedJson;
|
return $encodedJson;
|
||||||
|
@ -100,26 +100,13 @@ class JsonEncoder implements EncoderInterface, DecoderInterface
|
|||||||
* Resolves json_last_error message.
|
* Resolves json_last_error message.
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
|
*
|
||||||
|
* @deprecated since 2.8, to be removed in 3.0. Use json_last_error_msg() instead.
|
||||||
*/
|
*/
|
||||||
public static function getLastErrorMessage()
|
public static function getLastErrorMessage()
|
||||||
{
|
{
|
||||||
if (function_exists('json_last_error_msg')) {
|
@trigger_error('The '.__METHOD__.' method is deprecated since version 2.8 and will be removed in 3.0. Use json_last_error_msg() instead.', E_USER_DEPRECATED);
|
||||||
|
|
||||||
return json_last_error_msg();
|
return json_last_error_msg();
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (json_last_error()) {
|
|
||||||
case JSON_ERROR_DEPTH:
|
|
||||||
return 'Maximum stack depth exceeded';
|
|
||||||
case JSON_ERROR_STATE_MISMATCH:
|
|
||||||
return 'Underflow or the modes mismatch';
|
|
||||||
case JSON_ERROR_CTRL_CHAR:
|
|
||||||
return 'Unexpected control character found';
|
|
||||||
case JSON_ERROR_SYNTAX:
|
|
||||||
return 'Syntax error, malformed JSON';
|
|
||||||
case JSON_ERROR_UTF8:
|
|
||||||
return 'Malformed UTF-8 characters, possibly incorrectly encoded';
|
|
||||||
default:
|
|
||||||
return 'Unknown error';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,8 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.3.9"
|
"php": ">=5.3.9",
|
||||||
|
"symfony/polyfill-php54": "~1.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"symfony/yaml": "~2.0,>=2.0.5|~3.0.0",
|
"symfony/yaml": "~2.0,>=2.0.5|~3.0.0",
|
||||||
|
@ -330,6 +330,9 @@ class PhpEngine implements EngineInterface, \ArrayAccess
|
|||||||
*/
|
*/
|
||||||
public function setCharset($charset)
|
public function setCharset($charset)
|
||||||
{
|
{
|
||||||
|
if ('UTF8' === $charset = strtoupper($charset)) {
|
||||||
|
$charset = 'UTF-8'; // iconv on Windows requires "UTF-8" instead of "UTF8"
|
||||||
|
}
|
||||||
$this->charset = $charset;
|
$this->charset = $charset;
|
||||||
|
|
||||||
foreach ($this->helpers as $helper) {
|
foreach ($this->helpers as $helper) {
|
||||||
@ -448,7 +451,7 @@ class PhpEngine implements EngineInterface, \ArrayAccess
|
|||||||
*/
|
*/
|
||||||
function ($value) use ($that) {
|
function ($value) use ($that) {
|
||||||
if ('UTF-8' != $that->getCharset()) {
|
if ('UTF-8' != $that->getCharset()) {
|
||||||
$value = $that->convertEncoding($value, 'UTF-8', $that->getCharset());
|
$value = iconv($that->getCharset(), 'UTF-8', $value);
|
||||||
}
|
}
|
||||||
|
|
||||||
$callback = function ($matches) use ($that) {
|
$callback = function ($matches) use ($that) {
|
||||||
@ -460,7 +463,7 @@ class PhpEngine implements EngineInterface, \ArrayAccess
|
|||||||
}
|
}
|
||||||
|
|
||||||
// \uHHHH
|
// \uHHHH
|
||||||
$char = $that->convertEncoding($char, 'UTF-16BE', 'UTF-8');
|
$char = iconv('UTF-8', 'UTF-16BE', $char);
|
||||||
|
|
||||||
return '\\u'.substr('0000'.bin2hex($char), -4);
|
return '\\u'.substr('0000'.bin2hex($char), -4);
|
||||||
};
|
};
|
||||||
@ -470,7 +473,7 @@ class PhpEngine implements EngineInterface, \ArrayAccess
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ('UTF-8' != $that->getCharset()) {
|
if ('UTF-8' != $that->getCharset()) {
|
||||||
$value = $that->convertEncoding($value, $that->getCharset(), 'UTF-8');
|
$value = iconv('UTF-8', $that->getCharset(), $value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $value;
|
return $value;
|
||||||
@ -489,17 +492,13 @@ class PhpEngine implements EngineInterface, \ArrayAccess
|
|||||||
*
|
*
|
||||||
* @return string The string with the new encoding
|
* @return string The string with the new encoding
|
||||||
*
|
*
|
||||||
* @throws \RuntimeException if no suitable encoding function is found (iconv or mbstring)
|
* @deprecated since 2.8, to be removed in 3.0. Use iconv() instead.
|
||||||
*/
|
*/
|
||||||
public function convertEncoding($string, $to, $from)
|
public function convertEncoding($string, $to, $from)
|
||||||
{
|
{
|
||||||
if (function_exists('mb_convert_encoding')) {
|
@trigger_error('The '.__METHOD__.' method is deprecated since version 2.8 and will be removed in 3.0. Use iconv() instead.', E_USER_DEPRECATED);
|
||||||
return mb_convert_encoding($string, $to, $from);
|
|
||||||
} elseif (function_exists('iconv')) {
|
|
||||||
return iconv($from, $to, $string);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new \RuntimeException('No suitable convert encoding function (use UTF-8 as your encoding or install the iconv or mbstring extension).');
|
return iconv($from, $to, $string);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -137,7 +137,7 @@ class TranslationDataCollector extends DataCollector implements LateDataCollecto
|
|||||||
{
|
{
|
||||||
$string = trim(preg_replace('/\s+/', ' ', $string));
|
$string = trim(preg_replace('/\s+/', ' ', $string));
|
||||||
|
|
||||||
if (function_exists('mb_strlen') && false !== $encoding = mb_detect_encoding($string)) {
|
if (false !== $encoding = mb_detect_encoding($string, null, true)) {
|
||||||
if (mb_strlen($string, $encoding) > $length) {
|
if (mb_strlen($string, $encoding) > $length) {
|
||||||
return mb_substr($string, 0, $length - 3, $encoding).'...';
|
return mb_substr($string, 0, $length - 3, $encoding).'...';
|
||||||
}
|
}
|
||||||
|
@ -153,17 +153,9 @@ class XliffFileLoader implements LoaderInterface
|
|||||||
private function utf8ToCharset($content, $encoding = null)
|
private function utf8ToCharset($content, $encoding = null)
|
||||||
{
|
{
|
||||||
if ('UTF-8' !== $encoding && !empty($encoding)) {
|
if ('UTF-8' !== $encoding && !empty($encoding)) {
|
||||||
if (function_exists('mb_convert_encoding')) {
|
|
||||||
return mb_convert_encoding($content, $encoding, 'UTF-8');
|
return mb_convert_encoding($content, $encoding, 'UTF-8');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (function_exists('iconv')) {
|
|
||||||
return iconv('UTF-8', $encoding, $content);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new \RuntimeException('No suitable convert encoding function (use UTF-8 as your encoding or install the iconv or mbstring extension).');
|
|
||||||
}
|
|
||||||
|
|
||||||
return $content;
|
return $content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,9 +16,6 @@ use Symfony\Component\Translation\Dumper\IcuResFileDumper;
|
|||||||
|
|
||||||
class IcuResFileDumperTest extends \PHPUnit_Framework_TestCase
|
class IcuResFileDumperTest extends \PHPUnit_Framework_TestCase
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* @requires extension mbstring
|
|
||||||
*/
|
|
||||||
public function testFormatCatalogue()
|
public function testFormatCatalogue()
|
||||||
{
|
{
|
||||||
$catalogue = new MessageCatalogue('en');
|
$catalogue = new MessageCatalogue('en');
|
||||||
|
@ -59,9 +59,6 @@ class XliffFileLoaderTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertEquals(array('foo' => 'bar', 'extra' => 'extra', 'key' => '', 'test' => 'with'), $catalogue->all('domain1'));
|
$this->assertEquals(array('foo' => 'bar', 'extra' => 'extra', 'key' => '', 'test' => 'with'), $catalogue->all('domain1'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @requires extension mbstring
|
|
||||||
*/
|
|
||||||
public function testEncoding()
|
public function testEncoding()
|
||||||
{
|
{
|
||||||
$loader = new XliffFileLoader();
|
$loader = new XliffFileLoader();
|
||||||
|
@ -16,7 +16,8 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.3.9"
|
"php": ">=5.3.9",
|
||||||
|
"symfony/polyfill-mbstring": "~1.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"symfony/config": "~2.8",
|
"symfony/config": "~2.8",
|
||||||
|
@ -42,29 +42,11 @@ class LengthValidator extends ConstraintValidator
|
|||||||
$invalidCharset = false;
|
$invalidCharset = false;
|
||||||
|
|
||||||
if ('UTF8' === $charset = strtoupper($constraint->charset)) {
|
if ('UTF8' === $charset = strtoupper($constraint->charset)) {
|
||||||
$charset = 'UTF-8';
|
$charset = 'UTF-8'; // iconv on Windows requires "UTF-8" instead of "UTF8"
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('UTF-8' === $charset) {
|
$length = @iconv_strlen($stringValue, $charset);
|
||||||
if (!preg_match('//u', $stringValue)) {
|
|
||||||
$invalidCharset = true;
|
|
||||||
} elseif (function_exists('utf8_decode')) {
|
|
||||||
$length = strlen(utf8_decode($stringValue));
|
|
||||||
} else {
|
|
||||||
preg_replace('/./u', '', $stringValue, -1, $length);
|
|
||||||
}
|
|
||||||
} elseif (function_exists('mb_strlen')) {
|
|
||||||
if (@mb_check_encoding($stringValue, $constraint->charset)) {
|
|
||||||
$length = mb_strlen($stringValue, $constraint->charset);
|
|
||||||
} else {
|
|
||||||
$invalidCharset = true;
|
|
||||||
}
|
|
||||||
} elseif (function_exists('iconv_strlen')) {
|
|
||||||
$length = @iconv_strlen($stringValue, $constraint->charset);
|
|
||||||
$invalidCharset = false === $length;
|
$invalidCharset = false === $length;
|
||||||
} else {
|
|
||||||
$length = strlen($stringValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($invalidCharset) {
|
if ($invalidCharset) {
|
||||||
if ($this->context instanceof ExecutionContextInterface) {
|
if ($this->context instanceof ExecutionContextInterface) {
|
||||||
|
@ -87,9 +87,6 @@ class LengthValidatorTest extends AbstractConstraintValidatorTest
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @requires extension mbstring
|
|
||||||
*/
|
|
||||||
public function getOneCharset()
|
public function getOneCharset()
|
||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
|
@ -48,7 +48,7 @@ class CutStub extends Stub
|
|||||||
case 'string':
|
case 'string':
|
||||||
$this->type = self::TYPE_STRING;
|
$this->type = self::TYPE_STRING;
|
||||||
$this->class = preg_match('//u', $value) ? self::STRING_UTF8 : self::STRING_BINARY;
|
$this->class = preg_match('//u', $value) ? self::STRING_UTF8 : self::STRING_BINARY;
|
||||||
$this->cut = self::STRING_BINARY === $this->class ? strlen($value) : (function_exists('iconv_strlen') ? iconv_strlen($value, 'UTF-8') : -1);
|
$this->cut = self::STRING_BINARY === $this->class ? strlen($value) : mb_strlen($value, 'UTF-8');
|
||||||
$this->value = '';
|
$this->value = '';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -185,9 +185,6 @@ abstract class AbstractCloner implements ClonerInterface
|
|||||||
$this->filter = $filter;
|
$this->filter = $filter;
|
||||||
$this->prevErrorHandler = set_error_handler(array($this, 'handleError'));
|
$this->prevErrorHandler = set_error_handler(array($this, 'handleError'));
|
||||||
try {
|
try {
|
||||||
if (!function_exists('iconv')) {
|
|
||||||
$this->maxString = -1;
|
|
||||||
}
|
|
||||||
$data = $this->doClone($var);
|
$data = $this->doClone($var);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,6 @@ abstract class AbstractDumper implements DataDumperInterface, DumperInterface
|
|||||||
protected $indentPad = ' ';
|
protected $indentPad = ' ';
|
||||||
|
|
||||||
private $charset;
|
private $charset;
|
||||||
private $charsetConverter;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param callable|resource|string|null $output A line dumper callable, an opened stream or an output path, defaults to static::$defaultOutput.
|
* @param callable|resource|string|null $output A line dumper callable, an opened stream or an output path, defaults to static::$defaultOutput.
|
||||||
@ -82,29 +81,11 @@ abstract class AbstractDumper implements DataDumperInterface, DumperInterface
|
|||||||
public function setCharset($charset)
|
public function setCharset($charset)
|
||||||
{
|
{
|
||||||
$prev = $this->charset;
|
$prev = $this->charset;
|
||||||
$this->charsetConverter = 'fallback';
|
|
||||||
|
|
||||||
$charset = strtoupper($charset);
|
$charset = strtoupper($charset);
|
||||||
$charset = null === $charset || 'UTF-8' === $charset || 'UTF8' === $charset ? 'CP1252' : $charset;
|
$charset = null === $charset || 'UTF-8' === $charset || 'UTF8' === $charset ? 'CP1252' : $charset;
|
||||||
|
|
||||||
$supported = true;
|
|
||||||
set_error_handler(function () use (&$supported) {$supported = false;});
|
|
||||||
|
|
||||||
if (function_exists('mb_encoding_aliases') && mb_encoding_aliases($charset)) {
|
|
||||||
$this->charset = $charset;
|
$this->charset = $charset;
|
||||||
$this->charsetConverter = 'mbstring';
|
|
||||||
} elseif (function_exists('iconv')) {
|
|
||||||
$supported = true;
|
|
||||||
iconv($charset, 'UTF-8', '');
|
|
||||||
if ($supported) {
|
|
||||||
$this->charset = $charset;
|
|
||||||
$this->charsetConverter = 'iconv';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ('fallback' === $this->charsetConverter) {
|
|
||||||
$this->charset = 'ISO-8859-1';
|
|
||||||
}
|
|
||||||
restore_error_handler();
|
|
||||||
|
|
||||||
return $prev;
|
return $prev;
|
||||||
}
|
}
|
||||||
@ -183,40 +164,13 @@ abstract class AbstractDumper implements DataDumperInterface, DumperInterface
|
|||||||
*/
|
*/
|
||||||
protected function utf8Encode($s)
|
protected function utf8Encode($s)
|
||||||
{
|
{
|
||||||
if ('mbstring' === $this->charsetConverter) {
|
if (false !== $c = @iconv($this->charset, 'UTF-8', $s)) {
|
||||||
return mb_convert_encoding($s, 'UTF-8', mb_check_encoding($s, $this->charset) ? $this->charset : '8bit');
|
|
||||||
}
|
|
||||||
if ('iconv' === $this->charsetConverter) {
|
|
||||||
$valid = true;
|
|
||||||
set_error_handler(function () use (&$valid) {$valid = false;});
|
|
||||||
$c = iconv($this->charset, 'UTF-8', $s);
|
|
||||||
restore_error_handler();
|
|
||||||
if ($valid) {
|
|
||||||
return $c;
|
return $c;
|
||||||
}
|
}
|
||||||
|
if ('CP1252' !== $this->charset && false !== $c = @iconv('CP1252', 'UTF-8', $s)) {
|
||||||
|
return $c;
|
||||||
}
|
}
|
||||||
|
|
||||||
$s .= $s;
|
return iconv('CP850', 'UTF-8', $s);
|
||||||
$len = strlen($s);
|
|
||||||
|
|
||||||
for ($i = $len >> 1, $j = 0; $i < $len; ++$i, ++$j) {
|
|
||||||
switch (true) {
|
|
||||||
case $s[$i] < "\x80":
|
|
||||||
$s[$j] = $s[$i];
|
|
||||||
break;
|
|
||||||
|
|
||||||
case $s[$i] < "\xC0":
|
|
||||||
$s[$j] = "\xC2";
|
|
||||||
$s[++$j] = $s[$i];
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
$s[$j] = "\xC3";
|
|
||||||
$s[++$j] = chr(ord($s[$i]) - 64);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return substr($s, 0, $j);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,10 +91,8 @@ class CliDumper extends AbstractDumper
|
|||||||
*/
|
*/
|
||||||
public function setMaxStringWidth($maxStringWidth)
|
public function setMaxStringWidth($maxStringWidth)
|
||||||
{
|
{
|
||||||
if (function_exists('iconv')) {
|
|
||||||
$this->maxStringWidth = (int) $maxStringWidth;
|
$this->maxStringWidth = (int) $maxStringWidth;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures styles.
|
* Configures styles.
|
||||||
@ -171,7 +169,7 @@ class CliDumper extends AbstractDumper
|
|||||||
$this->dumpLine($cursor->depth, true);
|
$this->dumpLine($cursor->depth, true);
|
||||||
} else {
|
} else {
|
||||||
$attr = array(
|
$attr = array(
|
||||||
'length' => 0 <= $cut && function_exists('iconv_strlen') ? iconv_strlen($str, 'UTF-8') + $cut : 0,
|
'length' => 0 <= $cut ? iconv_strlen($str, 'UTF-8') + $cut : 0,
|
||||||
'binary' => $bin,
|
'binary' => $bin,
|
||||||
);
|
);
|
||||||
$str = explode("\n", $str);
|
$str = explode("\n", $str);
|
||||||
|
@ -442,30 +442,7 @@ EOHTML;
|
|||||||
}
|
}
|
||||||
$this->lastDepth = $depth;
|
$this->lastDepth = $depth;
|
||||||
|
|
||||||
// Replaces non-ASCII UTF-8 chars by numeric HTML entities
|
$this->line = mb_convert_encoding($this->line, 'HTML-ENTITIES', 'UTF-8');
|
||||||
$this->line = preg_replace_callback(
|
|
||||||
'/[\x80-\xFF]+/',
|
|
||||||
function ($m) {
|
|
||||||
$m = unpack('C*', $m[0]);
|
|
||||||
$i = 1;
|
|
||||||
$entities = '';
|
|
||||||
|
|
||||||
while (isset($m[$i])) {
|
|
||||||
if (0xF0 <= $m[$i]) {
|
|
||||||
$c = (($m[$i++] - 0xF0) << 18) + (($m[$i++] - 0x80) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
|
|
||||||
} elseif (0xE0 <= $m[$i]) {
|
|
||||||
$c = (($m[$i++] - 0xE0) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
|
|
||||||
} else {
|
|
||||||
$c = (($m[$i++] - 0xC0) << 6) + $m[$i++] - 0x80;
|
|
||||||
}
|
|
||||||
|
|
||||||
$entities .= '&#'.$c.';';
|
|
||||||
}
|
|
||||||
|
|
||||||
return $entities;
|
|
||||||
},
|
|
||||||
$this->line
|
|
||||||
);
|
|
||||||
|
|
||||||
if (-1 === $depth) {
|
if (-1 === $depth) {
|
||||||
AbstractDumper::dumpLine(0);
|
AbstractDumper::dumpLine(0);
|
||||||
|
@ -52,7 +52,7 @@ class HtmlDumperTest extends \PHPUnit_Framework_TestCase
|
|||||||
$closure54 = <<<EOTXT
|
$closure54 = <<<EOTXT
|
||||||
|
|
||||||
<span class=sf-dump-meta>class</span>: "<span class=sf-dump-str title="48 characters">Symfony\Component\VarDumper\Tests\HtmlDumperTest</span>"
|
<span class=sf-dump-meta>class</span>: "<span class=sf-dump-str title="48 characters">Symfony\Component\VarDumper\Tests\HtmlDumperTest</span>"
|
||||||
<span class=sf-dump-meta>this</span>: <abbr title="Symfony\Component\VarDumper\Tests\HtmlDumperTest" class=sf-dump-note>HtmlDumperTest</abbr> {{$r} …}
|
<span class=sf-dump-meta>this</span>: <abbr title="Symfony\Component\VarDumper\Tests\HtmlDumperTest" class=sf-dump-note>HtmlDumperTest</abbr> {{$r} &%s;}
|
||||||
EOTXT;
|
EOTXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,8 +68,8 @@ EOTXT;
|
|||||||
<span class=sf-dump-key>4</span> => <span class=sf-dump-num>INF</span>
|
<span class=sf-dump-key>4</span> => <span class=sf-dump-num>INF</span>
|
||||||
<span class=sf-dump-key>5</span> => <span class=sf-dump-num>-INF</span>
|
<span class=sf-dump-key>5</span> => <span class=sf-dump-num>-INF</span>
|
||||||
<span class=sf-dump-key>6</span> => <span class=sf-dump-num>{$intMax}</span>
|
<span class=sf-dump-key>6</span> => <span class=sf-dump-num>{$intMax}</span>
|
||||||
"<span class=sf-dump-key>str</span>" => "<span class=sf-dump-str title="5 characters">déjà</span>\\n"
|
"<span class=sf-dump-key>str</span>" => "<span class=sf-dump-str title="5 characters">d&%s;j&%s;</span>\\n"
|
||||||
<span class=sf-dump-key>7</span> => b"<span class=sf-dump-str title="2 binary or non-UTF-8 characters">é</span>\\x00"
|
<span class=sf-dump-key>7</span> => b"<span class=sf-dump-str title="2 binary or non-UTF-8 characters">&%s;</span>\\x00"
|
||||||
"<span class=sf-dump-key>[]</span>" => []
|
"<span class=sf-dump-key>[]</span>" => []
|
||||||
"<span class=sf-dump-key>res</span>" => <span class=sf-dump-note>stream resource</span> <a class=sf-dump-ref>@{$res}</a><samp>
|
"<span class=sf-dump-key>res</span>" => <span class=sf-dump-note>stream resource</span> <a class=sf-dump-ref>@{$res}</a><samp>
|
||||||
<span class=sf-dump-meta>wrapper_type</span>: "<span class=sf-dump-str title="9 characters">plainfile</span>"
|
<span class=sf-dump-meta>wrapper_type</span>: "<span class=sf-dump-str title="9 characters">plainfile</span>"
|
||||||
@ -109,7 +109,7 @@ EOTXT;
|
|||||||
"<span class=sf-dump-key>snobj</span>" => <a class=sf-dump-ref href=#{$dumpId}-ref03 title="2 occurrences">&3</a> {<a class=sf-dump-ref href=#{$dumpId}-ref2%d title="3 occurrences">#%d</a>}
|
"<span class=sf-dump-key>snobj</span>" => <a class=sf-dump-ref href=#{$dumpId}-ref03 title="2 occurrences">&3</a> {<a class=sf-dump-ref href=#{$dumpId}-ref2%d title="3 occurrences">#%d</a>}
|
||||||
"<span class=sf-dump-key>snobj2</span>" => {<a class=sf-dump-ref href=#{$dumpId}-ref2%d title="3 occurrences">#%d</a>}
|
"<span class=sf-dump-key>snobj2</span>" => {<a class=sf-dump-ref href=#{$dumpId}-ref2%d title="3 occurrences">#%d</a>}
|
||||||
"<span class=sf-dump-key>file</span>" => "<span class=sf-dump-str title="%d characters">{$var['file']}</span>"
|
"<span class=sf-dump-key>file</span>" => "<span class=sf-dump-str title="%d characters">{$var['file']}</span>"
|
||||||
b"<span class=sf-dump-key>bin-key-é</span>" => ""
|
b"<span class=sf-dump-key>bin-key-&%s;</span>" => ""
|
||||||
</samp>]
|
</samp>]
|
||||||
</bar>
|
</bar>
|
||||||
|
|
||||||
@ -120,9 +120,6 @@ EOTXT
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @requires extension mbstring
|
|
||||||
*/
|
|
||||||
public function testCharset()
|
public function testCharset()
|
||||||
{
|
{
|
||||||
$var = mb_convert_encoding('Словарь', 'CP1251', 'UTF-8');
|
$var = mb_convert_encoding('Словарь', 'CP1251', 'UTF-8');
|
||||||
|
@ -16,7 +16,8 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.3.9"
|
"php": ">=5.3.9",
|
||||||
|
"symfony/polyfill-mbstring": "~1.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"twig/twig": "~1.20|~2.0"
|
"twig/twig": "~1.20|~2.0"
|
||||||
|
@ -52,7 +52,7 @@ class Inline
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (function_exists('mb_internal_encoding') && ((int) ini_get('mbstring.func_overload')) & 2) {
|
if (2 /* MB_OVERLOAD_STRING */ & (int) ini_get('mbstring.func_overload')) {
|
||||||
$mbEncoding = mb_internal_encoding();
|
$mbEncoding = mb_internal_encoding();
|
||||||
mb_internal_encoding('ASCII');
|
mb_internal_encoding('ASCII');
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ class Parser
|
|||||||
$value = $this->cleanup($value);
|
$value = $this->cleanup($value);
|
||||||
$this->lines = explode("\n", $value);
|
$this->lines = explode("\n", $value);
|
||||||
|
|
||||||
if (function_exists('mb_internal_encoding') && ((int) ini_get('mbstring.func_overload')) & 2) {
|
if (2 /* MB_OVERLOAD_STRING */ & (int) ini_get('mbstring.func_overload')) {
|
||||||
$mbEncoding = mb_internal_encoding();
|
$mbEncoding = mb_internal_encoding();
|
||||||
mb_internal_encoding('UTF-8');
|
mb_internal_encoding('UTF-8');
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user