Skip to content
This repository has been archived by the owner on Jan 30, 2020. It is now read-only.

Commit

Permalink
Merging develop to master in preparation for 2.9.0 release.
Browse files Browse the repository at this point in the history
  • Loading branch information
weierophinney committed Jan 8, 2019
2 parents e70ed2a + 71eab8e commit 7027fa2
Show file tree
Hide file tree
Showing 12 changed files with 201 additions and 21 deletions.
11 changes: 9 additions & 2 deletions .travis.yml
@@ -1,5 +1,3 @@
sudo: false

language: php

cache:
Expand Down Expand Up @@ -54,6 +52,15 @@ matrix:
- php: 7.2
env:
- DEPS=latest
- php: 7.3
env:
- DEPS=lowest
- php: 7.3
env:
- DEPS=locked
- php: 7.3
env:
- DEPS=latest

before_install:
- if [[ $TEST_COVERAGE != 'true' ]]; then phpenv config-rm xdebug.ini || return 0 ; fi
Expand Down
38 changes: 38 additions & 0 deletions CHANGELOG.md
Expand Up @@ -2,6 +2,44 @@

All notable changes to this project will be documented in this file, in reverse chronological order by release.

## 2.9.0 - 2019-01-08

### Added

- [#154](https://github.com/zendframework/zend-http/pull/154) adds the method `SetCookie::setEncodeValue()`. By default, Set-Cookie
values are passed through `urlencode()`; when a boolean `false` is provided to
this new method, the raw value will be used instead.

- [#166](https://github.com/zendframework/zend-http/pull/166) adds support for PHP 7.3.

### Changed

- [#154](https://github.com/zendframework/zend-http/pull/154) changes the behavior of `SetCookie::fromString()` slightly: if the parsed
cookie value is the same as the one passed through `urldecode()`, the
`SetCookie` header's `$encodeValue` property will be toggled off to ensure the
value is not encoded in subsequent serializations, thus retaining the
integrity of the value between usages.

- [#161](https://github.com/zendframework/zend-http/pull/161) changes how the Socket and Test adapters aggregate headers. Previously,
they would `ucfirst()` the header name; now, they correctly leave the header
names untouched, as header names should be considered case-insensitive.

- [#156](https://github.com/zendframework/zend-http/pull/156) changes how gzip and deflate decompression occur in responses, ensuring
that if the Content-Length header reports 0, no decompression is attempted,
and an empty string is returned.

### Deprecated

- Nothing.

### Removed

- [#166](https://github.com/zendframework/zend-http/pull/166) removes support for zend-stdlib v2 releases.

### Fixed

- Nothing.

## 2.8.3 - 2019-01-08

### Added
Expand Down
6 changes: 3 additions & 3 deletions composer.json
Expand Up @@ -20,7 +20,7 @@
"require": {
"php": "^5.6 || ^7.0",
"zendframework/zend-loader": "^2.5.1",
"zendframework/zend-stdlib": "^3.1 || ^2.7.7",
"zendframework/zend-stdlib": "^3.2.1",
"zendframework/zend-uri": "^2.5.2",
"zendframework/zend-validator": "^2.10.1"
},
Expand All @@ -47,8 +47,8 @@
},
"extra": {
"branch-alias": {
"dev-master": "2.8.x-dev",
"dev-develop": "2.9.x-dev"
"dev-master": "2.9.x-dev",
"dev-develop": "2.10.x-dev"
}
},
"scripts": {
Expand Down
27 changes: 14 additions & 13 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/Client/Adapter/Socket.php
Expand Up @@ -389,7 +389,7 @@ public function write($method, $uri, $httpVer = '1.1', $headers = [], $body = ''
$request = $method . ' ' . $path . ' HTTP/' . $httpVer . "\r\n";
foreach ($headers as $k => $v) {
if (is_string($k)) {
$v = ucfirst($k) . ': ' . $v;
$v = $k . ': ' . $v;
}
$request .= $v . "\r\n";
}
Expand Down
2 changes: 1 addition & 1 deletion src/Client/Adapter/Test.php
Expand Up @@ -132,7 +132,7 @@ public function write($method, $uri, $httpVer = '1.1', $headers = [], $body = ''
$request = $method . ' ' . $path . ' HTTP/' . $httpVer . "\r\n";
foreach ($headers as $k => $v) {
if (is_string($k)) {
$v = ucfirst($k) . ': ' . $v;
$v = $k . ': ' . $v;
}
$request .= $v . "\r\n";
}
Expand Down
8 changes: 8 additions & 0 deletions src/Header/Cookie.php
Expand Up @@ -75,12 +75,20 @@ public function __construct(array $array = [])
parent::__construct($array, ArrayObject::ARRAY_AS_PROPS);
}

/**
* @param bool $encodeValue
*
* @return $this
*/
public function setEncodeValue($encodeValue)
{
$this->encodeValue = (bool) $encodeValue;
return $this;
}

/**
* @return bool
*/
public function getEncodeValue()
{
return $this->encodeValue;
Expand Down
29 changes: 28 additions & 1 deletion src/Header/SetCookie.php
Expand Up @@ -85,6 +85,11 @@ class SetCookie implements MultipleHeaderInterface
*/
protected $httponly;

/**
* @var bool
*/
protected $encodeValue = true;

/**
* @static
* @throws Exception\InvalidArgumentException
Expand All @@ -99,6 +104,7 @@ public static function fromString($headerLine, $bypassHeaderFieldName = false)
if ($setCookieProcessor === null) {
$setCookieClass = get_called_class();
$setCookieProcessor = function ($headerLine) use ($setCookieClass) {
/** @var SetCookie $header */
$header = new $setCookieClass();
$keyValuePairs = preg_split('#;\s*#', $headerLine);

Expand All @@ -115,6 +121,11 @@ public static function fromString($headerLine, $bypassHeaderFieldName = false)
if ($header->getName() === null) {
$header->setName($headerKey);
$header->setValue(urldecode($headerValue));

// set no encode value if raw and encoded values are the same
if (urldecode($headerValue) === $headerValue) {
$header->setEncodeValue(false);
}
continue;
}

Expand Down Expand Up @@ -213,6 +224,22 @@ public function __construct(
->setHttpOnly($httponly);
}

/**
* @return bool
*/
public function getEncodeValue()
{
return $this->encodeValue;
}

/**
* @param bool $encodeValue
*/
public function setEncodeValue($encodeValue)
{
$this->encodeValue = (bool) $encodeValue;
}

/**
* @return string 'Set-Cookie'
*/
Expand All @@ -231,7 +258,7 @@ public function getFieldValue()
return '';
}

$value = urlencode($this->getValue());
$value = $this->encodeValue ? urlencode($this->getValue()) : $this->getValue();
if ($this->hasQuoteFieldValue()) {
$value = '"' . $value . '"';
}
Expand Down
10 changes: 10 additions & 0 deletions src/Response.php
Expand Up @@ -564,6 +564,11 @@ protected function decodeGzip($body)
);
}

if ($this->getHeaders()->has('content-length')
&& 0 === (int) $this->getHeaders()->get('content-length')->getFieldValue()) {
return '';
}

ErrorHandler::start();
$return = gzinflate(substr($body, 10));
$test = ErrorHandler::stop();
Expand Down Expand Up @@ -594,6 +599,11 @@ protected function decodeDeflate($body)
);
}

if ($this->getHeaders()->has('content-length')
&& 0 === (int) $this->getHeaders()->get('content-length')->getFieldValue()) {
return '';
}

/**
* Some servers (IIS ?) send a broken deflate response, without the
* RFC-required zlib header.
Expand Down
18 changes: 18 additions & 0 deletions test/Client/SocketTest.php
Expand Up @@ -339,6 +339,24 @@ public function testAllowsZeroWrittenBytes()
$this->_adapter->write('GET', new Uri('tcp://localhost:80/'), '1.1', [], 'test body');
}

/**
* Verifies that the headers are being set as given without changing any
* character case.
*/
public function testCaseInsensitiveHeaders()
{
$this->_adapter->connect('localhost');
$requestString = $this->_adapter->write(
'GET',
new Uri('tcp://localhost:80/'),
'1.1',
['x-test-header' => 'someTestHeader'],
'someTestBody'
);

$this->assertContains('x-test-header', $requestString);
}

/**
* Data Providers
*/
Expand Down
27 changes: 27 additions & 0 deletions test/Header/SetCookieTest.php
Expand Up @@ -50,6 +50,14 @@ public function testSetCookieFromStringWithQuotedValue()
$this->assertEquals('myname=quotedValue', $setCookieHeader->getFieldValue());
}

public function testSetCookieFromStringWithNotEncodedValue()
{
$setCookieHeader = SetCookie::fromString('Set-Cookie: foo=a:b; Path=/');
$this->assertFalse($setCookieHeader->getEncodeValue());
$this->assertEquals('a:b', $setCookieHeader->getValue());
$this->assertEquals('foo=a:b; Path=/', $setCookieHeader->getFieldValue());
}

public function testSetCookieFromStringCreatesValidSetCookieHeader()
{
$setCookieHeader = SetCookie::fromString('Set-Cookie: xxx');
Expand Down Expand Up @@ -457,6 +465,25 @@ public function testPreventsCRLFAttackViaSetValue()
$this->assertEquals('Set-Cookie: leo_auth_token=example%0D%0A%0D%0AevilContent', $header->toString());
}

public function testSetCookieWithEncodeValue()
{
$header = new SetCookie('test');
$header->setValue('a:b');

$this->assertSame('a:b', $header->getValue());
$this->assertSame('test=a%3Ab', $header->getFieldValue());
}

public function testSetCookieWithNoEncodeValue()
{
$header = new SetCookie('test');
$header->setValue('a:b');
$header->setEncodeValue(false);

$this->assertSame('a:b', $header->getValue());
$this->assertSame('test=a:b', $header->getFieldValue());
}

public function setterInjections()
{
return [
Expand Down

0 comments on commit 7027fa2

Please sign in to comment.