|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 00034 class Zend_Http_Response 00035 { 00042 protected static $messages = array( 00043 // Informational 1xx 00044 100 => 'Continue', 00045 101 => 'Switching Protocols', 00046 00047 // Success 2xx 00048 200 => 'OK', 00049 201 => 'Created', 00050 202 => 'Accepted', 00051 203 => 'Non-Authoritative Information', 00052 204 => 'No Content', 00053 205 => 'Reset Content', 00054 206 => 'Partial Content', 00055 00056 // Redirection 3xx 00057 300 => 'Multiple Choices', 00058 301 => 'Moved Permanently', 00059 302 => 'Found', // 1.1 00060 303 => 'See Other', 00061 304 => 'Not Modified', 00062 305 => 'Use Proxy', 00063 // 306 is deprecated but reserved 00064 307 => 'Temporary Redirect', 00065 00066 // Client Error 4xx 00067 400 => 'Bad Request', 00068 401 => 'Unauthorized', 00069 402 => 'Payment Required', 00070 403 => 'Forbidden', 00071 404 => 'Not Found', 00072 405 => 'Method Not Allowed', 00073 406 => 'Not Acceptable', 00074 407 => 'Proxy Authentication Required', 00075 408 => 'Request Timeout', 00076 409 => 'Conflict', 00077 410 => 'Gone', 00078 411 => 'Length Required', 00079 412 => 'Precondition Failed', 00080 413 => 'Request Entity Too Large', 00081 414 => 'Request-URI Too Long', 00082 415 => 'Unsupported Media Type', 00083 416 => 'Requested Range Not Satisfiable', 00084 417 => 'Expectation Failed', 00085 00086 // Server Error 5xx 00087 500 => 'Internal Server Error', 00088 501 => 'Not Implemented', 00089 502 => 'Bad Gateway', 00090 503 => 'Service Unavailable', 00091 504 => 'Gateway Timeout', 00092 505 => 'HTTP Version Not Supported', 00093 509 => 'Bandwidth Limit Exceeded' 00094 ); 00095 00101 protected $version; 00102 00108 protected $code; 00109 00116 protected $message; 00117 00123 protected $headers = array(); 00124 00130 protected $body; 00131 00151 public function __construct($code, $headers, $body = null, $version = '1.1', $message = null) 00152 { 00153 // Make sure the response code is valid and set it 00154 if (self::responseCodeAsText($code) === null) { 00155 require_once 'Zend/Http/Exception.php'; 00156 throw new Zend_Http_Exception("{$code} is not a valid HTTP response code"); 00157 } 00158 00159 $this->code = $code; 00160 00161 // Make sure we got valid headers and set them 00162 if (! is_array($headers)) { 00163 require_once 'Zend/Http/Exception.php'; 00164 throw new Zend_Http_Exception('No valid headers were passed'); 00165 } 00166 00167 foreach ($headers as $name => $value) { 00168 if (is_int($name)) 00169 list($name, $value) = explode(": ", $value, 1); 00170 00171 $this->headers[ucwords(strtolower($name))] = $value; 00172 } 00173 00174 // Set the body 00175 $this->body = $body; 00176 00177 // Set the HTTP version 00178 if (! preg_match('|^\d\.\d$|', $version)) { 00179 require_once 'Zend/Http/Exception.php'; 00180 throw new Zend_Http_Exception("Invalid HTTP response version: $version"); 00181 } 00182 00183 $this->version = $version; 00184 00185 // If we got the response message, set it. Else, set it according to 00186 // the response code 00187 if (is_string($message)) { 00188 $this->message = $message; 00189 } else { 00190 $this->message = self::responseCodeAsText($code); 00191 } 00192 } 00193 00199 public function isError() 00200 { 00201 $restype = floor($this->code / 100); 00202 if ($restype == 4 || $restype == 5) { 00203 return true; 00204 } 00205 00206 return false; 00207 } 00208 00214 public function isSuccessful() 00215 { 00216 $restype = floor($this->code / 100); 00217 if ($restype == 2 || $restype == 1) { // Shouldn't 3xx count as success as well ??? 00218 return true; 00219 } 00220 00221 return false; 00222 } 00223 00229 public function isRedirect() 00230 { 00231 $restype = floor($this->code / 100); 00232 if ($restype == 3) { 00233 return true; 00234 } 00235 00236 return false; 00237 } 00238 00251 public function getBody() 00252 { 00253 $body = ''; 00254 00255 // Decode the body if it was transfer-encoded 00256 switch (strtolower($this->getHeader('transfer-encoding'))) { 00257 00258 // Handle chunked body 00259 case 'chunked': 00260 $body = self::decodeChunkedBody($this->body); 00261 break; 00262 00263 // No transfer encoding, or unknown encoding extension: 00264 // return body as is 00265 default: 00266 $body = $this->body; 00267 break; 00268 } 00269 00270 // Decode any content-encoding (gzip or deflate) if needed 00271 switch (strtolower($this->getHeader('content-encoding'))) { 00272 00273 // Handle gzip encoding 00274 case 'gzip': 00275 $body = self::decodeGzip($body); 00276 break; 00277 00278 // Handle deflate encoding 00279 case 'deflate': 00280 $body = self::decodeDeflate($body); 00281 break; 00282 00283 default: 00284 break; 00285 } 00286 00287 return $body; 00288 } 00289 00298 public function getRawBody() 00299 { 00300 return $this->body; 00301 } 00302 00308 public function getVersion() 00309 { 00310 return $this->version; 00311 } 00312 00318 public function getStatus() 00319 { 00320 return $this->code; 00321 } 00322 00329 public function getMessage() 00330 { 00331 return $this->message; 00332 } 00333 00339 public function getHeaders() 00340 { 00341 return $this->headers; 00342 } 00343 00350 public function getHeader($header) 00351 { 00352 $header = ucwords(strtolower($header)); 00353 if (! is_string($header) || ! isset($this->headers[$header])) return null; 00354 00355 return $this->headers[$header]; 00356 } 00357 00365 public function getHeadersAsString($status_line = true, $br = "\n") 00366 { 00367 $str = ''; 00368 00369 if ($status_line) { 00370 $str = "HTTP/{$this->version} {$this->code} {$this->message}{$br}"; 00371 } 00372 00373 // Iterate over the headers and stringify them 00374 foreach ($this->headers as $name => $value) 00375 { 00376 if (is_string($value)) 00377 $str .= "{$name}: {$value}{$br}"; 00378 00379 elseif (is_array($value)) { 00380 foreach ($value as $subval) { 00381 $str .= "{$name}: {$subval}{$br}"; 00382 } 00383 } 00384 } 00385 00386 return $str; 00387 } 00388 00395 public function asString($br = "\n") 00396 { 00397 return $this->getHeadersAsString(true, $br) . $br . $this->getRawBody(); 00398 } 00399 00405 public function __toString() 00406 { 00407 return $this->asString(); 00408 } 00409 00422 public static function responseCodeAsText($code = null, $http11 = true) 00423 { 00424 $messages = self::$messages; 00425 if (! $http11) $messages[302] = 'Moved Temporarily'; 00426 00427 if ($code === null) { 00428 return $messages; 00429 } elseif (isset($messages[$code])) { 00430 return $messages[$code]; 00431 } else { 00432 return 'Unknown'; 00433 } 00434 } 00435 00442 public static function extractCode($response_str) 00443 { 00444 preg_match("|^HTTP/[\d\.x]+ (\d+)|", $response_str, $m); 00445 00446 if (isset($m[1])) { 00447 return (int) $m[1]; 00448 } else { 00449 return false; 00450 } 00451 } 00452 00459 public static function extractMessage($response_str) 00460 { 00461 preg_match("|^HTTP/[\d\.x]+ \d+ ([^\r\n]+)|", $response_str, $m); 00462 00463 if (isset($m[1])) { 00464 return $m[1]; 00465 } else { 00466 return false; 00467 } 00468 } 00469 00476 public static function extractVersion($response_str) 00477 { 00478 preg_match("|^HTTP/([\d\.x]+) \d+|", $response_str, $m); 00479 00480 if (isset($m[1])) { 00481 return $m[1]; 00482 } else { 00483 return false; 00484 } 00485 } 00486 00493 public static function extractHeaders($response_str) 00494 { 00495 $headers = array(); 00496 00497 // First, split body and headers 00498 $parts = preg_split('|(?:\r?\n){2}|m', $response_str, 2); 00499 if (! $parts[0]) return $headers; 00500 00501 // Split headers part to lines 00502 $lines = explode("\n", $parts[0]); 00503 unset($parts); 00504 $last_header = null; 00505 00506 foreach($lines as $line) { 00507 $line = trim($line, "\r\n"); 00508 if ($line == "") break; 00509 00510 if (preg_match("|^([\w-]+):\s+(.+)|", $line, $m)) { 00511 unset($last_header); 00512 $h_name = strtolower($m[1]); 00513 $h_value = $m[2]; 00514 00515 if (isset($headers[$h_name])) { 00516 if (! is_array($headers[$h_name])) { 00517 $headers[$h_name] = array($headers[$h_name]); 00518 } 00519 00520 $headers[$h_name][] = $h_value; 00521 } else { 00522 $headers[$h_name] = $h_value; 00523 } 00524 $last_header = $h_name; 00525 } elseif (preg_match("|^\s+(.+)$|", $line, $m) && $last_header !== null) { 00526 if (is_array($headers[$last_header])) { 00527 end($headers[$last_header]); 00528 $last_header_key = key($headers[$last_header]); 00529 $headers[$last_header][$last_header_key] .= $m[1]; 00530 } else { 00531 $headers[$last_header] .= $m[1]; 00532 } 00533 } 00534 } 00535 00536 return $headers; 00537 } 00538 00545 public static function extractBody($response_str) 00546 { 00547 $parts = preg_split('|(?:\r?\n){2}|m', $response_str, 2); 00548 if (isset($parts[1])) { 00549 return $parts[1]; 00550 } 00551 return ''; 00552 } 00553 00560 public static function decodeChunkedBody($body) 00561 { 00562 $decBody = ''; 00563 00564 // If mbstring overloads substr and strlen functions, we have to 00565 // override it's internal encoding 00566 if (function_exists('mb_internal_encoding') && 00567 ((int) ini_get('mbstring.func_overload')) & 2) { 00568 00569 $mbIntEnc = mb_internal_encoding(); 00570 mb_internal_encoding('ASCII'); 00571 } 00572 00573 while (trim($body)) { 00574 if (! preg_match("/^([\da-fA-F]+)[^\r\n]*\r\n/sm", $body, $m)) { 00575 require_once 'Zend/Http/Exception.php'; 00576 throw new Zend_Http_Exception("Error parsing body - doesn't seem to be a chunked message"); 00577 } 00578 00579 $length = hexdec(trim($m[1])); 00580 $cut = strlen($m[0]); 00581 $decBody .= substr($body, $cut, $length); 00582 $body = substr($body, $cut + $length + 2); 00583 } 00584 00585 if (isset($mbIntEnc)) { 00586 mb_internal_encoding($mbIntEnc); 00587 } 00588 00589 return $decBody; 00590 } 00591 00600 public static function decodeGzip($body) 00601 { 00602 if (! function_exists('gzinflate')) { 00603 require_once 'Zend/Http/Exception.php'; 00604 throw new Zend_Http_Exception( 00605 'zlib extension is required in order to decode "gzip" encoding' 00606 ); 00607 } 00608 00609 return gzinflate(substr($body, 10)); 00610 } 00611 00620 public static function decodeDeflate($body) 00621 { 00622 if (! function_exists('gzuncompress')) { 00623 require_once 'Zend/Http/Exception.php'; 00624 throw new Zend_Http_Exception( 00625 'zlib extension is required in order to decode "deflate" encoding' 00626 ); 00627 } 00628 00640 $zlibHeader = unpack('n', substr($body, 0, 2)); 00641 if ($zlibHeader[1] % 31 == 0) { 00642 return gzuncompress($body); 00643 } else { 00644 return gzinflate($body); 00645 } 00646 } 00647 00654 public static function fromString($response_str) 00655 { 00656 $code = self::extractCode($response_str); 00657 $headers = self::extractHeaders($response_str); 00658 $body = self::extractBody($response_str); 00659 $version = self::extractVersion($response_str); 00660 $message = self::extractMessage($response_str); 00661 00662 return new Zend_Http_Response($code, $headers, $body, $version, $message); 00663 } 00664 }