PageRenderTime 44ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/wordpress/wp-includes/http.php

https://gitlab.com/Blueprint-Marketing/wordpress-unit-tests
PHP | 393 lines | 148 code | 48 blank | 197 comment | 57 complexity | c8071e10cdeb0747a7d9fdcd6acad082 MD5 | raw file
  1. <?php
  2. /**
  3. * Simple and uniform HTTP request API.
  4. *
  5. * Will eventually replace and standardize the WordPress HTTP requests made.
  6. *
  7. * @link http://trac.wordpress.org/ticket/4779 HTTP API Proposal
  8. *
  9. * @package WordPress
  10. * @subpackage HTTP
  11. * @since 2.7.0
  12. */
  13. /**
  14. * Returns the initialized WP_Http Object
  15. *
  16. * @since 2.7.0
  17. * @access private
  18. *
  19. * @return WP_Http HTTP Transport object.
  20. */
  21. function _wp_http_get_object() {
  22. static $http;
  23. if ( is_null($http) )
  24. $http = new WP_Http();
  25. return $http;
  26. }
  27. /**
  28. * Retrieve the raw response from the HTTP request.
  29. *
  30. * The array structure is a little complex.
  31. *
  32. * <code>
  33. * $res = array( 'headers' => array(), 'response' => array('code' => int, 'message' => string) );
  34. * </code>
  35. *
  36. * All of the headers in $res['headers'] are with the name as the key and the
  37. * value as the value. So to get the User-Agent, you would do the following.
  38. *
  39. * <code>
  40. * $user_agent = $res['headers']['user-agent'];
  41. * </code>
  42. *
  43. * The body is the raw response content and can be retrieved from $res['body'].
  44. *
  45. * This function is called first to make the request and there are other API
  46. * functions to abstract out the above convoluted setup.
  47. *
  48. * List of default arguments:
  49. * 'method' => 'GET'
  50. * - Default 'GET' for wp_remote_get()
  51. * - Default 'POST' for wp_remote_post()
  52. * - Default 'HEAD' for wp_remote_head()
  53. * 'timeout' => 5
  54. * 'redirection' => 5
  55. * 'httpversion' => '1.0'
  56. * 'user-agent' => 'WordPress/' . $wp_version . '; ' . get_bloginfo( 'url' )
  57. * 'blocking' => true
  58. * 'headers' => array()
  59. * 'cookies' => array()
  60. * 'body' => null
  61. * 'compress' => false,
  62. * 'decompress' => true,
  63. * 'sslverify' => true,
  64. * 'stream' => false,
  65. * 'filename' => null
  66. *
  67. * @since 2.7.0
  68. *
  69. * @param string $url Site URL to retrieve.
  70. * @param array $args Optional. Override the defaults.
  71. * @return WP_Error|array The response or WP_Error on failure.
  72. */
  73. function wp_remote_request($url, $args = array()) {
  74. $objFetchSite = _wp_http_get_object();
  75. return $objFetchSite->request($url, $args);
  76. }
  77. /**
  78. * Retrieve the raw response from the HTTP request using the GET method.
  79. *
  80. * @see wp_remote_request() For more information on the response array format and default arguments.
  81. *
  82. * @since 2.7.0
  83. *
  84. * @param string $url Site URL to retrieve.
  85. * @param array $args Optional. Override the defaults.
  86. * @return WP_Error|array The response or WP_Error on failure.
  87. */
  88. function wp_remote_get($url, $args = array()) {
  89. $objFetchSite = _wp_http_get_object();
  90. return $objFetchSite->get($url, $args);
  91. }
  92. /**
  93. * Retrieve the raw response from the HTTP request using the POST method.
  94. *
  95. * @see wp_remote_request() For more information on the response array format and default arguments.
  96. *
  97. * @since 2.7.0
  98. *
  99. * @param string $url Site URL to retrieve.
  100. * @param array $args Optional. Override the defaults.
  101. * @return WP_Error|array The response or WP_Error on failure.
  102. */
  103. function wp_remote_post($url, $args = array()) {
  104. $objFetchSite = _wp_http_get_object();
  105. return $objFetchSite->post($url, $args);
  106. }
  107. /**
  108. * Retrieve the raw response from the HTTP request using the HEAD method.
  109. *
  110. * @see wp_remote_request() For more information on the response array format and default arguments.
  111. *
  112. * @since 2.7.0
  113. *
  114. * @param string $url Site URL to retrieve.
  115. * @param array $args Optional. Override the defaults.
  116. * @return WP_Error|array The response or WP_Error on failure.
  117. */
  118. function wp_remote_head($url, $args = array()) {
  119. $objFetchSite = _wp_http_get_object();
  120. return $objFetchSite->head($url, $args);
  121. }
  122. /**
  123. * Retrieve only the headers from the raw response.
  124. *
  125. * @since 2.7.0
  126. *
  127. * @param array $response HTTP response.
  128. * @return array The headers of the response. Empty array if incorrect parameter given.
  129. */
  130. function wp_remote_retrieve_headers(&$response) {
  131. if ( is_wp_error($response) || ! isset($response['headers']) || ! is_array($response['headers']))
  132. return array();
  133. return $response['headers'];
  134. }
  135. /**
  136. * Retrieve a single header by name from the raw response.
  137. *
  138. * @since 2.7.0
  139. *
  140. * @param array $response
  141. * @param string $header Header name to retrieve value from.
  142. * @return string The header value. Empty string on if incorrect parameter given, or if the header doesn't exist.
  143. */
  144. function wp_remote_retrieve_header(&$response, $header) {
  145. if ( is_wp_error($response) || ! isset($response['headers']) || ! is_array($response['headers']))
  146. return '';
  147. if ( array_key_exists($header, $response['headers']) )
  148. return $response['headers'][$header];
  149. return '';
  150. }
  151. /**
  152. * Retrieve only the response code from the raw response.
  153. *
  154. * Will return an empty array if incorrect parameter value is given.
  155. *
  156. * @since 2.7.0
  157. *
  158. * @param array $response HTTP response.
  159. * @return string the response code. Empty string on incorrect parameter given.
  160. */
  161. function wp_remote_retrieve_response_code(&$response) {
  162. if ( is_wp_error($response) || ! isset($response['response']) || ! is_array($response['response']))
  163. return '';
  164. return $response['response']['code'];
  165. }
  166. /**
  167. * Retrieve only the response message from the raw response.
  168. *
  169. * Will return an empty array if incorrect parameter value is given.
  170. *
  171. * @since 2.7.0
  172. *
  173. * @param array $response HTTP response.
  174. * @return string The response message. Empty string on incorrect parameter given.
  175. */
  176. function wp_remote_retrieve_response_message(&$response) {
  177. if ( is_wp_error($response) || ! isset($response['response']) || ! is_array($response['response']))
  178. return '';
  179. return $response['response']['message'];
  180. }
  181. /**
  182. * Retrieve only the body from the raw response.
  183. *
  184. * @since 2.7.0
  185. *
  186. * @param array $response HTTP response.
  187. * @return string The body of the response. Empty string if no body or incorrect parameter given.
  188. */
  189. function wp_remote_retrieve_body(&$response) {
  190. if ( is_wp_error($response) || ! isset($response['body']) )
  191. return '';
  192. return $response['body'];
  193. }
  194. /**
  195. * Determines if there is an HTTP Transport that can process this request.
  196. *
  197. * @since 3.2.0
  198. *
  199. * @param array $capabilities Array of capabilities to test or a wp_remote_request() $args array.
  200. * @param string $url Optional. If given, will check if the URL requires SSL and adds that requirement to the capabilities array.
  201. *
  202. * @return bool
  203. */
  204. function wp_http_supports( $capabilities = array(), $url = null ) {
  205. $objFetchSite = _wp_http_get_object();
  206. $capabilities = wp_parse_args( $capabilities );
  207. $count = count( $capabilities );
  208. // If we have a numeric $capabilities array, spoof a wp_remote_request() associative $args array
  209. if ( $count && count( array_filter( array_keys( $capabilities ), 'is_numeric' ) ) == $count ) {
  210. $capabilities = array_combine( array_values( $capabilities ), array_fill( 0, $count, true ) );
  211. }
  212. if ( $url && !isset( $capabilities['ssl'] ) ) {
  213. $scheme = parse_url( $url, PHP_URL_SCHEME );
  214. if ( 'https' == $scheme || 'ssl' == $scheme ) {
  215. $capabilities['ssl'] = true;
  216. }
  217. }
  218. return (bool) $objFetchSite->_get_first_available_transport( $capabilities );
  219. }
  220. /**
  221. * Get the HTTP Origin of the current request.
  222. *
  223. * @since 3.4.0
  224. *
  225. * @return string URL of the origin. Empty string if no origin.
  226. */
  227. function get_http_origin() {
  228. $origin = '';
  229. if ( ! empty ( $_SERVER[ 'HTTP_ORIGIN' ] ) )
  230. $origin = $_SERVER[ 'HTTP_ORIGIN' ];
  231. return apply_filters( 'http_origin', $origin );
  232. }
  233. /**
  234. * Retrieve list of allowed http origins.
  235. *
  236. * @since 3.4.0
  237. *
  238. * @return array Array of origin URLs.
  239. */
  240. function get_allowed_http_origins() {
  241. $admin_origin = parse_url( admin_url() );
  242. $home_origin = parse_url( home_url() );
  243. // @todo preserve port?
  244. $allowed_origins = array_unique( array(
  245. 'http://' . $admin_origin[ 'host' ],
  246. 'https://' . $admin_origin[ 'host' ],
  247. 'http://' . $home_origin[ 'host' ],
  248. 'https://' . $home_origin[ 'host' ],
  249. ) );
  250. return apply_filters( 'allowed_http_origins' , $allowed_origins );
  251. }
  252. /**
  253. * Determines if the http origin is an authorized one.
  254. *
  255. * @since 3.4.0
  256. *
  257. * @param string Origin URL. If not provided, the value of get_http_origin() is used.
  258. * @return bool True if the origin is allowed. False otherwise.
  259. */
  260. function is_allowed_http_origin( $origin = null ) {
  261. $origin_arg = $origin;
  262. if ( null === $origin )
  263. $origin = get_http_origin();
  264. if ( $origin && ! in_array( $origin, get_allowed_http_origins() ) )
  265. $origin = '';
  266. return apply_filters( 'allowed_http_origin', $origin, $origin_arg );
  267. }
  268. /**
  269. * Send Access-Control-Allow-Origin and related headers if the current request
  270. * is from an allowed origin.
  271. *
  272. * If the request is an OPTIONS request, the script exits with either access
  273. * control headers sent, or a 403 response if the origin is not allowed. For
  274. * other request methods, you will receive a return value.
  275. *
  276. * @since 3.4.0
  277. *
  278. * @return bool|string Returns the origin URL if headers are sent. Returns false
  279. * if headers are not sent.
  280. */
  281. function send_origin_headers() {
  282. $origin = get_http_origin();
  283. if ( is_allowed_http_origin( $origin ) ) {
  284. @header( 'Access-Control-Allow-Origin: ' . $origin );
  285. @header( 'Access-Control-Allow-Credentials: true' );
  286. if ( 'OPTIONS' === $_SERVER['REQUEST_METHOD'] )
  287. exit;
  288. return $origin;
  289. }
  290. if ( 'OPTIONS' === $_SERVER['REQUEST_METHOD'] ) {
  291. status_header( 403 );
  292. exit;
  293. }
  294. return false;
  295. }
  296. /**
  297. * Validate a URL for safe use in the HTTP API.
  298. *
  299. * @since 3.5.2
  300. *
  301. * @return mixed URL or false on failure.
  302. */
  303. function wp_http_validate_url( $url ) {
  304. $url = wp_kses_bad_protocol( $url, array( 'http', 'https' ) );
  305. if ( ! $url )
  306. return false;
  307. $parsed_url = @parse_url( $url );
  308. if ( ! $parsed_url || empty( $parsed_url['host'] ) )
  309. return false;
  310. if ( isset( $parsed_url['user'] ) || isset( $parsed_url['pass'] ) )
  311. return false;
  312. if ( false !== strpos( $parsed_url['host'], ':' ) )
  313. return false;
  314. $parsed_home = @parse_url( get_option( 'home' ) );
  315. $same_host = strtolower( $parsed_home['host'] ) === strtolower( $parsed_url['host'] );
  316. if ( ! $same_host ) {
  317. $host = trim( $parsed_url['host'], '.' );
  318. if ( preg_match( '#^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$#', $host ) ) {
  319. $ip = $host;
  320. } else {
  321. $ip = gethostbyname( $host );
  322. if ( $ip === $host ) // Error condition for gethostbyname()
  323. $ip = false;
  324. }
  325. if ( $ip ) {
  326. if ( '127.0.0.1' === $ip )
  327. return false;
  328. $parts = array_map( 'intval', explode( '.', $ip ) );
  329. if ( 10 === $parts[0] )
  330. return false;
  331. if ( 172 === $parts[0] && 16 <= $parts[1] && 31 >= $parts[1] )
  332. return false;
  333. if ( 192 === $parts[0] && 168 === $parts[1] )
  334. return false;
  335. }
  336. }
  337. if ( empty( $parsed_url['port'] ) )
  338. return $url;
  339. $port = $parsed_url['port'];
  340. if ( 80 === $port || 443 === $port || 8080 === $port )
  341. return $url;
  342. if ( $parsed_home && $same_host && $parsed_home['port'] === $port )
  343. return $url;
  344. return false;
  345. }