Google_IO_Stream

The WordPress Core Google IO Stream class.

Defined (1)

The class is defined in the following location(s).

/tools/src/Google/IO/Stream.php  
  1. class Google_IO_Stream extends Google_IO_Abstract 
  2.  
  3. const TIMEOUT = "timeout"; 
  4.  
  5. const ZLIB = "compress.zlib://"; 
  6.  
  7. private $options = array(); 
  8.  
  9. private $trappedErrorNumber; 
  10.  
  11. private $trappedErrorString; 
  12.  
  13. private static $DEFAULT_HTTP_CONTEXT = array( 
  14. "follow_location" => 0,  
  15. "ignore_errors" => 1 
  16. ); 
  17.  
  18. private static $DEFAULT_SSL_CONTEXT = array( 
  19. "verify_peer" => true 
  20. ); 
  21.  
  22. /** 
  23. * Execute an HTTP Request 
  24. * @param Google_HttpRequest $request 
  25. * the http request to be executed 
  26. * @return Google_HttpRequest http request with the response http code,  
  27. * response headers and response body filled in 
  28. * @throws Google_IO_Exception on curl or IO error 
  29. */ 
  30. public function executeRequest(Google_Http_Request $request) 
  31. $default_options = stream_context_get_options(stream_context_get_default()); 
  32. $requestHttpContext = array_key_exists('http', $default_options) ? $default_options['http'] : array(); 
  33. if ($request->getPostBody()) { 
  34. $requestHttpContext["content"] = $request->getPostBody(); 
  35. $requestHeaders = $request->getRequestHeaders(); 
  36. if ($requestHeaders && is_array($requestHeaders)) { 
  37. $headers = ""; 
  38. foreach ($requestHeaders as $k => $v) { 
  39. $headers .= "$k: $v\r\n"; 
  40. $requestHttpContext["header"] = $headers; 
  41. $requestHttpContext["method"] = $request->getRequestMethod(); 
  42. $requestHttpContext["user_agent"] = $request->getUserAgent(); 
  43. $requestSslContext = array_key_exists('ssl', $default_options) ? $default_options['ssl'] : array(); 
  44. if (! array_key_exists("cafile", $requestSslContext)) { 
  45. $requestSslContext["cafile"] = dirname(__FILE__) . '/cacerts.pem'; 
  46. $options = array( 
  47. "http" => array_merge(self::$DEFAULT_HTTP_CONTEXT, $requestHttpContext),  
  48. "ssl" => array_merge(self::$DEFAULT_SSL_CONTEXT, $requestSslContext) 
  49. ); 
  50. $context = stream_context_create($options); 
  51. $url = $request->getUrl(); 
  52. if ($request->canGzip()) { 
  53. $url = self::ZLIB . $url; 
  54. $this->client->getLogger()->debug('Stream request', array( 
  55. 'url' => $url,  
  56. 'method' => $request->getRequestMethod(),  
  57. 'headers' => $requestHeaders,  
  58. 'body' => $request->getPostBody() 
  59. )); 
  60. // We are trapping any thrown errors in this method only and 
  61. // throwing an exception. 
  62. $this->trappedErrorNumber = null; 
  63. $this->trappedErrorString = null; 
  64. // START - error trap. 
  65. set_error_handler(array( 
  66. $this,  
  67. 'trapError' 
  68. )); 
  69. $fh = fopen($url, 'r', false, $context); 
  70. restore_error_handler(); 
  71. // END - error trap. 
  72. if ($this->trappedErrorNumber) { 
  73. $error = sprintf("HTTP Error: Unable to connect: '%s'", $this->trappedErrorString); 
  74. $this->client->getLogger()->error('Stream ' . $error); 
  75. throw new Google_IO_Exception($error, $this->trappedErrorNumber); 
  76. $response_data = false; 
  77. $respHttpCode = self::UNKNOWN_CODE; 
  78. if ($fh) { 
  79. if (isset($this->options[self::TIMEOUT])) { 
  80. stream_set_timeout($fh, $this->options[self::TIMEOUT]); 
  81. $response_data = stream_get_contents($fh); 
  82. fclose($fh); 
  83. $respHttpCode = $this->getHttpResponseCode($http_response_header); 
  84. if (false === $response_data) { 
  85. $error = sprintf("HTTP Error: Unable to connect: '%s'", $respHttpCode); 
  86. $this->client->getLogger()->error('Stream ' . $error); 
  87. throw new Google_IO_Exception($error, $respHttpCode); 
  88. $responseHeaders = $this->getHttpResponseHeaders($http_response_header); 
  89. $this->client->getLogger()->debug('Stream response', array( 
  90. 'code' => $respHttpCode,  
  91. 'headers' => $responseHeaders,  
  92. 'body' => $response_data 
  93. )); 
  94. return array( 
  95. $response_data,  
  96. $responseHeaders,  
  97. $respHttpCode 
  98. ); 
  99.  
  100. /** 
  101. * Set options that update the transport implementation's behavior. 
  102. * @param 
  103. * $options 
  104. */ 
  105. public function setOptions($options) 
  106. $this->options = $options + $this->options; 
  107.  
  108. /** 
  109. * Method to handle errors, used for error handling around 
  110. * stream connection methods. 
  111. */ 
  112. public function trapError($errno, $errstr) 
  113. $this->trappedErrorNumber = $errno; 
  114. $this->trappedErrorString = $errstr; 
  115.  
  116. /** 
  117. * Set the maximum request time in seconds. 
  118. * @param $timeout in 
  119. * seconds 
  120. */ 
  121. public function setTimeout($timeout) 
  122. $this->options[self::TIMEOUT] = $timeout; 
  123.  
  124. /** 
  125. * Get the maximum request time in seconds. 
  126. * @return timeout in seconds 
  127. */ 
  128. public function getTimeout() 
  129. return $this->options[self::TIMEOUT]; 
  130.  
  131. /** 
  132. * Test for the presence of a cURL header processing bug 
  133. * {@inheritDoc} 
  134. * @return boolean 
  135. */ 
  136. protected function needsQuirk() 
  137. return false; 
  138.  
  139. protected function getHttpResponseCode($response_headers) 
  140. $header_count = count($response_headers); 
  141. for ($i = 0; $i < $header_count; $i ++) { 
  142. $header = $response_headers[$i]; 
  143. if (strncasecmp("HTTP", $header, strlen("HTTP")) == 0) { 
  144. $response = explode(' ', $header); 
  145. return $response[1]; 
  146. return self::UNKNOWN_CODE;