FileGetContents.php 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. <?php
  2. /**
  3. * Copyright (c) 2007-2011, Servigistics, Inc.
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions are met:
  8. *
  9. * - Redistributions of source code must retain the above copyright notice,
  10. * this list of conditions and the following disclaimer.
  11. * - Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * - Neither the name of Servigistics, Inc. nor the names of
  15. * its contributors may be used to endorse or promote products derived from
  16. * this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  19. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  20. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  21. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  22. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  23. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  24. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  25. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  26. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  27. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  28. * POSSIBILITY OF SUCH DAMAGE.
  29. *
  30. * @copyright Copyright 2007-2011 Servigistics, Inc. (http://servigistics.com)
  31. * @license http://solr-php-client.googlecode.com/svn/trunk/COPYING New BSD
  32. * @version $Id: $
  33. *
  34. * @package Apache
  35. * @subpackage Solr
  36. * @author Donovan Jimenez <djimenez@conduit-it.com>
  37. */
  38. // Require Apache_Solr_HttpTransport_Abstract
  39. require_once(dirname(__FILE__) . '/Abstract.php');
  40. /**
  41. * HTTP Transport implemenation that uses the builtin http URL wrappers and file_get_contents
  42. */
  43. class Apache_Solr_HttpTransport_FileGetContents extends Apache_Solr_HttpTransport_Abstract
  44. {
  45. /**
  46. * SVN Revision meta data for this class
  47. */
  48. const SVN_REVISION = '$Revision: $';
  49. /**
  50. * SVN ID meta data for this class
  51. */
  52. const SVN_ID = '$Id: $';
  53. /**
  54. * Reusable stream context resources for GET and POST operations
  55. *
  56. * @var resource
  57. */
  58. private $_getContext, $_headContext, $_postContext;
  59. /**
  60. * Initializes our reuseable get and post stream contexts
  61. */
  62. public function __construct()
  63. {
  64. $this->_getContext = stream_context_create();
  65. $this->_headContext = stream_context_create();
  66. $this->_postContext = stream_context_create();
  67. }
  68. public function performGetRequest($url, $timeout = false)
  69. {
  70. // set the timeout if specified
  71. if ($timeout !== FALSE && $timeout > 0.0)
  72. {
  73. // timeouts with file_get_contents seem to need
  74. // to be halved to work as expected
  75. $timeout = (float) $timeout / 2;
  76. stream_context_set_option($this->_getContext, 'http', 'timeout', $timeout);
  77. }
  78. else
  79. {
  80. // use the default timeout pulled from default_socket_timeout otherwise
  81. stream_context_set_option($this->_getContext, 'http', 'timeout', $this->getDefaultTimeout());
  82. }
  83. // $http_response_headers will be updated by the call to file_get_contents later
  84. // see http://us.php.net/manual/en/wrappers.http.php for documentation
  85. // Unfortunately, it will still create a notice in analyzers if we don't set it here
  86. $http_response_header = null;
  87. $responseBody = @file_get_contents($url, false, $this->_getContext);
  88. return $this->_getResponseFromParts($responseBody, $http_response_header);
  89. }
  90. public function performHeadRequest($url, $timeout = false)
  91. {
  92. stream_context_set_option($this->_headContext, array(
  93. 'http' => array(
  94. // set HTTP method
  95. 'method' => 'HEAD',
  96. // default timeout
  97. 'timeout' => $this->getDefaultTimeout()
  98. )
  99. )
  100. );
  101. // set the timeout if specified
  102. if ($timeout !== FALSE && $timeout > 0.0)
  103. {
  104. // timeouts with file_get_contents seem to need
  105. // to be halved to work as expected
  106. $timeout = (float) $timeout / 2;
  107. stream_context_set_option($this->_headContext, 'http', 'timeout', $timeout);
  108. }
  109. // $http_response_headers will be updated by the call to file_get_contents later
  110. // see http://us.php.net/manual/en/wrappers.http.php for documentation
  111. // Unfortunately, it will still create a notice in analyzers if we don't set it here
  112. $http_response_header = null;
  113. $responseBody = @file_get_contents($url, false, $this->_headContext);
  114. return $this->_getResponseFromParts($responseBody, $http_response_header);
  115. }
  116. public function performPostRequest($url, $rawPost, $contentType, $timeout = false)
  117. {
  118. stream_context_set_option($this->_postContext, array(
  119. 'http' => array(
  120. // set HTTP method
  121. 'method' => 'POST',
  122. // Add our posted content type
  123. 'header' => "Content-Type: $contentType",
  124. // the posted content
  125. 'content' => $rawPost,
  126. // default timeout
  127. 'timeout' => $this->getDefaultTimeout()
  128. )
  129. )
  130. );
  131. // set the timeout if specified
  132. if ($timeout !== FALSE && $timeout > 0.0)
  133. {
  134. // timeouts with file_get_contents seem to need
  135. // to be halved to work as expected
  136. $timeout = (float) $timeout / 2;
  137. stream_context_set_option($this->_postContext, 'http', 'timeout', $timeout);
  138. }
  139. // $http_response_header will be updated by the call to file_get_contents later
  140. // see http://us.php.net/manual/en/wrappers.http.php for documentation
  141. // Unfortunately, it will still create a notice in analyzers if we don't set it here
  142. $http_response_header = null;
  143. $responseBody = @file_get_contents($url, false, $this->_postContext);
  144. // reset content of post context to reclaim memory
  145. stream_context_set_option($this->_postContext, 'http', 'content', '');
  146. return $this->_getResponseFromParts($responseBody, $http_response_header);
  147. }
  148. private function _getResponseFromParts($rawResponse, $httpHeaders)
  149. {
  150. //Assume 0, false as defaults
  151. $status = 0;
  152. $contentType = false;
  153. //iterate through headers for real status, type, and encoding
  154. if (is_array($httpHeaders) && count($httpHeaders) > 0)
  155. {
  156. //look at the first headers for the HTTP status code
  157. //and message (errors are usually returned this way)
  158. //
  159. //HTTP 100 Continue response can also be returned before
  160. //the REAL status header, so we need look until we find
  161. //the last header starting with HTTP
  162. //
  163. //the spec: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.1
  164. //
  165. //Thanks to Daniel Andersson for pointing out this oversight
  166. while (isset($httpHeaders[0]) && substr($httpHeaders[0], 0, 4) == 'HTTP')
  167. {
  168. // we can do a intval on status line without the "HTTP/1.X " to get the code
  169. $status = intval(substr($httpHeaders[0], 9));
  170. // remove this from the headers so we can check for more
  171. array_shift($httpHeaders);
  172. }
  173. //Look for the Content-Type response header and determine type
  174. //and encoding from it (if possible - such as 'Content-Type: text/plain; charset=UTF-8')
  175. foreach ($httpHeaders as $header)
  176. {
  177. // look for the header that starts appropriately
  178. if (strncasecmp($header, 'Content-Type:', 13) == 0)
  179. {
  180. $contentType = substr($header, 13);
  181. break;
  182. }
  183. }
  184. }
  185. return new Apache_Solr_HttpTransport_Response($status, $contentType, $rawResponse);
  186. }
  187. }