comparison vendor/zendframework/zend-diactoros/src/AbstractSerializer.php @ 0:c75dbcec494b

Initial commit from drush-created site
author Chris Cannam
date Thu, 05 Jul 2018 14:24:15 +0000
parents
children 5311817fb629
comparison
equal deleted inserted replaced
-1:000000000000 0:c75dbcec494b
1 <?php
2 /**
3 * Zend Framework (http://framework.zend.com/)
4 *
5 * @see http://github.com/zendframework/zend-diactoros for the canonical source repository
6 * @copyright Copyright (c) 2015-2016 Zend Technologies USA Inc. (http://www.zend.com)
7 * @license https://github.com/zendframework/zend-diactoros/blob/master/LICENSE.md New BSD License
8 */
9
10 namespace Zend\Diactoros;
11
12 use Psr\Http\Message\StreamInterface;
13 use UnexpectedValueException;
14
15 /**
16 * Provides base functionality for request and response de/serialization
17 * strategies, including functionality for retrieving a line at a time from
18 * the message, splitting headers from the body, and serializing headers.
19 */
20 abstract class AbstractSerializer
21 {
22 const CR = "\r";
23 const EOL = "\r\n";
24 const LF = "\n";
25
26 /**
27 * Retrieve a single line from the stream.
28 *
29 * Retrieves a line from the stream; a line is defined as a sequence of
30 * characters ending in a CRLF sequence.
31 *
32 * @param StreamInterface $stream
33 * @return string
34 * @throws UnexpectedValueException if the sequence contains a CR or LF in
35 * isolation, or ends in a CR.
36 */
37 protected static function getLine(StreamInterface $stream)
38 {
39 $line = '';
40 $crFound = false;
41 while (! $stream->eof()) {
42 $char = $stream->read(1);
43
44 if ($crFound && $char === self::LF) {
45 $crFound = false;
46 break;
47 }
48
49 // CR NOT followed by LF
50 if ($crFound && $char !== self::LF) {
51 throw new UnexpectedValueException('Unexpected carriage return detected');
52 }
53
54 // LF in isolation
55 if (! $crFound && $char === self::LF) {
56 throw new UnexpectedValueException('Unexpected line feed detected');
57 }
58
59 // CR found; do not append
60 if ($char === self::CR) {
61 $crFound = true;
62 continue;
63 }
64
65 // Any other character: append
66 $line .= $char;
67 }
68
69 // CR found at end of stream
70 if ($crFound) {
71 throw new UnexpectedValueException("Unexpected end of headers");
72 }
73
74 return $line;
75 }
76
77 /**
78 * Split the stream into headers and body content.
79 *
80 * Returns an array containing two elements
81 *
82 * - The first is an array of headers
83 * - The second is a StreamInterface containing the body content
84 *
85 * @param StreamInterface $stream
86 * @return array
87 * @throws UnexpectedValueException For invalid headers.
88 */
89 protected static function splitStream(StreamInterface $stream)
90 {
91 $headers = [];
92 $currentHeader = false;
93
94 while ($line = self::getLine($stream)) {
95 if (preg_match(';^(?P<name>[!#$%&\'*+.^_`\|~0-9a-zA-Z-]+):(?P<value>.*)$;', $line, $matches)) {
96 $currentHeader = $matches['name'];
97 if (! isset($headers[$currentHeader])) {
98 $headers[$currentHeader] = [];
99 }
100 $headers[$currentHeader][] = ltrim($matches['value']);
101 continue;
102 }
103
104 if (! $currentHeader) {
105 throw new UnexpectedValueException('Invalid header detected');
106 }
107
108 if (! preg_match('#^[ \t]#', $line)) {
109 throw new UnexpectedValueException('Invalid header continuation');
110 }
111
112 // Append continuation to last header value found
113 $value = array_pop($headers[$currentHeader]);
114 $headers[$currentHeader][] = $value . ltrim($line);
115 }
116
117 // use RelativeStream to avoid copying initial stream into memory
118 return [$headers, new RelativeStream($stream, $stream->tell())];
119 }
120
121 /**
122 * Serialize headers to string values.
123 *
124 * @param array $headers
125 * @return string
126 */
127 protected static function serializeHeaders(array $headers)
128 {
129 $lines = [];
130 foreach ($headers as $header => $values) {
131 $normalized = self::filterHeader($header);
132 foreach ($values as $value) {
133 $lines[] = sprintf('%s: %s', $normalized, $value);
134 }
135 }
136
137 return implode("\r\n", $lines);
138 }
139
140 /**
141 * Filter a header name to wordcase
142 *
143 * @param string $header
144 * @return string
145 */
146 protected static function filterHeader($header)
147 {
148 $filtered = str_replace('-', ' ', $header);
149 $filtered = ucwords($filtered);
150 return str_replace(' ', '-', $filtered);
151 }
152 }