diff --git a/cake/libs/http_socket.php b/cake/libs/http_socket.php index fa6d6f9c3..3876caa0d 100644 --- a/cake/libs/http_socket.php +++ b/cake/libs/http_socket.php @@ -82,7 +82,8 @@ class HttpSocket extends CakeSocket { 'Connection' => 'close', 'User-Agent' => 'CakePHP' ), - 'raw' => null + 'raw' => null, + 'cookies' => array() ); /** * The default structure for storing the response @@ -103,7 +104,8 @@ class HttpSocket extends CakeSocket { 'reason-phrase' => null ), 'header' => array(), - 'body' => '' + 'body' => '', + 'cookies' => array(), ); /** @@ -128,7 +130,8 @@ class HttpSocket extends CakeSocket { 'method' => 'basic', 'user' => null, 'pass' => null - ) + ), + 'cookies' => array(), ) ); @@ -191,8 +194,12 @@ class HttpSocket extends CakeSocket { $this->config['host'] = $host; } + $cookies = null; if (is_array($this->request['header'])) { $this->request['header'] = $this->parseHeader($this->request['header']); + if (!empty($this->request['cookies'])) { + $cookies = $this->buildCookies($this->request['cookies']); + } $this->request['header'] = am(array('Host' => $this->request['uri']['host']), $this->request['header']); } @@ -208,7 +215,8 @@ class HttpSocket extends CakeSocket { $this->request['header']['Content-Length'] = strlen($this->request['body']); } - $this->request['header'] = $this->buildHeader($this->request['header']); + $connectionType = @$this->request['header']['Connection']; + $this->request['header'] = $this->buildHeader($this->request['header']).$cookies; if (empty($this->request['line'])) { $this->request['line'] = $this->buildRequestLine($this->request); @@ -234,7 +242,15 @@ class HttpSocket extends CakeSocket { while ($data = $this->read()) { $response .= $data; } + + if ($connectionType == 'close') { + $this->disconnect(); + } + $this->response = $this->parseResponse($response); + if (!empty($this->response['cookies'])) { + $this->config['request']['cookies'] = am($this->config['request']['cookies'], $this->response['cookies']); + } return $this->response['body']; } @@ -359,27 +375,30 @@ class HttpSocket extends CakeSocket { } $response = $responseTemplate; - if (preg_match("/^(.+\r\n)(.*)(?<=\r\n)\r\n/Us", $message, $match)) { - list(, $response['raw']['status-line'], $response['raw']['header']) = $match; - $response['raw']['response'] = $message; - $response['raw']['body'] = substr($message, strlen($match[0])); - - if (preg_match("/(.+) ([0-9]{3}) (.+)\r\n/DU", $response['raw']['status-line'], $match)) { - $response['status']['http-version'] = $match[1]; - $response['status']['code'] = (int)$match[2]; - $response['status']['reason-phrase'] = $match[3]; - } - - $response['header'] = $this->parseHeader($response['raw']['header']); - $decoded = $this->decodeBody($response['raw']['body'], @$response['header']['Transfer-Encoding']); - $response['body'] = $decoded['body']; - if (!empty($decoded['header'])) { - $response['header'] = $this->parseHeader($this->buildHeader($response['header']).$this->buildHeader($decoded['header'])); - } - - } else { + if (!preg_match("/^(.+\r\n)(.*)(?<=\r\n)\r\n/Us", $message, $match)) { return false; } + + list(, $response['raw']['status-line'], $response['raw']['header']) = $match; + $response['raw']['response'] = $message; + $response['raw']['body'] = substr($message, strlen($match[0])); + + if (preg_match("/(.+) ([0-9]{3}) (.+)\r\n/DU", $response['raw']['status-line'], $match)) { + $response['status']['http-version'] = $match[1]; + $response['status']['code'] = (int)$match[2]; + $response['status']['reason-phrase'] = $match[3]; + } + + $response['header'] = $this->parseHeader($response['raw']['header']); + $decoded = $this->decodeBody($response['raw']['body'], @$response['header']['Transfer-Encoding']); + $response['body'] = $decoded['body']; + if (!empty($decoded['header'])) { + $response['header'] = $this->parseHeader($this->buildHeader($response['header']).$this->buildHeader($decoded['header'])); + } + + if (!empty($response['header'])) { + $response['cookies'] = $this->parseCookies($response['header']); + } foreach ($response['raw'] as $field => $val) { if ($val === '') { @@ -809,7 +828,7 @@ class HttpSocket extends CakeSocket { } $cookies = array(); - foreach ($header['Set-Cookie'] as $cookie) { + foreach ((array)$header['Set-Cookie'] as $cookie) { $parts = preg_split('/(? $cookie) { - $serialized = $name.'='.$this->escapeToken($cookie['value'], array(';')); - unset($cookie['value']); - foreach ($cookie as $key => $val) { - $serialized .= ';'.Inflector::camelize($key).'='.$this->escapeToken($val, array(';')); - } - $header[] = $serialized; + $header[] = $name.'='.$this->escapeToken($cookie['value'], array(';')); } $header = $this->buildHeader(array('Cookie' => $header), 'pragmatic'); return $header; } +/** + * undocumented function + * + * @return void + * @access public + */ + function saveCookies() { + + } +/** + * undocumented function + * + * @return void + * @access public + */ + function loadCookies() { + + } /** * Unescapes a given $token according to RFC 2616 (HTTP 1.1 specs) * diff --git a/cake/tests/cases/libs/http_socket.test.php b/cake/tests/cases/libs/http_socket.test.php index ac3516445..faacb1338 100755 --- a/cake/tests/cases/libs/http_socket.test.php +++ b/cake/tests/cases/libs/http_socket.test.php @@ -104,7 +104,8 @@ class HttpSocketTest extends UnitTestCase { 'method' => 'basic' , 'user' => 'bob' , 'pass' => 'secret' - ) + ), + 'cookies' => array(), ) ); $this->assertIdentical($this->Socket->config, $expected); @@ -132,7 +133,8 @@ class HttpSocketTest extends UnitTestCase { 'method' => 'basic' , 'user' => null , 'pass' => null - ) + ), + 'cookies' => array() ) ); $this->assertIdentical($this->Socket->config, $expected); @@ -177,6 +179,7 @@ class HttpSocketTest extends UnitTestCase { ,'user' => null ,'pass' => null ), + 'cookies' => array(), ), ) , 'request' => array( @@ -201,6 +204,7 @@ class HttpSocketTest extends UnitTestCase { , 'line' => "GET /?foo=bar HTTP/1.1\r\n" , 'header' => "Host: www.cakephp.org\r\nConnection: close\r\nUser-Agent: CakePHP\r\n" , 'raw' => "" + , 'cookies' => array(), ) ) ) @@ -312,6 +316,22 @@ class HttpSocketTest extends UnitTestCase { ) ) ) + , 10 => array( + 'request' => array( + 'method' => 'POST', + 'uri' => 'https://www.cakephp.org/posts/add', + 'body' => array('name' => 'HttpSocket-is-released', 'date' => 'today'), + 'cookies' => array('foo' => array('value' => 'bar')) + ) + , 'expectation' => array( + 'request' => array( + 'header' => "Host: www.cakephp.org\r\nConnection: close\r\nUser-Agent: CakePHP\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 38\r\nCookie: foo=bar\r\n", + 'cookies' => array( + 'foo' => array('value' => 'bar'), + ) + ) + ) + ) ); $expectation = array(); @@ -341,12 +361,12 @@ class HttpSocketTest extends UnitTestCase { } $expectation['request']['raw'] = $raw; } - + $this->Socket->reset(); $request = array('method' => 'POST', 'uri' => 'http://www.cakephp.org/posts/add', 'body' => array('name' => 'HttpSocket-is-released', 'date' => 'today')); $response = $this->Socket->request($request); $this->assertIdentical($this->Socket->request['body'], "name=HttpSocket-is-released&date=today"); - + $request = array('uri' => '*', 'method' => 'GET'); $this->expectError(new PatternExpectation('/activate quirks mode/i')); $response = $this->Socket->request($request); @@ -365,6 +385,23 @@ class HttpSocketTest extends UnitTestCase { $this->Socket->expectCallCount('read', 2); $response = $this->Socket->request($request); $this->assertIdentical($response, "