diff --git a/cake/libs/http_response.php b/cake/libs/http_response.php index f0cc637c8..aea0133ae 100644 --- a/cake/libs/http_response.php +++ b/cake/libs/http_response.php @@ -69,6 +69,16 @@ class HttpResponse implements ArrayAccess { */ public $raw = ''; +/** + * Contructor + * + */ + public function __construct($message = null) { + if ($message !== null) { + $this->parseResponse($message); + } + } + /** * Body content * @@ -105,6 +115,245 @@ class HttpResponse implements ArrayAccess { return $this->code == 200; } +/** + * Parses the given message and breaks it down in parts. + * + * @param string $message Message to parse + * @return void + * @throw Exception + */ + public function parseResponse($message) { + if (!is_string($message)) { + throw new Exception(__('Invalid response.')); + } + + if (!preg_match("/^(.+\r\n)(.*)(?<=\r\n)\r\n/Us", $message, $match)) { + throw new Exception(__('Invalid HTTP response.')); + } + + list(, $statusLine, $header) = $match; + $this->raw = $message; + $this->body = (string)substr($message, strlen($match[0])); + + if (preg_match("/(.+) ([0-9]{3}) (.+)\r\n/DU", $statusLine, $match)) { + $this->httpVersion = $match[1]; + $this->code = $match[2]; + $this->reasonPhrase = $match[3]; + } + + $this->headers = $this->_parseHeader($header); + $transferEncoding = $this->getHeader('Transfer-Encoding'); + $decoded = $this->_decodeBody($this->body, $transferEncoding); + $this->body = $decoded['body']; + + if (!empty($decoded['header'])) { + $this->headers = $this->_parseHeader($this->_buildHeader($this->headers) . $this->_buildHeader($decoded['header'])); + } + + if (!empty($this->headers)) { + $this->cookies = $this->parseCookies($this->headers); + } + } + +/** + * Generic function to decode a $body with a given $encoding. Returns either an array with the keys + * 'body' and 'header' or false on failure. + * + * @param string $body A string continaing the body to decode. + * @param mixed $encoding Can be false in case no encoding is being used, or a string representing the encoding. + * @return mixed Array of response headers and body or false. + */ + protected function _decodeBody($body, $encoding = 'chunked') { + if (!is_string($body)) { + return false; + } + if (empty($encoding)) { + return array('body' => $body, 'header' => false); + } + $decodeMethod = '_decode' . Inflector::camelize(str_replace('-', '_', $encoding)) . 'Body'; + + if (!is_callable(array(&$this, $decodeMethod))) { + return array('body' => $body, 'header' => false); + } + return $this->{$decodeMethod}($body); + } + +/** + * Decodes a chunked message $body and returns either an array with the keys 'body' and 'header' or false as + * a result. + * + * @param string $body A string continaing the chunked body to decode. + * @return mixed Array of response headers and body or false. + * @throws Exception + */ + protected function _decodeChunkedBody($body) { + if (!is_string($body)) { + return false; + } + + $decodedBody = null; + $chunkLength = null; + + while ($chunkLength !== 0) { + if (!preg_match("/^([0-9a-f]+) *(?:;(.+)=(.+))?\r\n/iU", $body, $match)) { + throw new Exception(__('HttpSocket::_decodeChunkedBody - Could not parse malformed chunk.')); + } + + $chunkSize = 0; + $hexLength = 0; + $chunkExtensionName = ''; + $chunkExtensionValue = ''; + if (isset($match[0])) { + $chunkSize = $match[0]; + } + if (isset($match[1])) { + $hexLength = $match[1]; + } + if (isset($match[2])) { + $chunkExtensionName = $match[2]; + } + if (isset($match[3])) { + $chunkExtensionValue = $match[3]; + } + + $body = substr($body, strlen($chunkSize)); + $chunkLength = hexdec($hexLength); + $chunk = substr($body, 0, $chunkLength); + if (!empty($chunkExtensionName)) { + /** + * @todo See if there are popular chunk extensions we should implement + */ + } + $decodedBody .= $chunk; + if ($chunkLength !== 0) { + $body = substr($body, $chunkLength + strlen("\r\n")); + } + } + + $entityHeader = false; + if (!empty($body)) { + $entityHeader = $this->_parseHeader($body); + } + return array('body' => $decodedBody, 'header' => $entityHeader); + } + +/** + * Parses an array based header. + * + * @param array $header Header as an indexed array (field => value) + * @return array Parsed header + */ + protected function _parseHeader($header) { + if (is_array($header)) { + return $header; + } elseif (!is_string($header)) { + return false; + } + + preg_match_all("/(.+):(.+)(?:(?_unescapeToken($field); + + if (!isset($header[$field])) { + $header[$field] = $value; + } else { + $header[$field] = array_merge((array)$header[$field], (array)$value); + } + } + return $header; + } + +/** + * Parses cookies in response headers. + * + * @param array $header Header array containing one ore more 'Set-Cookie' headers. + * @return mixed Either false on no cookies, or an array of cookies recieved. + * @todo Make this 100% RFC 2965 confirm + */ + public function parseCookies($header) { + if (!isset($header['Set-Cookie'])) { + return false; + } + + $cookies = array(); + foreach ((array)$header['Set-Cookie'] as $cookie) { + if (strpos($cookie, '";"') !== false) { + $cookie = str_replace('";"', "{__cookie_replace__}", $cookie); + $parts = str_replace("{__cookie_replace__}", '";"', explode(';', $cookie)); + } else { + $parts = preg_split('/\;[ \t]*/', $cookie); + } + + list($name, $value) = explode('=', array_shift($parts), 2); + $cookies[$name] = compact('value'); + + foreach ($parts as $part) { + if (strpos($part, '=') !== false) { + list($key, $value) = explode('=', $part); + } else { + $key = $part; + $value = true; + } + + $key = strtolower($key); + if (!isset($cookies[$name][$key])) { + $cookies[$name][$key] = $value; + } + } + } + return $cookies; + } + +/** + * Unescapes a given $token according to RFC 2616 (HTTP 1.1 specs) + * + * @param string $token Token to unescape + * @param array $chars + * @return string Unescaped token + * @todo Test $chars parameter + */ + protected function _unescapeToken($token, $chars = null) { + $regex = '/"([' . implode('', $this->_tokenEscapeChars(true, $chars)) . '])"/'; + $token = preg_replace($regex, '\\1', $token); + return $token; + } + +/** + * Gets escape chars according to RFC 2616 (HTTP 1.1 specs). + * + * @param boolean $hex true to get them as HEX values, false otherwise + * @param array $chars + * @return array Escape chars + * @todo Test $chars parameter + */ + protected function _tokenEscapeChars($hex = true, $chars = null) { + if (!empty($chars)) { + $escape = $chars; + } else { + $escape = array('"', "(", ")", "<", ">", "@", ",", ";", ":", "\\", "/", "[", "]", "?", "=", "{", "}", " "); + for ($i = 0; $i <= 31; $i++) { + $escape[] = chr($i); + } + $escape[] = chr(127); + } + + if ($hex == false) { + return $escape; + } + $regexChars = ''; + foreach ($escape as $key => $char) { + $escape[$key] = '\\x' . str_pad(dechex(ord($char)), 2, '0', STR_PAD_LEFT); + } + return $escape; + } + /** * ArrayAccess - Offset Exists * diff --git a/cake/libs/http_socket.php b/cake/libs/http_socket.php index aa4769319..c226b574f 100644 --- a/cake/libs/http_socket.php +++ b/cake/libs/http_socket.php @@ -367,7 +367,7 @@ class HttpSocket extends CakeSocket { $this->disconnect(); } - $this->response = $this->_parseResponse($response); + $this->response = new HttpResponse($response); if (!empty($this->response->cookies)) { if (!isset($this->config['request']['cookies'][$Host])) { $this->config['request']['cookies'][$Host] = array(); @@ -566,137 +566,6 @@ class HttpSocket extends CakeSocket { call_user_func("$authClass::proxyAuthentication", $this, &$this->_proxy); } -/** - * Parses the given message and breaks it down in parts. - * - * @param string $message Message to parse - * @return object Parsed message as HttpResponse - */ - protected function _parseResponse($message) { - if (!is_string($message)) { - throw new Exception(__('Invalid response.')); - } - - if (!preg_match("/^(.+\r\n)(.*)(?<=\r\n)\r\n/Us", $message, $match)) { - throw new Exception(__('Invalid HTTP response.')); - } - - $response = new HttpResponse(); - - list(, $statusLine, $header) = $match; - $response->raw = $message; - $response->body = (string)substr($message, strlen($match[0])); - - if (preg_match("/(.+) ([0-9]{3}) (.+)\r\n/DU", $statusLine, $match)) { - $response->httpVersion = $match[1]; - $response->code = $match[2]; - $response->reasonPhrase = $match[3]; - } - - $response->headers = $this->_parseHeader($header); - $transferEncoding = $response->getHeader('Transfer-Encoding'); - $decoded = $this->_decodeBody($response->body, $transferEncoding); - $response->body = $decoded['body']; - - if (!empty($decoded['header'])) { - $response->headers = $this->_parseHeader($this->_buildHeader($response->headers) . $this->_buildHeader($decoded['header'])); - } - - if (!empty($response->headers)) { - $response->cookies = $this->parseCookies($response->headers); - } - - return $response; - } - -/** - * Generic function to decode a $body with a given $encoding. Returns either an array with the keys - * 'body' and 'header' or false on failure. - * - * @param string $body A string continaing the body to decode. - * @param mixed $encoding Can be false in case no encoding is being used, or a string representing the encoding. - * @return mixed Array of response headers and body or false. - */ - protected function _decodeBody($body, $encoding = 'chunked') { - if (!is_string($body)) { - return false; - } - if (empty($encoding)) { - return array('body' => $body, 'header' => false); - } - $decodeMethod = '_decode'.Inflector::camelize(str_replace('-', '_', $encoding)) . 'Body'; - - if (!is_callable(array(&$this, $decodeMethod))) { - if (!$this->quirksMode) { - trigger_error(sprintf(__('HttpSocket::_decodeBody - Unknown encoding: %s. Activate quirks mode to surpress error.'), h($encoding)), E_USER_WARNING); - } - return array('body' => $body, 'header' => false); - } - return $this->{$decodeMethod}($body); - } - -/** - * Decodes a chunked message $body and returns either an array with the keys 'body' and 'header' or false as - * a result. - * - * @param string $body A string continaing the chunked body to decode. - * @return mixed Array of response headers and body or false. - * @throws Exception - */ - protected function _decodeChunkedBody($body) { - if (!is_string($body)) { - return false; - } - - $decodedBody = null; - $chunkLength = null; - - while ($chunkLength !== 0) { - if (!preg_match("/^([0-9a-f]+) *(?:;(.+)=(.+))?\r\n/iU", $body, $match)) { - if (!$this->quirksMode) { - throw new Exception(__('HttpSocket::_decodeChunkedBody - Could not parse malformed chunk. Activate quirks mode to do this.')); - } - break; - } - - $chunkSize = 0; - $hexLength = 0; - $chunkExtensionName = ''; - $chunkExtensionValue = ''; - if (isset($match[0])) { - $chunkSize = $match[0]; - } - if (isset($match[1])) { - $hexLength = $match[1]; - } - if (isset($match[2])) { - $chunkExtensionName = $match[2]; - } - if (isset($match[3])) { - $chunkExtensionValue = $match[3]; - } - - $body = substr($body, strlen($chunkSize)); - $chunkLength = hexdec($hexLength); - $chunk = substr($body, 0, $chunkLength); - if (!empty($chunkExtensionName)) { - /** - * @todo See if there are popular chunk extensions we should implement - */ - } - $decodedBody .= $chunk; - if ($chunkLength !== 0) { - $body = substr($body, $chunkLength + strlen("\r\n")); - } - } - - $entityHeader = false; - if (!empty($body)) { - $entityHeader = $this->_parseHeader($body); - } - return array('body' => $decodedBody, 'header' => $entityHeader); - } - /** * Parses and sets the specified URI into current request configuration. * @@ -1002,7 +871,7 @@ class HttpSocket extends CakeSocket { return false; } - preg_match_all("/(.+):(.+)(?:(?lineBreak . "|\$)/Uis", $header, $matches, PREG_SET_ORDER); + preg_match_all("/(.+):(.+)(?:(?HttpResponse = new HttpResponse(); + $this->HttpResponse = new TestHttpResponse(); } /** @@ -102,6 +133,209 @@ class HttpResponseTest extends CakeTestCase { $this->assertTrue($this->HttpResponse->isOk()); } +/** + * testParseResponse method + * + * @return void + */ + public function testParseResponse() { + $tests = array( + 'simple-request' => array( + 'response' => array( + 'status-line' => "HTTP/1.x 200 OK\r\n", + 'header' => "Date: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\n", + 'body' => "

Hello World

\r\n

It's good to be html

" + ), + 'expectations' => array( + 'httpVersion' => 'HTTP/1.x', + 'code' => 200, + 'reasonPhrase' => 'OK', + 'headers' => array('Date' => 'Mon, 16 Apr 2007 04:14:16 GMT', 'Server' => 'CakeHttp Server'), + 'body' => "

Hello World

\r\n

It's good to be html

" + ) + ), + 'no-header' => array( + 'response' => array( + 'status-line' => "HTTP/1.x 404 OK\r\n", + 'header' => null + ), + 'expectations' => array( + 'code' => 404, + 'headers' => array() + ) + ) + ); + + $testResponse = array(); + $expectations = array(); + + foreach ($tests as $name => $test) { + $testResponse = array_merge($testResponse, $test['response']); + $testResponse['response'] = $testResponse['status-line'] . $testResponse['header'] . "\r\n" . $testResponse['body']; + $this->HttpResponse->parseResponse($testResponse['response']); + $expectations = array_merge($expectations, $test['expectations']); + + foreach ($expectations as $property => $expectedVal) { + $this->assertEquals($this->HttpResponse->{$property}, $expectedVal, 'Test "' . $name . '": response.' . $property . ' - %s'); + } + + foreach (array('status-line', 'header', 'body', 'response') as $field) { + $this->assertEquals($this->HttpResponse['raw'][$field], $testResponse[$field], 'Test response.raw.' . $field . ': %s'); + } + } + } + +/** + * data provider function for testInvalidParseResponseData + * + * @return array + */ + public static function invalidParseResponseDataProvider() { + return array( + array(array('foo' => 'bar')), + array(true), + array("HTTP Foo\r\nBar: La"), + array('HTTP/1.1 TEST ERROR') + ); + } + +/** + * testInvalidParseResponseData + * + * @dataProvider invalidParseResponseDataProvider + * @expectedException Exception + * return void + */ + public function testInvalidParseResponseData($value) { + $this->HttpResponse->parseResponse($value); + } + +/** + * testDecodeBody method + * + * @return void + */ + public function testDecodeBody() { + $r = $this->HttpResponse->decodeBody(true); + $this->assertEquals($r, false); + + $r = $this->HttpResponse->decodeBody('Foobar', false); + $this->assertEquals($r, array('body' => 'Foobar', 'header' => false)); + + $encoding = 'chunked'; + $sample = array( + 'encoded' => "19\r\nThis is a chunked message\r\n0\r\n", + 'decoded' => array('body' => "This is a chunked message", 'header' => false) + ); + + $r = $this->HttpResponse->decodeBody($sample['encoded'], $encoding); + $this->assertEquals($r, $sample['decoded']); + } + +/** + * testDecodeFooCoded + * + * @return void + */ + public function testDecodeFooCoded() { + $r = $this->HttpResponse->decodeBody(true); + $this->assertEquals($r, false); + + $r = $this->HttpResponse->decodeBody('Foobar', false); + $this->assertEquals($r, array('body' => 'Foobar', 'header' => false)); + + $encoding = 'foo-bar'; + $sample = array( + 'encoded' => '!Foobar!', + 'decoded' => array('body' => '!Foobar!', 'header' => false), + ); + + $r = $this->HttpResponse->decodeBody($sample['encoded'], $encoding); + $this->assertEquals($r, $sample['decoded']); + } + +/** + * testDecodeChunkedBody method + * + * @return void + */ + public function testDecodeChunkedBody() { + $r = $this->HttpResponse->decodeChunkedBody(true); + $this->assertEquals($r, false); + + $encoded = "19\r\nThis is a chunked message\r\n0\r\n"; + $decoded = "This is a chunked message"; + $r = $this->HttpResponse->decodeChunkedBody($encoded); + $this->assertEquals($r['body'], $decoded); + $this->assertEquals($r['header'], false); + + $encoded = "19 \r\nThis is a chunked message\r\n0\r\n"; + $r = $this->HttpResponse->decodeChunkedBody($encoded); + $this->assertEquals($r['body'], $decoded); + + $encoded = "19\r\nThis is a chunked message\r\nE\r\n\nThat is cool\n\r\n0\r\n"; + $decoded = "This is a chunked message\nThat is cool\n"; + $r = $this->HttpResponse->decodeChunkedBody($encoded); + $this->assertEquals($r['body'], $decoded); + $this->assertEquals($r['header'], false); + + $encoded = "19\r\nThis is a chunked message\r\nE;foo-chunk=5\r\n\nThat is cool\n\r\n0\r\n"; + $r = $this->HttpResponse->decodeChunkedBody($encoded); + $this->assertEquals($r['body'], $decoded); + $this->assertEquals($r['header'], false); + + $encoded = "19\r\nThis is a chunked message\r\nE\r\n\nThat is cool\n\r\n0\r\nfoo-header: bar\r\ncake: PHP\r\n\r\n"; + $r = $this->HttpResponse->decodeChunkedBody($encoded); + $this->assertEquals($r['body'], $decoded); + $this->assertEquals($r['header'], array('foo-header' => 'bar', 'cake' => 'PHP')); + + $encoded = "19\r\nThis is a chunked message\r\nE\r\n\nThat is cool\n\r\n"; + $this->expectError(); + $r = $this->HttpResponse->decodeChunkedBody($encoded); + $this->assertEquals($r, false); + } + +/** + * testParseCookies method + * + * @return void + */ + public function testParseCookies() { + $header = array( + 'Set-Cookie' => array( + 'foo=bar', + 'people=jim,jack,johnny";";Path=/accounts', + 'google=not=nice' + ), + 'Transfer-Encoding' => 'chunked', + 'Date' => 'Sun, 18 Nov 2007 18:57:42 GMT', + ); + $cookies = $this->HttpResponse->parseCookies($header); + $expected = array( + 'foo' => array( + 'value' => 'bar' + ), + 'people' => array( + 'value' => 'jim,jack,johnny";"', + 'path' => '/accounts', + ), + 'google' => array( + 'value' => 'not=nice', + ) + ); + $this->assertEqual($cookies, $expected); + + $header['Set-Cookie'][] = 'cakephp=great; Secure'; + $expected['cakephp'] = array('value' => 'great', 'secure' => true); + $cookies = $this->HttpResponse->parseCookies($header); + $this->assertEqual($cookies, $expected); + + $header['Set-Cookie'] = 'foo=bar'; + unset($expected['people'], $expected['cakephp'], $expected['google']); + $cookies = $this->HttpResponse->parseCookies($header); + $this->assertEqual($cookies, $expected); + } + /** * testArrayAccess * diff --git a/cake/tests/cases/libs/http_socket.test.php b/cake/tests/cases/libs/http_socket.test.php index 9dff42b8f..b6a540759 100644 --- a/cake/tests/cases/libs/http_socket.test.php +++ b/cake/tests/cases/libs/http_socket.test.php @@ -99,16 +99,6 @@ class TestHttpSocket extends HttpSocket { return parent::_buildHeader($header, $mode); } -/** - * Convenience method for testing protected method - * - * @param string $message Message to parse - * @return array Parsed message (with indexed elements such as raw, status, header, body) - */ - public function parseResponse($message) { - return parent::_parseResponse($message); - } - /** * Convenience method for testing protected method * @@ -129,27 +119,6 @@ class TestHttpSocket extends HttpSocket { return parent::_parseQuery($query); } -/** - * Convenience method for testing protected method - * - * @param string $body A string continaing the body to decode - * @param mixed $encoding Can be false in case no encoding is being used, or a string representing the encoding - * @return mixed Array or false - */ - public function decodeBody($body, $encoding = 'chunked') { - return parent::_decodeBody($body, $encoding); - } - -/** - * Convenience method for testing protected method - * - * @param string $body A string continaing the chunked body to decode - * @return mixed Array or false - */ - public function decodeChunkedBody($body) { - return parent::_decodeChunkedBody($body); - } - /** * Convenience method for testing protected method * @@ -191,18 +160,6 @@ class TestHttpSocket extends HttpSocket { return parent::_unescapeToken($token, $chars); } -/** - * Convenience method for testing protected method - * - * @param string $message - * @return object HttpResponse - */ - protected function _parseResponse($message) { - if (!is_string($message)) { - return false; - } - return parent::_parseResponse($message); - } } /** @@ -976,194 +933,6 @@ class HttpSocketTest extends CakeTestCase { $this->RequestSocket->delete('http://www.google.com/', null, array('line' => 'Hey Server')); } -/** - * testParseResponse method - * - * @return void - */ - public function testParseResponse() { - $this->Socket->reset(); - - $tests = array( - 'simple-request' => array( - 'response' => array( - 'status-line' => "HTTP/1.x 200 OK\r\n", - 'header' => "Date: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\n", - 'body' => "

Hello World

\r\n

It's good to be html

" - ), - 'expectations' => array( - 'httpVersion' => 'HTTP/1.x', - 'code' => 200, - 'reasonPhrase' => 'OK', - 'headers' => array('Date' => 'Mon, 16 Apr 2007 04:14:16 GMT', 'Server' => 'CakeHttp Server'), - 'body' => "

Hello World

\r\n

It's good to be html

" - ) - ), - 'no-header' => array( - 'response' => array( - 'status-line' => "HTTP/1.x 404 OK\r\n", - 'header' => null - ), - 'expectations' => array( - 'code' => 404, - 'headers' => array() - ) - ) - ); - - $testResponse = array(); - $expectations = array(); - - foreach ($tests as $name => $test) { - $testResponse = array_merge($testResponse, $test['response']); - $testResponse['response'] = $testResponse['status-line'] . $testResponse['header'] . "\r\n" . $testResponse['body']; - $r = $this->Socket->parseResponse($testResponse['response']); - $expectations = array_merge($expectations, $test['expectations']); - - foreach ($expectations as $property => $expectedVal) { - $this->assertEquals($r->{$property}, $expectedVal, 'Test "' . $name . '": response.' . $property . ' - %s'); - } - - foreach (array('status-line', 'header', 'body', 'response') as $field) { - $this->assertEquals($r['raw'][$field], $testResponse[$field], 'Test response.raw.' . $field . ': %s'); - } - } - } - -/** - * data provider function for testInvalidParseResponseData - * - * @return array - */ - public static function invalidParseResponseDataProvider() { - return array( - array(array('foo' => 'bar')), - array(true), - array("HTTP Foo\r\nBar: La"), - array('HTTP/1.1 TEST ERROR') - ); - } - -/** - * testInvalidParseResponseData - * - * @dataProvider invalidParseResponseDataProvider - * @expectedException Exception - * return void - */ - public function testInvalidParseResponseData($value) { - $this->Socket->parseResponse($value); - } - -/** - * testDecodeBody method - * - * @return void - */ - public function testDecodeBody() { - $this->Socket->reset(); - - $r = $this->Socket->decodeBody(true); - $this->assertEquals($r, false); - - $r = $this->Socket->decodeBody('Foobar', false); - $this->assertEquals($r, array('body' => 'Foobar', 'header' => false)); - - $encoding = 'chunked'; - $sample = array( - 'encoded' => "19\r\nThis is a chunked message\r\n0\r\n", - 'decoded' => array('body' => "This is a chunked message", 'header' => false) - ); - - $r = $this->Socket->decodeBody($sample['encoded'], $encoding); - $this->assertEquals($r, $sample['decoded']); - } - -/** - * testDecodeFooCoded - * - * @return void - */ - public function testDecodeFooCoded() { - $this->Socket->reset(); - - $r = $this->Socket->decodeBody(true); - $this->assertEquals($r, false); - - $r = $this->Socket->decodeBody('Foobar', false); - $this->assertEquals($r, array('body' => 'Foobar', 'header' => false)); - - $encoding = 'foo-bar'; - $sample = array( - 'encoded' => '!Foobar!', - 'decoded' => array('body' => '!Foobar!', 'header' => false), - ); - - $this->Socket->quirksMode = true; - $r = $this->Socket->decodeBody($sample['encoded'], $encoding); - $this->assertEquals($r, $sample['decoded']); - $this->Socket->quirksMode = false; - - $this->expectError(); - $r = $this->Socket->decodeBody($sample['encoded'], $encoding); - $this->assertEquals($r, $sample['decoded']); - } - -/** - * testDecodeChunkedBody method - * - * @return void - */ - public function testDecodeChunkedBody() { - $this->Socket->reset(); - - $r = $this->Socket->decodeChunkedBody(true); - $this->assertEquals($r, false); - - $encoded = "19\r\nThis is a chunked message\r\n0\r\n"; - $decoded = "This is a chunked message"; - $r = $this->Socket->decodeChunkedBody($encoded); - $this->assertEquals($r['body'], $decoded); - $this->assertEquals($r['header'], false); - - $encoded = "19 \r\nThis is a chunked message\r\n0\r\n"; - $r = $this->Socket->decodeChunkedBody($encoded); - $this->assertEquals($r['body'], $decoded); - - $encoded = "19\r\nThis is a chunked message\r\nE\r\n\nThat is cool\n\r\n0\r\n"; - $decoded = "This is a chunked message\nThat is cool\n"; - $r = $this->Socket->decodeChunkedBody($encoded); - $this->assertEquals($r['body'], $decoded); - $this->assertEquals($r['header'], false); - - $encoded = "19\r\nThis is a chunked message\r\nE;foo-chunk=5\r\n\nThat is cool\n\r\n0\r\n"; - $r = $this->Socket->decodeChunkedBody($encoded); - $this->assertEquals($r['body'], $decoded); - $this->assertEquals($r['header'], false); - - $encoded = "19\r\nThis is a chunked message\r\nE\r\n\nThat is cool\n\r\n0\r\nfoo-header: bar\r\ncake: PHP\r\n\r\n"; - $r = $this->Socket->decodeChunkedBody($encoded); - $this->assertEquals($r['body'], $decoded); - $this->assertEquals($r['header'], array('foo-header' => 'bar', 'cake' => 'PHP')); - - $this->Socket->quirksMode = true; - $encoded = "19\r\nThis is a chunked message\r\nE\r\n\nThat is cool\n\r\nfoo-header: bar\r\ncake: PHP\r\n\r\n"; - $r = $this->Socket->decodeChunkedBody($encoded); - $this->assertEquals($r['body'], $decoded); - $this->assertEquals($r['header'], array('foo-header' => 'bar', 'cake' => 'PHP')); - - $encoded = "19\r\nThis is a chunked message\r\nE\r\n\nThat is cool\n\r\n"; - $r = $this->Socket->decodeChunkedBody($encoded); - $this->assertEquals($r['body'], $decoded); - $this->assertEquals($r['header'], false); - - $this->Socket->quirksMode = false; - $encoded = "19\r\nThis is a chunked message\r\nE\r\n\nThat is cool\n\r\n"; - $this->expectError(); - $r = $this->Socket->decodeChunkedBody($encoded); - $this->assertEquals($r, false); - } - /** * testBuildRequestLine method * @@ -1627,47 +1396,6 @@ class HttpSocketTest extends CakeTestCase { $this->assertEquals($r, $expected); } -/** - * testParseCookies method - * - * @return void - */ - public function testParseCookies() { - $header = array( - 'Set-Cookie' => array( - 'foo=bar', - 'people=jim,jack,johnny";";Path=/accounts', - 'google=not=nice' - ), - 'Transfer-Encoding' => 'chunked', - 'Date' => 'Sun, 18 Nov 2007 18:57:42 GMT', - ); - $cookies = $this->Socket->parseCookies($header); - $expected = array( - 'foo' => array( - 'value' => 'bar' - ), - 'people' => array( - 'value' => 'jim,jack,johnny";"', - 'path' => '/accounts', - ), - 'google' => array( - 'value' => 'not=nice', - ) - ); - $this->assertEqual($cookies, $expected); - - $header['Set-Cookie'][] = 'cakephp=great; Secure'; - $expected['cakephp'] = array('value' => 'great', 'secure' => true); - $cookies = $this->Socket->parseCookies($header); - $this->assertEqual($cookies, $expected); - - $header['Set-Cookie'] = 'foo=bar'; - unset($expected['people'], $expected['cakephp'], $expected['google']); - $cookies = $this->Socket->parseCookies($header); - $this->assertEqual($cookies, $expected); - } - /** * testBuildCookies method *