diff --git a/src/BeSimple/SoapCommon/Mime/Boundary/MimeBoundaryAnalyser.php b/src/BeSimple/SoapCommon/Mime/Boundary/MimeBoundaryAnalyser.php index 5192d14..6aacb33 100644 --- a/src/BeSimple/SoapCommon/Mime/Boundary/MimeBoundaryAnalyser.php +++ b/src/BeSimple/SoapCommon/Mime/Boundary/MimeBoundaryAnalyser.php @@ -21,6 +21,7 @@ class MimeBoundaryAnalyser } /** + * @todo: This method is not reliable at all * @param string $mimeMessageLine * @return bool */ diff --git a/src/BeSimple/SoapCommon/Mime/Parser.php b/src/BeSimple/SoapCommon/Mime/Parser.php index c39b5ad..60f2f61 100644 --- a/src/BeSimple/SoapCommon/Mime/Parser.php +++ b/src/BeSimple/SoapCommon/Mime/Parser.php @@ -29,25 +29,16 @@ class Parser /** * Parse the given Mime-Message and return a \BeSimple\SoapCommon\Mime\MultiPart object. * - * @param string $mimeMessage Mime message string - * @param string[] $headers array(string=>string) of header elements (e.g. coming from http request) - * - * @return \BeSimple\SoapCommon\Mime\MultiPart + * @param string $mimeMessage Mime message string + * @param string[] $headers array(string=>string) of header elements (e.g. coming from http request) + * @return MultiPart */ public static function parseMimeMessage($mimeMessage, array $headers = []) { $multiPart = new MultiPart(); $mimeMessageLines = explode("\n", $mimeMessage); $mimeMessageLineCount = count($mimeMessageLines); - if ($mimeMessageLineCount <= 1) { - throw new Exception( - sprintf( - 'Cannot process message of %d characters: got unexpectable low number of lines: %s', - mb_strlen($mimeMessage), - (string)$mimeMessageLineCount - ) - ); - } + // add given headers, e.g. coming from HTTP headers if (count($headers) > 0) { self::setMultiPartHeaders($multiPart, $headers); @@ -56,6 +47,15 @@ class Parser $hasHttpRequestHeaders = ParsedPartsGetter::HAS_NO_HTTP_REQUEST_HEADERS; } if (MimeBoundaryAnalyser::hasMessageBoundary($mimeMessageLines) === true) { + if ($mimeMessageLineCount <= 1) { + throw new Exception( + sprintf( + 'Cannot parse MultiPart message of %d characters: got unexpectable low number of lines: %s', + mb_strlen($mimeMessage), + (string)$mimeMessageLineCount + ) + ); + } $parsedPartList = ParsedPartsGetter::getPartsFromMimeMessageLines( $multiPart, $mimeMessageLines, diff --git a/tests/BeSimple/SoapCommon/Mime/ParserTest.php b/tests/BeSimple/SoapCommon/Mime/ParserTest.php new file mode 100644 index 0000000..f7ad5a7 --- /dev/null +++ b/tests/BeSimple/SoapCommon/Mime/ParserTest.php @@ -0,0 +1,99 @@ +setExpectedException(Exception::class, $failedTestCaseFailMessage); + } + + $mimeMessage = Parser::parseMimeMessage($mimeMessage, $headers); + + if ($testCaseShouldFail === false) { + self::assertInstanceOf(MultiPart::class, $mimeMessage); + self::assertInstanceOf(Part::class, $mimeMessage->getMainPart()); + } + } + + public function provideMimeMessages() + { + return [ + 'ParseRequest' => [ + $this->getMimeMessageFromFile(__DIR__.'/../../../Fixtures/Message/Request/dummyServiceMethod.message.request'), + [], + self::TEST_CASE_SHOULD_NOT_FAIL + ], + 'ParseRequestOneLiner' => [ + $this->getMimeMessageFromFile(__DIR__.'/../../../Fixtures/Message/Request/dummyServiceMethod.oneliner.message.request'), + [], + self::TEST_CASE_SHOULD_NOT_FAIL + ], + 'ParseSwaResponseWith2FilesAnd1BinaryFile' => [ + $this->getMimeMessageFromFile(__DIR__.'/../../../Fixtures/Message/Response/dummyServiceMethodWithOutgoingLargeSwa.response.mimepart.message'), + [ + 'Content-Type' => 'multipart/related;'. + ' type="application/soap+xml"; charset=utf-8;'. + ' boundary=Part_13_58e3bc35f3743.58e3bc35f376f;'. + ' start=""' + ], + self::TEST_CASE_SHOULD_NOT_FAIL + ], + 'ParseSwaResponseWith2FilesAnd1BinaryFileShouldFailWithNoHeaders' => [ + $this->getMimeMessageFromFile(__DIR__.'/../../../Fixtures/Message/Response/dummyServiceMethodWithOutgoingLargeSwa.response.mimepart.message'), + [], + self::TEST_CASE_SHOULD_FAIL, + 'Unable to get Content-Type boundary' + ], + 'ParseSwaResponseWith2FilesAnd1BinaryFileShouldFailWithWrongHeaders' => [ + $this->getMimeMessageFromFile(__DIR__.'/../../../Fixtures/Message/Response/dummyServiceMethodWithOutgoingLargeSwa.response.mimepart.message'), + [ + 'Content-Type' => 'multipart/related; type="application/soap+xml"; charset=utf-8; boundary=DOES_NOT_EXIST; start=""' + ], + self::TEST_CASE_SHOULD_FAIL, + 'cannot parse headers before hitting the first boundary' + ], + 'ParseSwaRequestWith2Files' => [ + $this->getMimeMessageFromFile(__DIR__ . '/../../../Fixtures/Message/Request/dummyServiceMethodWithAttachments.request.mimepart.message'), + [ + 'Content-Type' => 'multipart/related; type="application/soap+xml"; charset=utf-8; boundary=----=_Part_6_2094841787.1482231370463; start=""' + ], + self::TEST_CASE_SHOULD_NOT_FAIL + ], + 'ParseSwaRequestWith2FilesShouldFailWithNoHeaders' => [ + $this->getMimeMessageFromFile(__DIR__ . '/../../../Fixtures/Message/Request/dummyServiceMethodWithAttachments.request.mimepart.message'), + [], + self::TEST_CASE_SHOULD_FAIL, + 'Unable to get Content-Type boundary' + ], + ]; + } + + private function getMimeMessageFromFile($filePath) + { + if (file_exists($filePath) === false) { + self::fail('Please, update tests data provider - file not found: '.$filePath); + } + + return file_get_contents($filePath); + } +} diff --git a/tests/Fixtures/Message/Request/dummyServiceMethod.oneliner.message.request b/tests/Fixtures/Message/Request/dummyServiceMethod.oneliner.message.request new file mode 100644 index 0000000..8ab0658 --- /dev/null +++ b/tests/Fixtures/Message/Request/dummyServiceMethod.oneliner.message.request @@ -0,0 +1 @@ +admin1 \ No newline at end of file