laravel-6 support

This commit is contained in:
RafficMohammed
2023-01-08 01:17:22 +05:30
parent 1a5c16ae4b
commit 774eed8b0e
4962 changed files with 279380 additions and 297961 deletions

View File

@@ -1,73 +0,0 @@
# Changelog
All notable changes to this project will be documented in this file, in reverse chronological order by release.
## 2.6.1 - 2019-09-05
### Added
- [#32](https://github.com/zendframework/zend-escaper/pull/32) adds support for PHP 7.3.
### Changed
- Nothing.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- Nothing.
## 2.6.0 - 2018-04-25
### Added
- [#28](https://github.com/zendframework/zend-escaper/pull/28) adds support for PHP 7.1 and 7.2.
### Changed
- [#25](https://github.com/zendframework/zend-escaper/pull/25) changes the behavior of the `Escaper` constructor; it now raises an
exception for non-null, non-string `$encoding` arguments.
### Deprecated
- Nothing.
### Removed
- [#28](https://github.com/zendframework/zend-escaper/pull/28) removes support for PHP 5.5.
- [#28](https://github.com/zendframework/zend-escaper/pull/28) removes support for HHVM.
### Fixed
- Nothing.
## 2.5.2 - 2016-06-30
### Added
- [#11](https://github.com/zendframework/zend-escaper/pull/11),
[#12](https://github.com/zendframework/zend-escaper/pull/12), and
[#13](https://github.com/zendframework/zend-escaper/pull/13) prepare and
publish documentation to https://zendframework.github.io/zend-escaper/
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [#3](https://github.com/zendframework/zend-escaper/pull/3) updates the
the escaping mechanism to add support for escaping characters outside the Basic
Multilingual Plane when escaping for JS, CSS, or HTML attributes.

View File

@@ -1,27 +0,0 @@
Copyright (c) 2005-2019, Zend Technologies USA, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
- Neither the name of Zend Technologies USA, Inc. nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -1,28 +0,0 @@
# zend-escaper
[![Build Status](https://secure.travis-ci.org/zendframework/zend-escaper.svg?branch=master)](https://secure.travis-ci.org/zendframework/zend-escaper)
[![Coverage Status](https://coveralls.io/repos/github/zendframework/zend-escaper/badge.svg?branch=master)](https://coveralls.io/github/zendframework/zend-escaper?branch=master)
The OWASP Top 10 web security risks study lists Cross-Site Scripting (XSS) in
second place. PHPs sole functionality against XSS is limited to two functions
of which one is commonly misapplied. Thus, the zend-escaper component was written.
It offers developers a way to escape output and defend from XSS and related
vulnerabilities by introducing contextual escaping based on peer-reviewed rules.
## Installation
Run the following to install this library:
```bash
$ composer require zendframework/zend-escaper
```
## Documentation
Browse the documentation online at https://docs.zendframework.com/zend-escaper/
## Support
* [Issues](https://github.com/zendframework/zend-escaper/issues/)
* [Chat](https://zendframework-slack.herokuapp.com/)
* [Forum](https://discourse.zendframework.com/)

View File

@@ -1,54 +0,0 @@
{
"name": "zendframework/zend-escaper",
"description": "Securely and safely escape HTML, HTML attributes, JavaScript, CSS, and URLs",
"license": "BSD-3-Clause",
"keywords": [
"zf",
"zendframework",
"escaper"
],
"support": {
"docs": "https://docs.zendframework.com/zend-escaper/",
"issues": "https://github.com/zendframework/zend-escaper/issues",
"source": "https://github.com/zendframework/zend-escaper",
"rss": "https://github.com/zendframework/zend-escaper/releases.atom",
"chat": "https://zendframework-slack.herokuapp.com",
"forum": "https://discourse.zendframework.com/c/questions/components"
},
"require": {
"php": "^5.6 || ^7.0"
},
"require-dev": {
"phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.2",
"zendframework/zend-coding-standard": "~1.0.0"
},
"autoload": {
"psr-4": {
"Zend\\Escaper\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"ZendTest\\Escaper\\": "test/"
}
},
"config": {
"sort-packages": true
},
"extra": {
"branch-alias": {
"dev-master": "2.6.x-dev",
"dev-develop": "2.7.x-dev"
}
},
"scripts": {
"check": [
"@cs-check",
"@test"
],
"cs-check": "phpcs",
"cs-fix": "phpcbf",
"test": "phpunit --colors=always",
"test-coverage": "phpunit --colors=always --coverage-clover clover.xml"
}
}

View File

@@ -1,392 +0,0 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Escaper;
/**
* Context specific methods for use in secure output escaping
*/
class Escaper
{
/**
* Entity Map mapping Unicode codepoints to any available named HTML entities.
*
* While HTML supports far more named entities, the lowest common denominator
* has become HTML5's XML Serialisation which is restricted to the those named
* entities that XML supports. Using HTML entities would result in this error:
* XML Parsing Error: undefined entity
*
* @var array
*/
protected static $htmlNamedEntityMap = [
34 => 'quot', // quotation mark
38 => 'amp', // ampersand
60 => 'lt', // less-than sign
62 => 'gt', // greater-than sign
];
/**
* Current encoding for escaping. If not UTF-8, we convert strings from this encoding
* pre-escaping and back to this encoding post-escaping.
*
* @var string
*/
protected $encoding = 'utf-8';
/**
* Holds the value of the special flags passed as second parameter to
* htmlspecialchars().
*
* @var int
*/
protected $htmlSpecialCharsFlags;
/**
* Static Matcher which escapes characters for HTML Attribute contexts
*
* @var callable
*/
protected $htmlAttrMatcher;
/**
* Static Matcher which escapes characters for Javascript contexts
*
* @var callable
*/
protected $jsMatcher;
/**
* Static Matcher which escapes characters for CSS Attribute contexts
*
* @var callable
*/
protected $cssMatcher;
/**
* List of all encoding supported by this class
*
* @var array
*/
protected $supportedEncodings = [
'iso-8859-1', 'iso8859-1', 'iso-8859-5', 'iso8859-5',
'iso-8859-15', 'iso8859-15', 'utf-8', 'cp866',
'ibm866', '866', 'cp1251', 'windows-1251',
'win-1251', '1251', 'cp1252', 'windows-1252',
'1252', 'koi8-r', 'koi8-ru', 'koi8r',
'big5', '950', 'gb2312', '936',
'big5-hkscs', 'shift_jis', 'sjis', 'sjis-win',
'cp932', '932', 'euc-jp', 'eucjp',
'eucjp-win', 'macroman'
];
/**
* Constructor: Single parameter allows setting of global encoding for use by
* the current object.
*
* @param string $encoding
* @throws Exception\InvalidArgumentException
*/
public function __construct($encoding = null)
{
if ($encoding !== null) {
if (! is_string($encoding)) {
throw new Exception\InvalidArgumentException(
get_class($this) . ' constructor parameter must be a string, received ' . gettype($encoding)
);
}
if ($encoding === '') {
throw new Exception\InvalidArgumentException(
get_class($this) . ' constructor parameter does not allow a blank value'
);
}
$encoding = strtolower($encoding);
if (! in_array($encoding, $this->supportedEncodings)) {
throw new Exception\InvalidArgumentException(
'Value of \'' . $encoding . '\' passed to ' . get_class($this)
. ' constructor parameter is invalid. Provide an encoding supported by htmlspecialchars()'
);
}
$this->encoding = $encoding;
}
// We take advantage of ENT_SUBSTITUTE flag to correctly deal with invalid UTF-8 sequences.
$this->htmlSpecialCharsFlags = ENT_QUOTES | ENT_SUBSTITUTE;
// set matcher callbacks
$this->htmlAttrMatcher = [$this, 'htmlAttrMatcher'];
$this->jsMatcher = [$this, 'jsMatcher'];
$this->cssMatcher = [$this, 'cssMatcher'];
}
/**
* Return the encoding that all output/input is expected to be encoded in.
*
* @return string
*/
public function getEncoding()
{
return $this->encoding;
}
/**
* Escape a string for the HTML Body context where there are very few characters
* of special meaning. Internally this will use htmlspecialchars().
*
* @param string $string
* @return string
*/
public function escapeHtml($string)
{
return htmlspecialchars($string, $this->htmlSpecialCharsFlags, $this->encoding);
}
/**
* Escape a string for the HTML Attribute context. We use an extended set of characters
* to escape that are not covered by htmlspecialchars() to cover cases where an attribute
* might be unquoted or quoted illegally (e.g. backticks are valid quotes for IE).
*
* @param string $string
* @return string
*/
public function escapeHtmlAttr($string)
{
$string = $this->toUtf8($string);
if ($string === '' || ctype_digit($string)) {
return $string;
}
$result = preg_replace_callback('/[^a-z0-9,\.\-_]/iSu', $this->htmlAttrMatcher, $string);
return $this->fromUtf8($result);
}
/**
* Escape a string for the Javascript context. This does not use json_encode(). An extended
* set of characters are escaped beyond ECMAScript's rules for Javascript literal string
* escaping in order to prevent misinterpretation of Javascript as HTML leading to the
* injection of special characters and entities. The escaping used should be tolerant
* of cases where HTML escaping was not applied on top of Javascript escaping correctly.
* Backslash escaping is not used as it still leaves the escaped character as-is and so
* is not useful in a HTML context.
*
* @param string $string
* @return string
*/
public function escapeJs($string)
{
$string = $this->toUtf8($string);
if ($string === '' || ctype_digit($string)) {
return $string;
}
$result = preg_replace_callback('/[^a-z0-9,\._]/iSu', $this->jsMatcher, $string);
return $this->fromUtf8($result);
}
/**
* Escape a string for the URI or Parameter contexts. This should not be used to escape
* an entire URI - only a subcomponent being inserted. The function is a simple proxy
* to rawurlencode() which now implements RFC 3986 since PHP 5.3 completely.
*
* @param string $string
* @return string
*/
public function escapeUrl($string)
{
return rawurlencode($string);
}
/**
* Escape a string for the CSS context. CSS escaping can be applied to any string being
* inserted into CSS and escapes everything except alphanumerics.
*
* @param string $string
* @return string
*/
public function escapeCss($string)
{
$string = $this->toUtf8($string);
if ($string === '' || ctype_digit($string)) {
return $string;
}
$result = preg_replace_callback('/[^a-z0-9]/iSu', $this->cssMatcher, $string);
return $this->fromUtf8($result);
}
/**
* Callback function for preg_replace_callback that applies HTML Attribute
* escaping to all matches.
*
* @param array $matches
* @return string
*/
protected function htmlAttrMatcher($matches)
{
$chr = $matches[0];
$ord = ord($chr);
/**
* The following replaces characters undefined in HTML with the
* hex entity for the Unicode replacement character.
*/
if (($ord <= 0x1f && $chr != "\t" && $chr != "\n" && $chr != "\r")
|| ($ord >= 0x7f && $ord <= 0x9f)
) {
return '&#xFFFD;';
}
/**
* Check if the current character to escape has a name entity we should
* replace it with while grabbing the integer value of the character.
*/
if (strlen($chr) > 1) {
$chr = $this->convertEncoding($chr, 'UTF-32BE', 'UTF-8');
}
$hex = bin2hex($chr);
$ord = hexdec($hex);
if (isset(static::$htmlNamedEntityMap[$ord])) {
return '&' . static::$htmlNamedEntityMap[$ord] . ';';
}
/**
* Per OWASP recommendations, we'll use upper hex entities
* for any other characters where a named entity does not exist.
*/
if ($ord > 255) {
return sprintf('&#x%04X;', $ord);
}
return sprintf('&#x%02X;', $ord);
}
/**
* Callback function for preg_replace_callback that applies Javascript
* escaping to all matches.
*
* @param array $matches
* @return string
*/
protected function jsMatcher($matches)
{
$chr = $matches[0];
if (strlen($chr) == 1) {
return sprintf('\\x%02X', ord($chr));
}
$chr = $this->convertEncoding($chr, 'UTF-16BE', 'UTF-8');
$hex = strtoupper(bin2hex($chr));
if (strlen($hex) <= 4) {
return sprintf('\\u%04s', $hex);
}
$highSurrogate = substr($hex, 0, 4);
$lowSurrogate = substr($hex, 4, 4);
return sprintf('\\u%04s\\u%04s', $highSurrogate, $lowSurrogate);
}
/**
* Callback function for preg_replace_callback that applies CSS
* escaping to all matches.
*
* @param array $matches
* @return string
*/
protected function cssMatcher($matches)
{
$chr = $matches[0];
if (strlen($chr) == 1) {
$ord = ord($chr);
} else {
$chr = $this->convertEncoding($chr, 'UTF-32BE', 'UTF-8');
$ord = hexdec(bin2hex($chr));
}
return sprintf('\\%X ', $ord);
}
/**
* Converts a string to UTF-8 from the base encoding. The base encoding is set via this
* class' constructor.
*
* @param string $string
* @throws Exception\RuntimeException
* @return string
*/
protected function toUtf8($string)
{
if ($this->getEncoding() === 'utf-8') {
$result = $string;
} else {
$result = $this->convertEncoding($string, 'UTF-8', $this->getEncoding());
}
if (! $this->isUtf8($result)) {
throw new Exception\RuntimeException(
sprintf('String to be escaped was not valid UTF-8 or could not be converted: %s', $result)
);
}
return $result;
}
/**
* Converts a string from UTF-8 to the base encoding. The base encoding is set via this
* class' constructor.
* @param string $string
* @return string
*/
protected function fromUtf8($string)
{
if ($this->getEncoding() === 'utf-8') {
return $string;
}
return $this->convertEncoding($string, $this->getEncoding(), 'UTF-8');
}
/**
* Checks if a given string appears to be valid UTF-8 or not.
*
* @param string $string
* @return bool
*/
protected function isUtf8($string)
{
return ($string === '' || preg_match('/^./su', $string));
}
/**
* Encoding conversion helper which wraps iconv and mbstring where they exist or throws
* and exception where neither is available.
*
* @param string $string
* @param string $to
* @param array|string $from
* @throws Exception\RuntimeException
* @return string
*/
protected function convertEncoding($string, $to, $from)
{
if (function_exists('iconv')) {
$result = iconv($from, $to, $string);
} elseif (function_exists('mb_convert_encoding')) {
$result = mb_convert_encoding($string, $to, $from);
} else {
throw new Exception\RuntimeException(
get_class($this)
. ' requires either the iconv or mbstring extension to be installed'
. ' when escaping for non UTF-8 strings.'
);
}
if ($result === false) {
return ''; // return non-fatal blank string on encoding errors from users
}
return $result;
}
}

View File

@@ -1,14 +0,0 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Escaper\Exception;
interface ExceptionInterface
{
}

View File

@@ -1,18 +0,0 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Escaper\Exception;
/**
* Invalid argument exception
*/
class InvalidArgumentException extends \InvalidArgumentException implements
ExceptionInterface
{
}

View File

@@ -1,18 +0,0 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Escaper\Exception;
/**
* Invalid argument exception
*/
class RuntimeException extends \RuntimeException implements
ExceptionInterface
{
}

View File

@@ -1 +0,0 @@
always_populate_raw_post_data=-1

View File

@@ -1,6 +0,0 @@
<VirtualHost *:8081>
ProxyRequests On
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

View File

@@ -1,21 +0,0 @@
<VirtualHost *:80>
DocumentRoot %TRAVIS_BUILD_DIR%/test/Client/_files
<Directory "%TRAVIS_BUILD_DIR%/test/Client/_files/">
Options FollowSymLinks MultiViews ExecCGI
AllowOverride All
Require all granted
</Directory>
# Wire up Apache to use Travis CI's php-fpm.
<IfModule mod_fastcgi.c>
AddHandler php%PHP_VERSION%-fcgi .php
Action php%PHP_VERSION%-fcgi /php%PHP_VERSION%-fcgi
Alias /php%PHP_VERSION%-fcgi /usr/lib/cgi-bin/php%PHP_VERSION%-fcgi
FastCgiExternalServer /usr/lib/cgi-bin/php%PHP_VERSION%-fcgi -host 127.0.0.1:9000 -pass-header Authorization
<Directory /usr/lib/cgi-bin>
Require all granted
</Directory>
</IfModule>
</VirtualHost>

View File

@@ -1,546 +0,0 @@
# Changelog
All notable changes to this project will be documented in this file, in reverse chronological order by release.
## 2.11.2 - 2019-12-30
### Added
- Nothing.
### Changed
- Nothing.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [#207](https://github.com/zendframework/zend-http/pull/207) fixes case sensitivity for SameSite directive.
## 2.11.1 - 2019-12-04
### Added
- Nothing.
### Changed
- Nothing.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [#204](https://github.com/zendframework/zend-http/pull/204) fixes numerous header classes to cast field value to string (since `HeaderInterface::getFieldValue()` specifies a return value of a string).
- [#182](https://github.com/zendframework/zend-http/pull/182) fixes detecting base uri in Request. Now `argv` is used only for CLI request as a fallback to detect script filename.
## 2.11.0 - 2019-12-03
### Added
- [#175](https://github.com/zendframework/zend-http/pull/175) adds support for Content Security Policy Level 3 Header directives.
- [#200](https://github.com/zendframework/zend-http/pull/200) adds support for additional directives in Content Security Policy header:
- `block-all-mixed-content`,
- `require-sri-for`,
- `trusted-types`,
- `upgrade-insecure-requests`.
- [#177](https://github.com/zendframework/zend-http/pull/177) adds support for Feature Policy header.
- [#186](https://github.com/zendframework/zend-http/pull/186) adds support for SameSite directive in Set-Cookie header.
### Changed
- [#194](https://github.com/zendframework/zend-http/pull/194) changes range of valid HTTP status codes to 100-599 (inclusive).
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [#200](https://github.com/zendframework/zend-http/pull/200) fixes support for directives without value in Content Security Policy header.
## 2.10.1 - 2019-12-02
### Added
- Nothing.
### Changed
- [#190](https://github.com/zendframework/zend-http/pull/190) changes `ContentSecurityPolicy` to allow multiple values. Before it was not possible to provide multiple headers of that type.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [#184](https://github.com/zendframework/zend-http/pull/184) fixes responses for request through the proxy with `HTTP/1.1 200 Connection established` header.
- [#187](https://github.com/zendframework/zend-http/pull/187) fixes infinite recursion on invalid header. Now `InvalidArgumentException` exception is thrown.
- [#188](https://github.com/zendframework/zend-http/pull/188) fixes `Client::setCookies` method to properly handle array of `SetCookie` objects. Per [documentation](https://docs.zendframework.com/zend-http/client/cookies/#usage) it should be allowed.
- [#189](https://github.com/zendframework/zend-http/pull/189) fixes `Headers::toArray` method to properly handle headers of the same type. Behaviour was different depends how header has been attached (`addHeader` or `addHeaderLine` broken before).
- [#198](https://github.com/zendframework/zend-http/pull/198) fixes merging options in Curl adapter. It was not possible to override integer-key options (constants) set via constructor with method `setOptions`.
- [#198](https://github.com/zendframework/zend-http/pull/198) fixes allowed options type in `Proxy::setOptions`. `Traversable`, `array` or `Zend\Config` object is expected.
- [#198](https://github.com/zendframework/zend-http/pull/198) fixes various issues with `Proxy` adapter.
- [#199](https://github.com/zendframework/zend-http/pull/199) fixes saving resource to the file when streaming while client supports compression. Before, incorrectly, compressed resource was saved into the file.
## 2.10.0 - 2019-02-19
### Added
- [#173](https://github.com/zendframework/zend-http/pull/173) adds support for HTTP/2 requests and responses.
### Changed
- Nothing.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- Nothing.
## 2.9.1 - 2019-01-22
### Added
- Nothing.
### Changed
- Nothing.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [#168](https://github.com/zendframework/zend-http/pull/168) fixes a problem when validating the connection timeout for the `Curl` and
`Socket` client adapters; it now correctly identifies both integer and string
integer values.
## 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
- Nothing.
### Changed
- Nothing.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [#165](https://github.com/zendframework/zend-http/pull/165) fixes detection of the base URL when operating under a CLI environment.
- [#149](https://github.com/zendframework/zend-http/pull/149) provides fixes to `Client::setUri()` to ensure its status as a relative
or absolute URI is correctly memoized.
- [#162](https://github.com/zendframework/zend-http/pull/162) fixes a typo in an exception message raised within `Cookies::fromString()`.
- [#121](https://github.com/zendframework/zend-http/pull/121) adds detection for non-numeric connection timeout values as well as
integer casting to ensure the timeout is set properly in both the Curl and
Socket adapters.
## 2.8.2 - 2018-08-13
### Added
- Nothing.
### Changed
- [#153](https://github.com/zendframework/zend-diactoros/pull/153) changes the reason phrase associated with the status code 425
from "Unordered Collection" to "Too Early", corresponding to a new definition
of the code as specified by the IANA.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [#151](https://github.com/zendframework/zend-http/pull/151) fixes how Referer and other location-based headers report problems with
invalid URLs provided in the header value, raising a `Zend\Http\Exception\InvalidArgumentException`
in such cases. This change ensures the behavior is consistent with behavior
prior to the 2.8.0 release.
## 2.8.1 - 2018-08-01
### Added
- Nothing.
### Changed
- This release modifies how `Zend\Http\PhpEnvironment\Request` marshals the
request URI. In prior releases, we would attempt to inspect the
`X-Rewrite-Url` and `X-Original-Url` headers, using their values, if present.
These headers are issued by the ISAPI_Rewrite module for IIS (developed by
HeliconTech). However, we have no way of guaranteeing that the module is what
issued the headers, making it an unreliable source for discovering the URI. As
such, we have removed this feature in this release of zend-http.
If you are developing a zend-mvc application, you can mimic the
functionality by adding a bootstrap listener like the following:
```php
public function onBootstrap(MvcEvent $mvcEvent)
{
$request = $mvcEvent->getRequest();
$requestUri = null;
$httpXRewriteUrl = $request->getHeader('X-Rewrite-Url');
if ($httpXRewriteUrl) {
$requestUri = $httpXRewriteUrl->getFieldValue();
}
$httpXOriginalUrl = $request->getHeader('X-Original-Url');
if ($httpXOriginalUrl) {
$requestUri = $httpXOriginalUrl->getFieldValue();
}
if ($requestUri) {
$request->setUri($requestUri)
}
}
```
If you use a listener such as the above, make sure you also instruct your web
server to strip any incoming headers of the same name so that you can
guarantee they are issued by the ISAPI_Rewrite module.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- Nothing.
## 2.8.0 - 2018-04-26
### Added
- [#135](https://github.com/zendframework/zend-http/pull/135) adds a package suggestion of paragonie/certainty, which provides automated
management of cacert.pem files.
- [#143](https://github.com/zendframework/zend-http/pull/143) adds support for PHP 7.2.
### Changed
- Nothing.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [#140](https://github.com/zendframework/zend-http/pull/140) fixes retrieval of headers when multiple headers of the same name
are added to the `Headers` instance; it now ensures that the last header added of the same
type is retrieved when it is not a multi-value type. Previous values are overwritten.
- [#112](https://github.com/zendframework/zend-http/pull/112) provides performance improvements when parsing large chunked messages.
- introduces changes to `Response::fromString()` to pull the next line of the response
and parse it for the status when a 100 status code is initially encountered, per https://tools.ietf.org/html/rfc7231\#section-6.2.1
- [#122](https://github.com/zendframework/zend-http/pull/122) fixes an issue with the stream response whereby if the `outputstream`
option is set, the output file was opened twice; it is now opened exactly once.
- [#147](https://github.com/zendframework/zend-http/pull/147) fixes an issue with header retrieval when the header line is malformed.
Previously, an exception would be raised if a specific `HeaderInterface` implementation determined
the header line was invalid. Now, `Header::has()` will return false for such headers, allowing
`Request::getHeader()` to return `false` or the provided default value. Additionally, in cases
where the header name is malformed (e.g., `Useragent` instead of `User-Agent`, users can still
retrieve by the submitted header name; they will receive a `GenericHeader` instance in such
cases, however.
- [#133](https://github.com/zendframework/zend-http/pull/133) Adds back missing
sprintf placeholder in CacheControl exception message
## 2.7.0 - 2017-10-13
### Added
- [#110](https://github.com/zendframework/zend-http/pull/110) Adds status
codes 226, 308, 444, 499, 510, 599 with their corresponding constants and
reason phrases.
### Changed
- [#120](https://github.com/zendframework/zend-http/pull/120) Changes handling
of Cookie Max-Age parameter to conform to specification
[rfc6265#section-5.2.2](https://tools.ietf.org/html/rfc6265#section-5.2.2).
Specifically, non-numeric values are ignored and negative numbers are changed
to 0.
### Deprecated
- Nothing.
### Removed
- [#115](https://github.com/zendframework/zend-http/pull/115) dropped php 5.5
support
### Fixed
- [#130](https://github.com/zendframework/zend-http/pull/130) Fixed cURL
adapter not resetting headers from previous request when used with output
stream.
## 2.6.0 - 2017-01-31
### Added
- [#99](https://github.com/zendframework/zend-http/pull/99) added
TimeoutException for cURL adapter.
- [#98](https://github.com/zendframework/zend-http/pull/98) added connection
timeout (`connecttimeout`) for cURL and Socket adapters.
- [#97](https://github.com/zendframework/zend-http/pull/97) added support to
`sslcafile` and `sslcapath` to cURL adapter.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- Nothing.
## 2.5.6 - 2017-01-31
### Added
- Nothing.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [#107](https://github.com/zendframework/zend-http/pull/107) fixes the
`Expires` header to allow values of `0` or `'0'`; these now resolve
to the start of the unix epoch (1970-01-01).
- [#102](https://github.com/zendframework/zend-http/pull/102) fixes the Curl
adapter timeout detection.
- [#93](https://github.com/zendframework/zend-http/pull/93) fixes the Content
Security Policy CSP HTTP header when it is `none` (empty value).
- [#92](https://github.com/zendframework/zend-http/pull/92) fixes the flatten
cookies value for array value (also multidimensional).
- [#34](https://github.com/zendframework/zend-http/pull/34) fixes the
standard separator (&) for application/x-www-form-urlencoded.
## 2.5.5 - 2016-08-08
### Added
- [#44](https://github.com/zendframework/zend-http/pull/44),
[#45](https://github.com/zendframework/zend-http/pull/45),
[#46](https://github.com/zendframework/zend-http/pull/46),
[#47](https://github.com/zendframework/zend-http/pull/47),
[#48](https://github.com/zendframework/zend-http/pull/48), and
[#49](https://github.com/zendframework/zend-http/pull/49) prepare the
documentation for publication at https://zendframework.github.io/zend-http/
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [#87](https://github.com/zendframework/zend-http/pull/87) fixes the
`ContentLength` constructor to test for a non null value (vs a falsy value)
before validating the value; this ensures 0 values may be specified for the
length.
- [#85](https://github.com/zendframework/zend-http/pull/85) fixes infinite recursion
on AbstractAccept. If you create a new Accept and try to call getFieldValue(),
an infinite recursion and a fatal error happens.
- [#58](https://github.com/zendframework/zend-http/pull/58) avoid triggering a notice
with special crafted accept headers. In the case the value of an accept header
does not contain an equal sign, an "Undefined offset" notice is triggered.
## 2.5.4 - 2016-02-04
### Added
- Nothing.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [#42](https://github.com/zendframework/zend-http/pull/42) updates dependencies
to ensure it can work with PHP 5.5+ and 7.0+, as well as zend-stdlib
2.5+/3.0+.
## 2.5.3 - 2015-09-14
### Added
- Nothing.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [#23](https://github.com/zendframework/zend-http/pull/23) fixes a BC break
introduced with fixes for [ZF2015-04](http://framework.zend.com/security/advisory/ZF2015-04),
pertaining specifically to the `SetCookie` header. The fix backs out a
check for message splitting syntax, as that particular class already encodes
the value in a manner that prevents the attack. It also adds tests to ensure
the security vulnerability remains patched.
## 2.5.2 - 2015-08-05
### Added
- Nothing.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [#7](https://github.com/zendframework/zend-http/pull/7) fixes a call in the
proxy adapter to `Response::extractCode()`, which does not exist, to
`Response::fromString()->getStatusCode()`, which does.
- [#8](https://github.com/zendframework/zend-http/pull/8) ensures that the Curl
client adapter enables the `CURLINFO_HEADER_OUT`, which is required to ensure
we can fetch the raw request after it is sent.
- [#14](https://github.com/zendframework/zend-http/pull/14) fixes
`Zend\Http\PhpEnvironment\Request` to ensure that empty `SCRIPT_FILENAME` and
`SCRIPT_NAME` values which result in an empty `$baseUrl` will not raise an
`E_WARNING` when used to do a `strpos()` check during base URI detection.

View File

@@ -1,27 +0,0 @@
Copyright (c) 2005-2019, Zend Technologies USA, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
- Neither the name of Zend Technologies USA, Inc. nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -1,30 +0,0 @@
# zend-http
[![Build Status](https://secure.travis-ci.org/zendframework/zend-http.svg?branch=master)](https://secure.travis-ci.org/zendframework/zend-http)
[![Coverage Status](https://coveralls.io/repos/github/zendframework/zend-http/badge.svg?branch=master)](https://coveralls.io/github/zendframework/zend-http?branch=master)
zend-http provides the HTTP message abstraction used by
[zend-mvc](https://docs.zendframework.com/zend-mvc/), and also provides an
extensible, adapter-driven HTTP client library.
This library **does not** support [PSR-7](http://www.php-fig.org/psr/psr-7), as
it predates that specification. For PSR-7 support, please see our
[Diactoros component](https://docs.zendframework.com/zend-diactoros/).
## Installation
Run the following to install this library:
```bash
$ composer require zendframework/zend-http
```
## Documentation
Browse the documentation online at https://docs.zendframework.com/zend-http/
## Support
* [Issues](https://github.com/zendframework/zend-http/issues/)
* [Chat](https://zendframework-slack.herokuapp.com/)
* [Forum](https://discourse.zendframework.com/)

View File

@@ -1,64 +0,0 @@
{
"name": "zendframework/zend-http",
"description": "Provides an easy interface for performing Hyper-Text Transfer Protocol (HTTP) requests",
"license": "BSD-3-Clause",
"keywords": [
"zf",
"zend",
"zendframework",
"http",
"HTTP client"
],
"support": {
"docs": "https://docs.zendframework.com/zend-http/",
"issues": "https://github.com/zendframework/zend-http/issues",
"source": "https://github.com/zendframework/zend-http",
"rss": "https://github.com/zendframework/zend-http/releases.atom",
"chat": "https://zendframework-slack.herokuapp.com",
"forum": "https://discourse.zendframework.com/c/questions/components"
},
"require": {
"php": "^5.6 || ^7.0",
"zendframework/zend-loader": "^2.5.1",
"zendframework/zend-stdlib": "^3.2.1",
"zendframework/zend-uri": "^2.5.2",
"zendframework/zend-validator": "^2.10.1"
},
"require-dev": {
"phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.3",
"zendframework/zend-coding-standard": "~1.0.0",
"zendframework/zend-config": "^3.1 || ^2.6"
},
"suggest": {
"paragonie/certainty": "For automated management of cacert.pem"
},
"autoload": {
"psr-4": {
"Zend\\Http\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"ZendTest\\Http\\": "test/"
}
},
"config": {
"sort-packages": true
},
"extra": {
"branch-alias": {
"dev-master": "2.11.x-dev",
"dev-develop": "2.12.x-dev"
}
},
"scripts": {
"check": [
"@cs-check",
"@test"
],
"cs-check": "phpcs",
"cs-fix": "phpcbf",
"test": "phpunit --colors=always",
"test-coverage": "phpunit --colors=always --coverage-clover clover.xml"
}
}

View File

@@ -1,104 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http;
use Zend\Stdlib\Message;
/**
* HTTP standard message (Request/Response)
*
* @link http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4
*/
abstract class AbstractMessage extends Message
{
/**#@+
* @const string Version constant numbers
*/
const VERSION_10 = '1.0';
const VERSION_11 = '1.1';
const VERSION_2 = '2';
/**#@-*/
/**
* @var string
*/
protected $version = self::VERSION_11;
/**
* @var Headers|null
*/
protected $headers;
/**
* Set the HTTP version for this object, one of 1.0, 1.1 or 2
* (AbstractMessage::VERSION_10, AbstractMessage::VERSION_11, AbstractMessage::VERSION_2)
*
* @param string $version (Must be 1.0, 1.1 or 2)
* @return $this
* @throws Exception\InvalidArgumentException
*/
public function setVersion($version)
{
if (! in_array($version, [self::VERSION_10, self::VERSION_11, self::VERSION_2])) {
throw new Exception\InvalidArgumentException(
'Not valid or not supported HTTP version: ' . $version
);
}
$this->version = $version;
return $this;
}
/**
* Return the HTTP version for this request
*
* @return string
*/
public function getVersion()
{
return $this->version;
}
/**
* Provide an alternate Parameter Container implementation for headers in this object,
* (this is NOT the primary API for value setting, for that see getHeaders())
*
* @see getHeaders()
* @param Headers $headers
* @return $this
*/
public function setHeaders(Headers $headers)
{
$this->headers = $headers;
return $this;
}
/**
* Return the header container responsible for headers
*
* @return Headers
*/
public function getHeaders()
{
if ($this->headers === null || is_string($this->headers)) {
// this is only here for fromString lazy loading
$this->headers = (is_string($this->headers)) ? Headers::fromString($this->headers) : new Headers();
}
return $this->headers;
}
/**
* Allow PHP casting of this object
*
* @return string
*/
public function __toString()
{
return $this->toString();
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,58 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Client\Adapter;
/**
* An interface description for Zend\Http\Client\Adapter classes.
*
* These classes are used as connectors for Zend\Http\Client, performing the
* tasks of connecting, writing, reading and closing connection to the server.
*/
interface AdapterInterface
{
/**
* Set the configuration array for the adapter
*
* @param array $options
*/
public function setOptions($options = []);
/**
* Connect to the remote server
*
* @param string $host
* @param int $port
* @param bool $secure
*/
public function connect($host, $port = 80, $secure = false);
/**
* Send request to the remote server
*
* @param string $method
* @param \Zend\Uri\Uri $url
* @param string $httpVer
* @param array $headers
* @param string $body
* @return string Request as text
*/
public function write($method, $url, $httpVer = '1.1', $headers = [], $body = '');
/**
* Read response from server
*
* @return string
*/
public function read();
/**
* Close the connection to the server
*
*/
public function close();
}

View File

@@ -1,576 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Client\Adapter;
use Traversable;
use Zend\Http\Client\Adapter\AdapterInterface as HttpAdapter;
use Zend\Http\Client\Adapter\Exception as AdapterException;
use Zend\Stdlib\ArrayUtils;
/**
* An adapter class for Zend\Http\Client based on the curl extension.
* Curl requires libcurl. See for full requirements the PHP manual: http://php.net/curl
*/
class Curl implements HttpAdapter, StreamInterface
{
/**
* Operation timeout.
*
* @var int
*/
const ERROR_OPERATION_TIMEDOUT = 28;
/**
* Parameters array
*
* @var array
*/
protected $config = [];
/**
* What host/port are we connected to?
*
* @var array
*/
protected $connectedTo = [null, null];
/**
* The curl session handle
*
* @var resource|null
*/
protected $curl;
/**
* List of cURL options that should never be overwritten
*
* @var array
*/
protected $invalidOverwritableCurlOptions;
/**
* Response gotten from server
*
* @var string
*/
protected $response;
/**
* Stream for storing output
*
* @var resource
*/
protected $outputStream;
/**
* Adapter constructor
*
* Config is set using setOptions()
*
* @throws AdapterException\InitializationException
*/
public function __construct()
{
if (! extension_loaded('curl')) {
throw new AdapterException\InitializationException(
'cURL extension has to be loaded to use this Zend\Http\Client adapter'
);
}
$this->invalidOverwritableCurlOptions = [
CURLOPT_HTTPGET,
CURLOPT_POST,
CURLOPT_UPLOAD,
CURLOPT_CUSTOMREQUEST,
CURLOPT_HEADER,
CURLOPT_RETURNTRANSFER,
CURLOPT_HTTPHEADER,
CURLOPT_INFILE,
CURLOPT_INFILESIZE,
CURLOPT_PORT,
CURLOPT_MAXREDIRS,
CURLOPT_CONNECTTIMEOUT,
];
}
/**
* Set the configuration array for the adapter
*
* @param array|Traversable $options
* @return $this
* @throws AdapterException\InvalidArgumentException
*/
public function setOptions($options = [])
{
if ($options instanceof Traversable) {
$options = ArrayUtils::iteratorToArray($options);
}
if (! is_array($options)) {
throw new AdapterException\InvalidArgumentException(sprintf(
'Array or Traversable object expected, got %s',
gettype($options)
));
}
/** Config Key Normalization */
foreach ($options as $k => $v) {
unset($options[$k]); // unset original value
$options[str_replace(['-', '_', ' ', '.'], '', strtolower($k))] = $v; // replace w/ normalized
}
if (isset($options['proxyuser']) && isset($options['proxypass'])) {
$this->setCurlOption(CURLOPT_PROXYUSERPWD, $options['proxyuser'] . ':' . $options['proxypass']);
unset($options['proxyuser'], $options['proxypass']);
}
if (isset($options['sslverifypeer'])) {
$this->setCurlOption(CURLOPT_SSL_VERIFYPEER, $options['sslverifypeer']);
unset($options['sslverifypeer']);
}
foreach ($options as $k => $v) {
$option = strtolower($k);
switch ($option) {
case 'proxyhost':
$this->setCurlOption(CURLOPT_PROXY, $v);
break;
case 'proxyport':
$this->setCurlOption(CURLOPT_PROXYPORT, $v);
break;
default:
if (is_array($v) && isset($this->config[$option]) && is_array($this->config[$option])) {
$v = ArrayUtils::merge($this->config[$option], $v, true);
}
$this->config[$option] = $v;
break;
}
}
return $this;
}
/**
* Retrieve the array of all configuration options
*
* @return array
*/
public function getConfig()
{
return $this->config;
}
/**
* Direct setter for cURL adapter related options.
*
* @param string|int $option
* @param mixed $value
* @return $this
*/
public function setCurlOption($option, $value)
{
if (! isset($this->config['curloptions'])) {
$this->config['curloptions'] = [];
}
$this->config['curloptions'][$option] = $value;
return $this;
}
/**
* Initialize curl
*
* @param string $host
* @param int $port
* @param bool $secure
* @return void
* @throws AdapterException\RuntimeException if unable to connect
*/
public function connect($host, $port = 80, $secure = false)
{
// If we're already connected, disconnect first
if ($this->curl) {
$this->close();
}
// Do the actual connection
$this->curl = curl_init();
if ($port != 80) {
curl_setopt($this->curl, CURLOPT_PORT, intval($port));
}
if (isset($this->config['connecttimeout'])) {
$connectTimeout = $this->config['connecttimeout'];
} elseif (isset($this->config['timeout'])) {
$connectTimeout = $this->config['timeout'];
} else {
$connectTimeout = null;
}
if ($connectTimeout !== null && ! is_numeric($connectTimeout)) {
throw new AdapterException\InvalidArgumentException(sprintf(
'integer or numeric string expected, got %s',
gettype($connectTimeout)
));
}
if ($connectTimeout !== null) {
$connectTimeout = (int) $connectTimeout;
}
if ($connectTimeout !== null) {
if (defined('CURLOPT_CONNECTTIMEOUT_MS')) {
curl_setopt($this->curl, CURLOPT_CONNECTTIMEOUT_MS, $connectTimeout * 1000);
} else {
curl_setopt($this->curl, CURLOPT_CONNECTTIMEOUT, $connectTimeout);
}
}
if (isset($this->config['timeout'])) {
if (defined('CURLOPT_TIMEOUT_MS')) {
curl_setopt($this->curl, CURLOPT_TIMEOUT_MS, $this->config['timeout'] * 1000);
} else {
curl_setopt($this->curl, CURLOPT_TIMEOUT, $this->config['timeout']);
}
}
if (isset($this->config['sslcafile']) && $this->config['sslcafile']) {
curl_setopt($this->curl, CURLOPT_CAINFO, $this->config['sslcafile']);
}
if (isset($this->config['sslcapath']) && $this->config['sslcapath']) {
curl_setopt($this->curl, CURLOPT_CAPATH, $this->config['sslcapath']);
}
if (isset($this->config['maxredirects'])) {
// Set Max redirects
curl_setopt($this->curl, CURLOPT_MAXREDIRS, $this->config['maxredirects']);
}
if (! $this->curl) {
$this->close();
throw new AdapterException\RuntimeException('Unable to Connect to ' . $host . ':' . $port);
}
if ($secure !== false) {
// Behave the same like Zend\Http\Adapter\Socket on SSL options.
if (isset($this->config['sslcert'])) {
curl_setopt($this->curl, CURLOPT_SSLCERT, $this->config['sslcert']);
}
if (isset($this->config['sslpassphrase'])) {
curl_setopt($this->curl, CURLOPT_SSLCERTPASSWD, $this->config['sslpassphrase']);
}
}
// Update connected_to
$this->connectedTo = [$host, $port];
}
/**
* Send request to the remote server
*
* @param string $method
* @param \Zend\Uri\Uri $uri
* @param float $httpVersion
* @param array $headers
* @param string $body
* @return string $request
* @throws AdapterException\RuntimeException If connection fails, connected
* to wrong host, no PUT file defined, unsupported method, or unsupported
* cURL option.
* @throws AdapterException\InvalidArgumentException if $method is currently not supported
* @throws AdapterException\TimeoutException if connection timed out
*/
public function write($method, $uri, $httpVersion = 1.1, $headers = [], $body = '')
{
// Make sure we're properly connected
if (! $this->curl) {
throw new AdapterException\RuntimeException('Trying to write but we are not connected');
}
if ($this->connectedTo[0] != $uri->getHost() || $this->connectedTo[1] != $uri->getPort()) {
throw new AdapterException\RuntimeException('Trying to write but we are connected to the wrong host');
}
// set URL
curl_setopt($this->curl, CURLOPT_URL, $uri->__toString());
// ensure correct curl call
$curlValue = true;
switch ($method) {
case 'GET':
$curlMethod = CURLOPT_HTTPGET;
break;
case 'POST':
$curlMethod = CURLOPT_POST;
break;
case 'PUT':
// There are two different types of PUT request, either a Raw Data string has been set
// or CURLOPT_INFILE and CURLOPT_INFILESIZE are used.
if (is_resource($body)) {
$this->config['curloptions'][CURLOPT_INFILE] = $body;
}
if (isset($this->config['curloptions'][CURLOPT_INFILE])) {
// Now we will probably already have Content-Length set, so that we have to delete it
// from $headers at this point:
if (! isset($headers['Content-Length'])
&& ! isset($this->config['curloptions'][CURLOPT_INFILESIZE])
) {
throw new AdapterException\RuntimeException(
'Cannot set a file-handle for cURL option CURLOPT_INFILE'
. ' without also setting its size in CURLOPT_INFILESIZE.'
);
}
if (isset($headers['Content-Length'])) {
$this->config['curloptions'][CURLOPT_INFILESIZE] = (int) $headers['Content-Length'];
unset($headers['Content-Length']);
}
if (is_resource($body)) {
$body = '';
}
$curlMethod = CURLOPT_UPLOAD;
} else {
$curlMethod = CURLOPT_CUSTOMREQUEST;
$curlValue = 'PUT';
}
break;
case 'PATCH':
$curlMethod = CURLOPT_CUSTOMREQUEST;
$curlValue = 'PATCH';
break;
case 'DELETE':
$curlMethod = CURLOPT_CUSTOMREQUEST;
$curlValue = 'DELETE';
break;
case 'OPTIONS':
$curlMethod = CURLOPT_CUSTOMREQUEST;
$curlValue = 'OPTIONS';
break;
case 'TRACE':
$curlMethod = CURLOPT_CUSTOMREQUEST;
$curlValue = 'TRACE';
break;
case 'HEAD':
$curlMethod = CURLOPT_CUSTOMREQUEST;
$curlValue = 'HEAD';
break;
default:
// For now, through an exception for unsupported request methods
throw new AdapterException\InvalidArgumentException(sprintf(
'Method \'%s\' currently not supported',
$method
));
}
if (is_resource($body) && $curlMethod != CURLOPT_UPLOAD) {
throw new AdapterException\RuntimeException('Streaming requests are allowed only with PUT');
}
// get http version to use
$curlHttp = $httpVersion == 1.1 ? CURL_HTTP_VERSION_1_1 : CURL_HTTP_VERSION_1_0;
// mark as HTTP request and set HTTP method
curl_setopt($this->curl, CURLOPT_HTTP_VERSION, $curlHttp);
curl_setopt($this->curl, $curlMethod, $curlValue);
// Set the CURLINFO_HEADER_OUT flag so that we can retrieve the full request string later
curl_setopt($this->curl, CURLINFO_HEADER_OUT, true);
if ($this->outputStream) {
// headers will be read into the response
curl_setopt($this->curl, CURLOPT_HEADER, false);
curl_setopt($this->curl, CURLOPT_HEADERFUNCTION, [$this, 'readHeader']);
// and data will be written into the file
curl_setopt($this->curl, CURLOPT_FILE, $this->outputStream);
} else {
// ensure headers are also returned
curl_setopt($this->curl, CURLOPT_HEADER, true);
// ensure actual response is returned
curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true);
}
// Treating basic auth headers in a special way
if (array_key_exists('Authorization', $headers) && 'Basic' == substr($headers['Authorization'], 0, 5)) {
curl_setopt($this->curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($this->curl, CURLOPT_USERPWD, base64_decode(substr($headers['Authorization'], 6)));
unset($headers['Authorization']);
}
// set additional headers
if (! isset($headers['Accept'])) {
$headers['Accept'] = '';
}
$curlHeaders = [];
foreach ($headers as $key => $value) {
$curlHeaders[] = $key . ': ' . $value;
}
curl_setopt($this->curl, CURLOPT_HTTPHEADER, $curlHeaders);
/**
* Make sure POSTFIELDS is set after $curlMethod is set:
* @link http://de2.php.net/manual/en/function.curl-setopt.php#81161
*/
if ($curlMethod == CURLOPT_UPLOAD) {
// this covers a PUT by file-handle:
// Make the setting of this options explicit (rather than setting it through the loop following a bit lower)
// to group common functionality together.
curl_setopt($this->curl, CURLOPT_INFILE, $this->config['curloptions'][CURLOPT_INFILE]);
curl_setopt($this->curl, CURLOPT_INFILESIZE, $this->config['curloptions'][CURLOPT_INFILESIZE]);
unset($this->config['curloptions'][CURLOPT_INFILE]);
unset($this->config['curloptions'][CURLOPT_INFILESIZE]);
} elseif (in_array($method, ['POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'], true)) {
curl_setopt($this->curl, CURLOPT_POSTFIELDS, $body);
}
// set additional curl options
if (isset($this->config['curloptions'])) {
foreach ((array) $this->config['curloptions'] as $k => $v) {
if (! in_array($k, $this->invalidOverwritableCurlOptions)) {
if (curl_setopt($this->curl, $k, $v) == false) {
throw new AdapterException\RuntimeException(sprintf(
'Unknown or erroreous cURL option "%s" set',
$k
));
}
}
}
}
$this->response = '';
// send the request
$response = curl_exec($this->curl);
// if we used streaming, headers are already there
if (! is_resource($this->outputStream)) {
$this->response = $response;
}
$request = curl_getinfo($this->curl, CURLINFO_HEADER_OUT);
$request .= $body;
if ($response === false || empty($this->response)) {
if (curl_errno($this->curl) === static::ERROR_OPERATION_TIMEDOUT) {
throw new AdapterException\TimeoutException(
'Read timed out',
AdapterException\TimeoutException::READ_TIMEOUT
);
}
throw new AdapterException\RuntimeException(sprintf(
'Error in cURL request: %s',
curl_error($this->curl)
));
}
// separating header from body because it is dangerous to accidentially replace strings in the body
$responseHeaderSize = curl_getinfo($this->curl, CURLINFO_HEADER_SIZE);
$responseHeaders = substr($this->response, 0, $responseHeaderSize);
// cURL automatically decodes chunked-messages, this means we have to
// disallow the Zend\Http\Response to do it again.
$responseHeaders = preg_replace("/Transfer-Encoding:\s*chunked\\r\\n/i", '', $responseHeaders);
// cURL can automatically handle content encoding; prevent double-decoding from occurring
if (isset($this->config['curloptions'][CURLOPT_ENCODING])
&& '' == $this->config['curloptions'][CURLOPT_ENCODING]
) {
$responseHeaders = preg_replace("/Content-Encoding:\s*gzip\\r\\n/i", '', $responseHeaders);
}
// cURL automatically handles Proxy rewrites, remove the "HTTP/1.0 200 Connection established" string:
$responseHeaders = preg_replace(
"/HTTP\/1.[01]\s*200\s*Connection\s*established\\r\\n\\r\\n/",
'',
$responseHeaders
);
// replace old header with new, cleaned up, header
$this->response = substr_replace($this->response, $responseHeaders, 0, $responseHeaderSize);
// Eliminate multiple HTTP responses.
do {
$parts = preg_split('|(?:\r?\n){2}|m', $this->response, 2);
$again = false;
if (isset($parts[1]) && preg_match("|^HTTP/1\.[01](.*?)\r\n|mi", $parts[1])) {
$this->response = $parts[1];
$again = true;
}
} while ($again);
return $request;
}
/**
* Return read response from server
*
* @return string
*/
public function read()
{
return $this->response;
}
/**
* Close the connection to the server
*
*/
public function close()
{
if (is_resource($this->curl)) {
curl_close($this->curl);
}
$this->curl = null;
$this->connectedTo = [null, null];
}
/**
* Get cUrl Handle
*
* @return resource
*/
public function getHandle()
{
return $this->curl;
}
/**
* Set output stream for the response
*
* @param resource $stream
* @return $this
*/
public function setOutputStream($stream)
{
$this->outputStream = $stream;
return $this;
}
/**
* Header reader function for CURL
*
* @param resource $curl
* @param string $header
* @return int
*/
public function readHeader($curl, $header)
{
$this->response .= $header;
return strlen($header);
}
}

View File

@@ -1,14 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Client\Adapter\Exception;
use Zend\Http\Client\Exception\ExceptionInterface as HttpClientException;
interface ExceptionInterface extends HttpClientException
{
}

View File

@@ -1,12 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Client\Adapter\Exception;
class InitializationException extends RuntimeException
{
}

View File

@@ -1,15 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Client\Adapter\Exception;
use Zend\Http\Client\Exception;
class InvalidArgumentException extends Exception\InvalidArgumentException implements
ExceptionInterface
{
}

View File

@@ -1,15 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Client\Adapter\Exception;
use Zend\Http\Client\Exception;
class OutOfRangeException extends Exception\OutOfRangeException implements
ExceptionInterface
{
}

View File

@@ -1,15 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Client\Adapter\Exception;
use Zend\Http\Client\Exception;
class RuntimeException extends Exception\RuntimeException implements
ExceptionInterface
{
}

View File

@@ -1,13 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Client\Adapter\Exception;
class TimeoutException extends RuntimeException implements ExceptionInterface
{
const READ_TIMEOUT = 1000;
}

View File

@@ -1,319 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Client\Adapter;
use Traversable;
use Zend\Http\Client;
use Zend\Http\Client\Adapter\Exception as AdapterException;
use Zend\Http\Response;
use Zend\Stdlib\ArrayUtils;
use Zend\Stdlib\ErrorHandler;
/**
* HTTP Proxy-supporting Zend\Http\Client adapter class, based on the default
* socket based adapter.
*
* Should be used if proxy HTTP access is required. If no proxy is set, will
* fall back to Zend\Http\Client\Adapter\Socket behavior. Just like the
* default Socket adapter, this adapter does not require any special extensions
* installed.
*/
class Proxy extends Socket
{
/**
* Parameters array
*
* @var array
*/
protected $config = [
'persistent' => false,
'ssltransport' => 'ssl',
'sslcert' => null,
'sslpassphrase' => null,
'sslverifypeer' => true,
'sslcafile' => null,
'sslcapath' => null,
'sslallowselfsigned' => false,
'sslusecontext' => false,
'sslverifypeername' => true,
'proxy_host' => '',
'proxy_port' => 8080,
'proxy_user' => '',
'proxy_pass' => '',
'proxy_auth' => Client::AUTH_BASIC,
];
/**
* Whether HTTPS CONNECT was already negotiated with the proxy or not
*
* @var bool
*/
protected $negotiated = false;
/**
* Set the configuration array for the adapter
*
* @param array $options
*/
public function setOptions($options = [])
{
if ($options instanceof Traversable) {
$options = ArrayUtils::iteratorToArray($options);
}
if (! is_array($options)) {
throw new AdapterException\InvalidArgumentException(
'Array or Zend\Config object expected, got ' . gettype($options)
);
}
//enforcing that the proxy keys are set in the form proxy_*
foreach ($options as $k => $v) {
if (preg_match('/^proxy[a-z]+/', $k)) {
$options['proxy_' . substr($k, 5, strlen($k))] = $v;
unset($options[$k]);
}
}
parent::setOptions($options);
}
/**
* Connect to the remote server
*
* Will try to connect to the proxy server. If no proxy was set, will
* fall back to the target server (behave like regular Socket adapter)
*
* @param string $host
* @param int $port
* @param bool $secure
* @throws AdapterException\RuntimeException
*/
public function connect($host, $port = 80, $secure = false)
{
// If no proxy is set, fall back to Socket adapter
if (! $this->config['proxy_host']) {
parent::connect($host, $port, $secure);
return;
}
/* Url might require stream context even if proxy connection doesn't */
if ($secure) {
$this->config['sslusecontext'] = true;
$this->setSslCryptoMethod = false;
}
// Connect (a non-secure connection) to the proxy server
parent::connect(
$this->config['proxy_host'],
$this->config['proxy_port'],
false
);
}
/**
* Send request to the proxy server
*
* @param string $method
* @param \Zend\Uri\Uri $uri
* @param string $httpVer
* @param array $headers
* @param string $body
* @throws AdapterException\RuntimeException
* @return string Request as string
*/
public function write($method, $uri, $httpVer = '1.1', $headers = [], $body = '')
{
// If no proxy is set, fall back to default Socket adapter
if (! $this->config['proxy_host']) {
return parent::write($method, $uri, $httpVer, $headers, $body);
}
// Make sure we're properly connected
if (! $this->socket) {
throw new AdapterException\RuntimeException('Trying to write but we are not connected');
}
$host = $this->config['proxy_host'];
$port = $this->config['proxy_port'];
$isSecure = strtolower($uri->getScheme()) === 'https';
$connectedHost = ($isSecure ? $this->config['ssltransport'] : 'tcp') . '://' . $host;
if ($this->connectedTo[1] !== $port || $this->connectedTo[0] !== $connectedHost) {
throw new AdapterException\RuntimeException(
'Trying to write but we are connected to the wrong proxy server'
);
}
// Add Proxy-Authorization header
if ($this->config['proxy_user'] && ! isset($headers['proxy-authorization'])) {
$headers['proxy-authorization'] = Client::encodeAuthHeader(
$this->config['proxy_user'],
$this->config['proxy_pass'],
$this->config['proxy_auth']
);
}
// if we are proxying HTTPS, preform CONNECT handshake with the proxy
if ($isSecure && ! $this->negotiated) {
$this->connectHandshake($uri->getHost(), $uri->getPort(), $httpVer, $headers);
$this->negotiated = true;
}
// Save request method for later
$this->method = $method;
if ($uri->getUserInfo()) {
$headers['Authorization'] = 'Basic ' . base64_encode($uri->getUserInfo());
}
$path = $uri->getPath();
$query = $uri->getQuery();
$path .= $query ? '?' . $query : '';
if (! $this->negotiated) {
$path = $uri->getScheme() . '://' . $uri->getHost() . $path;
}
// Build request headers
$request = sprintf('%s %s HTTP/%s%s', $method, $path, $httpVer, "\r\n");
// Add all headers to the request string
foreach ($headers as $k => $v) {
if (is_string($k)) {
$v = $k . ': ' . $v;
}
$request .= $v . "\r\n";
}
if (is_resource($body)) {
$request .= "\r\n";
} else {
// Add the request body
$request .= "\r\n" . $body;
}
// Send the request
ErrorHandler::start();
$test = fwrite($this->socket, $request);
$error = ErrorHandler::stop();
if ($test === false) {
throw new AdapterException\RuntimeException('Error writing request to proxy server', 0, $error);
}
if (is_resource($body)) {
if (stream_copy_to_stream($body, $this->socket) == 0) {
throw new AdapterException\RuntimeException('Error writing request to server');
}
}
return $request;
}
/**
* Preform handshaking with HTTPS proxy using CONNECT method
*
* @param string $host
* @param int $port
* @param string $httpVer
* @param array $headers
* @throws AdapterException\RuntimeException
*/
protected function connectHandshake($host, $port = 443, $httpVer = '1.1', array &$headers = [])
{
$request = 'CONNECT ' . $host . ':' . $port . ' HTTP/' . $httpVer . "\r\n"
. 'Host: ' . $host . "\r\n";
// Add the user-agent header
if (isset($this->config['useragent'])) {
$request .= 'User-agent: ' . $this->config['useragent'] . "\r\n";
}
// If the proxy-authorization header is set, send it to proxy but remove
// it from headers sent to target host
if (isset($headers['proxy-authorization'])) {
$request .= 'Proxy-authorization: ' . $headers['proxy-authorization'] . "\r\n";
unset($headers['proxy-authorization']);
}
$request .= "\r\n";
// Send the request
ErrorHandler::start();
$test = fwrite($this->socket, $request);
$error = ErrorHandler::stop();
if (! $test) {
throw new AdapterException\RuntimeException('Error writing request to proxy server', 0, $error);
}
// Read response headers only
$response = '';
$gotStatus = false;
ErrorHandler::start();
while ($line = fgets($this->socket)) {
$gotStatus = $gotStatus || (strpos($line, 'HTTP') !== false);
if ($gotStatus) {
$response .= $line;
if (! rtrim($line)) {
break;
}
}
}
ErrorHandler::stop();
// Check that the response from the proxy is 200
if (Response::fromString($response)->getStatusCode() != 200) {
throw new AdapterException\RuntimeException(sprintf(
'Unable to connect to HTTPS proxy. Server response: %s',
$response
));
}
// If all is good, switch socket to secure mode. We have to fall back
// through the different modes
$modes = [
STREAM_CRYPTO_METHOD_TLS_CLIENT,
STREAM_CRYPTO_METHOD_SSLv3_CLIENT,
STREAM_CRYPTO_METHOD_SSLv23_CLIENT,
STREAM_CRYPTO_METHOD_SSLv2_CLIENT,
];
$success = false;
foreach ($modes as $mode) {
$success = stream_socket_enable_crypto($this->socket, true, $mode);
if ($success) {
break;
}
}
if (! $success) {
throw new AdapterException\RuntimeException(
'Unable to connect to HTTPS server through proxy: could not negotiate secure connection.'
);
}
}
/**
* Close the connection to the server
*/
public function close()
{
parent::close();
$this->negotiated = false;
}
/**
* Destructor: make sure the socket is disconnected
*/
public function __destruct()
{
if ($this->socket) {
$this->close();
}
}
}

View File

@@ -1,683 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Client\Adapter;
use Traversable;
use Zend\Http\Client\Adapter\AdapterInterface as HttpAdapter;
use Zend\Http\Client\Adapter\Exception as AdapterException;
use Zend\Http\Request;
use Zend\Http\Response;
use Zend\Stdlib\ArrayUtils;
use Zend\Stdlib\ErrorHandler;
/**
* A sockets based (stream\socket\client) adapter class for Zend\Http\Client. Can be used
* on almost every PHP environment, and does not require any special extensions.
*/
class Socket implements HttpAdapter, StreamInterface
{
/**
* Map SSL transport wrappers to stream crypto method constants
*
* @var array
*/
protected static $sslCryptoTypes = [
'ssl' => STREAM_CRYPTO_METHOD_SSLv23_CLIENT,
'sslv2' => STREAM_CRYPTO_METHOD_SSLv2_CLIENT,
'sslv3' => STREAM_CRYPTO_METHOD_SSLv3_CLIENT,
'tls' => STREAM_CRYPTO_METHOD_TLS_CLIENT,
];
/**
* The socket for server connection
*
* @var resource|null
*/
protected $socket;
/**
* What host/port are we connected to?
*
* @var array
*/
protected $connectedTo = [null, null];
/**
* Stream for storing output
*
* @var resource
*/
protected $outStream;
/**
* Parameters array
*
* @var array
*/
protected $config = [
'persistent' => false,
'ssltransport' => 'ssl',
'sslcert' => null,
'sslpassphrase' => null,
'sslverifypeer' => true,
'sslcafile' => null,
'sslcapath' => null,
'sslallowselfsigned' => false,
'sslusecontext' => false,
'sslverifypeername' => true,
];
/**
* Request method - will be set by write() and might be used by read()
*
* @var string
*/
protected $method;
/**
* Stream context
*
* @var resource
*/
protected $context;
/**
* @var bool
*/
protected $setSslCryptoMethod = true;
/**
* Adapter constructor, currently empty. Config is set using setOptions()
*
*/
public function __construct()
{
}
/**
* Set the configuration array for the adapter
*
* @param array|Traversable $options
* @throws AdapterException\InvalidArgumentException
*/
public function setOptions($options = [])
{
if ($options instanceof Traversable) {
$options = ArrayUtils::iteratorToArray($options);
}
if (! is_array($options)) {
throw new AdapterException\InvalidArgumentException(
'Array or Zend\Config object expected, got ' . gettype($options)
);
}
foreach ($options as $k => $v) {
$this->config[strtolower($k)] = $v;
}
}
/**
* Retrieve the array of all configuration options
*
* @return array
*/
public function getConfig()
{
return $this->config;
}
/**
* Set the stream context for the TCP connection to the server
*
* Can accept either a pre-existing stream context resource, or an array
* of stream options, similar to the options array passed to the
* stream_context_create() PHP function. In such case a new stream context
* will be created using the passed options.
*
* @since Zend Framework 1.9
*
* @param mixed $context Stream context or array of context options
* @throws Exception\InvalidArgumentException
* @return $this
*/
public function setStreamContext($context)
{
if (is_resource($context) && get_resource_type($context) == 'stream-context') {
$this->context = $context;
} elseif (is_array($context)) {
$this->context = stream_context_create($context);
} else {
// Invalid parameter
throw new AdapterException\InvalidArgumentException(sprintf(
'Expecting either a stream context resource or array, got %s',
gettype($context)
));
}
return $this;
}
/**
* Get the stream context for the TCP connection to the server.
*
* If no stream context is set, will create a default one.
*
* @return resource
*/
public function getStreamContext()
{
if (! $this->context) {
$this->context = stream_context_create();
}
return $this->context;
}
/**
* Connect to the remote server
*
* @param string $host
* @param int $port
* @param bool $secure
* @throws AdapterException\RuntimeException
*/
public function connect($host, $port = 80, $secure = false)
{
// If we are connected to the wrong host, disconnect first
$connectedHost = (strpos($this->connectedTo[0], '://'))
? substr($this->connectedTo[0], (strpos($this->connectedTo[0], '://') + 3), strlen($this->connectedTo[0]))
: $this->connectedTo[0];
if ($connectedHost != $host || $this->connectedTo[1] != $port) {
if (is_resource($this->socket)) {
$this->close();
}
}
// Now, if we are not connected, connect
if (! is_resource($this->socket) || ! $this->config['keepalive']) {
$context = $this->getStreamContext();
if ($secure || $this->config['sslusecontext']) {
if ($this->config['sslverifypeer'] !== null) {
if (! stream_context_set_option($context, 'ssl', 'verify_peer', $this->config['sslverifypeer'])) {
throw new AdapterException\RuntimeException('Unable to set sslverifypeer option');
}
}
if ($this->config['sslcafile']) {
if (! stream_context_set_option($context, 'ssl', 'cafile', $this->config['sslcafile'])) {
throw new AdapterException\RuntimeException('Unable to set sslcafile option');
}
}
if ($this->config['sslcapath']) {
if (! stream_context_set_option($context, 'ssl', 'capath', $this->config['sslcapath'])) {
throw new AdapterException\RuntimeException('Unable to set sslcapath option');
}
}
if ($this->config['sslallowselfsigned'] !== null) {
if (! stream_context_set_option(
$context,
'ssl',
'allow_self_signed',
$this->config['sslallowselfsigned']
)) {
throw new AdapterException\RuntimeException('Unable to set sslallowselfsigned option');
}
}
if ($this->config['sslcert'] !== null) {
if (! stream_context_set_option($context, 'ssl', 'local_cert', $this->config['sslcert'])) {
throw new AdapterException\RuntimeException('Unable to set sslcert option');
}
}
if ($this->config['sslpassphrase'] !== null) {
if (! stream_context_set_option($context, 'ssl', 'passphrase', $this->config['sslpassphrase'])) {
throw new AdapterException\RuntimeException('Unable to set sslpassphrase option');
}
}
if ($this->config['sslverifypeername'] !== null) {
if (! stream_context_set_option(
$context,
'ssl',
'verify_peer_name',
$this->config['sslverifypeername']
)) {
throw new AdapterException\RuntimeException('Unable to set sslverifypeername option');
}
}
}
$flags = STREAM_CLIENT_CONNECT;
if ($this->config['persistent']) {
$flags |= STREAM_CLIENT_PERSISTENT;
}
if (isset($this->config['connecttimeout'])) {
$connectTimeout = $this->config['connecttimeout'];
} else {
$connectTimeout = $this->config['timeout'];
}
if ($connectTimeout !== null && ! is_numeric($connectTimeout)) {
throw new AdapterException\InvalidArgumentException(sprintf(
'integer or numeric string expected, got %s',
gettype($connectTimeout)
));
}
ErrorHandler::start();
$this->socket = stream_socket_client(
$host . ':' . $port,
$errno,
$errstr,
(int) $connectTimeout,
$flags,
$context
);
$error = ErrorHandler::stop();
if (! $this->socket) {
$this->close();
throw new AdapterException\RuntimeException(
sprintf(
'Unable to connect to %s:%d%s',
$host,
$port,
($error ? ' . Error #' . $error->getCode() . ': ' . $error->getMessage() : '')
),
0,
$error
);
}
// Set the stream timeout
if (! stream_set_timeout($this->socket, (int) $this->config['timeout'])) {
throw new AdapterException\RuntimeException('Unable to set the connection timeout');
}
if ($secure || $this->config['sslusecontext']) {
if ($this->setSslCryptoMethod) {
if ($this->config['ssltransport']
&& isset(static::$sslCryptoTypes[$this->config['ssltransport']])
) {
$sslCryptoMethod = static::$sslCryptoTypes[$this->config['ssltransport']];
} else {
$sslCryptoMethod = STREAM_CRYPTO_METHOD_SSLv3_CLIENT;
}
ErrorHandler::start();
$test = stream_socket_enable_crypto($this->socket, true, $sslCryptoMethod);
$error = ErrorHandler::stop();
if (! $test || $error) {
// Error handling is kind of difficult when it comes to SSL
$errorString = '';
if (extension_loaded('openssl')) {
while (($sslError = openssl_error_string()) != false) {
$errorString .= sprintf('; SSL error: %s', $sslError);
}
}
$this->close();
if ((! $errorString) && $this->config['sslverifypeer']) {
// There's good chance our error is due to sslcapath not being properly set
if (! ($this->config['sslcafile'] || $this->config['sslcapath'])) {
$errorString = 'make sure the "sslcafile" or "sslcapath" option are properly set for '
. 'the environment.';
} elseif ($this->config['sslcafile'] && ! is_file($this->config['sslcafile'])) {
$errorString = 'make sure the "sslcafile" option points to a valid SSL certificate '
. 'file';
} elseif ($this->config['sslcapath'] && ! is_dir($this->config['sslcapath'])) {
$errorString = 'make sure the "sslcapath" option points to a valid SSL certificate '
. 'directory';
}
}
if ($errorString) {
$errorString = sprintf(': %s', $errorString);
}
throw new AdapterException\RuntimeException(sprintf(
'Unable to enable crypto on TCP connection %s%s',
$host,
$errorString
), 0, $error);
}
}
$host = $this->config['ssltransport'] . '://' . $host;
} else {
$host = 'tcp://' . $host;
}
// Update connectedTo
$this->connectedTo = [$host, $port];
}
}
/**
* Send request to the remote server
*
* @param string $method
* @param \Zend\Uri\Uri $uri
* @param string $httpVer
* @param array $headers
* @param string $body
* @throws AdapterException\RuntimeException
* @return string Request as string
*/
public function write($method, $uri, $httpVer = '1.1', $headers = [], $body = '')
{
// Make sure we're properly connected
if (! $this->socket) {
throw new AdapterException\RuntimeException('Trying to write but we are not connected');
}
$host = $uri->getHost();
$host = (strtolower($uri->getScheme()) == 'https' ? $this->config['ssltransport'] : 'tcp') . '://' . $host;
if ($this->connectedTo[0] != $host || $this->connectedTo[1] != $uri->getPort()) {
throw new AdapterException\RuntimeException('Trying to write but we are connected to the wrong host');
}
// Save request method for later
$this->method = $method;
// Build request headers
$path = $uri->getPath();
$query = $uri->getQuery();
$path .= $query ? '?' . $query : '';
$request = $method . ' ' . $path . ' HTTP/' . $httpVer . "\r\n";
foreach ($headers as $k => $v) {
if (is_string($k)) {
$v = $k . ': ' . $v;
}
$request .= $v . "\r\n";
}
if (is_resource($body)) {
$request .= "\r\n";
} else {
// Add the request body
$request .= "\r\n" . $body;
}
// Send the request
ErrorHandler::start();
$test = fwrite($this->socket, $request);
$error = ErrorHandler::stop();
if (false === $test) {
throw new AdapterException\RuntimeException('Error writing request to server', 0, $error);
}
if (is_resource($body)) {
if (stream_copy_to_stream($body, $this->socket) == 0) {
throw new AdapterException\RuntimeException('Error writing request to server');
}
}
return $request;
}
/**
* Read response from server
*
* @throws AdapterException\RuntimeException
* @return string
*/
public function read()
{
// First, read headers only
$response = '';
$gotStatus = false;
while (($line = fgets($this->socket)) !== false) {
$gotStatus = $gotStatus || (strpos($line, 'HTTP') !== false);
if ($gotStatus) {
$response .= $line;
if (rtrim($line) === '') {
break;
}
}
}
$this->_checkSocketReadTimeout();
$responseObj = Response::fromString($response);
$statusCode = $responseObj->getStatusCode();
// Handle 100 and 101 responses internally by restarting the read again
if ($statusCode == 100 || $statusCode == 101) {
return $this->read();
}
// Check headers to see what kind of connection / transfer encoding we have
$headers = $responseObj->getHeaders();
/**
* Responses to HEAD requests and 204 or 304 responses are not expected
* to have a body - stop reading here
*/
if ($statusCode == 304
|| $statusCode == 204
|| $this->method == Request::METHOD_HEAD
) {
// Close the connection if requested to do so by the server
$connection = $headers->get('connection');
if ($connection && $connection->getFieldValue() == 'close') {
$this->close();
}
return $response;
}
// If we got a 'transfer-encoding: chunked' header
$transferEncoding = $headers->get('transfer-encoding');
$contentLength = $headers->get('content-length');
if ($transferEncoding !== false) {
if (strtolower($transferEncoding->getFieldValue()) == 'chunked') {
do {
$line = fgets($this->socket);
$this->_checkSocketReadTimeout();
$chunk = $line;
// Figure out the next chunk size
$chunksize = trim($line);
if (! ctype_xdigit($chunksize)) {
$this->close();
throw new AdapterException\RuntimeException(sprintf(
'Invalid chunk size "%s" unable to read chunked body',
$chunksize
));
}
// Convert the hexadecimal value to plain integer
$chunksize = hexdec($chunksize);
// Read next chunk
$readTo = ftell($this->socket) + $chunksize;
do {
$currentPos = ftell($this->socket);
if ($currentPos >= $readTo) {
break;
}
if ($this->outStream) {
if (stream_copy_to_stream($this->socket, $this->outStream, $readTo - $currentPos) == 0) {
$this->_checkSocketReadTimeout();
break;
}
} else {
$line = fread($this->socket, $readTo - $currentPos);
if ($line === false || strlen($line) === 0) {
$this->_checkSocketReadTimeout();
break;
}
$chunk .= $line;
}
} while (! feof($this->socket));
ErrorHandler::start();
$chunk .= fgets($this->socket);
ErrorHandler::stop();
$this->_checkSocketReadTimeout();
if (! $this->outStream) {
$response .= $chunk;
}
} while ($chunksize > 0);
} else {
$this->close();
throw new AdapterException\RuntimeException(sprintf(
'Cannot handle "%s" transfer encoding',
$transferEncoding->getFieldValue()
));
}
// We automatically decode chunked-messages when writing to a stream
// this means we have to disallow the Zend\Http\Response to do it again
if ($this->outStream) {
$response = str_ireplace("Transfer-Encoding: chunked\r\n", '', $response);
}
// Else, if we got the content-length header, read this number of bytes
} elseif ($contentLength !== false) {
// If we got more than one Content-Length header (see ZF-9404) use
// the last value sent
if (is_array($contentLength)) {
$contentLength = $contentLength[count($contentLength) - 1];
}
$contentLength = $contentLength->getFieldValue();
$currentPos = ftell($this->socket);
for ($readTo = $currentPos + $contentLength;
$readTo > $currentPos;
$currentPos = ftell($this->socket)) {
if ($this->outStream) {
if (stream_copy_to_stream($this->socket, $this->outStream, $readTo - $currentPos) == 0) {
$this->_checkSocketReadTimeout();
break;
}
} else {
$chunk = fread($this->socket, $readTo - $currentPos);
if ($chunk === false || strlen($chunk) === 0) {
$this->_checkSocketReadTimeout();
break;
}
$response .= $chunk;
}
// Break if the connection ended prematurely
if (feof($this->socket)) {
break;
}
}
// Fallback: just read the response until EOF
} else {
do {
if ($this->outStream) {
if (stream_copy_to_stream($this->socket, $this->outStream) == 0) {
$this->_checkSocketReadTimeout();
break;
}
} else {
$buff = fread($this->socket, 8192);
if ($buff === false || strlen($buff) === 0) {
$this->_checkSocketReadTimeout();
break;
} else {
$response .= $buff;
}
}
} while (feof($this->socket) === false);
$this->close();
}
// Close the connection if requested to do so by the server
$connection = $headers->get('connection');
if ($connection && $connection->getFieldValue() == 'close') {
$this->close();
}
return $response;
}
/**
* Close the connection to the server
*
*/
public function close()
{
if (is_resource($this->socket)) {
ErrorHandler::start();
fclose($this->socket);
ErrorHandler::stop();
}
$this->socket = null;
$this->connectedTo = [null, null];
}
/**
* Check if the socket has timed out - if so close connection and throw
* an exception
*
* @throws AdapterException\TimeoutException with READ_TIMEOUT code
*/
// @codingStandardsIgnoreStart
protected function _checkSocketReadTimeout()
{
// @codingStandardsIgnoreEnd
if ($this->socket) {
$info = stream_get_meta_data($this->socket);
$timedout = $info['timed_out'];
if ($timedout) {
$this->close();
throw new AdapterException\TimeoutException(
sprintf('Read timed out after %d seconds', $this->config['timeout']),
AdapterException\TimeoutException::READ_TIMEOUT
);
}
}
}
/**
* Set output stream for the response
*
* @param resource $stream
* @return \Zend\Http\Client\Adapter\Socket
*/
public function setOutputStream($stream)
{
$this->outStream = $stream;
return $this;
}
/**
* Destructor: make sure the socket is disconnected
*
* If we are in persistent TCP mode, will not close the connection
*
*/
public function __destruct()
{
if (! $this->config['persistent']) {
if ($this->socket) {
$this->close();
}
}
}
}

View File

@@ -1,26 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Client\Adapter;
/**
* An interface description for Zend\Http\Client\Adapter\Stream classes.
*
* This interface describes Zend\Http\Client\Adapter which supports streaming.
*/
interface StreamInterface
{
/**
* Set output stream
*
* This function sets output stream where the result will be stored.
*
* @param resource $stream Stream to write the output to
*
*/
public function setOutputStream($stream);
}

View File

@@ -1,214 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Client\Adapter;
use Traversable;
use Zend\Http\Response;
use Zend\Stdlib\ArrayUtils;
/**
* A testing-purposes adapter.
*
* Should be used to test all components that rely on Zend\Http\Client,
* without actually performing an HTTP request. You should instantiate this
* object manually, and then set it as the client's adapter. Then, you can
* set the expected response using the setResponse() method.
*/
class Test implements AdapterInterface
{
/**
* Parameters array
*
* @var array
*/
protected $config = [];
/**
* Buffer of responses to be returned by the read() method. Can be
* set using setResponse() and addResponse().
*
* @var array
*/
protected $responses = ["HTTP/1.1 400 Bad Request\r\n\r\n"];
/**
* Current position in the response buffer
*
* @var int
*/
protected $responseIndex = 0;
/**
* Whether or not the next request will fail with an exception
*
* @var bool
*/
protected $nextRequestWillFail = false;
/**
* Adapter constructor, currently empty. Config is set using setOptions()
*/
public function __construct()
{
}
/**
* Set the nextRequestWillFail flag
*
* @param bool $flag
* @return \Zend\Http\Client\Adapter\Test
*/
public function setNextRequestWillFail($flag)
{
$this->nextRequestWillFail = (bool) $flag;
return $this;
}
/**
* Set the configuration array for the adapter
*
* @param array|Traversable $options
* @throws Exception\InvalidArgumentException
*/
public function setOptions($options = [])
{
if ($options instanceof Traversable) {
$options = ArrayUtils::iteratorToArray($options);
}
if (! is_array($options)) {
throw new Exception\InvalidArgumentException(
'Array or Traversable object expected, got ' . gettype($options)
);
}
foreach ($options as $k => $v) {
$this->config[strtolower($k)] = $v;
}
}
/**
* Connect to the remote server
*
* @param string $host
* @param int $port
* @param bool $secure
* @throws Exception\RuntimeException
*/
public function connect($host, $port = 80, $secure = false)
{
if ($this->nextRequestWillFail) {
$this->nextRequestWillFail = false;
throw new Exception\RuntimeException('Request failed');
}
}
/**
* Send request to the remote server
*
* @param string $method
* @param \Zend\Uri\Uri $uri
* @param string $httpVer
* @param array $headers
* @param string $body
* @return string Request as string
*/
public function write($method, $uri, $httpVer = '1.1', $headers = [], $body = '')
{
// Build request headers
$path = $uri->getPath();
if (empty($path)) {
$path = '/';
}
$query = $uri->getQuery();
$path .= $query ? '?' . $query : '';
$request = $method . ' ' . $path . ' HTTP/' . $httpVer . "\r\n";
foreach ($headers as $k => $v) {
if (is_string($k)) {
$v = $k . ': ' . $v;
}
$request .= $v . "\r\n";
}
// Add the request body
$request .= "\r\n" . $body;
// Do nothing - just return the request as string
return $request;
}
/**
* Return the response set in $this->setResponse()
*
* @return string
*/
public function read()
{
if ($this->responseIndex >= count($this->responses)) {
$this->responseIndex = 0;
}
return $this->responses[$this->responseIndex++];
}
/**
* Close the connection (dummy)
*
*/
public function close()
{
}
/**
* Set the HTTP response(s) to be returned by this adapter
*
* @param \Zend\Http\Response|array|string $response
*/
public function setResponse($response)
{
if ($response instanceof Response) {
$response = $response->toString();
}
$this->responses = (array) $response;
$this->responseIndex = 0;
}
/**
* Add another response to the response buffer.
*
* @param string|Response $response
*/
public function addResponse($response)
{
if ($response instanceof Response) {
$response = $response->toString();
}
$this->responses[] = $response;
}
/**
* Sets the position of the response buffer. Selects which
* response will be returned on the next call to read().
*
* @param int $index
* @throws Exception\OutOfRangeException
*/
public function setResponseIndex($index)
{
if ($index < 0 || $index >= count($this->responses)) {
throw new Exception\OutOfRangeException(
'Index out of range of response buffer size'
);
}
$this->responseIndex = $index;
}
}

View File

@@ -1,14 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Client\Exception;
use Zend\Http\Exception\ExceptionInterface as HttpException;
interface ExceptionInterface extends HttpException
{
}

View File

@@ -1,15 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Client\Exception;
use Zend\Http\Exception;
class InvalidArgumentException extends Exception\InvalidArgumentException implements
ExceptionInterface
{
}

View File

@@ -1,15 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Client\Exception;
use Zend\Http\Exception;
class OutOfRangeException extends Exception\OutOfRangeException implements
ExceptionInterface
{
}

View File

@@ -1,15 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Client\Exception;
use Zend\Http\Exception;
class RuntimeException extends Exception\RuntimeException implements
ExceptionInterface
{
}

View File

@@ -1,110 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http;
/**
* Http static client
*/
class ClientStatic
{
/**
* @var Client
*/
protected static $client;
/**
* Get the static HTTP client
*
* @param array|Traversable $options
* @return Client
*/
protected static function getStaticClient($options = null)
{
if (! isset(static::$client) || $options !== null) {
static::$client = new Client(null, $options);
}
return static::$client;
}
/**
* HTTP GET METHOD (static)
*
* @param string $url
* @param array $query
* @param array $headers
* @param mixed $body
* @param array|Traversable $clientOptions
* @return Response|bool
*/
public static function get($url, $query = [], $headers = [], $body = null, $clientOptions = null)
{
if (empty($url)) {
return false;
}
$request = new Request();
$request->setUri($url);
$request->setMethod(Request::METHOD_GET);
if (! empty($query) && is_array($query)) {
$request->getQuery()->fromArray($query);
}
if (! empty($headers) && is_array($headers)) {
$request->getHeaders()->addHeaders($headers);
}
if (! empty($body)) {
$request->setContent($body);
}
return static::getStaticClient($clientOptions)->send($request);
}
/**
* HTTP POST METHOD (static)
*
* @param string $url
* @param array $params
* @param array $headers
* @param mixed $body
* @param array|Traversable $clientOptions
* @throws Exception\InvalidArgumentException
* @return Response|bool
*/
public static function post($url, $params, $headers = [], $body = null, $clientOptions = null)
{
if (empty($url)) {
return false;
}
$request = new Request();
$request->setUri($url);
$request->setMethod(Request::METHOD_POST);
if (! empty($params) && is_array($params)) {
$request->getPost()->fromArray($params);
} else {
throw new Exception\InvalidArgumentException('The array of post parameters is empty');
}
if (! isset($headers['Content-Type'])) {
$headers['Content-Type'] = Client::ENC_URLENCODED;
}
if (! empty($headers) && is_array($headers)) {
$request->getHeaders()->addHeaders($headers);
}
if (! empty($body)) {
$request->setContent($body);
}
return static::getStaticClient($clientOptions)->send($request);
}
}

View File

@@ -1,371 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http;
use ArrayIterator;
use Zend\Http\Header\SetCookie;
use Zend\Uri;
/**
* A Zend\Http\Cookies object is designed to contain and maintain HTTP cookies, and should
* be used along with Zend\Http\Client in order to manage cookies across HTTP requests and
* responses.
*
* The class contains an array of Zend\Http\Header\Cookie objects. Cookies can be added
* automatically from a request or manually. Then, the Cookies class can find and return the
* cookies needed for a specific HTTP request.
*
* A special parameter can be passed to all methods of this class that return cookies: Cookies
* can be returned either in their native form (as Zend\Http\Header\Cookie objects) or as strings -
* the later is suitable for sending as the value of the "Cookie" header in an HTTP request.
* You can also choose, when returning more than one cookie, whether to get an array of strings
* (by passing Zend\Http\Client\Cookies::COOKIE_STRING_ARRAY) or one unified string for all cookies
* (by passing Zend\Http\Client\Cookies::COOKIE_STRING_CONCAT).
*
* @link http://wp.netscape.com/newsref/std/cookie_spec.html for some specs.
*/
class Cookies extends Headers
{
/**
* Return cookie(s) as a Zend\Http\Cookie object
*/
const COOKIE_OBJECT = 0;
/**
* Return cookie(s) as a string (suitable for sending in an HTTP request)
*/
const COOKIE_STRING_ARRAY = 1;
/**
* Return all cookies as one long string (suitable for sending in an HTTP request)
*/
const COOKIE_STRING_CONCAT = 2;
/**
* Return all cookies as one long string (strict mode)
* - Single space after the semi-colon separating each cookie
* - Remove trailing semi-colon, if any
*/
const COOKIE_STRING_CONCAT_STRICT = 3;
/**
* @var array
*/
protected $cookies = [];
/**
* @var \Zend\Http\Headers
*/
protected $headers;
/**
* @var array
*/
protected $rawCookies;
/**
* @static
* @throws Exception\RuntimeException
* @param $string
* @return void
*/
public static function fromString($string)
{
throw new Exception\RuntimeException(
__CLASS__ . '::' . __FUNCTION__ . ' should not be used as a factory, use '
. __NAMESPACE__ . '\Headers::fromString() instead.'
);
}
/**
* Add a cookie to the class. Cookie should be passed either as a Zend\Http\Header\SetCookie object
* or as a string - in which case an object is created from the string.
*
* @param SetCookie|string $cookie
* @param Uri\Uri|string $refUri Optional reference URI (for domain, path, secure)
* @throws Exception\InvalidArgumentException
*/
public function addCookie($cookie, $refUri = null)
{
if (is_string($cookie)) {
$cookie = SetCookie::fromString($cookie, $refUri);
}
if ($cookie instanceof SetCookie) {
$domain = $cookie->getDomain();
$path = $cookie->getPath();
if (! isset($this->cookies[$domain])) {
$this->cookies[$domain] = [];
}
if (! isset($this->cookies[$domain][$path])) {
$this->cookies[$domain][$path] = [];
}
$this->cookies[$domain][$path][$cookie->getName()] = $cookie;
$this->rawCookies[] = $cookie;
} else {
throw new Exception\InvalidArgumentException('Supplient argument is not a valid cookie string or object');
}
}
/**
* Parse an HTTP response, adding all the cookies set in that response
*
* @param Response $response
* @param Uri\Uri|string $refUri Requested URI
*/
public function addCookiesFromResponse(Response $response, $refUri)
{
$cookieHdrs = $response->getHeaders()->get('Set-Cookie');
if (is_array($cookieHdrs) || $cookieHdrs instanceof ArrayIterator) {
foreach ($cookieHdrs as $cookie) {
$this->addCookie($cookie, $refUri);
}
} elseif (is_string($cookieHdrs)) {
$this->addCookie($cookieHdrs, $refUri);
}
}
/**
* Get all cookies in the cookie jar as an array
*
* @param int $retAs Whether to return cookies as objects of \Zend\Http\Header\SetCookie or as strings
* @return array|string
*/
public function getAllCookies($retAs = self::COOKIE_OBJECT)
{
$cookies = $this->_flattenCookiesArray($this->cookies, $retAs);
return $cookies;
}
/**
* Return an array of all cookies matching a specific request according to the request URI,
* whether session cookies should be sent or not, and the time to consider as "now" when
* checking cookie expiry time.
*
* @param string|Uri\Uri $uri URI to check against (secure, domain, path)
* @param bool $matchSessionCookies Whether to send session cookies
* @param int $retAs Whether to return cookies as objects of \Zend\Http\Header\Cookie or as strings
* @param int $now Override the current time when checking for expiry time
* @throws Exception\InvalidArgumentException if invalid URI specified
* @return array|string
*/
public function getMatchingCookies(
$uri,
$matchSessionCookies = true,
$retAs = self::COOKIE_OBJECT,
$now = null
) {
if (is_string($uri)) {
$uri = Uri\UriFactory::factory($uri, 'http');
} elseif (! $uri instanceof Uri\Uri) {
throw new Exception\InvalidArgumentException('Invalid URI string or object passed');
}
$host = $uri->getHost();
if (empty($host)) {
throw new Exception\InvalidArgumentException('Invalid URI specified; does not contain a host');
}
// First, reduce the array of cookies to only those matching domain and path
$cookies = $this->_matchDomain($host);
$cookies = $this->_matchPath($cookies, $uri->getPath());
$cookies = $this->_flattenCookiesArray($cookies, self::COOKIE_OBJECT);
// Next, run Cookie->match on all cookies to check secure, time and session matching
$ret = [];
foreach ($cookies as $cookie) {
if ($cookie->match($uri, $matchSessionCookies, $now)) {
$ret[] = $cookie;
}
}
// Now, use self::_flattenCookiesArray again - only to convert to the return format ;)
$ret = $this->_flattenCookiesArray($ret, $retAs);
return $ret;
}
/**
* Get a specific cookie according to a URI and name
*
* @param Uri\Uri|string $uri The uri (domain and path) to match
* @param string $cookieName The cookie's name
* @param int $retAs Whether to return cookies as objects of \Zend\Http\Header\SetCookie or as strings
* @throws Exception\InvalidArgumentException if invalid URI specified or invalid $retAs value
* @return SetCookie|string
*/
public function getCookie($uri, $cookieName, $retAs = self::COOKIE_OBJECT)
{
if (is_string($uri)) {
$uri = Uri\UriFactory::factory($uri, 'http');
} elseif (! $uri instanceof Uri\Uri) {
throw new Exception\InvalidArgumentException('Invalid URI specified');
}
$host = $uri->getHost();
if (empty($host)) {
throw new Exception\InvalidArgumentException('Invalid URI specified; host missing');
}
// Get correct cookie path
$path = $uri->getPath();
$lastSlashPos = strrpos($path, '/') ?: 0;
$path = substr($path, 0, $lastSlashPos);
if (! $path) {
$path = '/';
}
if (isset($this->cookies[$uri->getHost()][$path][$cookieName])) {
$cookie = $this->cookies[$uri->getHost()][$path][$cookieName];
switch ($retAs) {
case self::COOKIE_OBJECT:
return $cookie;
case self::COOKIE_STRING_ARRAY:
case self::COOKIE_STRING_CONCAT:
return $cookie->__toString();
default:
throw new Exception\InvalidArgumentException(sprintf(
'Invalid value passed for $retAs: %s',
$retAs
));
}
}
return false;
}
/**
* Helper function to recursively flatten an array. Should be used when exporting the
* cookies array (or parts of it)
*
* @param \Zend\Http\Header\SetCookie|array $ptr
* @param int $retAs What value to return
* @return array|string
*/
// @codingStandardsIgnoreStart
protected function _flattenCookiesArray($ptr, $retAs = self::COOKIE_OBJECT)
{
// @codingStandardsIgnoreEnd
if (is_array($ptr)) {
$ret = ($retAs == self::COOKIE_STRING_CONCAT ? '' : []);
foreach ($ptr as $item) {
if ($retAs == self::COOKIE_STRING_CONCAT) {
$ret .= $this->_flattenCookiesArray($item, $retAs);
} else {
$ret = array_merge($ret, $this->_flattenCookiesArray($item, $retAs));
}
}
return $ret;
} elseif ($ptr instanceof SetCookie) {
switch ($retAs) {
case self::COOKIE_STRING_ARRAY:
return [$ptr->__toString()];
case self::COOKIE_STRING_CONCAT:
return $ptr->__toString();
case self::COOKIE_OBJECT:
default:
return [$ptr];
}
}
return;
}
/**
* Return a subset of the cookies array matching a specific domain
*
* @param string $domain
* @return array
*/
// @codingStandardsIgnoreStart
protected function _matchDomain($domain)
{
// @codingStandardsIgnoreEnd
$ret = [];
foreach (array_keys($this->cookies) as $cdom) {
if (SetCookie::matchCookieDomain($cdom, $domain)) {
$ret[$cdom] = $this->cookies[$cdom];
}
}
return $ret;
}
/**
* Return a subset of a domain-matching cookies that also match a specified path
*
* @param array $domains
* @param string $path
* @return array
*/
// @codingStandardsIgnoreStart
protected function _matchPath($domains, $path)
{
// @codingStandardsIgnoreEnd
$ret = [];
foreach ($domains as $dom => $pathsArray) {
foreach (array_keys($pathsArray) as $cpath) {
if (SetCookie::matchCookiePath($cpath, $path)) {
if (! isset($ret[$dom])) {
$ret[$dom] = [];
}
$ret[$dom][$cpath] = $pathsArray[$cpath];
}
}
}
return $ret;
}
/**
* Create a new Cookies object and automatically load into it all the
* cookies set in a Response object. If $uri is set, it will be
* considered as the requested URI for setting default domain and path
* of the cookie.
*
* @param Response $response HTTP Response object
* @param Uri\Uri|string $refUri The requested URI
* @return static
* @todo Add the $uri functionality.
*/
public static function fromResponse(Response $response, $refUri)
{
$jar = new static();
$jar->addCookiesFromResponse($response, $refUri);
return $jar;
}
/**
* Tells if the array of cookies is empty
*
* @return bool
*/
public function isEmpty()
{
return count($this) == 0;
}
/**
* Empties the cookieJar of any cookie
*
* @return $this
*/
public function reset()
{
$this->cookies = $this->rawCookies = [];
return $this;
}
}

View File

@@ -1,12 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Exception;
interface ExceptionInterface
{
}

View File

@@ -1,13 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Exception;
class InvalidArgumentException extends \InvalidArgumentException implements
ExceptionInterface
{
}

View File

@@ -1,12 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Exception;
class OutOfRangeException extends \OutOfRangeException implements ExceptionInterface
{
}

View File

@@ -1,13 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Exception;
class RuntimeException extends \RuntimeException implements
ExceptionInterface
{
}

View File

@@ -1,457 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
use stdClass;
/**
* Abstract Accept Header
*
* Naming conventions:
*
* Accept: audio/mp3; q=0.2; version=0.5, audio/basic+mp3
* |------------------------------------------------------| header line
* |------| field name
* |-----------------------------------------------| field value
* |-------------------------------| field value part
* |------| type
* |--| subtype
* |--| format
* |----| subtype
* |---| format
* |-------------------| parameter set
* |-----------| parameter
* |-----| parameter key
* |--| parameter value
* |---| priority
*
*
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1
* @author Dolf Schimmel - Freeaqingme
*/
abstract class AbstractAccept implements HeaderInterface
{
/**
* @var stdClass[]
*/
protected $fieldValueParts = [];
protected $regexAddType;
/**
* Determines if since last mutation the stack was sorted
*
* @var bool
*/
protected $sorted = false;
/**
* Parse a full header line or just the field value part.
*
* @param string $headerLine
*/
public function parseHeaderLine($headerLine)
{
if (strpos($headerLine, ':') !== false) {
list($name, $value) = GenericHeader::splitHeaderLine($headerLine);
if (strtolower($name) !== strtolower($this->getFieldName())) {
$value = $headerLine; // This is just for preserve the BC.
}
} else {
$value = $headerLine;
}
HeaderValue::assertValid($value);
foreach ($this->getFieldValuePartsFromHeaderLine($value) as $value) {
$this->addFieldValuePartToQueue($value);
}
}
/**
* Factory method: parse Accept header string
*
* @param string $headerLine
* @return static
*/
public static function fromString($headerLine)
{
$obj = new static();
$obj->parseHeaderLine($headerLine);
return $obj;
}
/**
* Parse the Field Value Parts represented by a header line
*
* @param string $headerLine
* @throws Exception\InvalidArgumentException If header is invalid
* @return array
*/
public function getFieldValuePartsFromHeaderLine($headerLine)
{
// process multiple accept values, they may be between quotes
if (! preg_match_all('/(?:[^,"]|"(?:[^\\\"]|\\\.)*")+/', $headerLine, $values)
|| ! isset($values[0])
) {
throw new Exception\InvalidArgumentException(
'Invalid header line for ' . $this->getFieldName() . ' header string'
);
}
$out = [];
foreach ($values[0] as $value) {
$value = trim($value);
$out[] = $this->parseFieldValuePart($value);
}
return $out;
}
/**
* Parse the accept params belonging to a media range
*
* @param string $fieldValuePart
* @return stdClass
*/
protected function parseFieldValuePart($fieldValuePart)
{
$raw = $subtypeWhole = $type = $fieldValuePart;
if ($pos = strpos($fieldValuePart, ';')) {
$type = substr($fieldValuePart, 0, $pos);
}
$params = $this->getParametersFromFieldValuePart($fieldValuePart);
if ($pos = strpos($fieldValuePart, ';')) {
$fieldValuePart = trim(substr($fieldValuePart, 0, $pos));
}
$format = '*';
$subtype = '*';
return (object) [
'typeString' => trim($fieldValuePart),
'type' => $type,
'subtype' => $subtype,
'subtypeRaw' => $subtypeWhole,
'format' => $format,
'priority' => isset($params['q']) ? $params['q'] : 1,
'params' => $params,
'raw' => trim($raw),
];
}
/**
* Parse the keys contained in the header line
*
* @param string $fieldValuePart
* @return array
*/
protected function getParametersFromFieldValuePart($fieldValuePart)
{
$params = [];
if ((($pos = strpos($fieldValuePart, ';')) !== false)) {
preg_match_all('/(?:[^;"]|"(?:[^\\\"]|\\\.)*")+/', $fieldValuePart, $paramsStrings);
if (isset($paramsStrings[0])) {
array_shift($paramsStrings[0]);
$paramsStrings = $paramsStrings[0];
}
foreach ($paramsStrings as $param) {
$explode = explode('=', $param, 2);
if (count($explode) === 2) {
$value = trim($explode[1]);
} else {
$value = null;
}
if (isset($value[0]) && $value[0] == '"' && substr($value, -1) == '"') {
$value = substr(substr($value, 1), 0, -1);
}
$params[trim($explode[0])] = stripslashes($value);
}
}
return $params;
}
/**
* Get field value
*
* @param array|null $values
* @return string
*/
public function getFieldValue($values = null)
{
if ($values === null) {
return $this->getFieldValue($this->fieldValueParts);
}
$strings = [];
foreach ($values as $value) {
$params = $value->params;
array_walk($params, [$this, 'assembleAcceptParam']);
$strings[] = implode(';', [$value->typeString] + $params);
}
return implode(', ', $strings);
}
/**
* Assemble and escape the field value parameters based on RFC 2616 section 2.1
*
* @todo someone should review this thoroughly
* @param string $value
* @param string $key
* @return string
*/
protected function assembleAcceptParam(&$value, $key)
{
$separators = ['(', ')', '<', '>', '@', ',', ';', ':', '/', '[', ']', '?', '=', '{', '}', ' ', "\t"];
$escaped = preg_replace_callback(
'/[[:cntrl:]"\\\\]/', // escape cntrl, ", \
function ($v) {
return '\\' . $v[0];
},
$value
);
if ($escaped == $value && ! array_intersect(str_split($value), $separators)) {
$value = $key . ($value ? '=' . $value : '');
} else {
$value = $key . ($value ? '="' . $escaped . '"' : '');
}
return $value;
}
/**
* Add a type, with the given priority
*
* @param string $type
* @param int|float $priority
* @param array (optional) $params
* @throws Exception\InvalidArgumentException
* @return $this
*/
protected function addType($type, $priority = 1, array $params = [])
{
if (! preg_match($this->regexAddType, $type)) {
throw new Exception\InvalidArgumentException(sprintf(
'%s expects a valid type; received "%s"',
__METHOD__,
(string) $type
));
}
if (! is_int($priority) && ! is_float($priority) && ! is_numeric($priority)
|| $priority > 1 || $priority < 0
) {
throw new Exception\InvalidArgumentException(sprintf(
'%s expects a numeric priority; received %s',
__METHOD__,
(string) $priority
));
}
if ($priority != 1) {
$params = ['q' => sprintf('%01.1f', $priority)] + $params;
}
$assembledString = $this->getFieldValue(
[(object) ['typeString' => $type, 'params' => $params]]
);
$value = $this->parseFieldValuePart($assembledString);
$this->addFieldValuePartToQueue($value);
return $this;
}
/**
* Does the header have the requested type?
*
* @param array|string $matchAgainst
* @return bool
*/
protected function hasType($matchAgainst)
{
return (bool) $this->match($matchAgainst);
}
/**
* Match a media string against this header
*
* @param array|string $matchAgainst
* @return Accept\FieldValuePArt\AcceptFieldValuePart|bool The matched value or false
*/
public function match($matchAgainst)
{
if (is_string($matchAgainst)) {
$matchAgainst = $this->getFieldValuePartsFromHeaderLine($matchAgainst);
}
foreach ($this->getPrioritized() as $left) {
foreach ($matchAgainst as $right) {
if ($right->type == '*' || $left->type == '*') {
if ($this->matchAcceptParams($left, $right)) {
$left->setMatchedAgainst($right);
return $left;
}
}
if ($left->type == $right->type) {
if (($left->subtype == $right->subtype || ($right->subtype == '*' || $left->subtype == '*'))
&& ($left->format == $right->format || $right->format == '*' || $left->format == '*')
) {
if ($this->matchAcceptParams($left, $right)) {
$left->setMatchedAgainst($right);
return $left;
}
}
}
}
}
return false;
}
/**
* Return a match where all parameters in argument #1 match those in argument #2
*
* @param array $match1
* @param array $match2
* @return bool|array
*/
protected function matchAcceptParams($match1, $match2)
{
foreach ($match2->params as $key => $value) {
if (isset($match1->params[$key])) {
if (strpos($value, '-')) {
preg_match(
'/^(?|([^"-]*)|"([^"]*)")-(?|([^"-]*)|"([^"]*)")\z/',
$value,
$pieces
);
if (count($pieces) == 3
&& (version_compare($pieces[1], $match1->params[$key], '<=')
xor version_compare($pieces[2], $match1->params[$key], '>='))
) {
return false;
}
} elseif (strpos($value, '|')) {
$options = explode('|', $value);
$good = false;
foreach ($options as $option) {
if ($option == $match1->params[$key]) {
$good = true;
break;
}
}
if (! $good) {
return false;
}
} elseif ($match1->params[$key] != $value) {
return false;
}
}
}
return $match1;
}
/**
* Add a key/value combination to the internal queue
*
* @param stdClass $value
* @return number
*/
protected function addFieldValuePartToQueue($value)
{
$this->fieldValueParts[] = $value;
$this->sorted = false;
}
/**
* Sort the internal Field Value Parts
*
* @See rfc2616 sect 14.1
* Media ranges can be overridden by more specific media ranges or
* specific media types. If more than one media range applies to a given
* type, the most specific reference has precedence. For example,
*
* Accept: text/*, text/html, text/html;level=1, * /*
*
* have the following precedence:
*
* 1) text/html;level=1
* 2) text/html
* 3) text/*
* 4) * /*
*
* @return number
*/
protected function sortFieldValueParts()
{
$sort = function ($a, $b) {
// If A has higher precedence than B, return -1.
if ($a->priority > $b->priority) {
return -1;
} elseif ($a->priority < $b->priority) {
return 1;
}
// Asterisks
$values = ['type', 'subtype', 'format'];
foreach ($values as $value) {
if ($a->$value == '*' && $b->$value != '*') {
return 1;
} elseif ($b->$value == '*' && $a->$value != '*') {
return -1;
}
}
if ($a->type == 'application' && $b->type != 'application') {
return -1;
} elseif ($b->type == 'application' && $a->type != 'application') {
return 1;
}
// @todo count number of dots in case of type==application in subtype
// So far they're still the same. Longest string length may be more specific
if (strlen($a->raw) == strlen($b->raw)) {
return 0;
}
return (strlen($a->raw) > strlen($b->raw)) ? -1 : 1;
};
usort($this->fieldValueParts, $sort);
$this->sorted = true;
}
/**
* @return array with all the keys, values and parameters this header represents:
*/
public function getPrioritized()
{
if (! $this->sorted) {
$this->sortFieldValueParts();
}
return $this->fieldValueParts;
}
}

View File

@@ -1,263 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
use DateTime;
use DateTimeZone;
/**
* Abstract Date/Time Header
* Supports headers that have date/time as value
*
* @see Zend\Http\Header\Date
* @see Zend\Http\Header\Expires
* @see Zend\Http\Header\IfModifiedSince
* @see Zend\Http\Header\IfUnmodifiedSince
* @see Zend\Http\Header\LastModified
*
* Note for 'Location' header:
* While RFC 1945 requires an absolute URI, most of the browsers also support relative URI
* This class allows relative URIs, and let user retrieve URI instance if strict validation needed
*/
abstract class AbstractDate implements HeaderInterface
{
/**
* Date formats according to RFC 2616
* @link http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3
*/
const DATE_RFC1123 = 0;
const DATE_RFC1036 = 1;
const DATE_ANSIC = 2;
/**
* Date instance for this header
*
* @var DateTime
*/
protected $date;
/**
* Date output format
*
* @var string
*/
protected static $dateFormat = 'D, d M Y H:i:s \G\M\T';
/**
* Date formats defined by RFC 2616. RFC 1123 date is required
* RFC 1036 and ANSI C formats are provided for compatibility with old servers/clients
* @link http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3
*
* @var array
*/
protected static $dateFormats = [
self::DATE_RFC1123 => 'D, d M Y H:i:s \G\M\T',
self::DATE_RFC1036 => 'D, d M y H:i:s \G\M\T',
self::DATE_ANSIC => 'D M j H:i:s Y',
];
/**
* Create date-based header from string
*
* @param string $headerLine
* @return static
* @throws Exception\InvalidArgumentException
*/
public static function fromString($headerLine)
{
$dateHeader = new static();
list($name, $date) = GenericHeader::splitHeaderLine($headerLine);
// check to ensure proper header type for this factory
if (strtolower($name) !== strtolower($dateHeader->getFieldName())) {
throw new Exception\InvalidArgumentException(
'Invalid header line for "' . $dateHeader->getFieldName() . '" header string'
);
}
$dateHeader->setDate($date);
return $dateHeader;
}
/**
* Create date-based header from strtotime()-compatible string
*
* @param int|string $time
* @return static
* @throws Exception\InvalidArgumentException
*/
public static function fromTimeString($time)
{
return static::fromTimestamp(strtotime($time));
}
/**
* Create date-based header from Unix timestamp
*
* @param int $time
* @return static
* @throws Exception\InvalidArgumentException
*/
public static function fromTimestamp($time)
{
$dateHeader = new static();
if (! $time || ! is_numeric($time)) {
throw new Exception\InvalidArgumentException(
'Invalid time for "' . $dateHeader->getFieldName() . '" header string'
);
}
$dateHeader->setDate(new DateTime('@' . $time));
return $dateHeader;
}
/**
* Set date output format
*
* @param int $format
* @throws Exception\InvalidArgumentException
*/
public static function setDateFormat($format)
{
if (! isset(static::$dateFormats[$format])) {
throw new Exception\InvalidArgumentException(sprintf(
'No constant defined for provided date format: %s',
$format
));
}
static::$dateFormat = static::$dateFormats[$format];
}
/**
* Return current date output format
*
* @return string
*/
public static function getDateFormat()
{
return static::$dateFormat;
}
/**
* Set the date for this header, this can be a string or an instance of \DateTime
*
* @param string|DateTime $date
* @return $this
* @throws Exception\InvalidArgumentException
*/
public function setDate($date)
{
if (is_string($date)) {
try {
$date = new DateTime($date, new DateTimeZone('GMT'));
} catch (\Exception $e) {
throw new Exception\InvalidArgumentException(
sprintf('Invalid date passed as string (%s)', (string) $date),
$e->getCode(),
$e
);
}
} elseif (! ($date instanceof DateTime)) {
throw new Exception\InvalidArgumentException('Date must be an instance of \DateTime or a string');
}
$date->setTimezone(new DateTimeZone('GMT'));
$this->date = $date;
return $this;
}
/**
* Return date for this header
*
* @return string
*/
public function getDate()
{
return $this->date()->format(static::$dateFormat);
}
/**
* Return date for this header as an instance of \DateTime
*
* @return DateTime
*/
public function date()
{
if ($this->date === null) {
$this->date = new DateTime(null, new DateTimeZone('GMT'));
}
return $this->date;
}
/**
* Compare provided date to date for this header
* Returns < 0 if date in header is less than $date; > 0 if it's greater, and 0 if they are equal.
* @see \strcmp()
*
* @param string|DateTime $date
* @return int
* @throws Exception\InvalidArgumentException
*/
public function compareTo($date)
{
if (is_string($date)) {
try {
$date = new DateTime($date, new DateTimeZone('GMT'));
} catch (\Exception $e) {
throw new Exception\InvalidArgumentException(
sprintf('Invalid Date passed as string (%s)', (string) $date),
$e->getCode(),
$e
);
}
} elseif (! ($date instanceof DateTime)) {
throw new Exception\InvalidArgumentException('Date must be an instance of \DateTime or a string');
}
$dateTimestamp = $date->getTimestamp();
$thisTimestamp = $this->date()->getTimestamp();
return ($thisTimestamp === $dateTimestamp) ? 0 : (($thisTimestamp > $dateTimestamp) ? 1 : -1);
}
/**
* Get header value as formatted date
*
* @return string
*/
public function getFieldValue()
{
return $this->getDate();
}
/**
* Return header line
*
* @return string
*/
public function toString()
{
return $this->getFieldName() . ': ' . $this->getDate();
}
/**
* Allow casting to string
*
* @return string
*/
public function __toString()
{
return $this->toString();
}
}

View File

@@ -1,149 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
use Zend\Uri\Exception as UriException;
use Zend\Uri\UriFactory;
use Zend\Uri\UriInterface;
/**
* Abstract Location Header
* Supports headers that have URI as value
* @see Zend\Http\Header\Location
* @see Zend\Http\Header\ContentLocation
* @see Zend\Http\Header\Referer
*
* Note for 'Location' header:
* While RFC 1945 requires an absolute URI, most of the browsers also support relative URI
* This class allows relative URIs, and let user retrieve URI instance if strict validation needed
*/
abstract class AbstractLocation implements HeaderInterface
{
/**
* URI for this header
*
* @var UriInterface
*/
protected $uri;
/**
* Create location-based header from string
*
* @param string $headerLine
* @return static
* @throws Exception\InvalidArgumentException
*/
public static function fromString($headerLine)
{
$locationHeader = new static();
// ZF-5520 - IIS bug, no space after colon
list($name, $uri) = GenericHeader::splitHeaderLine($headerLine);
// check to ensure proper header type for this factory
if (strtolower($name) !== strtolower($locationHeader->getFieldName())) {
throw new Exception\InvalidArgumentException(
'Invalid header line for "' . $locationHeader->getFieldName() . '" header string'
);
}
HeaderValue::assertValid($uri);
$locationHeader->setUri(trim($uri));
return $locationHeader;
}
/**
* Set the URI/URL for this header, this can be a string or an instance of Zend\Uri\Http
*
* @param string|UriInterface $uri
* @return $this
* @throws Exception\InvalidArgumentException
*/
public function setUri($uri)
{
if (is_string($uri)) {
try {
$uri = UriFactory::factory($uri);
} catch (UriException\InvalidUriPartException $e) {
throw new Exception\InvalidArgumentException(
sprintf('Invalid URI passed as string (%s)', (string) $uri),
$e->getCode(),
$e
);
} catch (UriException\InvalidArgumentException $e) {
throw new Exception\InvalidArgumentException(
sprintf('Invalid URI passed as string (%s)', (string) $uri),
$e->getCode(),
$e
);
}
} elseif (! ($uri instanceof UriInterface)) {
throw new Exception\InvalidArgumentException('URI must be an instance of Zend\Uri\Http or a string');
}
$this->uri = $uri;
return $this;
}
/**
* Return the URI for this header
*
* @return string
*/
public function getUri()
{
if ($this->uri instanceof UriInterface) {
return $this->uri->toString();
}
return $this->uri;
}
/**
* Return the URI for this header as an instance of Zend\Uri\Http
*
* @return UriInterface
*/
public function uri()
{
if ($this->uri === null || is_string($this->uri)) {
$this->uri = UriFactory::factory($this->uri);
}
return $this->uri;
}
/**
* Get header value as URI string
*
* @return string
*/
public function getFieldValue()
{
return $this->getUri();
}
/**
* Output header line
*
* @return string
*/
public function toString()
{
return $this->getFieldName() . ': ' . $this->getUri();
}
/**
* Allow casting to string
*
* @return string
*/
public function __toString()
{
return $this->toString();
}
}

View File

@@ -1,117 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
use Zend\Http\Header\Accept\FieldValuePart;
/**
* Accept Header
*
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1
*/
class Accept extends AbstractAccept
{
/**
* @var string
*/
protected $regexAddType = '#^([a-zA-Z+-]+|\*)/(\*|[a-zA-Z0-9+-]+)$#';
/**
* Get field name
*
* @return string
*/
public function getFieldName()
{
return 'Accept';
}
/**
* Cast to string
*
* @return string
*/
public function toString()
{
return 'Accept: ' . $this->getFieldValue();
}
/**
* Add a media type, with the given priority
*
* @param string $type
* @param int|float $priority
* @param array $params
* @return $this
*/
public function addMediaType($type, $priority = 1, array $params = [])
{
return $this->addType($type, $priority, $params);
}
/**
* Does the header have the requested media type?
*
* @param string $type
* @return bool
*/
public function hasMediaType($type)
{
return $this->hasType($type);
}
/**
* Parse the keys contained in the header line
*
* @param string $fieldValuePart
* @return FieldValuePart\AcceptFieldValuePart
* @see \Zend\Http\Header\AbstractAccept::parseFieldValuePart()
*/
protected function parseFieldValuePart($fieldValuePart)
{
$raw = $fieldValuePart;
if ($pos = strpos($fieldValuePart, '/')) {
$type = trim(substr($fieldValuePart, 0, $pos));
} else {
$type = trim($fieldValuePart);
}
$params = $this->getParametersFromFieldValuePart($fieldValuePart);
if ($pos = strpos($fieldValuePart, ';')) {
$fieldValuePart = trim(substr($fieldValuePart, 0, $pos));
}
if (strpos($fieldValuePart, '/')) {
$subtypeWhole = $format = $subtype = trim(substr($fieldValuePart, strpos($fieldValuePart, '/') + 1));
} else {
$subtypeWhole = '';
$format = '*';
$subtype = '*';
}
$pos = strpos($subtype, '+');
if (false !== $pos) {
$format = trim(substr($subtype, $pos + 1));
$subtype = trim(substr($subtype, 0, $pos));
}
$aggregated = [
'typeString' => trim($fieldValuePart),
'type' => $type,
'subtype' => $subtype,
'subtypeRaw' => $subtypeWhole,
'format' => $format,
'priority' => isset($params['q']) ? $params['q'] : 1,
'params' => $params,
'raw' => trim($raw),
];
return new FieldValuePart\AcceptFieldValuePart((object) $aggregated);
}
}

View File

@@ -1,107 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header\Accept\FieldValuePart;
/**
* Field Value Part
*
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1
*/
abstract class AbstractFieldValuePart
{
/**
* Internal object used for value retrieval
* @var object
*/
private $internalValues;
/**
* A Field Value Part this Field Value Part matched against.
* @var AbstractFieldValuePart
*/
protected $matchedAgainst;
/**
* @param object $internalValues
*/
public function __construct($internalValues)
{
$this->internalValues = $internalValues;
}
/**
* Set a Field Value Part this Field Value Part matched against.
*
* @param AbstractFieldValuePart $matchedAgainst
* @return $this
*/
public function setMatchedAgainst(AbstractFieldValuePart $matchedAgainst)
{
$this->matchedAgainst = $matchedAgainst;
return $this;
}
/**
* Get a Field Value Part this Field Value Part matched against.
*
* @return AbstractFieldValuePart|null
*/
public function getMatchedAgainst()
{
return $this->matchedAgainst;
}
/**
* @return object
*/
protected function getInternalValues()
{
return $this->internalValues;
}
/**
* @return string $typeString
*/
public function getTypeString()
{
return $this->getInternalValues()->typeString;
}
/**
* @return float $priority
*/
public function getPriority()
{
return (float) $this->getInternalValues()->priority;
}
/**
* @return \stdClass $params
*/
public function getParams()
{
return (object) $this->getInternalValues()->params;
}
/**
* @return string $raw
*/
public function getRaw()
{
return $this->getInternalValues()->raw;
}
/**
* @param mixed $key
* @return mixed
*/
public function __get($key)
{
return $this->getInternalValues()->$key;
}
}

View File

@@ -1,40 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header\Accept\FieldValuePart;
/**
* Field Value Part
*
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1
*/
class AcceptFieldValuePart extends AbstractFieldValuePart
{
/**
* @return string
*/
public function getSubtype()
{
return $this->getInternalValues()->subtype;
}
/**
* @return string
*/
public function getSubtypeRaw()
{
return $this->getInternalValues()->subtypeRaw;
}
/**
* @return string
*/
public function getFormat()
{
return $this->getInternalValues()->format;
}
}

View File

@@ -1,24 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header\Accept\FieldValuePart;
/**
* Field Value Part
*
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1
*/
class CharsetFieldValuePart extends AbstractFieldValuePart
{
/**
* @return string
*/
public function getCharset()
{
return $this->getInternalValues()->type;
}
}

View File

@@ -1,24 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header\Accept\FieldValuePart;
/**
* Field Value Part
*
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1
*/
class EncodingFieldValuePart extends AbstractFieldValuePart
{
/**
* @return string
*/
public function getEncoding()
{
return $this->getInternalValues()->type;
}
}

View File

@@ -1,31 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header\Accept\FieldValuePart;
/**
* Field Value Part
*
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1
*/
class LanguageFieldValuePart extends AbstractFieldValuePart
{
public function getLanguage()
{
return $this->getInternalValues()->typeString;
}
public function getPrimaryTag()
{
return $this->getInternalValues()->type;
}
public function getSubTag()
{
return $this->getInternalValues()->subtype;
}
}

View File

@@ -1,77 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
use Zend\Http\Header\Accept\FieldValuePart;
/**
* Accept Charset Header
*
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.2
*/
class AcceptCharset extends AbstractAccept
{
protected $regexAddType = '#^([a-zA-Z0-9+-]+|\*)$#';
/**
* Get field name
*
* @return string
*/
public function getFieldName()
{
return 'Accept-Charset';
}
/**
* Cast to string
*
* @return string
*/
public function toString()
{
return 'Accept-Charset: ' . $this->getFieldValue();
}
/**
* Add a charset, with the given priority
*
* @param string $type
* @param int|float $priority
* @return $this
*/
public function addCharset($type, $priority = 1)
{
return $this->addType($type, $priority);
}
/**
* Does the header have the requested charset?
*
* @param string $type
* @return bool
*/
public function hasCharset($type)
{
return $this->hasType($type);
}
/**
* Parse the keys contained in the header line
*
* @param string $fieldValuePart
* @return \Zend\Http\Header\Accept\FieldValuePart\CharsetFieldValuePart
* @see \Zend\Http\Header\AbstractAccept::parseFieldValuePart()
*/
protected function parseFieldValuePart($fieldValuePart)
{
$internalValues = parent::parseFieldValuePart($fieldValuePart);
return new FieldValuePart\CharsetFieldValuePart($internalValues);
}
}

View File

@@ -1,77 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
use Zend\Http\Header\Accept\FieldValuePart;
/**
* Accept Encoding Header
*
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.3
*/
class AcceptEncoding extends AbstractAccept
{
protected $regexAddType = '#^([a-zA-Z0-9+-]+|\*)$#';
/**
* Get field name
*
* @return string
*/
public function getFieldName()
{
return 'Accept-Encoding';
}
/**
* Cast to string
*
* @return string
*/
public function toString()
{
return 'Accept-Encoding: ' . $this->getFieldValue();
}
/**
* Add an encoding, with the given priority
*
* @param string $type
* @param int|float $priority
* @return $this
*/
public function addEncoding($type, $priority = 1)
{
return $this->addType($type, $priority);
}
/**
* Does the header have the requested encoding?
*
* @param string $type
* @return bool
*/
public function hasEncoding($type)
{
return $this->hasType($type);
}
/**
* Parse the keys contained in the header line
*
* @param string $fieldValuePart
* @return \Zend\Http\Header\Accept\FieldValuePart\EncodingFieldValuePart
* @see \Zend\Http\Header\AbstractAccept::parseFieldValuePart()
*/
protected function parseFieldValuePart($fieldValuePart)
{
$internalValues = parent::parseFieldValuePart($fieldValuePart);
return new FieldValuePart\EncodingFieldValuePart($internalValues);
}
}

View File

@@ -1,107 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
use Zend\Http\Header\Accept\FieldValuePart;
/**
* Accept Language Header
*
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4
*/
class AcceptLanguage extends AbstractAccept
{
protected $regexAddType = '#^([a-zA-Z0-9+-]+|\*)$#';
/**
* Get field name
*
* @return string
*/
public function getFieldName()
{
return 'Accept-Language';
}
/**
* Cast to string
*
* @return string
*/
public function toString()
{
return 'Accept-Language: ' . $this->getFieldValue();
}
/**
* Add a language, with the given priority
*
* @param string $type
* @param int|float $priority
* @return $this
*/
public function addLanguage($type, $priority = 1)
{
return $this->addType($type, $priority);
}
/**
* Does the header have the requested language?
*
* @param string $type
* @return bool
*/
public function hasLanguage($type)
{
return $this->hasType($type);
}
/**
* Parse the keys contained in the header line
*
* @param string $fieldValuePart
* @return \Zend\Http\Header\Accept\FieldValuePart\LanguageFieldValuePart
* @see \Zend\Http\Header\AbstractAccept::parseFieldValuePart()
*/
protected function parseFieldValuePart($fieldValuePart)
{
$raw = $fieldValuePart;
if ($pos = strpos($fieldValuePart, '-')) {
$type = trim(substr($fieldValuePart, 0, $pos));
} else {
$type = trim(substr($fieldValuePart, 0));
}
$params = $this->getParametersFromFieldValuePart($fieldValuePart);
if ($pos = strpos($fieldValuePart, ';')) {
$fieldValuePart = $type = trim(substr($fieldValuePart, 0, $pos));
}
if (strpos($fieldValuePart, '-')) {
$subtypeWhole = $format = $subtype = trim(substr($fieldValuePart, strpos($fieldValuePart, '-') + 1));
} else {
$subtypeWhole = '';
$format = '*';
$subtype = '*';
}
$aggregated = [
'typeString' => trim($fieldValuePart),
'type' => $type,
'subtype' => $subtype,
'subtypeRaw' => $subtypeWhole,
'format' => $format,
'priority' => isset($params['q']) ? $params['q'] : 1,
'params' => $params,
'raw' => trim($raw),
];
return new FieldValuePart\LanguageFieldValuePart((object) $aggregated);
}
}

View File

@@ -1,66 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
/**
* Accept Ranges Header
*
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.5
*/
class AcceptRanges implements HeaderInterface
{
protected $rangeUnit;
public static function fromString($headerLine)
{
list($name, $value) = GenericHeader::splitHeaderLine($headerLine);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'accept-ranges') {
throw new Exception\InvalidArgumentException(
'Invalid header line for Accept-Ranges string'
);
}
return new static($value);
}
public function __construct($rangeUnit = null)
{
if ($rangeUnit !== null) {
$this->setRangeUnit($rangeUnit);
}
}
public function getFieldName()
{
return 'Accept-Ranges';
}
public function getFieldValue()
{
return $this->getRangeUnit();
}
public function setRangeUnit($rangeUnit)
{
HeaderValue::assertValid($rangeUnit);
$this->rangeUnit = $rangeUnit;
return $this;
}
public function getRangeUnit()
{
return (string) $this->rangeUnit;
}
public function toString()
{
return 'Accept-Ranges: ' . $this->getFieldValue();
}
}

View File

@@ -1,105 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
/**
* Age HTTP Header
*
* @link http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.6
*/
class Age implements HeaderInterface
{
/**
* Estimate of the amount of time in seconds since the response
*
* @var int
*/
protected $deltaSeconds;
/**
* Create Age header from string
*
* @param string $headerLine
* @return static
* @throws Exception\InvalidArgumentException
*/
public static function fromString($headerLine)
{
list($name, $value) = GenericHeader::splitHeaderLine($headerLine);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'age') {
throw new Exception\InvalidArgumentException('Invalid header line for Age string: "' . $name . '"');
}
return new static($value);
}
public function __construct($deltaSeconds = null)
{
if ($deltaSeconds !== null) {
$this->setDeltaSeconds($deltaSeconds);
}
}
/**
* Get header name
*
* @return string
*/
public function getFieldName()
{
return 'Age';
}
/**
* Get header value (number of seconds)
*
* @return string
*/
public function getFieldValue()
{
return (string) $this->getDeltaSeconds();
}
/**
* Set number of seconds
*
* @param int $delta
* @return $this
*/
public function setDeltaSeconds($delta)
{
if (! is_int($delta) && ! is_numeric($delta)) {
throw new Exception\InvalidArgumentException('Invalid delta provided');
}
$this->deltaSeconds = (int) $delta;
return $this;
}
/**
* Get number of seconds
*
* @return int
*/
public function getDeltaSeconds()
{
return $this->deltaSeconds;
}
/**
* Return header line
* In case of overflow RFC states to set value of 2147483648 (2^31)
*
* @return string
*/
public function toString()
{
return 'Age: ' . (($this->deltaSeconds >= PHP_INT_MAX) ? '2147483648' : $this->deltaSeconds);
}
}

View File

@@ -1,183 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
use Zend\Http\Request;
/**
* Allow Header
*
* @link http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.7
*/
class Allow implements HeaderInterface
{
/**
* List of request methods
* true states that method is allowed, false - disallowed
* By default GET and POST are allowed
*
* @var array
*/
protected $methods = [
Request::METHOD_OPTIONS => false,
Request::METHOD_GET => true,
Request::METHOD_HEAD => false,
Request::METHOD_POST => true,
Request::METHOD_PUT => false,
Request::METHOD_DELETE => false,
Request::METHOD_TRACE => false,
Request::METHOD_CONNECT => false,
Request::METHOD_PATCH => false,
];
/**
* Create Allow header from header line
*
* @param string $headerLine
* @return static
* @throws Exception\InvalidArgumentException
*/
public static function fromString($headerLine)
{
list($name, $value) = GenericHeader::splitHeaderLine($headerLine);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'allow') {
throw new Exception\InvalidArgumentException('Invalid header line for Allow string: "' . $name . '"');
}
$header = new static();
$header->disallowMethods(array_keys($header->getAllMethods()));
$header->allowMethods(explode(',', $value));
return $header;
}
/**
* Get header name
*
* @return string
*/
public function getFieldName()
{
return 'Allow';
}
/**
* Get comma-separated list of allowed methods
*
* @return string
*/
public function getFieldValue()
{
return implode(', ', array_keys($this->methods, true, true));
}
/**
* Get list of all defined methods
*
* @return array
*/
public function getAllMethods()
{
return $this->methods;
}
/**
* Get list of allowed methods
*
* @return array
*/
public function getAllowedMethods()
{
return array_keys($this->methods, true, true);
}
/**
* Allow methods or list of methods
*
* @param array|string $allowedMethods
* @return $this
*/
public function allowMethods($allowedMethods)
{
foreach ((array) $allowedMethods as $method) {
$method = trim(strtoupper($method));
if (preg_match('/\s/', $method)) {
throw new Exception\InvalidArgumentException(sprintf(
'Unable to whitelist method; "%s" is not a valid method',
$method
));
}
$this->methods[$method] = true;
}
return $this;
}
/**
* Disallow methods or list of methods
*
* @param array|string $disallowedMethods
* @return $this
*/
public function disallowMethods($disallowedMethods)
{
foreach ((array) $disallowedMethods as $method) {
$method = trim(strtoupper($method));
if (preg_match('/\s/', $method)) {
throw new Exception\InvalidArgumentException(sprintf(
'Unable to blacklist method; "%s" is not a valid method',
$method
));
}
$this->methods[$method] = false;
}
return $this;
}
/**
* Convenience alias for @see disallowMethods()
*
* @param array|string $disallowedMethods
* @return $this
*/
public function denyMethods($disallowedMethods)
{
return $this->disallowMethods($disallowedMethods);
}
/**
* Check whether method is allowed
*
* @param string $method
* @return bool
*/
public function isAllowedMethod($method)
{
$method = trim(strtoupper($method));
// disallow unknown method
if (! isset($this->methods[$method])) {
$this->methods[$method] = false;
}
return $this->methods[$method];
}
/**
* Return header as string
*
* @return string
*/
public function toString()
{
return 'Allow: ' . $this->getFieldValue();
}
}

View File

@@ -1,59 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
/**
* @throws Exception\InvalidArgumentException
* @see http://www.ietf.org/rfc/rfc2617.txt
*/
class AuthenticationInfo implements HeaderInterface
{
/**
* @var string
*/
protected $value;
public static function fromString($headerLine)
{
list($name, $value) = GenericHeader::splitHeaderLine($headerLine);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'authentication-info') {
throw new Exception\InvalidArgumentException(sprintf(
'Invalid header line for Authentication-Info string: "%s"',
$name
));
}
// @todo implementation details
return new static($value);
}
public function __construct($value = null)
{
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
}
public function getFieldName()
{
return 'Authentication-Info';
}
public function getFieldValue()
{
return (string) $this->value;
}
public function toString()
{
return 'Authentication-Info: ' . $this->getFieldValue();
}
}

View File

@@ -1,59 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
/**
* @throws Exception\InvalidArgumentException
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.8
*/
class Authorization implements HeaderInterface
{
/**
* @var string
*/
protected $value;
public static function fromString($headerLine)
{
list($name, $value) = GenericHeader::splitHeaderLine($headerLine);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'authorization') {
throw new Exception\InvalidArgumentException(sprintf(
'Invalid header line for Authorization string: "%s"',
$name
));
}
// @todo implementation details
return new static($value);
}
public function __construct($value = null)
{
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
}
public function getFieldName()
{
return 'Authorization';
}
public function getFieldValue()
{
return (string) $this->value;
}
public function toString()
{
return 'Authorization: ' . $this->getFieldValue();
}
}

View File

@@ -1,249 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
/**
* @throws Exception\InvalidArgumentException
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9
*/
class CacheControl implements HeaderInterface
{
/**
* @var string
*/
protected $value;
/**
* Array of Cache-Control directives
*
* @var array
*/
protected $directives = [];
/**
* Creates a CacheControl object from a headerLine
*
* @param string $headerLine
* @throws Exception\InvalidArgumentException
* @return static
*/
public static function fromString($headerLine)
{
list($name, $value) = GenericHeader::splitHeaderLine($headerLine);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'cache-control') {
throw new Exception\InvalidArgumentException(sprintf(
'Invalid header line for Cache-Control string: "%s"',
$name
));
}
HeaderValue::assertValid($value);
$directives = static::parseValue($value);
// @todo implementation details
$header = new static();
foreach ($directives as $key => $value) {
$header->addDirective($key, $value);
}
return $header;
}
/**
* Required from HeaderDescription interface
*
* @return string
*/
public function getFieldName()
{
return 'Cache-Control';
}
/**
* Checks if the internal directives array is empty
*
* @return bool
*/
public function isEmpty()
{
return empty($this->directives);
}
/**
* Add a directive
* For directives like 'max-age=60', $value = '60'
* For directives like 'private', use the default $value = true
*
* @param string $key
* @param string|bool $value
* @return $this
*/
public function addDirective($key, $value = true)
{
HeaderValue::assertValid($key);
if (! is_bool($value)) {
HeaderValue::assertValid($value);
}
$this->directives[$key] = $value;
return $this;
}
/**
* Check the internal directives array for a directive
*
* @param string $key
* @return bool
*/
public function hasDirective($key)
{
return array_key_exists($key, $this->directives);
}
/**
* Fetch the value of a directive from the internal directive array
*
* @param string $key
* @return string|null
*/
public function getDirective($key)
{
return array_key_exists($key, $this->directives) ? $this->directives[$key] : null;
}
/**
* Remove a directive
*
* @param string $key
* @return $this
*/
public function removeDirective($key)
{
unset($this->directives[$key]);
return $this;
}
/**
* Assembles the directives into a comma-delimited string
*
* @return string
*/
public function getFieldValue()
{
$parts = [];
ksort($this->directives);
foreach ($this->directives as $key => $value) {
if (true === $value) {
$parts[] = $key;
} else {
if (preg_match('#[^a-zA-Z0-9._-]#', $value)) {
$value = '"' . $value . '"';
}
$parts[] = $key . '=' . $value;
}
}
return implode(', ', $parts);
}
/**
* Returns a string representation of the HTTP Cache-Control header
*
* @return string
*/
public function toString()
{
return 'Cache-Control: ' . $this->getFieldValue();
}
/**
* Internal function for parsing the value part of a
* HTTP Cache-Control header
*
* @param string $value
* @throws Exception\InvalidArgumentException
* @return array
*/
protected static function parseValue($value)
{
$value = trim($value);
$directives = [];
// handle empty string early so we don't need a separate start state
if ($value == '') {
return $directives;
}
$lastMatch = null;
state_directive:
switch (static::match(['[a-zA-Z][a-zA-Z_-]*'], $value, $lastMatch)) {
case 0:
$directive = $lastMatch;
goto state_value;
// intentional fall-through
default:
throw new Exception\InvalidArgumentException('expected DIRECTIVE');
}
state_value:
switch (static::match(['="[^"]*"', '=[^",\s;]*'], $value, $lastMatch)) {
case 0:
$directives[$directive] = substr($lastMatch, 2, -1);
goto state_separator;
// intentional fall-through
case 1:
$directives[$directive] = rtrim(substr($lastMatch, 1));
goto state_separator;
// intentional fall-through
default:
$directives[$directive] = true;
goto state_separator;
}
state_separator:
switch (static::match(['\s*,\s*', '$'], $value, $lastMatch)) {
case 0:
goto state_directive;
// intentional fall-through
case 1:
return $directives;
default:
throw new Exception\InvalidArgumentException('expected SEPARATOR or END');
}
}
/**
* Internal function used by parseValue to match tokens
*
* @param array $tokens
* @param string $string
* @param string $lastMatch
* @return int
*/
protected static function match($tokens, &$string, &$lastMatch)
{
// Ensure we have a string
$value = (string) $string;
foreach ($tokens as $i => $token) {
if (preg_match('/^' . $token . '/', $value, $matches)) {
$lastMatch = $matches[0];
$string = substr($value, strlen($matches[0]));
return $i;
}
}
return -1;
}
}

View File

@@ -1,115 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
/**
* Connection Header
*
* @link http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.10
*/
class Connection implements HeaderInterface
{
const CONNECTION_CLOSE = 'close';
const CONNECTION_KEEP_ALIVE = 'keep-alive';
/**
* Value of this header
*
* @var string
*/
protected $value = self::CONNECTION_KEEP_ALIVE;
/**
* @param string $headerLine
* @return static
* @throws Exception\InvalidArgumentException
*/
public static function fromString($headerLine)
{
$header = new static();
list($name, $value) = GenericHeader::splitHeaderLine($headerLine);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'connection') {
throw new Exception\InvalidArgumentException('Invalid header line for Connection string: "' . $name . '"');
}
$header->setValue(trim($value));
return $header;
}
/**
* Set Connection header to define persistent connection
*
* @param bool $flag
* @return $this
*/
public function setPersistent($flag)
{
$this->value = (bool) $flag
? self::CONNECTION_KEEP_ALIVE
: self::CONNECTION_CLOSE;
return $this;
}
/**
* Get whether this connection is persistent
*
* @return bool
*/
public function isPersistent()
{
return ($this->value === self::CONNECTION_KEEP_ALIVE);
}
/**
* Set arbitrary header value
* RFC allows any token as value, 'close' and 'keep-alive' are commonly used
*
* @param string $value
* @return $this
*/
public function setValue($value)
{
HeaderValue::assertValid($value);
$this->value = strtolower($value);
return $this;
}
/**
* Connection header name
*
* @return string
*/
public function getFieldName()
{
return 'Connection';
}
/**
* Connection header value
*
* @return string
*/
public function getFieldValue()
{
return $this->value;
}
/**
* Return header line
*
* @return string
*/
public function toString()
{
return 'Connection: ' . $this->getFieldValue();
}
}

View File

@@ -1,59 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
/**
* @throws Exception\InvalidArgumentException
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.5.1
*/
class ContentDisposition implements HeaderInterface
{
/**
* @var string
*/
protected $value;
public static function fromString($headerLine)
{
list($name, $value) = GenericHeader::splitHeaderLine($headerLine);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'content-disposition') {
throw new Exception\InvalidArgumentException(sprintf(
'Invalid header line for Content-Disposition string: "%s"',
$name
));
}
// @todo implementation details
return new static($value);
}
public function __construct($value = null)
{
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
}
public function getFieldName()
{
return 'Content-Disposition';
}
public function getFieldValue()
{
return (string) $this->value;
}
public function toString()
{
return 'Content-Disposition: ' . $this->getFieldValue();
}
}

View File

@@ -1,58 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
/**
* @throws Exception\InvalidArgumentException
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.11
*/
class ContentEncoding implements HeaderInterface
{
/**
* @var string
*/
protected $value;
public static function fromString($headerLine)
{
list($name, $value) = GenericHeader::splitHeaderLine($headerLine);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'content-encoding') {
throw new Exception\InvalidArgumentException(
'Invalid header line for Content-Encoding string: "' . $name . '"'
);
}
// @todo implementation details
return new static($value);
}
public function __construct($value = null)
{
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
}
public function getFieldName()
{
return 'Content-Encoding';
}
public function getFieldValue()
{
return (string) $this->value;
}
public function toString()
{
return 'Content-Encoding: ' . $this->getFieldValue();
}
}

View File

@@ -1,59 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
/**
* @throws Exception\InvalidArgumentException
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.12
*/
class ContentLanguage implements HeaderInterface
{
/**
* @var string
*/
protected $value;
public static function fromString($headerLine)
{
list($name, $value) = GenericHeader::splitHeaderLine($headerLine);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'content-language') {
throw new Exception\InvalidArgumentException(sprintf(
'Invalid header line for Content-Language string: "%s"',
$name
));
}
// @todo implementation details
return new static($value);
}
public function __construct($value = null)
{
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
}
public function getFieldName()
{
return 'Content-Language';
}
public function getFieldValue()
{
return (string) $this->value;
}
public function toString()
{
return 'Content-Language: ' . $this->getFieldValue();
}
}

View File

@@ -1,59 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
/**
* @throws Exception\InvalidArgumentException
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.13
*/
class ContentLength implements HeaderInterface
{
/**
* @var string
*/
protected $value;
public static function fromString($headerLine)
{
list($name, $value) = GenericHeader::splitHeaderLine($headerLine);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'content-length') {
throw new Exception\InvalidArgumentException(sprintf(
'Invalid header line for Content-Length string: "%s"',
$name
));
}
// @todo implementation details
return new static($value);
}
public function __construct($value = null)
{
if (null !== $value) {
HeaderValue::assertValid($value);
$this->value = $value;
}
}
public function getFieldName()
{
return 'Content-Length';
}
public function getFieldValue()
{
return (string) $this->value;
}
public function toString()
{
return 'Content-Length: ' . $this->getFieldValue();
}
}

View File

@@ -1,26 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
/**
* Content-Location Header
*
* @link http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.14
*/
class ContentLocation extends AbstractLocation
{
/**
* Return header name
*
* @return string
*/
public function getFieldName()
{
return 'Content-Location';
}
}

View File

@@ -1,56 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
/**
* @throws Exception\InvalidArgumentException
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.15
*/
class ContentMD5 implements HeaderInterface
{
/**
* @var string
*/
protected $value;
public static function fromString($headerLine)
{
list($name, $value) = GenericHeader::splitHeaderLine($headerLine);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'content-md5') {
throw new Exception\InvalidArgumentException('Invalid header line for Content-MD5 string: "' . $name . '"');
}
// @todo implementation details
return new static($value);
}
public function __construct($value = null)
{
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
}
public function getFieldName()
{
return 'Content-MD5';
}
public function getFieldValue()
{
return (string) $this->value;
}
public function toString()
{
return 'Content-MD5: ' . $this->getFieldValue();
}
}

View File

@@ -1,59 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
/**
* @throws Exception\InvalidArgumentException
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.16
*/
class ContentRange implements HeaderInterface
{
/**
* @var string
*/
protected $value;
public static function fromString($headerLine)
{
list($name, $value) = GenericHeader::splitHeaderLine($headerLine);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'content-range') {
throw new Exception\InvalidArgumentException(sprintf(
'Invalid header line for Content-Range string: "%s"',
$name
));
}
// @todo implementation details
return new static($value);
}
public function __construct($value = null)
{
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
}
public function getFieldName()
{
return 'Content-Range';
}
public function getFieldValue()
{
return (string) $this->value;
}
public function toString()
{
return 'Content-Range: ' . $this->getFieldValue();
}
}

View File

@@ -1,219 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
/**
* Content Security Policy Level 3 Header
*
* @link http://www.w3.org/TR/CSP/
*/
class ContentSecurityPolicy implements MultipleHeaderInterface
{
/**
* Valid directive names
*
* @var array
*/
protected $validDirectiveNames = [
// As per http://www.w3.org/TR/CSP/#directives
// Fetch directives
'child-src',
'connect-src',
'default-src',
'font-src',
'frame-src',
'img-src',
'manifest-src',
'media-src',
'object-src',
'prefetch-src',
'script-src',
'script-src-elem',
'script-src-attr',
'style-src',
'style-src-elem',
'style-src-attr',
'worker-src',
// Document directives
'base-uri',
'plugin-types',
'sandbox',
// Navigation directives
'form-action',
'frame-ancestors',
'navigate-to',
// Reporting directives
'report-uri',
'report-to',
// Other directives
'block-all-mixed-content',
'require-sri-for',
'trusted-types',
'upgrade-insecure-requests',
];
/**
* The directives defined for this policy
*
* @var array
*/
protected $directives = [];
/**
* Get the list of defined directives
*
* @return array
*/
public function getDirectives()
{
return $this->directives;
}
/**
* Sets the directive to consist of the source list
*
* Reverses http://www.w3.org/TR/CSP/#parsing-1
*
* @param string $name The directive name.
* @param array $sources The source list.
* @return $this
* @throws Exception\InvalidArgumentException If the name is not a valid directive name.
*/
public function setDirective($name, array $sources)
{
if (! in_array($name, $this->validDirectiveNames, true)) {
throw new Exception\InvalidArgumentException(sprintf(
'%s expects a valid directive name; received "%s"',
__METHOD__,
(string) $name
));
}
if ($name === 'block-all-mixed-content'
|| $name === 'upgrade-insecure-requests'
) {
if ($sources) {
throw new Exception\InvalidArgumentException(sprintf(
'Received value for %s directive; none expected',
$name
));
}
$this->directives[$name] = '';
return $this;
}
if (empty($sources)) {
if ('report-uri' === $name) {
if (isset($this->directives[$name])) {
unset($this->directives[$name]);
}
return $this;
}
$this->directives[$name] = "'none'";
return $this;
}
array_walk($sources, [__NAMESPACE__ . '\HeaderValue', 'assertValid']);
$this->directives[$name] = implode(' ', $sources);
return $this;
}
/**
* Create Content Security Policy header from a given header line
*
* @param string $headerLine The header line to parse.
* @return static
* @throws Exception\InvalidArgumentException If the name field in the given header line does not match.
*/
public static function fromString($headerLine)
{
$header = new static();
$headerName = $header->getFieldName();
list($name, $value) = GenericHeader::splitHeaderLine($headerLine);
// Ensure the proper header name
if (strcasecmp($name, $headerName) != 0) {
throw new Exception\InvalidArgumentException(sprintf(
'Invalid header line for %s string: "%s"',
$headerName,
$name
));
}
// As per http://www.w3.org/TR/CSP/#parsing
$tokens = explode(';', $value);
foreach ($tokens as $token) {
$token = trim($token);
if ($token) {
list($directiveName, $directiveValue) = array_pad(explode(' ', $token, 2), 2, null);
if (! isset($header->directives[$directiveName])) {
$header->setDirective(
$directiveName,
$directiveValue === null ? [] : [$directiveValue]
);
}
}
}
return $header;
}
/**
* Get the header name
*
* @return string
*/
public function getFieldName()
{
return 'Content-Security-Policy';
}
/**
* Get the header value
*
* @return string
*/
public function getFieldValue()
{
$directives = [];
foreach ($this->directives as $name => $value) {
$directives[] = sprintf('%s %s;', $name, $value);
}
return str_replace(' ;', ';', implode(' ', $directives));
}
/**
* Return the header as a string
*
* @return string
*/
public function toString()
{
return sprintf('%s: %s', $this->getFieldName(), $this->getFieldValue());
}
public function toStringMultipleHeaders(array $headers)
{
$strings = [$this->toString()];
foreach ($headers as $header) {
if (! $header instanceof ContentSecurityPolicy) {
throw new Exception\RuntimeException(
'The ContentSecurityPolicy multiple header implementation can only'
. ' accept an array of ContentSecurityPolicy headers'
);
}
$strings[] = $header->toString();
}
return implode("\r\n", $strings) . "\r\n";
}
}

View File

@@ -1,59 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
/**
* @throws Exception\InvalidArgumentException
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.11 @todo find section
*/
class ContentTransferEncoding implements HeaderInterface
{
/**
* @var string
*/
protected $value;
public static function fromString($headerLine)
{
list($name, $value) = GenericHeader::splitHeaderLine($headerLine);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'content-transfer-encoding') {
throw new Exception\InvalidArgumentException(sprintf(
'Invalid header line for Content-Transfer-Encoding string: "%s"',
$name
));
}
// @todo implementation details
return new static(strtolower($value));
}
public function __construct($value = null)
{
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
}
public function getFieldName()
{
return 'Content-Transfer-Encoding';
}
public function getFieldValue()
{
return (string) $this->value;
}
public function toString()
{
return 'Content-Transfer-Encoding: ' . $this->getFieldValue();
}
}

View File

@@ -1,402 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
use stdClass;
/**
* @throws Exception\InvalidArgumentException
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.17
*/
class ContentType implements HeaderInterface
{
/**
* @var string
*/
protected $mediaType;
/**
* @var array
*/
protected $parameters = [];
/**
* @var string
*/
protected $value;
/**
* Factory method: create an object from a string representation
*
* @param string $headerLine
* @return static
*/
public static function fromString($headerLine)
{
list($name, $value) = GenericHeader::splitHeaderLine($headerLine);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'content-type') {
throw new Exception\InvalidArgumentException(sprintf(
'Invalid header line for Content-Type string: "%s"',
$name
));
}
$parts = explode(';', $value);
$mediaType = array_shift($parts);
$header = new static($value, trim($mediaType));
if (count($parts) > 0) {
$parameters = [];
foreach ($parts as $parameter) {
$parameter = trim($parameter);
if (! preg_match('/^(?P<key>[^\s\=]+)\="?(?P<value>[^\s\"]*)"?$/', $parameter, $matches)) {
continue;
}
$parameters[$matches['key']] = $matches['value'];
}
$header->setParameters($parameters);
}
return $header;
}
public function __construct($value = null, $mediaType = null)
{
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
$this->mediaType = $mediaType;
}
/**
* Determine if the mediatype value in this header matches the provided criteria
*
* @param array|string $matchAgainst
* @return string|bool Matched value or false
*/
public function match($matchAgainst)
{
if (is_string($matchAgainst)) {
$matchAgainst = $this->splitMediaTypesFromString($matchAgainst);
}
$mediaType = $this->getMediaType();
$left = $this->getMediaTypeObjectFromString($mediaType);
foreach ($matchAgainst as $matchType) {
$matchType = strtolower($matchType);
if ($mediaType == $matchType) {
return $matchType;
}
$right = $this->getMediaTypeObjectFromString($matchType);
// Is the right side a wildcard type?
if ($right->type == '*') {
if ($this->validateSubtype($right, $left)) {
return $matchType;
}
}
// Do the types match?
if ($right->type == $left->type) {
if ($this->validateSubtype($right, $left)) {
return $matchType;
}
}
}
return false;
}
/**
* Create a string representation of the header
*
* @return string
*/
public function toString()
{
return 'Content-Type: ' . $this->getFieldValue();
}
/**
* Get the field name
*
* @return string
*/
public function getFieldName()
{
return 'Content-Type';
}
/**
* Get the field value
*
* @return string
*/
public function getFieldValue()
{
if (null !== $this->value) {
return (string) $this->value;
}
return $this->assembleValue();
}
/**
* Set the media type
*
* @param string $mediaType
* @return $this
*/
public function setMediaType($mediaType)
{
HeaderValue::assertValid($mediaType);
$this->mediaType = strtolower($mediaType);
$this->value = null;
return $this;
}
/**
* Get the media type
*
* @return string
*/
public function getMediaType()
{
return (string) $this->mediaType;
}
/**
* Set additional content-type parameters
*
* @param array $parameters
* @return $this
*/
public function setParameters(array $parameters)
{
foreach ($parameters as $key => $value) {
HeaderValue::assertValid($key);
HeaderValue::assertValid($value);
}
$this->parameters = array_merge($this->parameters, $parameters);
$this->value = null;
return $this;
}
/**
* Get any additional content-type parameters currently set
*
* @return array
*/
public function getParameters()
{
return $this->parameters;
}
/**
* Set the content-type character set encoding
*
* @param string $charset
* @return $this
*/
public function setCharset($charset)
{
HeaderValue::assertValid($charset);
$this->parameters['charset'] = $charset;
$this->value = null;
return $this;
}
/**
* Get the content-type character set encoding, if any
*
* @return null|string
*/
public function getCharset()
{
if (isset($this->parameters['charset'])) {
return $this->parameters['charset'];
}
return null;
}
/**
* Assemble the value based on the media type and any available parameters
*
* @return string
*/
protected function assembleValue()
{
$mediaType = $this->getMediaType();
if (empty($this->parameters)) {
return $mediaType;
}
$parameters = [];
foreach ($this->parameters as $key => $value) {
$parameters[] = sprintf('%s=%s', $key, $value);
}
return sprintf('%s; %s', $mediaType, implode('; ', $parameters));
}
/**
* Split comma-separated media types into an array
*
* @param string $criteria
* @return array
*/
protected function splitMediaTypesFromString($criteria)
{
$mediaTypes = explode(',', $criteria);
array_walk(
$mediaTypes,
function (&$value) {
$value = trim($value);
}
);
return $mediaTypes;
}
/**
* Split a mediatype string into an object with the following parts:
*
* - type
* - subtype
* - format
*
* @param string $string
* @return stdClass
*/
protected function getMediaTypeObjectFromString($string)
{
if (! is_string($string)) {
throw new Exception\InvalidArgumentException(sprintf(
'Non-string mediatype "%s" provided',
(is_object($string) ? get_class($string) : gettype($string))
));
}
$parts = explode('/', $string, 2);
if (1 == count($parts)) {
throw new Exception\DomainException(sprintf(
'Invalid mediatype "%s" provided',
$string
));
}
$type = array_shift($parts);
$subtype = array_shift($parts);
$format = $subtype;
if (false !== strpos($subtype, '+')) {
$parts = explode('+', $subtype, 2);
$subtype = array_shift($parts);
$format = array_shift($parts);
}
$mediaType = (object) [
'type' => $type,
'subtype' => $subtype,
'format' => $format,
];
return $mediaType;
}
/**
* Validate a subtype
*
* @param stdClass $right
* @param stdClass $left
* @return bool
*/
protected function validateSubtype($right, $left)
{
// Is the right side a wildcard subtype?
if ($right->subtype == '*') {
return $this->validateFormat($right, $left);
}
// Do the right side and left side subtypes match?
if ($right->subtype == $left->subtype) {
return $this->validateFormat($right, $left);
}
// Is the right side a partial wildcard?
if ('*' == substr($right->subtype, -1)) {
// validate partial-wildcard subtype
if (! $this->validatePartialWildcard($right->subtype, $left->subtype)) {
return false;
}
// Finally, verify format is valid
return $this->validateFormat($right, $left);
}
// Does the right side subtype match the left side format?
if ($right->subtype == $left->format) {
return true;
}
// At this point, there is no valid match
return false;
}
/**
* Validate the format
*
* Validate that the right side format matches what the left side defines.
*
* @param string $right
* @param string $left
* @return bool
*/
protected function validateFormat($right, $left)
{
if ($right->format && $left->format) {
if ($right->format == '*') {
return true;
}
if ($right->format == $left->format) {
return true;
}
return false;
}
return true;
}
/**
* Validate a partial wildcard (i.e., string ending in '*')
*
* @param string $right
* @param string $left
* @return bool
*/
protected function validatePartialWildcard($right, $left)
{
$requiredSegment = substr($right, 0, strlen($right) - 1);
if ($requiredSegment == $left) {
return true;
}
if (strlen($requiredSegment) >= strlen($left)) {
return false;
}
if (0 === strpos($left, $requiredSegment)) {
return true;
}
return false;
}
}

View File

@@ -1,143 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
use ArrayObject;
/**
* @see http://www.ietf.org/rfc/rfc2109.txt
* @see http://www.w3.org/Protocols/rfc2109/rfc2109
*/
class Cookie extends ArrayObject implements HeaderInterface
{
protected $encodeValue = true;
public static function fromSetCookieArray(array $setCookies)
{
$nvPairs = [];
foreach ($setCookies as $setCookie) {
if (! $setCookie instanceof SetCookie) {
throw new Exception\InvalidArgumentException(sprintf(
'%s requires an array of SetCookie objects',
__METHOD__
));
}
if (array_key_exists($setCookie->getName(), $nvPairs)) {
throw new Exception\InvalidArgumentException(sprintf(
'Two cookies with the same name were provided to %s',
__METHOD__
));
}
$nvPairs[$setCookie->getName()] = $setCookie->getValue();
}
return new static($nvPairs);
}
public static function fromString($headerLine)
{
$header = new static();
list($name, $value) = GenericHeader::splitHeaderLine($headerLine);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'cookie') {
throw new Exception\InvalidArgumentException('Invalid header line for Server string: "' . $name . '"');
}
$nvPairs = preg_split('#;\s*#', $value);
$arrayInfo = [];
foreach ($nvPairs as $nvPair) {
$parts = explode('=', $nvPair, 2);
if (count($parts) != 2) {
throw new Exception\RuntimeException('Malformed Cookie header found');
}
list($name, $value) = $parts;
$arrayInfo[$name] = urldecode($value);
}
$header->exchangeArray($arrayInfo);
return $header;
}
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;
}
public function getFieldName()
{
return 'Cookie';
}
public function getFieldValue()
{
$nvPairs = [];
foreach ($this->flattenCookies($this) as $name => $value) {
$nvPairs[] = $name . '=' . (($this->encodeValue) ? urlencode($value) : $value);
}
return implode('; ', $nvPairs);
}
protected function flattenCookies($data, $prefix = null)
{
$result = [];
foreach ($data as $key => $value) {
$key = $prefix ? $prefix . '[' . $key . ']' : $key;
if (is_array($value)) {
$result = array_merge($result, $this->flattenCookies($value, $key));
} else {
$result[$key] = $value;
}
}
return $result;
}
public function toString()
{
return 'Cookie: ' . $this->getFieldValue();
}
/**
* Get the cookie as a string, suitable for sending as a "Cookie" header in an
* HTTP request
*
* @return string
*/
public function __toString()
{
return $this->toString();
}
}

View File

@@ -1,26 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
/**
* Date Header
*
* @link http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.18
*/
class Date extends AbstractDate
{
/**
* Get header name
*
* @return string
*/
public function getFieldName()
{
return 'Date';
}
}

View File

@@ -1,56 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
/**
* @throws Exception\InvalidArgumentException
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.19
*/
class Etag implements HeaderInterface
{
/**
* @var string
*/
protected $value;
public static function fromString($headerLine)
{
list($name, $value) = GenericHeader::splitHeaderLine($headerLine);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'etag') {
throw new Exception\InvalidArgumentException('Invalid header line for Etag string: "' . $name . '"');
}
// @todo implementation details
return new static($value);
}
public function __construct($value = null)
{
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
}
public function getFieldName()
{
return 'Etag';
}
public function getFieldValue()
{
return (string) $this->value;
}
public function toString()
{
return 'Etag: ' . $this->getFieldValue();
}
}

View File

@@ -1,12 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header\Exception;
class DomainException extends \DomainException implements ExceptionInterface
{
}

View File

@@ -1,14 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header\Exception;
use Zend\Http\Exception\ExceptionInterface as HttpException;
interface ExceptionInterface extends HttpException
{
}

View File

@@ -1,15 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header\Exception;
use Zend\Http\Exception;
class InvalidArgumentException extends Exception\InvalidArgumentException implements
ExceptionInterface
{
}

View File

@@ -1,15 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header\Exception;
use Zend\Http\Exception;
class RuntimeException extends Exception\RuntimeException implements
ExceptionInterface
{
}

View File

@@ -1,56 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
/**
* @throws Exception\InvalidArgumentException
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.20
*/
class Expect implements HeaderInterface
{
/**
* @var string
*/
protected $value;
public static function fromString($headerLine)
{
list($name, $value) = GenericHeader::splitHeaderLine($headerLine);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'expect') {
throw new Exception\InvalidArgumentException('Invalid header line for Expect string: "' . $name . '"');
}
// @todo implementation details
return new static($value);
}
public function __construct($value = null)
{
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
}
public function getFieldName()
{
return 'Expect';
}
public function getFieldValue()
{
return (string) $this->value;
}
public function toString()
{
return 'Expect: ' . $this->getFieldValue();
}
}

View File

@@ -1,34 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
/**
* Expires Header
*
* @link http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.21
*/
class Expires extends AbstractDate
{
/**
* Get header name
*
* @return string
*/
public function getFieldName()
{
return 'Expires';
}
public function setDate($date)
{
if ($date === '0' || $date === 0) {
$date = date(DATE_W3C, 0); // Thu, 01 Jan 1970 00:00:00 GMT
}
return parent::setDate($date);
}
}

View File

@@ -1,184 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2019 Zend Technologies USA Inc. (https://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
/**
* Feature Policy (based on Editors Draft, 28 November 2019)
*
* @link https://w3c.github.io/webappsec-feature-policy/
*/
class FeaturePolicy implements HeaderInterface
{
/**
* Valid directive names
*
* @var string[]
*
* @see https://github.com/w3c/webappsec-feature-policy/blob/master/features.md
*/
protected $validDirectiveNames = [
// Standardized Features
'accelerometer',
'ambient-light-sensor',
'autoplay',
'battery',
'camera',
'display-capture',
'document-domain',
'fullscreen',
'execution-while-not-rendered',
'execution-while-out-of-viewport',
'gyroscope',
'magnetometer',
'microphone',
'midi',
'payment',
'picture-in-picture',
'sync-xhr',
'usb',
'wake-lock',
'xr',
// Proposed Features
'encrypted-media',
'geolocation',
'speaker',
// Experimental Features
'document-write',
'font-display-late-swap',
'layout-animations',
'loading-frame-default-eager',
'loading-image-default-eager',
'legacy-image-formats',
'oversized-images',
'sync-script',
'unoptimized-lossy-images',
'unoptimized-lossless-images',
'unsized-media',
'vertical-scroll',
'serial',
];
/**
* The directives defined for this policy
*
* @var array
*/
protected $directives = [];
/**
* Get the list of defined directives
*
* @return array
*/
public function getDirectives()
{
return $this->directives;
}
/**
* Sets the directive to consist of the source list
*
* @param string $name The directive name.
* @param string[] $sources The source list.
* @return $this
* @throws Exception\InvalidArgumentException If the name is not a valid directive name.
*/
public function setDirective($name, array $sources)
{
if (! in_array($name, $this->validDirectiveNames, true)) {
throw new Exception\InvalidArgumentException(sprintf(
'%s expects a valid directive name; received "%s"',
__METHOD__,
(string) $name
));
}
if (empty($sources)) {
$this->directives[$name] = "'none'";
return $this;
}
array_walk($sources, [__NAMESPACE__ . '\HeaderValue', 'assertValid']);
$this->directives[$name] = implode(' ', $sources);
return $this;
}
/**
* Create Feature Policy header from a given header line
*
* @param string $headerLine The header line to parse.
* @return static
* @throws Exception\InvalidArgumentException If the name field in the given header line does not match.
*/
public static function fromString($headerLine)
{
$header = new static();
$headerName = $header->getFieldName();
list($name, $value) = GenericHeader::splitHeaderLine($headerLine);
// Ensure the proper header name
if (strcasecmp($name, $headerName) !== 0) {
throw new Exception\InvalidArgumentException(sprintf(
'Invalid header line for %s string: "%s"',
$headerName,
$name
));
}
// As per https://w3c.github.io/webappsec-feature-policy/#algo-parse-policy-directive
$tokens = explode(';', $value);
foreach ($tokens as $token) {
$token = trim($token);
if ($token) {
list($directiveName, $directiveValue) = array_pad(explode(' ', $token, 2), 2, null);
if (! isset($header->directives[$directiveName])) {
$header->setDirective(
$directiveName,
$directiveValue === null ? [] : [$directiveValue]
);
}
}
}
return $header;
}
/**
* Get the header name
*
* @return string
*/
public function getFieldName()
{
return 'Feature-Policy';
}
/**
* Get the header value
*
* @return string
*/
public function getFieldValue()
{
$directives = [];
foreach ($this->directives as $name => $value) {
$directives[] = sprintf('%s %s;', $name, $value);
}
return implode(' ', $directives);
}
/**
* Return the header as a string
*
* @return string
*/
public function toString()
{
return sprintf('%s: %s', $this->getFieldName(), $this->getFieldValue());
}
}

View File

@@ -1,56 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
/**
* @throws Exception\InvalidArgumentException
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.22
*/
class From implements HeaderInterface
{
/**
* @var string
*/
protected $value;
public static function fromString($headerLine)
{
list($name, $value) = GenericHeader::splitHeaderLine($headerLine);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'from') {
throw new Exception\InvalidArgumentException('Invalid header line for From string: "' . $name . '"');
}
// @todo implementation details
return new static($value);
}
public function __construct($value = null)
{
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
}
public function getFieldName()
{
return 'From';
}
public function getFieldValue()
{
return (string) $this->value;
}
public function toString()
{
return 'From: ' . $this->getFieldValue();
}
}

View File

@@ -1,160 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
/**
* Content-Location Header
*/
class GenericHeader implements HeaderInterface
{
/**
* @var string
*/
protected $fieldName;
/**
* @var string
*/
protected $fieldValue;
/**
* Factory to generate a header object from a string
*
* @param string $headerLine
* @return static
*/
public static function fromString($headerLine)
{
list($fieldName, $fieldValue) = GenericHeader::splitHeaderLine($headerLine);
return new static($fieldName, $fieldValue);
}
/**
* Splits the header line in `name` and `value` parts.
*
* @param string $headerLine
* @return string[] `name` in the first index and `value` in the second.
* @throws Exception\InvalidArgumentException If header does not match with the format ``name:value``
*/
public static function splitHeaderLine($headerLine)
{
$parts = explode(':', $headerLine, 2);
if (count($parts) !== 2) {
throw new Exception\InvalidArgumentException('Header must match with the format "name:value"');
}
if (! HeaderValue::isValid($parts[1])) {
throw new Exception\InvalidArgumentException('Invalid header value detected');
}
$parts[1] = ltrim($parts[1]);
return $parts;
}
/**
* Constructor
*
* @param null|string $fieldName
* @param null|string $fieldValue
*/
public function __construct($fieldName = null, $fieldValue = null)
{
if ($fieldName) {
$this->setFieldName($fieldName);
}
if ($fieldValue !== null) {
$this->setFieldValue($fieldValue);
}
}
/**
* Set header field name
*
* @param string $fieldName
* @return $this
* @throws Exception\InvalidArgumentException If the name does not match with RFC 2616 format.
*/
public function setFieldName($fieldName)
{
if (! is_string($fieldName) || empty($fieldName)) {
throw new Exception\InvalidArgumentException('Header name must be a string');
}
/*
* Following RFC 7230 section 3.2
*
* header-field = field-name ":" [ field-value ]
* field-name = token
* token = 1*tchar
* tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." /
* "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA
*/
if (! preg_match('/^[!#$%&\'*+\-\.\^_`|~0-9a-zA-Z]+$/', $fieldName)) {
throw new Exception\InvalidArgumentException(
'Header name must be a valid RFC 7230 (section 3.2) field-name.'
);
}
$this->fieldName = $fieldName;
return $this;
}
/**
* Retrieve header field name
*
* @return string
*/
public function getFieldName()
{
return $this->fieldName;
}
/**
* Set header field value
*
* @param string $fieldValue
* @return $this
*/
public function setFieldValue($fieldValue)
{
$fieldValue = (string) $fieldValue;
HeaderValue::assertValid($fieldValue);
if (preg_match('/^\s+$/', $fieldValue)) {
$fieldValue = '';
}
$this->fieldValue = $fieldValue;
return $this;
}
/**
* Retrieve header field value
*
* @return string
*/
public function getFieldValue()
{
return $this->fieldValue;
}
/**
* Cast to string as a well formed HTTP header line
*
* Returns in form of "NAME: VALUE\r\n"
*
* @return string
*/
public function toString()
{
return $this->getFieldName() . ': ' . $this->getFieldValue();
}
}

View File

@@ -1,42 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
class GenericMultiHeader extends GenericHeader implements MultipleHeaderInterface
{
public static function fromString($headerLine)
{
list($fieldName, $fieldValue) = GenericHeader::splitHeaderLine($headerLine);
if (strpos($fieldValue, ',')) {
$headers = [];
foreach (explode(',', $fieldValue) as $multiValue) {
$headers[] = new static($fieldName, $multiValue);
}
return $headers;
} else {
$header = new static($fieldName, $fieldValue);
return $header;
}
}
public function toStringMultipleHeaders(array $headers)
{
$name = $this->getFieldName();
$values = [$this->getFieldValue()];
foreach ($headers as $header) {
if (! $header instanceof static) {
throw new Exception\InvalidArgumentException(
'This method toStringMultipleHeaders was expecting an array of headers of the same type'
);
}
$values[] = $header->getFieldValue();
}
return $name . ': ' . implode(',', $values) . "\r\n";
}
}

View File

@@ -1,47 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
/**
* Interface for HTTP Header classes.
*/
interface HeaderInterface
{
/**
* Factory to generate a header object from a string
*
* @param string $headerLine
* @return static
* @throws Exception\InvalidArgumentException If the header does not match RFC 2616 definition.
* @see http://tools.ietf.org/html/rfc2616#section-4.2
*/
public static function fromString($headerLine);
/**
* Retrieve header name
*
* @return string
*/
public function getFieldName();
/**
* Retrieve header value
*
* @return string
*/
public function getFieldValue();
/**
* Cast to string
*
* Returns in form of "NAME: VALUE"
*
* @return string
*/
public function toString();
}

View File

@@ -1,105 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
final class HeaderValue
{
/**
* Private constructor; non-instantiable.
*/
private function __construct()
{
}
/**
* Filter a header value
*
* Ensures CRLF header injection vectors are filtered.
*
* Per RFC 7230, only VISIBLE ASCII characters, spaces, and horizontal
* tabs are allowed in values; only one whitespace character is allowed
* between visible characters.
*
* @see http://en.wikipedia.org/wiki/HTTP_response_splitting
* @param string $value
* @return string
*/
public static function filter($value)
{
$value = (string) $value;
$length = strlen($value);
$string = '';
for ($i = 0; $i < $length; $i += 1) {
$ascii = ord($value[$i]);
// Non-visible, non-whitespace characters
// 9 === horizontal tab
// 32-126, 128-254 === visible
// 127 === DEL
// 255 === null byte
if (($ascii < 32 && $ascii !== 9)
|| $ascii === 127
|| $ascii > 254
) {
continue;
}
$string .= $value[$i];
}
return $string;
}
/**
* Validate a header value.
*
* Per RFC 7230, only VISIBLE ASCII characters, spaces, and horizontal
* tabs are allowed in values; only one whitespace character is allowed
* between visible characters.
*
* @see http://en.wikipedia.org/wiki/HTTP_response_splitting
* @param string $value
* @return bool
*/
public static function isValid($value)
{
$value = (string) $value;
$length = strlen($value);
for ($i = 0; $i < $length; $i += 1) {
$ascii = ord($value[$i]);
// Non-visible, non-whitespace characters
// 9 === horizontal tab
// 32-126, 128-254 === visible
// 127 === DEL
// 255 === null byte
if (($ascii < 32 && $ascii !== 9)
|| $ascii === 127
|| $ascii > 254
) {
return false;
}
}
return true;
}
/**
* Assert a header value is valid.
*
* @param string $value
* @throws Exception\RuntimeException for invalid values
* @return void
*/
public static function assertValid($value)
{
if (! self::isValid($value)) {
throw new Exception\InvalidArgumentException('Invalid header value');
}
}
}

View File

@@ -1,56 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
/**
* @throws Exception\InvalidArgumentException
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.23
*/
class Host implements HeaderInterface
{
/**
* @var string
*/
protected $value;
public static function fromString($headerLine)
{
list($name, $value) = GenericHeader::splitHeaderLine($headerLine);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'host') {
throw new Exception\InvalidArgumentException('Invalid header line for Host string: "' . $name . '"');
}
// @todo implementation details
return new static($value);
}
public function __construct($value = null)
{
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
}
public function getFieldName()
{
return 'Host';
}
public function getFieldValue()
{
return (string) $this->value;
}
public function toString()
{
return 'Host: ' . $this->getFieldValue();
}
}

View File

@@ -1,56 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
/**
* @throws Exception\InvalidArgumentException
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.24
*/
class IfMatch implements HeaderInterface
{
/**
* @var string
*/
protected $value;
public static function fromString($headerLine)
{
list($name, $value) = GenericHeader::splitHeaderLine($headerLine);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'if-match') {
throw new Exception\InvalidArgumentException('Invalid header line for If-Match string: "' . $name . '"');
}
// @todo implementation details
return new static($value);
}
public function __construct($value = null)
{
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
}
public function getFieldName()
{
return 'If-Match';
}
public function getFieldValue()
{
return (string) $this->value;
}
public function toString()
{
return 'If-Match: ' . $this->getFieldValue();
}
}

View File

@@ -1,26 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
/**
* If-Modified-Since Header
*
* @link http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.25
*/
class IfModifiedSince extends AbstractDate
{
/**
* Get header name
*
* @return string
*/
public function getFieldName()
{
return 'If-Modified-Since';
}
}

View File

@@ -1,59 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
/**
* @throws Exception\InvalidArgumentException
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.26
*/
class IfNoneMatch implements HeaderInterface
{
/**
* @var string
*/
protected $value;
public static function fromString($headerLine)
{
list($name, $value) = GenericHeader::splitHeaderLine($headerLine);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'if-none-match') {
throw new Exception\InvalidArgumentException(sprintf(
'Invalid header line for If-None-Match string: "%s"',
$name
));
}
// @todo implementation details
return new static($value);
}
public function __construct($value = null)
{
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
}
public function getFieldName()
{
return 'If-None-Match';
}
public function getFieldValue()
{
return (string) $this->value;
}
public function toString()
{
return 'If-None-Match: ' . $this->getFieldValue();
}
}

View File

@@ -1,56 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
/**
* @throws Exception\InvalidArgumentException
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.27
*/
class IfRange implements HeaderInterface
{
/**
* @var string
*/
protected $value;
public static function fromString($headerLine)
{
list($name, $value) = GenericHeader::splitHeaderLine($headerLine);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'if-range') {
throw new Exception\InvalidArgumentException('Invalid header line for If-Range string: "' . $name . '"');
}
// @todo implementation details
return new static($value);
}
public function __construct($value = null)
{
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
}
public function getFieldName()
{
return 'If-Range';
}
public function getFieldValue()
{
return (string) $this->value;
}
public function toString()
{
return 'If-Range: ' . $this->getFieldValue();
}
}

View File

@@ -1,26 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
/**
* If-Unmodified-Since Header
*
* @link http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.28
*/
class IfUnmodifiedSince extends AbstractDate
{
/**
* Get header name
*
* @return string
*/
public function getFieldName()
{
return 'If-Unmodified-Since';
}
}

View File

@@ -1,56 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
/**
* @throws Exception\InvalidArgumentException
* @todo Search for RFC for this header
*/
class KeepAlive implements HeaderInterface
{
/**
* @var string
*/
protected $value;
public static function fromString($headerLine)
{
list($name, $value) = GenericHeader::splitHeaderLine($headerLine);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'keep-alive') {
throw new Exception\InvalidArgumentException('Invalid header line for Keep-Alive string: "' . $name . '"');
}
// @todo implementation details
return new static($value);
}
public function __construct($value = null)
{
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
}
public function getFieldName()
{
return 'Keep-Alive';
}
public function getFieldValue()
{
return (string) $this->value;
}
public function toString()
{
return 'Keep-Alive: ' . $this->getFieldValue();
}
}

View File

@@ -1,26 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
/**
* Last-Modified Header
*
* @link http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.29
*/
class LastModified extends AbstractDate
{
/**
* Get header name
*
* @return string
*/
public function getFieldName()
{
return 'Last-Modified';
}
}

View File

@@ -1,26 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
/**
* Location Header
*
* @link http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.30
*/
class Location extends AbstractLocation
{
/**
* Return header name
*
* @return string
*/
public function getFieldName()
{
return 'Location';
}
}

View File

@@ -1,59 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
/**
* @throws Exception\InvalidArgumentException
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.31
*/
class MaxForwards implements HeaderInterface
{
/**
* @var string
*/
protected $value;
public static function fromString($headerLine)
{
list($name, $value) = GenericHeader::splitHeaderLine($headerLine);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'max-forwards') {
throw new Exception\InvalidArgumentException(sprintf(
'Invalid header line for Max-Forwards string: "%s"',
$name
));
}
// @todo implementation details
return new static($value);
}
public function __construct($value = null)
{
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
}
public function getFieldName()
{
return 'Max-Forwards';
}
public function getFieldValue()
{
return (string) $this->value;
}
public function toString()
{
return 'Max-Forwards: ' . $this->getFieldValue();
}
}

View File

@@ -1,13 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
interface MultipleHeaderInterface extends HeaderInterface
{
public function toStringMultipleHeaders(array $headers);
}

View File

@@ -1,65 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
use Zend\Uri\UriFactory;
/**
* @throws Exception\InvalidArgumentException
* @see http://tools.ietf.org/id/draft-abarth-origin-03.html#rfc.section.2
*/
class Origin implements HeaderInterface
{
/**
* @var string
*/
protected $value = '';
public static function fromString($headerLine)
{
list($name, $value) = explode(': ', $headerLine, 2);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'origin') {
throw new Exception\InvalidArgumentException('Invalid header line for Origin string: "' . $name . '"');
}
$uri = UriFactory::factory($value);
if (! $uri->isValid()) {
throw new Exception\InvalidArgumentException('Invalid header value for Origin key: "' . $name . '"');
}
return new static($value);
}
/**
* @param string|null $value
*/
public function __construct($value = null)
{
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
}
public function getFieldName()
{
return 'Origin';
}
public function getFieldValue()
{
return (string) $this->value;
}
public function toString()
{
return 'Origin: ' . $this->getFieldValue();
}
}

View File

@@ -1,56 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
/**
* @throws Exception\InvalidArgumentException
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.32
*/
class Pragma implements HeaderInterface
{
/**
* @var string
*/
protected $value;
public static function fromString($headerLine)
{
list($name, $value) = GenericHeader::splitHeaderLine($headerLine);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'pragma') {
throw new Exception\InvalidArgumentException('Invalid header line for Pragma string: "' . $name . '"');
}
// @todo implementation details
return new static($value);
}
public function __construct($value = null)
{
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
}
public function getFieldName()
{
return 'Pragma';
}
public function getFieldValue()
{
return (string) $this->value;
}
public function toString()
{
return 'Pragma: ' . $this->getFieldValue();
}
}

View File

@@ -1,74 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
/**
* @throws Exception\InvalidArgumentException
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.33
*/
class ProxyAuthenticate implements MultipleHeaderInterface
{
/**
* @var string
*/
protected $value;
public static function fromString($headerLine)
{
list($name, $value) = GenericHeader::splitHeaderLine($headerLine);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'proxy-authenticate') {
throw new Exception\InvalidArgumentException(sprintf(
'Invalid header line for Proxy-Authenticate string: "%s"',
$name
));
}
// @todo implementation details
return new static($value);
}
public function __construct($value = null)
{
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
}
public function getFieldName()
{
return 'Proxy-Authenticate';
}
public function getFieldValue()
{
return (string) $this->value;
}
public function toString()
{
return 'Proxy-Authenticate: ' . $this->getFieldValue();
}
public function toStringMultipleHeaders(array $headers)
{
$strings = [$this->toString()];
foreach ($headers as $header) {
if (! $header instanceof ProxyAuthenticate) {
throw new Exception\RuntimeException(
'The ProxyAuthenticate multiple header implementation can only accept'
. ' an array of ProxyAuthenticate headers'
);
}
$strings[] = $header->toString();
}
return implode("\r\n", $strings);
}
}

View File

@@ -1,59 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
/**
* @throws Exception\InvalidArgumentException
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.34
*/
class ProxyAuthorization implements HeaderInterface
{
/**
* @var string
*/
protected $value;
public static function fromString($headerLine)
{
list($name, $value) = GenericHeader::splitHeaderLine($headerLine);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'proxy-authorization') {
throw new Exception\InvalidArgumentException(sprintf(
'Invalid header line for Proxy-Authorization string: "%s"',
$name
));
}
// @todo implementation details
return new static($value);
}
public function __construct($value = null)
{
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
}
public function getFieldName()
{
return 'Proxy-Authorization';
}
public function getFieldValue()
{
return (string) $this->value;
}
public function toString()
{
return 'Proxy-Authorization: ' . $this->getFieldValue();
}
}

View File

@@ -1,56 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
/**
* @throws Exception\InvalidArgumentException
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35.2
*/
class Range implements HeaderInterface
{
/**
* @var string
*/
protected $value;
public static function fromString($headerLine)
{
list($name, $value) = GenericHeader::splitHeaderLine($headerLine);
// check to ensure proper header type for this factory
if (strtolower($name) !== 'range') {
throw new Exception\InvalidArgumentException('Invalid header line for Range string: "' . $name . '"');
}
// @todo implementation details
return new static($value);
}
public function __construct($value = null)
{
if ($value !== null) {
HeaderValue::assertValid($value);
$this->value = $value;
}
}
public function getFieldName()
{
return 'Range';
}
public function getFieldValue()
{
return (string) $this->value;
}
public function toString()
{
return 'Range: ' . $this->getFieldValue();
}
}

View File

@@ -1,43 +0,0 @@
<?php
/**
* @see https://github.com/zendframework/zend-http for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-http/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Http\Header;
use Zend\Uri\Http as HttpUri;
/**
* Content-Location Header
*
* @link http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.36
*/
class Referer extends AbstractLocation
{
/**
* Set the URI/URL for this header
* according to RFC Referer URI should not have fragment
*
* @param string|HttpUri $uri
* @return $this
*/
public function setUri($uri)
{
parent::setUri($uri);
$this->uri->setFragment(null);
return $this;
}
/**
* Return header name
*
* @return string
*/
public function getFieldName()
{
return 'Referer';
}
}

Some files were not shown because too many files have changed in this diff Show More