예제 #1
0
 private static function GetResponse($fp, $debug, $options, $startts, $timeout)
 {
     $recvstart = microtime(true);
     $rawdata = $data = "";
     $rawsize = $rawrecvheadersize = 0;
     do {
         $autodecode = !isset($options["auto_decode"]) || $options["auto_decode"];
         // Process the response line.
         while (strpos($data, "\n") === false && ($data2 = fgets($fp, 116000)) !== false) {
             if (self::StreamTimedOut($fp)) {
                 return array("success" => false, "error" => self::HTTPTranslate("Underlying stream timed out."), "errorcode" => "stream_timeout_exceeded");
             }
             if ($timeout !== false && self::GetTimeLeft($startts, $timeout) == 0) {
                 return array("success" => false, "error" => self::HTTPTranslate("HTTP timeout exceeded."), "errorcode" => "timeout_exceeded");
             }
             $rawsize += strlen($data2);
             $data .= $data2;
             if (isset($options["recvratelimit"])) {
                 self::ProcessRateLimit($rawsize, $recvstart, $options["recvratelimit"]);
             }
             if (isset($options["debug_callback"])) {
                 $options["debug_callback"]("rawrecv", $data2, $options["debug_callback_opts"]);
             } else {
                 if ($debug) {
                     $rawdata .= $data2;
                 }
             }
             if (feof($fp)) {
                 break;
             }
         }
         if (self::StreamTimedOut($fp)) {
             return array("success" => false, "error" => self::HTTPTranslate("Underlying stream timed out."), "errorcode" => "stream_timeout_exceeded");
         }
         $pos = strpos($data, "\n");
         if ($pos === false) {
             return array("success" => false, "error" => self::HTTPTranslate("Unable to retrieve response line."), "errorcode" => "get_response_line");
         }
         $line = trim(substr($data, 0, $pos));
         $data = substr($data, $pos + 1);
         $rawrecvheadersize += $pos + 1;
         $response = explode(" ", $line, 3);
         $response = array("line" => $line, "httpver" => strtoupper($response[0]), "code" => $response[1], "meaning" => $response[2]);
         // Process the headers.
         $headers = array();
         $lastheader = "";
         do {
             while (strpos($data, "\n") === false && ($data2 = fgets($fp, 116000)) !== false) {
                 if (self::StreamTimedOut($fp)) {
                     return array("success" => false, "error" => self::HTTPTranslate("Underlying stream timed out."), "errorcode" => "stream_timeout_exceeded");
                 }
                 if ($timeout !== false && self::GetTimeLeft($startts, $timeout) == 0) {
                     return array("success" => false, "error" => self::HTTPTranslate("HTTP timeout exceeded."), "errorcode" => "timeout_exceeded");
                 }
                 $rawsize += strlen($data2);
                 $data .= $data2;
                 if (isset($options["recvratelimit"])) {
                     self::ProcessRateLimit($rawsize, $recvstart, $options["recvratelimit"]);
                 }
                 if (isset($options["debug_callback"])) {
                     $options["debug_callback"]("rawrecv", $data2, $options["debug_callback_opts"]);
                 } else {
                     if ($debug) {
                         $rawdata .= $data2;
                     }
                 }
                 if (feof($fp)) {
                     break;
                 }
             }
             if (self::StreamTimedOut($fp)) {
                 return array("success" => false, "error" => self::HTTPTranslate("Underlying stream timed out."), "errorcode" => "stream_timeout_exceeded");
             }
             $pos = strpos($data, "\n");
             if ($pos === false) {
                 $pos = strlen($data);
             }
             $header = rtrim(substr($data, 0, $pos));
             $data = substr($data, $pos + 1);
             $rawrecvheadersize += $pos + 1;
             if ($header != "") {
                 if ($lastheader != "" && (substr($header, 0, 1) == " " || substr($header, 0, 1) == "\t")) {
                     $headers[$lastheader][count($headers[$lastheader]) - 1] .= $header;
                 } else {
                     $pos = strpos($header, ":");
                     if ($pos === false) {
                         $pos = strlen($header);
                     }
                     $lastheader = self::HeaderNameCleanup(substr($header, 0, $pos));
                     if (!isset($headers[$lastheader])) {
                         $headers[$lastheader] = array();
                     }
                     $headers[$lastheader][] = ltrim(substr($header, $pos + 1));
                 }
             }
         } while ($header != "");
         if ($response["code"] != 100 && isset($options["read_headers_callback"])) {
             if (!$options["read_headers_callback"]($response, $headers, $options["read_headers_callback_opts"])) {
                 return array("success" => false, "error" => self::HTTPTranslate("Read headers callback returned with a failure condition."), "errorcode" => "read_header_callback");
             }
         }
         $body = "";
         // Handle WebSocket among other things.
         if ($response["code"] == 101) {
             break;
         }
         // Determine if decoding the content is possible and necessary.
         if ($autodecode && !isset($headers["Content-Encoding"]) || strtolower($headers["Content-Encoding"][0]) != "gzip" && strtolower($headers["Content-Encoding"][0]) != "deflate") {
             $autodecode = false;
         }
         if (!$autodecode) {
             $autodecode_ds = false;
         } else {
             require_once str_replace("\\", "/", dirname(__FILE__)) . "/deflate_stream.php";
             // Since servers and browsers do everything wrong, ignore the encoding claim and attempt to auto-detect the encoding.
             $autodecode_ds = new DeflateStream();
             $autodecode_ds->Init("rb", -1, array("type" => "auto"));
         }
         // Process the body.
         if (isset($headers["Transfer-Encoding"]) && strtolower($headers["Transfer-Encoding"][0]) == "chunked") {
             do {
                 // Calculate the next chunked size and ignore chunked extensions.
                 while (strpos($data, "\n") === false && ($data2 = fgets($fp, 116000)) !== false) {
                     if (self::StreamTimedOut($fp)) {
                         return array("success" => false, "error" => self::HTTPTranslate("Underlying stream timed out."), "errorcode" => "stream_timeout_exceeded");
                     }
                     if ($timeout !== false && self::GetTimeLeft($startts, $timeout) == 0) {
                         return array("success" => false, "error" => self::HTTPTranslate("HTTP timeout exceeded."), "errorcode" => "timeout_exceeded");
                     }
                     $rawsize += strlen($data2);
                     $data .= $data2;
                     if (isset($options["recvratelimit"])) {
                         self::ProcessRateLimit($rawsize, $recvstart, $options["recvratelimit"]);
                     }
                     if (isset($options["debug_callback"])) {
                         $options["debug_callback"]("rawrecv", $data2, $options["debug_callback_opts"]);
                     } else {
                         if ($debug) {
                             $rawdata .= $data2;
                         }
                     }
                     if (feof($fp)) {
                         break;
                     }
                 }
                 if (self::StreamTimedOut($fp)) {
                     return array("success" => false, "error" => self::HTTPTranslate("Underlying stream timed out."), "errorcode" => "stream_timeout_exceeded");
                 }
                 $pos = strpos($data, "\n");
                 if ($pos === false) {
                     $pos = strlen($data);
                 }
                 $line = trim(substr($data, 0, $pos));
                 $data = substr($data, $pos + 1);
                 $pos = strpos($line, ";");
                 if ($pos === false) {
                     $pos = strlen($line);
                 }
                 $size = hexdec(substr($line, 0, $pos));
                 if ($size < 0) {
                     $size = 0;
                 }
                 // Retrieve content.
                 $size2 = $size;
                 $size3 = min(strlen($data), $size);
                 if ($size3 > 0) {
                     $data2 = substr($data, 0, $size3);
                     $data = substr($data, $size3);
                     $size2 -= $size3;
                     if ($response["code"] == 100 || !isset($options["read_body_callback"])) {
                         $body .= self::GetDecodedBody($autodecode_ds, $data2);
                     } else {
                         if (!$options["read_body_callback"]($response, self::GetDecodedBody($autodecode_ds, $data2), $options["read_body_callback_opts"])) {
                             return array("success" => false, "error" => self::HTTPTranslate("Read body callback returned with a failure condition."), "errorcode" => "read_body_callback");
                         }
                     }
                 }
                 while ($size2 > 0 && ($data2 = fread($fp, $size2 > 65536 ? 65536 : $size2)) !== false) {
                     if (self::StreamTimedOut($fp)) {
                         return array("success" => false, "error" => self::HTTPTranslate("Underlying stream timed out."), "errorcode" => "stream_timeout_exceeded");
                     }
                     if ($timeout !== false && self::GetTimeLeft($startts, $timeout) == 0) {
                         return array("success" => false, "error" => self::HTTPTranslate("HTTP timeout exceeded."), "errorcode" => "timeout_exceeded");
                     }
                     $tempsize = strlen($data2);
                     $rawsize += $tempsize;
                     $size2 -= $tempsize;
                     if ($response["code"] == 100 || !isset($options["read_body_callback"])) {
                         $body .= self::GetDecodedBody($autodecode_ds, $data2);
                     } else {
                         if (!$options["read_body_callback"]($response, self::GetDecodedBody($autodecode_ds, $data2), $options["read_body_callback_opts"])) {
                             return array("success" => false, "error" => self::HTTPTranslate("Read body callback returned with a failure condition."), "errorcode" => "read_body_callback");
                         }
                     }
                     if (isset($options["recvratelimit"])) {
                         self::ProcessRateLimit($rawsize, $recvstart, $options["recvratelimit"]);
                     }
                     if (isset($options["debug_callback"])) {
                         $options["debug_callback"]("rawrecv", $data2, $options["debug_callback_opts"]);
                     } else {
                         if ($debug) {
                             $rawdata .= $data2;
                         }
                     }
                     if (feof($fp)) {
                         break;
                     }
                 }
                 if (self::StreamTimedOut($fp)) {
                     return array("success" => false, "error" => self::HTTPTranslate("Underlying stream timed out."), "errorcode" => "stream_timeout_exceeded");
                 }
                 // Ignore one newline.
                 while (strpos($data, "\n") === false && ($data2 = fgets($fp, 116000)) !== false) {
                     if (self::StreamTimedOut($fp)) {
                         return array("success" => false, "error" => self::HTTPTranslate("Underlying stream timed out."), "errorcode" => "stream_timeout_exceeded");
                     }
                     if ($timeout !== false && self::GetTimeLeft($startts, $timeout) == 0) {
                         return array("success" => false, "error" => self::HTTPTranslate("HTTP timeout exceeded."), "errorcode" => "timeout_exceeded");
                     }
                     $rawsize += strlen($data2);
                     $data .= $data2;
                     if (isset($options["recvratelimit"])) {
                         self::ProcessRateLimit($rawsize, $recvstart, $options["recvratelimit"]);
                     }
                     if (isset($options["debug_callback"])) {
                         $options["debug_callback"]("rawrecv", $data2, $options["debug_callback_opts"]);
                     } else {
                         if ($debug) {
                             $rawdata .= $data2;
                         }
                     }
                     if (feof($fp)) {
                         break;
                     }
                 }
                 if (self::StreamTimedOut($fp)) {
                     return array("success" => false, "error" => self::HTTPTranslate("Underlying stream timed out."), "errorcode" => "stream_timeout_exceeded");
                 }
                 $pos = strpos($data, "\n");
                 if ($pos === false) {
                     $pos = strlen($data);
                 }
                 $data = substr($data, $pos + 1);
             } while ($size);
             // Process additional headers.
             $lastheader = "";
             do {
                 while (strpos($data, "\n") === false && ($data2 = fgets($fp, 116000)) !== false) {
                     if (self::StreamTimedOut($fp)) {
                         return array("success" => false, "error" => self::HTTPTranslate("Underlying stream timed out."), "errorcode" => "stream_timeout_exceeded");
                     }
                     if ($timeout !== false && self::GetTimeLeft($startts, $timeout) == 0) {
                         return array("success" => false, "error" => self::HTTPTranslate("HTTP timeout exceeded."), "errorcode" => "timeout_exceeded");
                     }
                     $rawsize += strlen($data2);
                     $data .= $data2;
                     if (isset($options["recvratelimit"])) {
                         self::ProcessRateLimit($rawsize, $recvstart, $options["recvratelimit"]);
                     }
                     if (isset($options["debug_callback"])) {
                         $options["debug_callback"]("rawrecv", $data2, $options["debug_callback_opts"]);
                     } else {
                         if ($debug) {
                             $rawdata .= $data2;
                         }
                     }
                     if (feof($fp)) {
                         break;
                     }
                 }
                 if (self::StreamTimedOut($fp)) {
                     return array("success" => false, "error" => self::HTTPTranslate("Underlying stream timed out."), "errorcode" => "stream_timeout_exceeded");
                 }
                 $pos = strpos($data, "\n");
                 if ($pos === false) {
                     $pos = strlen($data);
                 }
                 $header = rtrim(substr($data, 0, $pos));
                 $data = substr($data, $pos + 1);
                 $rawrecvheadersize += $pos + 1;
                 if ($header != "") {
                     if ($lastheader != "" && (substr($header, 0, 1) == " " || substr($header, 0, 1) == "\t")) {
                         $headers[$lastheader][count($headers[$lastheader]) - 1] .= $header;
                     } else {
                         $pos = strpos($header, ":");
                         if ($pos === false) {
                             $pos = strlen($header);
                         }
                         $lastheader = self::HeaderNameCleanup(substr($header, 0, $pos));
                         if (!isset($headers[$lastheader])) {
                             $headers[$lastheader] = array();
                         }
                         $headers[$lastheader][] = ltrim(substr($header, $pos + 1));
                     }
                 }
             } while ($header != "");
             if ($response["code"] != 100 && isset($options["read_headers_callback"])) {
                 if (!$options["read_headers_callback"]($response, $headers, $options["read_headers_callback_opts"])) {
                     return array("success" => false, "error" => self::HTTPTranslate("Read headers callback returned with a failure condition."), "errorcode" => "read_header_callback");
                 }
             }
         } else {
             if (isset($headers["Content-Length"])) {
                 $size = (int) $headers["Content-Length"][0];
                 $datasize = 0;
                 while ($datasize < $size && ($data2 = fread($fp, $size > 65536 ? 65536 : $size)) !== false) {
                     if (self::StreamTimedOut($fp)) {
                         return array("success" => false, "error" => self::HTTPTranslate("Underlying stream timed out."), "errorcode" => "stream_timeout_exceeded");
                     }
                     if ($timeout !== false && self::GetTimeLeft($startts, $timeout) == 0) {
                         return array("success" => false, "error" => self::HTTPTranslate("HTTP timeout exceeded."), "errorcode" => "timeout_exceeded");
                     }
                     $tempsize = strlen($data2);
                     $datasize += $tempsize;
                     $rawsize += $tempsize;
                     if ($response["code"] == 100 || !isset($options["read_body_callback"])) {
                         $body .= self::GetDecodedBody($autodecode_ds, $data2);
                     } else {
                         if (!$options["read_body_callback"]($response, self::GetDecodedBody($autodecode_ds, $data2), $options["read_body_callback_opts"])) {
                             return array("success" => false, "error" => self::HTTPTranslate("Read body callback returned with a failure condition."), "errorcode" => "read_body_callback");
                         }
                     }
                     if (isset($options["recvratelimit"])) {
                         self::ProcessRateLimit($rawsize, $recvstart, $options["recvratelimit"]);
                     }
                     if (isset($options["debug_callback"])) {
                         $options["debug_callback"]("rawrecv", $data2, $options["debug_callback_opts"]);
                     } else {
                         if ($debug) {
                             $rawdata .= $data2;
                         }
                     }
                     if (feof($fp)) {
                         break;
                     }
                 }
                 if (self::StreamTimedOut($fp)) {
                     return array("success" => false, "error" => self::HTTPTranslate("Underlying stream timed out."), "errorcode" => "stream_timeout_exceeded");
                 }
             } else {
                 if ($response["code"] != 100) {
                     while (($data2 = fread($fp, 65536)) !== false) {
                         if (self::StreamTimedOut($fp)) {
                             return array("success" => false, "error" => self::HTTPTranslate("Underlying stream timed out."), "errorcode" => "stream_timeout_exceeded");
                         }
                         if ($timeout !== false && self::GetTimeLeft($startts, $timeout) == 0) {
                             return array("success" => false, "error" => self::HTTPTranslate("HTTP timeout exceeded."), "errorcode" => "timeout_exceeded");
                         }
                         $tempsize = strlen($data2);
                         $rawsize += $tempsize;
                         if ($response["code"] == 100 || !isset($options["read_body_callback"])) {
                             $body .= self::GetDecodedBody($autodecode_ds, $data2);
                         } else {
                             if (!$options["read_body_callback"]($response, self::GetDecodedBody($autodecode_ds, $data2), $options["read_body_callback_opts"])) {
                                 return array("success" => false, "error" => self::HTTPTranslate("Read body callback returned with a failure condition."), "errorcode" => "read_body_callback");
                             }
                         }
                         if (isset($options["recvratelimit"])) {
                             self::ProcessRateLimit($rawsize, $recvstart, $options["recvratelimit"]);
                         }
                         if (isset($options["debug_callback"])) {
                             $options["debug_callback"]("rawrecv", $data2, $options["debug_callback_opts"]);
                         } else {
                             if ($debug) {
                                 $rawdata .= $data2;
                             }
                         }
                         if (feof($fp)) {
                             break;
                         }
                     }
                     if (self::StreamTimedOut($fp)) {
                         return array("success" => false, "error" => self::HTTPTranslate("Underlying stream timed out."), "errorcode" => "stream_timeout_exceeded");
                     }
                 }
             }
         }
         if ($autodecode_ds !== false) {
             $autodecode_ds->Finalize();
             $data2 = $autodecode_ds->Read();
             if ($response["code"] == 100 || !isset($options["read_body_callback"])) {
                 $body .= $data2;
             } else {
                 if (!$options["read_body_callback"]($response, $data2, $options["read_body_callback_opts"])) {
                     return array("success" => false, "error" => self::HTTPTranslate("Read body callback returned with a failure condition."), "errorcode" => "read_body_callback");
                 }
             }
         }
     } while ($response["code"] == 100);
     return array("success" => true, "rawrecv" => $rawdata, "rawrecvsize" => $rawsize, "rawrecvheadersize" => $rawrecvheadersize, "recvstart" => $recvstart, "response" => $response, "headers" => $headers, "body" => $body);
 }
예제 #2
0
 private function streamFileData($stream, $compress, $level)
 {
     $dataLength = Count64::construct(0, !$this->zip64);
     $gzLength = Count64::construct(0, !$this->zip64);
     $hashCtx = hash_init('crc32b');
     if (COMPR::DEFLATE === $compress) {
         $compStream = DeflateStream::create($level);
     }
     while (!feof($stream)) {
         $data = fread($stream, self::STREAM_CHUNK_SIZE);
         $dataLength->add(strlen($data));
         hash_update($hashCtx, $data);
         if (COMPR::DEFLATE === $compress) {
             $data = $compStream->update($data);
         }
         $gzLength->add(strlen($data));
         $this->write($data);
         $this->flush();
     }
     if (COMPR::DEFLATE === $compress) {
         $data = $compStream->finish();
         $gzLength->add(strlen($data));
         $this->write($data);
         $this->flush();
     }
     $crc = unpack('N', hash_final($hashCtx, true));
     return array($dataLength, $gzLength, $crc[1]);
 }