diff --git a/lib/Raven/Serializer.php b/lib/Raven/Serializer.php index 9573ebde8..c93dfdf27 100644 --- a/lib/Raven/Serializer.php +++ b/lib/Raven/Serializer.php @@ -94,19 +94,23 @@ public function serialize($value, $max_depth = 3, $_depth = 0) protected function serializeString($value) { $value = (string) $value; - if (function_exists('mb_detect_encoding') - && function_exists('mb_convert_encoding') - ) { + + // Check if mbstring extension is loaded + if (extension_loaded('mbstring')) { // we always guarantee this is coerced, even if we can't detect encoding if ($currentEncoding = mb_detect_encoding($value, $this->mb_detect_order)) { $value = mb_convert_encoding($value, 'UTF-8', $currentEncoding); } else { $value = mb_convert_encoding($value, 'UTF-8'); } - } - if (strlen($value) > $this->message_limit) { - $value = substr($value, 0, $this->message_limit - 10) . ' {clipped}'; + if (mb_strlen($value) > $this->message_limit) { + $value = mb_substr($value, 0, $this->message_limit - 10, 'UTF-8') . ' {clipped}'; + } + } else { + if (strlen($value) > $this->message_limit) { + $value = substr($value, 0, $this->message_limit - 10) . ' {clipped}'; + } } return $value; diff --git a/test/Raven/Tests/SerializerTest.php b/test/Raven/Tests/SerializerTest.php index 04a541774..21fe83f0f 100644 --- a/test/Raven/Tests/SerializerTest.php +++ b/test/Raven/Tests/SerializerTest.php @@ -121,8 +121,8 @@ public function testLongString() for ($i = 0; $i < 100; $i++) { foreach (array(100, 1000, 1010, 1024, 1050, 1100, 10000) as $length) { $input = ''; - for ($i = 0; $i < $length; $i++) { - $input .= chr(mt_rand(0, 255)); + for ($j = 0; $j < $length; $j++) { + $input .= chr(mt_rand(ord('a'), ord('z'))); } $result = $serializer->serialize($input); $this->assertInternalType('string', $result); @@ -141,8 +141,8 @@ public function testLongStringWithOverwrittenMessageLength() for ($i = 0; $i < 100; $i++) { foreach (array(100, 490, 499, 500, 501, 1000, 10000) as $length) { $input = ''; - for ($i = 0; $i < $length; $i++) { - $input .= chr(mt_rand(0, 255)); + for ($j = 0; $j < $length; $j++) { + $input .= chr(mt_rand(ord('a'), ord('z'))); } $result = $serializer->serialize($input); $this->assertInternalType('string', $result); @@ -164,4 +164,21 @@ public function testSerializeValueResource() $this->assertInternalType('string', $result); $this->assertEquals('Resource stream', $result); } + + public function testClippingUTF8Characters() + { + if (!extension_loaded('mbstring')) { + $this->markTestSkipped('mbstring extension is not enabled.'); + } + + $teststring = 'Прекратите надеяться, что ваши пользователи будут сообщать об ошибках'; + $serializer = new Raven_Serializer(null, 19); // Length of 19 will clip character in half if no mb_* string functions are used for the teststring + + $clipped = $serializer->serialize($teststring); + $this->assertEquals('Прекратит {clipped}', $clipped); + + Raven_Compat::json_encode($clipped); + + $this->assertEquals(JSON_ERROR_NONE, json_last_error()); + } }