From 96b9de6a65e26a581601396aa226bef485619a72 Mon Sep 17 00:00:00 2001 From: Jens Radtke Date: Sat, 6 Feb 2016 17:03:57 +0100 Subject: [PATCH 1/4] fix zero byte after full read will throw read exception (issue #39) --- src/Stomp/Connection.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Stomp/Connection.php b/src/Stomp/Connection.php index 87f4985..9358d88 100644 --- a/src/Stomp/Connection.php +++ b/src/Stomp/Connection.php @@ -320,7 +320,7 @@ public function readFrame() do { $read = @stream_get_line($this->connection, 8192, Parser::FRAME_END); - if ($read === false || $read === '') { + if ($read === false) { throw new ConnectionException('Was not possible to read data from stream.', $this->activeHost); } From b2db73143ed5d51410f302ad2db623d4cdcf53c7 Mon Sep 17 00:00:00 2001 From: Jens Radtke Date: Sun, 7 Feb 2016 17:52:36 +0100 Subject: [PATCH 2/4] allow to reset the parser state and buffer (issue #40) --- CHANGELOG.md | 7 ++++++- src/Stomp/Connection.php | 10 ++++++++++ src/Stomp/Parser.php | 14 ++++++++++++++ tests/Unit/Stomp/ParserTest.php | 19 +++++++++++++++++++ 4 files changed, 49 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a977e9..34ee4f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -64,4 +64,9 @@ Changelog stomp-php 3.0.5 ----- - - do not error when received header value is null (https://github.com/stomp-php/stomp-php/issues/30) \ No newline at end of file + - do not error when received header value is null (https://github.com/stomp-php/stomp-php/issues/30) + +3.0.6 +----- +- do not throw read exception if the next byte after a complete read is a zero byte. (https://github.com/stomp-php/stomp-php/issues/39) +- allow to reset the parser internal state and buffer. (https://github.com/stomp-php/stomp-php/issues/40) \ No newline at end of file diff --git a/src/Stomp/Connection.php b/src/Stomp/Connection.php index 9358d88..4d1f893 100644 --- a/src/Stomp/Connection.php +++ b/src/Stomp/Connection.php @@ -409,4 +409,14 @@ private function connectionHasDataToRead($timeoutSec, $timeoutMicros) return !empty($read); } + + /** + * Returns the used parser. + * + * @return Parser + */ + public function getParser() + { + return $this->parser; + } } diff --git a/src/Stomp/Parser.php b/src/Stomp/Parser.php index e30fdd6..ce4d0f3 100644 --- a/src/Stomp/Parser.php +++ b/src/Stomp/Parser.php @@ -164,4 +164,18 @@ private function getFrameEnd($offset) // No content-length, search for first 0-byte return strpos($this->buffer, self::FRAME_END, $offset); } + + /** + * Resets the buffer and all not delivered frames. + * Returns the not yet parsed buffer, which will be flushed. + * + * @return string + */ + public function flushBuffer() + { + $currentBuffer = $this->buffer; + $this->buffer = ''; + $this->frames = array(); + return $currentBuffer; + } } diff --git a/tests/Unit/Stomp/ParserTest.php b/tests/Unit/Stomp/ParserTest.php index 2abf9ca..74bf3f6 100644 --- a/tests/Unit/Stomp/ParserTest.php +++ b/tests/Unit/Stomp/ParserTest.php @@ -80,4 +80,23 @@ public function testParserOnFrameWithIncorrectHeaderValue() $this->assertEquals('var', $result->body); $this->assertEquals(true, $result->headers['header1 value1']); } + + public function testFlushResetsBufferAndReturnsCurrentlyNotParsedBuffer() + { + $msg = "CMD\nheader1:value1\n\n\nvar\x00"; + + $parser = new Parser(); + $parser->addData($msg); + $this->assertTrue($parser->parse()); + $this->assertTrue($parser->hasBufferedFrames()); + $parser->addData($msg); + $this->assertEquals($msg, $parser->flushBuffer()); + $this->assertFalse($parser->parse()); + $this->assertFalse($parser->hasBufferedFrames()); + + $parser->addData($msg); + $this->assertTrue($parser->parse()); + $result = $parser->getFrame(); + $this->assertInstanceOf('\Stomp\Frame', $result); + } } From e2de7979ab63fcf2a68e97cd9a8cc1b09cb2e740 Mon Sep 17 00:00:00 2001 From: Jens Radtke Date: Fri, 15 Sep 2017 19:04:20 +0200 Subject: [PATCH 3/4] add check for first available header marker #93 Otherwise carriage return + line feed will be used as marker, even if frame is escaped with line feed only. Thanks to @mattford --- src/Stomp/Parser.php | 21 +++++++++++++++++---- tests/Unit/Stomp/ParserTest.php | 28 ++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/src/Stomp/Parser.php b/src/Stomp/Parser.php index ce4d0f3..9020907 100644 --- a/src/Stomp/Parser.php +++ b/src/Stomp/Parser.php @@ -43,6 +43,13 @@ class Parser */ private $buffer = ''; + /** + * The frame header / content delimiter. + * + * @var string + */ + private $delimiter = null; + /** * Add data to parse. * @@ -104,7 +111,7 @@ public function parse() */ private function parseToFrame($source) { - list ($header, $body) = explode("\n\n", ltrim($source), 2); + list ($header, $body) = explode($this->delimiter, ltrim($source), 2); $header = explode("\n", $header); $headers = array(); $command = null; @@ -137,9 +144,12 @@ private function getFrameEnd($offset) $headerEnd = false; $activeMarker = false; foreach ($endMarkers as $marker) { - $activeMarker = $marker; - if (($headerEnd = strpos($this->buffer, $activeMarker, $offset)) !== false) { - break; + if (($markerPosition = strpos($this->buffer, $marker, $offset)) !== false) { + if ($headerEnd !== false && $headerEnd < $markerPosition) { + break; + } + $activeMarker = $marker; + $headerEnd = $markerPosition; } } @@ -148,6 +158,9 @@ private function getFrameEnd($offset) return false; } + // keep marker + $this->delimiter = $activeMarker; + $headers = substr($this->buffer, $offset, $headerEnd); // See if there is a content-length header diff --git a/tests/Unit/Stomp/ParserTest.php b/tests/Unit/Stomp/ParserTest.php index 74bf3f6..51711c0 100644 --- a/tests/Unit/Stomp/ParserTest.php +++ b/tests/Unit/Stomp/ParserTest.php @@ -99,4 +99,32 @@ public function testFlushResetsBufferAndReturnsCurrentlyNotParsedBuffer() $result = $parser->getFrame(); $this->assertInstanceOf('\Stomp\Frame', $result); } + + /** + * @see https://github.com/stomp-php/stomp-php/issues/93 + */ + public function testParserWhenHeaderStopSequenceWithCarriageReturnIsPartOfBody() + { + $parser = new Parser(); + $body = "{ \n\"value1\" : \"hello world\"\n,\n\n \"value2\" : \"2002-02-01\"\r\n\r\n}"; + $header = "MESSAGE\n\n"; + $parser->addData($header . $body . "\x00"); + $this->assertTrue($parser->parse()); + $message = $parser->getFrame(); + $this->assertEquals($body, $message->body); + } + + /** + * @see https://github.com/stomp-php/stomp-php/issues/93 + */ + public function testParserWhenHeaderStopSequenceWithoutCarriageReturnIsPartOfBody() + { + $parser = new Parser(); + $body = "{ \n\"value1\" : \"hello world\"\n,\n\n \"value2\" : \"2002-02-01\"\n\n}"; + $header = "MESSAGE\r\n\r\n"; + $parser->addData($header . $body . "\x00"); + $this->assertTrue($parser->parse()); + $message = $parser->getFrame(); + $this->assertEquals($body, $message->body); + } } From dd0cdd8aedb19e03d4d6585c50e32803b652696c Mon Sep 17 00:00:00 2001 From: Jens Radtke Date: Fri, 15 Sep 2017 20:09:36 +0200 Subject: [PATCH 4/4] fix for php5.3 builds on travis-ci --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 8f23f58..8dce43a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,6 @@ language: php sudo: false +dist: precise php: - "7.0" - "5.6"