1 <?php
2
3 4 5 6 7 8 9
10 class rex_socket_response
11 {
12 private $stream;
13 private $chunked = false;
14 private $chunkPos = 0;
15 private $chunkLength = 0;
16 private $statusCode;
17 private $statusMessage;
18 private = '';
19 private = [];
20 private $body;
21
22 23 24 25 26 27 28
29 public function __construct($stream)
30 {
31 if (!is_resource($stream)) {
32 throw new InvalidArgumentException(sprintf('Expecting $stream to be a resource, but %s given!', gettype($stream)));
33 }
34
35 $this->stream = $stream;
36
37 while (!feof($this->stream) && strpos($this->header, "\r\n\r\n") === false) {
38 $this->header .= fgets($this->stream);
39 }
40 $this->header = rtrim($this->header);
41 if (preg_match('@^HTTP/1\.\d ([0-9]+) (\V+)@', $this->header, $matches)) {
42 $this->statusCode = (int) ($matches[1]);
43 $this->statusMessage = $matches[2];
44 }
45 $this->chunked = stripos($this->header, 'transfer-encoding: chunked') !== false;
46 }
47
48 49 50 51 52
53 public function getStatusCode()
54 {
55 return $this->statusCode;
56 }
57
58 59 60 61 62
63 public function getStatusMessage()
64 {
65 return $this->statusMessage;
66 }
67
68 69 70 71 72
73 public function isOk()
74 {
75 return $this->statusCode == 200;
76 }
77
78 79 80 81 82
83 public function isInformational()
84 {
85 return $this->statusCode >= 100 && $this->statusCode < 200;
86 }
87
88 89 90 91 92
93 public function isSuccessful()
94 {
95 return $this->statusCode >= 200 && $this->statusCode < 300;
96 }
97
98 99 100 101 102
103 public function isRedirection()
104 {
105 return $this->statusCode >= 300 && $this->statusCode < 400;
106 }
107
108 109 110 111 112
113 public function isClientError()
114 {
115 return $this->statusCode >= 400 && $this->statusCode < 500;
116 }
117
118 119 120 121 122
123 public function isServerError()
124 {
125 return $this->statusCode >= 500 && $this->statusCode < 600;
126 }
127
128 129 130 131 132
133 public function isInvalid()
134 {
135 return $this->statusCode < 100 || $this->statusCode >= 600;
136 }
137
138 139 140 141 142 143 144 145
146 public function ($key = null, $default = null)
147 {
148 if ($key === null) {
149 return $this->header;
150 }
151 $key = strtolower($key);
152 if (isset($this->headers[$key])) {
153 return $this->headers[$key];
154 }
155 if (preg_match('@^' . preg_quote($key, '@') . ': (\V*)@im', $this->header, $matches)) {
156 return $this->headers[$key] = $matches[1];
157 }
158 return $this->headers[$key] = $default;
159 }
160
161 162 163 164 165 166 167
168 public function getBufferedBody($length = 1024)
169 {
170 if (feof($this->stream)) {
171 return false;
172 }
173 if ($this->chunked) {
174 if ($this->chunkPos == 0) {
175 $this->chunkLength = hexdec(fgets($this->stream));
176 if ($this->chunkLength == 0) {
177 return false;
178 }
179 }
180 $pos = ftell($this->stream);
181 $buf = fread($this->stream, min($length, $this->chunkLength - $this->chunkPos));
182 $this->chunkPos += ftell($this->stream) - $pos;
183 if ($this->chunkPos >= $this->chunkLength) {
184 fgets($this->stream);
185 $this->chunkPos = 0;
186 $this->chunkLength = 0;
187 }
188 return $buf;
189 }
190 return fread($this->stream, $length);
191 }
192
193 194 195 196 197
198 public function getBody()
199 {
200 if ($this->body === null) {
201 while (($buf = $this->getBufferedBody()) !== false) {
202 $this->body .= $buf;
203 }
204 }
205 return $this->body;
206 }
207
208 209 210 211 212 213 214
215 public function writeBodyTo($resource)
216 {
217 $close = false;
218 if (is_string($resource) && rex_dir::create(dirname($resource))) {
219 $resource = fopen($resource, 'w');
220 $close = true;
221 }
222 if (!is_resource($resource)) {
223 return false;
224 }
225 $success = true;
226 while ($success && ($buf = $this->getBufferedBody()) !== false) {
227 $success = (bool) fwrite($resource, $buf);
228 }
229 if ($close) {
230 fclose($resource);
231 }
232 return $success;
233 }
234 }
235