From 59a30c3b721afdd7958718cf79496e1c5eafcbe7 Mon Sep 17 00:00:00 2001 From: Chris Boden Date: Tue, 12 Jan 2016 20:44:07 -0500 Subject: [PATCH] Replace slow validator with preg_match UTF8 check --- src/Encoding/NullValidator.php | 14 ---- src/Encoding/ToggleableValidator.php | 34 -------- src/Encoding/Validator.php | 93 --------------------- src/Encoding/ValidatorInterface.php | 15 ---- src/Handshake/Negotiator.php | 10 +-- src/Messaging/Streaming/MessageStreamer.php | 12 +-- tests/ab/clientRunner.php | 3 - tests/ab/startServer.php | 7 +- 8 files changed, 6 insertions(+), 182 deletions(-) delete mode 100644 src/Encoding/NullValidator.php delete mode 100644 src/Encoding/ToggleableValidator.php delete mode 100644 src/Encoding/Validator.php delete mode 100644 src/Encoding/ValidatorInterface.php diff --git a/src/Encoding/NullValidator.php b/src/Encoding/NullValidator.php deleted file mode 100644 index 6cc7515..0000000 --- a/src/Encoding/NullValidator.php +++ /dev/null @@ -1,14 +0,0 @@ -validationResponse; - } -} \ No newline at end of file diff --git a/src/Encoding/ToggleableValidator.php b/src/Encoding/ToggleableValidator.php deleted file mode 100644 index 3178bbc..0000000 --- a/src/Encoding/ToggleableValidator.php +++ /dev/null @@ -1,34 +0,0 @@ -validator = new Validator; - $this->on = (boolean)$on; - } - - /** - * {@inheritdoc} - */ - public function checkEncoding($str, $encoding) { - if (!(boolean)$this->on) { - return true; - } - - return $this->validator->checkEncoding($str, $encoding); - } -} diff --git a/src/Encoding/Validator.php b/src/Encoding/Validator.php deleted file mode 100644 index 5b2f7f4..0000000 --- a/src/Encoding/Validator.php +++ /dev/null @@ -1,93 +0,0 @@ -hasMbString = extension_loaded('mbstring'); - $this->hasIconv = extension_loaded('iconv'); - } - - /** - * @param string $str The value to check the encoding - * @param string $against The type of encoding to check against - * @return bool - */ - public function checkEncoding($str, $against) { - if ('UTF-8' === $against) { - return $this->isUtf8($str); - } - - if ($this->hasMbString) { - return mb_check_encoding($str, $against); - } elseif ($this->hasIconv) { - return ($str === iconv($against, "{$against}//IGNORE", $str)); - } - - return true; - } - - protected function isUtf8($str) { - if ($this->hasMbString) { - if (false === mb_check_encoding($str, 'UTF-8')) { - return false; - } - } elseif ($this->hasIconv) { - if ($str !== iconv('UTF-8', 'UTF-8//IGNORE', $str)) { - return false; - } - } - - $state = static::UTF8_ACCEPT; - - for ($i = 0, $len = strlen($str); $i < $len; $i++) { - $state = static::$dfa[256 + ($state << 4) + static::$dfa[ord($str[$i])]]; - - if (static::UTF8_REJECT === $state) { - return false; - } - } - - return true; - } -} diff --git a/src/Encoding/ValidatorInterface.php b/src/Encoding/ValidatorInterface.php deleted file mode 100644 index 3870157..0000000 --- a/src/Encoding/ValidatorInterface.php +++ /dev/null @@ -1,15 +0,0 @@ -verifier = new RequestVerifier; - - $this->validator = $validator; } /** diff --git a/src/Messaging/Streaming/MessageStreamer.php b/src/Messaging/Streaming/MessageStreamer.php index fea0c9f..e0ef3bd 100644 --- a/src/Messaging/Streaming/MessageStreamer.php +++ b/src/Messaging/Streaming/MessageStreamer.php @@ -1,6 +1,5 @@ validator = $encodingValidator; $this->closeFrameChecker = $frameChecker; $this->checkForMask = (bool)$expectMask; @@ -166,7 +158,7 @@ class MessageStreamer { return $this->newCloseFrame(Frame::CLOSE_PROTOCOL); } - if (!$this->validator->checkEncoding(substr($bin, 2), 'UTF-8')) { + if (!preg_match('//u', substr($bin, 2))) { return $this->newCloseFrame(Frame::CLOSE_BAD_PAYLOAD); } @@ -201,7 +193,7 @@ class MessageStreamer { */ public function checkMessage(MessageInterface $message) { if (!$message->isBinary()) { - if (!$this->validator->checkEncoding($message->getPayload(), 'UTF-8')) { + if (!preg_match('//u', $message->getPayload())) { return Frame::CLOSE_BAD_PAYLOAD; } } diff --git a/tests/ab/clientRunner.php b/tests/ab/clientRunner.php index 13a99a7..ee8897f 100644 --- a/tests/ab/clientRunner.php +++ b/tests/ab/clientRunner.php @@ -19,7 +19,6 @@ $factory = new \React\SocketClient\Connector($loop, $dnsResolver); function echoStreamerFactory($conn) { return new \Ratchet\RFC6455\Messaging\Streaming\MessageStreamer( - new \Ratchet\RFC6455\Encoding\Validator, new \Ratchet\RFC6455\Messaging\Protocol\CloseFrameChecker, function (\Ratchet\RFC6455\Messaging\Protocol\MessageInterface $msg) use ($conn) { /** @var Frame $frame */ @@ -72,7 +71,6 @@ function getTestCases() { $deferred->reject(); } else { $ms = new \Ratchet\RFC6455\Messaging\Streaming\MessageStreamer( - new \Ratchet\RFC6455\Encoding\Validator, new \Ratchet\RFC6455\Messaging\Protocol\CloseFrameChecker, function (\Ratchet\RFC6455\Messaging\Protocol\MessageInterface $msg) use ($deferred, $stream) { $deferred->resolve($msg->getPayload()); @@ -180,7 +178,6 @@ function createReport() { $deferred->reject(); } else { $ms = new \Ratchet\RFC6455\Messaging\Streaming\MessageStreamer( - new \Ratchet\RFC6455\Encoding\Validator, new \Ratchet\RFC6455\Messaging\Protocol\CloseFrameChecker, function (\Ratchet\RFC6455\Messaging\Protocol\MessageInterface $msg) use ($deferred, $stream) { $deferred->resolve($msg->getPayload()); diff --git a/tests/ab/startServer.php b/tests/ab/startServer.php index 58b7814..778318d 100644 --- a/tests/ab/startServer.php +++ b/tests/ab/startServer.php @@ -10,13 +10,12 @@ $loop = \React\EventLoop\Factory::create(); $socket = new \React\Socket\Server($loop); $server = new \React\Http\Server($socket); -$encodingValidator = new \Ratchet\RFC6455\Encoding\Validator; $closeFrameChecker = new \Ratchet\RFC6455\Messaging\Protocol\CloseFrameChecker; -$negotiator = new \Ratchet\RFC6455\Handshake\Negotiator($encodingValidator); +$negotiator = new \Ratchet\RFC6455\Handshake\Negotiator; $uException = new \UnderflowException; -$server->on('request', function (\React\Http\Request $request, \React\Http\Response $response) use ($negotiator, $encodingValidator, $closeFrameChecker, $uException) { +$server->on('request', function (\React\Http\Request $request, \React\Http\Response $response) use ($negotiator, $closeFrameChecker, $uException) { $psrRequest = new \GuzzleHttp\Psr7\Request($request->getMethod(), $request->getPath(), $request->getHeaders()); $negotiatorResponse = $negotiator->handshake($psrRequest); @@ -34,7 +33,7 @@ $server->on('request', function (\React\Http\Request $request, \React\Http\Respo return; } - $parser = new \Ratchet\RFC6455\Messaging\Streaming\MessageStreamer($encodingValidator, $closeFrameChecker, function(MessageInterface $message) use ($response) { + $parser = new \Ratchet\RFC6455\Messaging\Streaming\MessageStreamer($closeFrameChecker, function(MessageInterface $message) use ($response) { $response->write($message->getContents()); }, function(FrameInterface $frame) use ($response, &$parser) { switch ($frame->getOpCode()) {