| 135 | | $readLength = 4096; |
|---|
| 136 | | } |
|---|
| 137 | | |
|---|
| 138 | | if (self::STATUS_CLASS_SUCCESS == $this->getType(self::TYPE_STATUS_CLASS)) { |
|---|
| 139 | | // if server sends chunked data |
|---|
| 140 | | if ($this->headers->containsKey('Transfer-Encoding') === true && $this->headers->get('Transfer-Encoding') === 'chunked') { |
|---|
| 141 | | // it gets a little bit more complicated because we can not read the data in a whole |
|---|
| 142 | | // the following lines implement the pseudo code given in RFC 2616 section 19.4.6: Introduction of Transfer-Encoding |
|---|
| 143 | | $readLength = 0; |
|---|
| 144 | | $chunksize = null; |
|---|
| 145 | | $extension = null; |
|---|
| 146 | | // read chunk-size, chunk-extension (if any) and CRLF |
|---|
| 147 | | sscanf($this->socket->read(1024), "%x%s\r\n", $chunksize, $extension); |
|---|
| 148 | | |
|---|
| 149 | | while (0 < $chunksize) { |
|---|
| 150 | | // read chunk-data and CRLF |
|---|
| 151 | | $data = $this->socket->readBinary($chunksize + 2); |
|---|
| 152 | | // append chunk-data to entity-body |
|---|
| 153 | | $this->body .= rtrim($data); |
|---|
| 154 | | $readLength = $readLength + $chunksize; |
|---|
| 155 | | // read chunk-size and CRLF |
|---|
| 156 | | sscanf($this->socket->read(1024), "%x\r\n", $chunksize); |
|---|
| 157 | | } |
|---|
| 158 | | |
|---|
| 159 | | #read entity-header |
|---|
| 160 | | #while (entity-header not empty) { |
|---|
| 161 | | # append entity-header to existing header fields |
|---|
| 162 | | # read entity-header |
|---|
| 163 | | #} |
|---|
| 164 | | |
|---|
| 165 | | // set correct content length |
|---|
| 166 | | $this->headers->put('Content-Length', $readLength); |
|---|
| 167 | | // remove "chunked" from Transfer-Encoding |
|---|
| 168 | | $this->headers->remove('Transfer-Encoding'); |
|---|
| 169 | | } else { |
|---|
| 170 | | // no chunked data, we just read all that we can get until we reach the end of data |
|---|
| 171 | | while ($this->socket->eof() === false) { |
|---|
| 172 | | $this->body .= $this->socket->read($readLength); |
|---|
| 173 | | } |
|---|
| 174 | | } |
|---|
| 175 | | } |
|---|
| | 135 | $this->body = $this->readDefault($this->headers->get('Content-Length', 4096)); |
|---|
| | 136 | } |
|---|
| | 137 | } |
|---|
| | 138 | |
|---|
| | 139 | /** |
|---|
| | 140 | * helper method to read chunked response body |
|---|
| | 141 | * |
|---|
| | 142 | * @return string |
|---|
| | 143 | */ |
|---|
| | 144 | protected function readChunked() |
|---|
| | 145 | { |
|---|
| | 146 | // it gets a little bit more complicated because we can not read the data in a whole |
|---|
| | 147 | // the following lines implement the pseudo code given in RFC 2616 section 19.4.6: Introduction of Transfer-Encoding |
|---|
| | 148 | $readLength = 0; |
|---|
| | 149 | $chunksize = null; |
|---|
| | 150 | $extension = null; |
|---|
| | 151 | $body = ''; |
|---|
| | 152 | // read chunk-size, chunk-extension (if any) and CRLF |
|---|
| | 153 | sscanf($this->socket->read(1024), "%x%s\r\n", $chunksize, $extension); |
|---|
| | 154 | while (0 < $chunksize) { |
|---|
| | 155 | // read chunk-data and CRLF |
|---|
| | 156 | $data = $this->socket->readBinary($chunksize + 2); |
|---|
| | 157 | // append chunk-data to entity-body |
|---|
| | 158 | $body .= rtrim($data); |
|---|
| | 159 | $readLength += $chunksize; |
|---|
| | 160 | // read chunk-size and CRLF |
|---|
| | 161 | sscanf($this->socket->read(1024), "%x\r\n", $chunksize); |
|---|
| | 162 | } |
|---|
| | 163 | |
|---|
| | 164 | #read entity-header |
|---|
| | 165 | #while (entity-header not empty) { |
|---|
| | 166 | # append entity-header to existing header fields |
|---|
| | 167 | # read entity-header |
|---|
| | 168 | #} |
|---|
| | 169 | |
|---|
| | 170 | // set correct content length |
|---|
| | 171 | $this->headers->put('Content-Length', $readLength); |
|---|
| | 172 | // remove "chunked" from Transfer-Encoding |
|---|
| | 173 | $this->headers->remove('Transfer-Encoding'); |
|---|
| | 174 | return $body; |
|---|
| | 175 | } |
|---|
| | 176 | |
|---|
| | 177 | /** |
|---|
| | 178 | * helper method for default reading of response body |
|---|
| | 179 | * |
|---|
| | 180 | * @param int $readLength expected length of response body |
|---|
| | 181 | * @return string |
|---|
| | 182 | */ |
|---|
| | 183 | protected function readDefault($readLength) |
|---|
| | 184 | { |
|---|
| | 185 | $body = ''; |
|---|
| | 186 | while ($this->socket->eof() === false) { |
|---|
| | 187 | $body .= $this->socket->read($readLength); |
|---|
| | 188 | } |
|---|
| | 189 | |
|---|
| | 190 | return $body; |
|---|
| 252 | | if (preg_match('=^(HTTP/\d+\.\d+) (\d{3}) ([^' . stubHTTPConnection::END_OF_LINE . ']*)=', $head, $matches) !== false) { |
|---|
| 253 | | $this->response[self::TYPE_STATUS_LINE] = $matches[0]; |
|---|
| 254 | | $this->response[self::TYPE_HTTP_VERSION] = $matches[1]; |
|---|
| 255 | | $this->response[self::TYPE_STATUS_CODE] = $matches[2]; |
|---|
| 256 | | $this->response[self::TYPE_REASON_PHRASE] = $matches[3]; |
|---|
| 257 | | switch ($this->response[self::TYPE_STATUS_CODE][0]) { |
|---|
| 258 | | case 1: |
|---|
| 259 | | $this->response[self::TYPE_STATUS_CLASS] = self::STATUS_CLASS_INFO; |
|---|
| 260 | | break; |
|---|
| 261 | | |
|---|
| 262 | | case 2: |
|---|
| 263 | | $this->response[self::TYPE_STATUS_CLASS] = self::STATUS_CLASS_SUCCESS; |
|---|
| 264 | | break; |
|---|
| 265 | | |
|---|
| 266 | | case 3: |
|---|
| 267 | | $this->response[self::TYPE_STATUS_CLASS] = self::STATUS_CLASS_REDIRECT; |
|---|
| 268 | | break; |
|---|
| 269 | | |
|---|
| 270 | | case 4: |
|---|
| 271 | | $this->response[self::TYPE_STATUS_CLASS] = self::STATUS_CLASS_ERROR_CLIENT; |
|---|
| 272 | | break; |
|---|
| 273 | | |
|---|
| 274 | | case 5: |
|---|
| 275 | | $this->response[self::TYPE_STATUS_CLASS] = self::STATUS_CLASS_ERROR_SERVER; |
|---|
| 276 | | break; |
|---|
| 277 | | |
|---|
| 278 | | default: |
|---|
| 279 | | $this->response[self::TYPE_STATUS_CLASS] = self::STATUS_CLASS_UNKNOWN; |
|---|
| 280 | | } |
|---|
| | 267 | if (preg_match('=^(HTTP/\d+\.\d+) (\d{3}) ([^' . stubHTTPConnection::END_OF_LINE . ']*)=', $head, $matches) == false) { |
|---|
| | 268 | return; |
|---|
| | 269 | } |
|---|
| | 270 | |
|---|
| | 271 | $this->response[self::TYPE_STATUS_LINE] = $matches[0]; |
|---|
| | 272 | $this->response[self::TYPE_HTTP_VERSION] = $matches[1]; |
|---|
| | 273 | $this->response[self::TYPE_STATUS_CODE] = $matches[2]; |
|---|
| | 274 | $this->response[self::TYPE_REASON_PHRASE] = $matches[3]; |
|---|
| | 275 | switch ($this->response[self::TYPE_STATUS_CODE][0]) { |
|---|
| | 276 | case 1: |
|---|
| | 277 | $this->response[self::TYPE_STATUS_CLASS] = self::STATUS_CLASS_INFO; |
|---|
| | 278 | break; |
|---|
| | 279 | |
|---|
| | 280 | case 2: |
|---|
| | 281 | $this->response[self::TYPE_STATUS_CLASS] = self::STATUS_CLASS_SUCCESS; |
|---|
| | 282 | break; |
|---|
| | 283 | |
|---|
| | 284 | case 3: |
|---|
| | 285 | $this->response[self::TYPE_STATUS_CLASS] = self::STATUS_CLASS_REDIRECT; |
|---|
| | 286 | break; |
|---|
| | 287 | |
|---|
| | 288 | case 4: |
|---|
| | 289 | $this->response[self::TYPE_STATUS_CLASS] = self::STATUS_CLASS_ERROR_CLIENT; |
|---|
| | 290 | break; |
|---|
| | 291 | |
|---|
| | 292 | case 5: |
|---|
| | 293 | $this->response[self::TYPE_STATUS_CLASS] = self::STATUS_CLASS_ERROR_SERVER; |
|---|
| | 294 | break; |
|---|
| | 295 | |
|---|
| | 296 | default: |
|---|
| | 297 | $this->response[self::TYPE_STATUS_CLASS] = self::STATUS_CLASS_UNKNOWN; |
|---|