mirror of
https://github.com/kamilwylegala/cakephp2-php8.git
synced 2024-11-15 11:28:25 +00:00
Added $mode parameter to HttpSocket::buildHeader
Implemented an initial not yet standards conform cookie parse / build function Added support for a $chars parameter in token escaping Modified HttpSocket::parseHeader()s default behavior for duplicate fields git-svn-id: https://svn.cakephp.org/repo/branches/1.2.x.x@6022 3807eeeb-6ff5-0310-8944-8be069107fe0
This commit is contained in:
parent
cc3614804f
commit
0eed95dda2
2 changed files with 129 additions and 17 deletions
|
@ -724,7 +724,7 @@ class HttpSocket extends CakeSocket {
|
||||||
* @return string Header built from array
|
* @return string Header built from array
|
||||||
* @access protected
|
* @access protected
|
||||||
*/
|
*/
|
||||||
function buildHeader($header) {
|
function buildHeader($header, $mode = 'standard') {
|
||||||
if (is_string($header)) {
|
if (is_string($header)) {
|
||||||
return $header;
|
return $header;
|
||||||
} elseif (!is_array($header)) {
|
} elseif (!is_array($header)) {
|
||||||
|
@ -733,14 +733,16 @@ class HttpSocket extends CakeSocket {
|
||||||
|
|
||||||
$returnHeader = '';
|
$returnHeader = '';
|
||||||
foreach ($header as $field => $contents) {
|
foreach ($header as $field => $contents) {
|
||||||
if (is_array($contents)) {
|
if (is_array($contents) && $mode == 'standard') {
|
||||||
$contents = join(',', $contents);
|
$contents = join(',', $contents);
|
||||||
}
|
}
|
||||||
$contents = preg_replace("/\r\n(?![\t ])/", "\r\n ", $contents);
|
foreach ((array)$contents as $content) {
|
||||||
|
$contents = preg_replace("/\r\n(?![\t ])/", "\r\n ", $content);
|
||||||
$field = $this->escapeToken($field);
|
$field = $this->escapeToken($field);
|
||||||
|
|
||||||
$returnHeader .= $field.': '.$contents.$this->lineBreak;
|
$returnHeader .= $field.': '.$contents.$this->lineBreak;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return $returnHeader;
|
return $returnHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -788,21 +790,73 @@ class HttpSocket extends CakeSocket {
|
||||||
if (!isset($header[$field])) {
|
if (!isset($header[$field])) {
|
||||||
$header[$field] = $value;
|
$header[$field] = $value;
|
||||||
} else {
|
} else {
|
||||||
$header[$field] .= ','.$value;
|
$header[$field] = am($header[$field], $value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $header;
|
return $header;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* undocumented function
|
||||||
|
*
|
||||||
|
* @param unknown $header
|
||||||
|
* @return void
|
||||||
|
* @access public
|
||||||
|
* @todo Make this 100% RFC 2965 confirm
|
||||||
|
*/
|
||||||
|
function parseCookies($header) {
|
||||||
|
if (!isset($header['Set-Cookie'])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$cookies = array();
|
||||||
|
foreach ($header['Set-Cookie'] as $cookie) {
|
||||||
|
$parts = preg_split('/(?<![^;]");[ \t]*/', $cookie);
|
||||||
|
list($name, $value) = explode('=', array_shift($parts));
|
||||||
|
$cookies[$name] = compact('value');
|
||||||
|
foreach ($parts as $part) {
|
||||||
|
@list($key, $value) = explode('=', $part);
|
||||||
|
if (is_null($value)) {
|
||||||
|
$value = true;
|
||||||
|
}
|
||||||
|
$key = low($key);
|
||||||
|
if (!isset($cookies[$name][$key])) {
|
||||||
|
$cookies[$name][$key] = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $cookies;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* undocumented function
|
||||||
|
*
|
||||||
|
* @param unknown $cookies
|
||||||
|
* @return void
|
||||||
|
* @access public
|
||||||
|
* @todo Refactor token escape mechanism to be configurable
|
||||||
|
*/
|
||||||
|
function buildCookies($cookies) {
|
||||||
|
$header = array();
|
||||||
|
foreach ($cookies as $name => $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 = $this->buildHeader(array('Cookie' => $header), 'pragmatic');
|
||||||
|
return $header;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Unescapes a given $token according to RFC 2616 (HTTP 1.1 specs)
|
* Unescapes a given $token according to RFC 2616 (HTTP 1.1 specs)
|
||||||
*
|
*
|
||||||
* @param string $token Token to unescape
|
* @param string $token Token to unescape
|
||||||
* @return string Unescaped token
|
* @return string Unescaped token
|
||||||
* @access protected
|
* @access protected
|
||||||
|
* @todo Test $chars parameter
|
||||||
*/
|
*/
|
||||||
function unescapeToken($token) {
|
function unescapeToken($token, $chars = null) {
|
||||||
$regex = '/"(['.join('', $this->__tokenEscapeChars()).'])"/';
|
$regex = '/"(['.join('', $this->__tokenEscapeChars(true, $chars)).'])"/';
|
||||||
$token = preg_replace($regex, '\\1', $token);
|
$token = preg_replace($regex, '\\1', $token);
|
||||||
return $token;
|
return $token;
|
||||||
}
|
}
|
||||||
|
@ -812,9 +866,10 @@ class HttpSocket extends CakeSocket {
|
||||||
* @param string $token Token to escape
|
* @param string $token Token to escape
|
||||||
* @return string Escaped token
|
* @return string Escaped token
|
||||||
* @access protected
|
* @access protected
|
||||||
|
* @todo Test $chars parameter
|
||||||
*/
|
*/
|
||||||
function escapeToken($token) {
|
function escapeToken($token, $chars = null) {
|
||||||
$regex = '/(['.join('', $this->__tokenEscapeChars()).'])/';
|
$regex = '/(['.join('', $this->__tokenEscapeChars(true, $chars)).'])/';
|
||||||
$token = preg_replace($regex, '"\\1"', $token);
|
$token = preg_replace($regex, '"\\1"', $token);
|
||||||
return $token;
|
return $token;
|
||||||
}
|
}
|
||||||
|
@ -825,13 +880,18 @@ class HttpSocket extends CakeSocket {
|
||||||
* @param boolean $hex true to get them as HEX values, false otherwise
|
* @param boolean $hex true to get them as HEX values, false otherwise
|
||||||
* @return array Escape chars
|
* @return array Escape chars
|
||||||
* @access private
|
* @access private
|
||||||
|
* @todo Test $chars parameter
|
||||||
*/
|
*/
|
||||||
function __tokenEscapeChars($hex = true) {
|
function __tokenEscapeChars($hex = true, $chars = null) {
|
||||||
|
if (!empty($chars)) {
|
||||||
|
$escape = $chars;
|
||||||
|
} else {
|
||||||
$escape = array('"', "(", ")", "<", ">", "@", ",", ";", ":", "\\", "/", "[", "]", "?", "=", "{", "}", " ");
|
$escape = array('"', "(", ")", "<", ">", "@", ",", ";", ":", "\\", "/", "[", "]", "?", "=", "{", "}", " ");
|
||||||
for ($i = 0; $i <= 31; $i++) {
|
for ($i = 0; $i <= 31; $i++) {
|
||||||
$escape[] = chr($i);
|
$escape[] = chr($i);
|
||||||
}
|
}
|
||||||
$escape[] = chr(127);
|
$escape[] = chr(127);
|
||||||
|
}
|
||||||
|
|
||||||
if ($hex == false) {
|
if ($hex == false) {
|
||||||
return $escape;
|
return $escape;
|
||||||
|
|
|
@ -1036,7 +1036,7 @@ class HttpSocketTest extends UnitTestCase {
|
||||||
$header = "People: Jim,John,Tim\r\nPeople: Lisa,Tina,Chelsea\r\n";
|
$header = "People: Jim,John,Tim\r\nPeople: Lisa,Tina,Chelsea\r\n";
|
||||||
$r = $this->Socket->parseHeader($header);
|
$r = $this->Socket->parseHeader($header);
|
||||||
$expected = array(
|
$expected = array(
|
||||||
'People' => 'Jim,John,Tim,Lisa,Tina,Chelsea'
|
'People' => array('Jim,John,Tim', 'Lisa,Tina,Chelsea')
|
||||||
);
|
);
|
||||||
$this->assertIdentical($r, $expected);
|
$this->assertIdentical($r, $expected);
|
||||||
|
|
||||||
|
@ -1055,7 +1055,59 @@ class HttpSocketTest extends UnitTestCase {
|
||||||
);
|
);
|
||||||
$this->assertIdentical($r, $expected);
|
$this->assertIdentical($r, $expected);
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* undocumented function
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
function testParseCookies() {
|
||||||
|
$header = array(
|
||||||
|
'Set-Cookie' => array(
|
||||||
|
'foo=bar',
|
||||||
|
'people=jim,jack,johnny";";Path=/accounts'
|
||||||
|
),
|
||||||
|
'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'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$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);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* undocumented function
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
* @access public
|
||||||
|
* @todo Test more scenarios
|
||||||
|
*/
|
||||||
|
function testBuildCookies() {
|
||||||
|
$cookies = array(
|
||||||
|
'foo' => array(
|
||||||
|
'value' => 'bar'
|
||||||
|
),
|
||||||
|
'people' => array(
|
||||||
|
'value' => 'jim,jack,johnny;',
|
||||||
|
'path' => '/accounts'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$expect = "Cookie: foo=bar\r\nCookie: people=jim,jack,johnny\";\";Path=/accounts\r\n";
|
||||||
|
$result = $this->Socket->buildCookies($cookies);
|
||||||
|
$this->assertEqual($result, $expect);
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Tests that HttpSocket::__tokenEscapeChars() returns the right characters.
|
* Tests that HttpSocket::__tokenEscapeChars() returns the right characters.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in a new issue