PageRenderTime 49ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/APP/wp-includes/http.php

https://bitbucket.org/AFelipeTrujillo/goblog
PHP | 558 lines | 185 code | 54 blank | 319 comment | 64 complexity | 73223c32394ecea2b382e4a4d8158141 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1
  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 a safe HTTP request.
  29. *
  30. * This function is ideal when the HTTP request is being made to an arbitrary
  31. * URL. The URL is validated to avoid redirection and request forgery attacks.
  32. *
  33. * @see wp_remote_request() For more information on the response array format
  34. * and default arguments.
  35. *
  36. * @since 3.6.0
  37. *
  38. * @param string $url Site URL to retrieve.
  39. * @param array $args Optional. Override the defaults.
  40. * @return WP_Error|array The response or WP_Error on failure.
  41. */
  42. function wp_safe_remote_request( $url, $args = array() ) {
  43. $args['reject_unsafe_urls'] = true;
  44. $http = _wp_http_get_object();
  45. return $http->request( $url, $args );
  46. }
  47. /**
  48. * Retrieve the raw response from a safe HTTP request using the GET method.
  49. *
  50. * This function is ideal when the HTTP request is being made to an arbitrary
  51. * URL. The URL is validated to avoid redirection and request forgery attacks.
  52. *
  53. * @see wp_remote_request() For more information on the response array format
  54. * and default arguments.
  55. *
  56. * @since 3.6.0
  57. *
  58. * @param string $url Site URL to retrieve.
  59. * @param array $args Optional. Override the defaults.
  60. * @return WP_Error|array The response or WP_Error on failure.
  61. */
  62. function wp_safe_remote_get( $url, $args = array() ) {
  63. $args['reject_unsafe_urls'] = true;
  64. $http = _wp_http_get_object();
  65. return $http->get( $url, $args );
  66. }
  67. /**
  68. * Retrieve the raw response from a safe HTTP request using the POST method.
  69. *
  70. * This function is ideal when the HTTP request is being made to an arbitrary
  71. * URL. The URL is validated to avoid redirection and request forgery attacks.
  72. *
  73. * @see wp_remote_request() For more information on the response array format
  74. * and default arguments.
  75. *
  76. * @since 3.6.0
  77. *
  78. * @param string $url Site URL to retrieve.
  79. * @param array $args Optional. Override the defaults.
  80. * @return WP_Error|array The response or WP_Error on failure.
  81. */
  82. function wp_safe_remote_post( $url, $args = array() ) {
  83. $args['reject_unsafe_urls'] = true;
  84. $http = _wp_http_get_object();
  85. return $http->post( $url, $args );
  86. }
  87. /**
  88. * Retrieve the raw response from a safe HTTP request using the HEAD method.
  89. *
  90. * This function is ideal when the HTTP request is being made to an arbitrary
  91. * URL. The URL is validated to avoid redirection and request forgery attacks.
  92. *
  93. * @see wp_remote_request() For more information on the response array format
  94. * and default arguments.
  95. *
  96. * @since 3.6.0
  97. *
  98. * @param string $url Site URL to retrieve.
  99. * @param array $args Optional. Override the defaults.
  100. * @return WP_Error|array The response or WP_Error on failure.
  101. */
  102. function wp_safe_remote_head( $url, $args = array() ) {
  103. $args['reject_unsafe_urls'] = true;
  104. $http = _wp_http_get_object();
  105. return $http->head( $url, $args );
  106. }
  107. /**
  108. * Retrieve the raw response from the HTTP request.
  109. *
  110. * The array structure is a little complex.
  111. *
  112. * <code>
  113. * $res = array( 'headers' => array(), 'response' => array('code' => int, 'message' => string) );
  114. * </code>
  115. *
  116. * All of the headers in $res['headers'] are with the name as the key and the
  117. * value as the value. So to get the User-Agent, you would do the following.
  118. *
  119. * <code>
  120. * $user_agent = $res['headers']['user-agent'];
  121. * </code>
  122. *
  123. * The body is the raw response content and can be retrieved from $res['body'].
  124. *
  125. * This function is called first to make the request and there are other API
  126. * functions to abstract out the above convoluted setup.
  127. *
  128. * List of default arguments:
  129. * 'method' => 'GET'
  130. * - Default 'GET' for wp_remote_get()
  131. * - Default 'POST' for wp_remote_post()
  132. * - Default 'HEAD' for wp_remote_head()
  133. * 'timeout' => 5
  134. * 'redirection' => 5
  135. * 'httpversion' => '1.0'
  136. * 'user-agent' => 'WordPress/' . $wp_version . '; ' . get_bloginfo( 'url' )
  137. * 'blocking' => true
  138. * 'headers' => array()
  139. * 'cookies' => array()
  140. * 'body' => null
  141. * 'compress' => false,
  142. * 'decompress' => true,
  143. * 'sslverify' => true,
  144. * 'stream' => false,
  145. * 'filename' => null
  146. *
  147. * @since 2.7.0
  148. *
  149. * @param string $url Site URL to retrieve.
  150. * @param array $args Optional. Override the defaults.
  151. * @return WP_Error|array The response or WP_Error on failure.
  152. */
  153. function wp_remote_request($url, $args = array()) {
  154. $objFetchSite = _wp_http_get_object();
  155. return $objFetchSite->request($url, $args);
  156. }
  157. /**
  158. * Retrieve the raw response from the HTTP request using the GET method.
  159. *
  160. * @see wp_remote_request() For more information on the response array format and default arguments.
  161. *
  162. * @since 2.7.0
  163. *
  164. * @param string $url Site URL to retrieve.
  165. * @param array $args Optional. Override the defaults.
  166. * @return WP_Error|array The response or WP_Error on failure.
  167. */
  168. function wp_remote_get($url, $args = array()) {
  169. $objFetchSite = _wp_http_get_object();
  170. return $objFetchSite->get($url, $args);
  171. }
  172. /**
  173. * Retrieve the raw response from the HTTP request using the POST method.
  174. *
  175. * @see wp_remote_request() For more information on the response array format and default arguments.
  176. *
  177. * @since 2.7.0
  178. *
  179. * @param string $url Site URL to retrieve.
  180. * @param array $args Optional. Override the defaults.
  181. * @return WP_Error|array The response or WP_Error on failure.
  182. */
  183. function wp_remote_post($url, $args = array()) {
  184. $objFetchSite = _wp_http_get_object();
  185. return $objFetchSite->post($url, $args);
  186. }
  187. /**
  188. * Retrieve the raw response from the HTTP request using the HEAD method.
  189. *
  190. * @see wp_remote_request() For more information on the response array format and default arguments.
  191. *
  192. * @since 2.7.0
  193. *
  194. * @param string $url Site URL to retrieve.
  195. * @param array $args Optional. Override the defaults.
  196. * @return WP_Error|array The response or WP_Error on failure.
  197. */
  198. function wp_remote_head($url, $args = array()) {
  199. $objFetchSite = _wp_http_get_object();
  200. return $objFetchSite->head($url, $args);
  201. }
  202. /**
  203. * Retrieve only the headers from the raw response.
  204. *
  205. * @since 2.7.0
  206. *
  207. * @param array $response HTTP response.
  208. * @return array The headers of the response. Empty array if incorrect parameter given.
  209. */
  210. function wp_remote_retrieve_headers(&$response) {
  211. if ( is_wp_error($response) || ! isset($response['headers']) || ! is_array($response['headers']))
  212. return array();
  213. return $response['headers'];
  214. }
  215. /**
  216. * Retrieve a single header by name from the raw response.
  217. *
  218. * @since 2.7.0
  219. *
  220. * @param array $response
  221. * @param string $header Header name to retrieve value from.
  222. * @return string The header value. Empty string on if incorrect parameter given, or if the header doesn't exist.
  223. */
  224. function wp_remote_retrieve_header(&$response, $header) {
  225. if ( is_wp_error($response) || ! isset($response['headers']) || ! is_array($response['headers']))
  226. return '';
  227. if ( array_key_exists($header, $response['headers']) )
  228. return $response['headers'][$header];
  229. return '';
  230. }
  231. /**
  232. * Retrieve only the response code from the raw response.
  233. *
  234. * Will return an empty array if incorrect parameter value is given.
  235. *
  236. * @since 2.7.0
  237. *
  238. * @param array $response HTTP response.
  239. * @return string the response code. Empty string on incorrect parameter given.
  240. */
  241. function wp_remote_retrieve_response_code(&$response) {
  242. if ( is_wp_error($response) || ! isset($response['response']) || ! is_array($response['response']))
  243. return '';
  244. return $response['response']['code'];
  245. }
  246. /**
  247. * Retrieve only the response message from the raw response.
  248. *
  249. * Will return an empty array if incorrect parameter value is given.
  250. *
  251. * @since 2.7.0
  252. *
  253. * @param array $response HTTP response.
  254. * @return string The response message. Empty string on incorrect parameter given.
  255. */
  256. function wp_remote_retrieve_response_message(&$response) {
  257. if ( is_wp_error($response) || ! isset($response['response']) || ! is_array($response['response']))
  258. return '';
  259. return $response['response']['message'];
  260. }
  261. /**
  262. * Retrieve only the body from the raw response.
  263. *
  264. * @since 2.7.0
  265. *
  266. * @param array $response HTTP response.
  267. * @return string The body of the response. Empty string if no body or incorrect parameter given.
  268. */
  269. function wp_remote_retrieve_body(&$response) {
  270. if ( is_wp_error($response) || ! isset($response['body']) )
  271. return '';
  272. return $response['body'];
  273. }
  274. /**
  275. * Determines if there is an HTTP Transport that can process this request.
  276. *
  277. * @since 3.2.0
  278. *
  279. * @param array $capabilities Array of capabilities to test or a wp_remote_request() $args array.
  280. * @param string $url Optional. If given, will check if the URL requires SSL and adds that requirement to the capabilities array.
  281. *
  282. * @return bool
  283. */
  284. function wp_http_supports( $capabilities = array(), $url = null ) {
  285. $objFetchSite = _wp_http_get_object();
  286. $capabilities = wp_parse_args( $capabilities );
  287. $count = count( $capabilities );
  288. // If we have a numeric $capabilities array, spoof a wp_remote_request() associative $args array
  289. if ( $count && count( array_filter( array_keys( $capabilities ), 'is_numeric' ) ) == $count ) {
  290. $capabilities = array_combine( array_values( $capabilities ), array_fill( 0, $count, true ) );
  291. }
  292. if ( $url && !isset( $capabilities['ssl'] ) ) {
  293. $scheme = parse_url( $url, PHP_URL_SCHEME );
  294. if ( 'https' == $scheme || 'ssl' == $scheme ) {
  295. $capabilities['ssl'] = true;
  296. }
  297. }
  298. return (bool) $objFetchSite->_get_first_available_transport( $capabilities );
  299. }
  300. /**
  301. * Get the HTTP Origin of the current request.
  302. *
  303. * @since 3.4.0
  304. *
  305. * @return string URL of the origin. Empty string if no origin.
  306. */
  307. function get_http_origin() {
  308. $origin = '';
  309. if ( ! empty ( $_SERVER[ 'HTTP_ORIGIN' ] ) )
  310. $origin = $_SERVER[ 'HTTP_ORIGIN' ];
  311. /**
  312. * Change the origin of an HTTP request.
  313. *
  314. * @since 3.4.0
  315. *
  316. * @param string $origin The original origin for the request.
  317. */
  318. return apply_filters( 'http_origin', $origin );
  319. }
  320. /**
  321. * Retrieve list of allowed HTTP origins.
  322. *
  323. * @since 3.4.0
  324. *
  325. * @return array Array of origin URLs.
  326. */
  327. function get_allowed_http_origins() {
  328. $admin_origin = parse_url( admin_url() );
  329. $home_origin = parse_url( home_url() );
  330. // @todo preserve port?
  331. $allowed_origins = array_unique( array(
  332. 'http://' . $admin_origin[ 'host' ],
  333. 'https://' . $admin_origin[ 'host' ],
  334. 'http://' . $home_origin[ 'host' ],
  335. 'https://' . $home_origin[ 'host' ],
  336. ) );
  337. /**
  338. * Change the origin types allowed for HTTP requests.
  339. *
  340. * @since 3.4.0
  341. *
  342. * @param array $allowed_origins {
  343. * Default allowed HTTP origins.
  344. * @type string Non-secure URL for admin origin.
  345. * @type string Secure URL for admin origin.
  346. * @type string Non-secure URL for home origin.
  347. * @type string Secure URL for home origin.
  348. * }
  349. */
  350. return apply_filters( 'allowed_http_origins' , $allowed_origins );
  351. }
  352. /**
  353. * Determines if the HTTP origin is an authorized one.
  354. *
  355. * @since 3.4.0
  356. *
  357. * @param string Origin URL. If not provided, the value of get_http_origin() is used.
  358. * @return bool True if the origin is allowed. False otherwise.
  359. */
  360. function is_allowed_http_origin( $origin = null ) {
  361. $origin_arg = $origin;
  362. if ( null === $origin )
  363. $origin = get_http_origin();
  364. if ( $origin && ! in_array( $origin, get_allowed_http_origins() ) )
  365. $origin = '';
  366. /**
  367. * Change the allowed HTTP origin result.
  368. *
  369. * @since 3.4.0
  370. *
  371. * @param string $origin Result of check for allowed origin.
  372. * @param string $origin_arg original origin string passed into is_allowed_http_origin function.
  373. */
  374. return apply_filters( 'allowed_http_origin', $origin, $origin_arg );
  375. }
  376. /**
  377. * Send Access-Control-Allow-Origin and related headers if the current request
  378. * is from an allowed origin.
  379. *
  380. * If the request is an OPTIONS request, the script exits with either access
  381. * control headers sent, or a 403 response if the origin is not allowed. For
  382. * other request methods, you will receive a return value.
  383. *
  384. * @since 3.4.0
  385. *
  386. * @return bool|string Returns the origin URL if headers are sent. Returns false
  387. * if headers are not sent.
  388. */
  389. function send_origin_headers() {
  390. $origin = get_http_origin();
  391. if ( is_allowed_http_origin( $origin ) ) {
  392. @header( 'Access-Control-Allow-Origin: ' . $origin );
  393. @header( 'Access-Control-Allow-Credentials: true' );
  394. if ( 'OPTIONS' === $_SERVER['REQUEST_METHOD'] )
  395. exit;
  396. return $origin;
  397. }
  398. if ( 'OPTIONS' === $_SERVER['REQUEST_METHOD'] ) {
  399. status_header( 403 );
  400. exit;
  401. }
  402. return false;
  403. }
  404. /**
  405. * Validate a URL for safe use in the HTTP API.
  406. *
  407. * @since 3.5.2
  408. *
  409. * @return mixed URL or false on failure.
  410. */
  411. function wp_http_validate_url( $url ) {
  412. $url = wp_kses_bad_protocol( $url, array( 'http', 'https' ) );
  413. if ( ! $url )
  414. return false;
  415. $parsed_url = @parse_url( $url );
  416. if ( ! $parsed_url || empty( $parsed_url['host'] ) )
  417. return false;
  418. if ( isset( $parsed_url['user'] ) || isset( $parsed_url['pass'] ) )
  419. return false;
  420. if ( false !== strpos( $parsed_url['host'], ':' ) )
  421. return false;
  422. $parsed_home = @parse_url( get_option( 'home' ) );
  423. $same_host = strtolower( $parsed_home['host'] ) === strtolower( $parsed_url['host'] );
  424. if ( ! $same_host ) {
  425. $host = trim( $parsed_url['host'], '.' );
  426. if ( preg_match( '#^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$#', $host ) ) {
  427. $ip = $host;
  428. } else {
  429. $ip = gethostbyname( $host );
  430. if ( $ip === $host ) // Error condition for gethostbyname()
  431. $ip = false;
  432. }
  433. if ( $ip ) {
  434. $parts = array_map( 'intval', explode( '.', $ip ) );
  435. if ( '127.0.0.1' === $ip
  436. || ( 10 === $parts[0] )
  437. || ( 172 === $parts[0] && 16 <= $parts[1] && 31 >= $parts[1] )
  438. || ( 192 === $parts[0] && 168 === $parts[1] )
  439. ) {
  440. // If host appears local, reject unless specifically allowed.
  441. /**
  442. * Check if HTTP request is external or not.
  443. *
  444. * Allows to change and allow external requests for the HTTP request.
  445. *
  446. * @since 3.6.0
  447. *
  448. * @param bool false Whether HTTP request is external or not.
  449. * @param string $host IP of the requested host.
  450. * @param string $url URL of the requested host.
  451. */
  452. if ( ! apply_filters( 'http_request_host_is_external', false, $host, $url ) )
  453. return false;
  454. }
  455. }
  456. }
  457. if ( empty( $parsed_url['port'] ) )
  458. return $url;
  459. $port = $parsed_url['port'];
  460. if ( 80 === $port || 443 === $port || 8080 === $port )
  461. return $url;
  462. if ( $parsed_home && $same_host && isset( $parsed_home['port'] ) && $parsed_home['port'] === $port )
  463. return $url;
  464. return false;
  465. }
  466. /**
  467. * Whitelists allowed redirect hosts for safe HTTP requests as well.
  468. *
  469. * Attached to the http_request_host_is_external filter.
  470. *
  471. * @since 3.6.0
  472. *
  473. * @param bool $is_external
  474. * @param string $host
  475. * @return bool
  476. */
  477. function allowed_http_request_hosts( $is_external, $host ) {
  478. if ( ! $is_external && wp_validate_redirect( 'http://' . $host ) )
  479. $is_external = true;
  480. return $is_external;
  481. }
  482. /**
  483. * Whitelists any domain in a multisite installation for safe HTTP requests.
  484. *
  485. * Attached to the http_request_host_is_external filter.
  486. *
  487. * @since 3.6.0
  488. *
  489. * @param bool $is_external
  490. * @param string $host
  491. * @return bool
  492. */
  493. function ms_allowed_http_request_hosts( $is_external, $host ) {
  494. global $wpdb;
  495. static $queried = array();
  496. if ( $is_external )
  497. return $is_external;
  498. if ( $host === get_current_site()->domain )
  499. return true;
  500. if ( isset( $queried[ $host ] ) )
  501. return $queried[ $host ];
  502. $queried[ $host ] = (bool) $wpdb->get_var( $wpdb->prepare( "SELECT domain FROM $wpdb->blogs WHERE domain = %s LIMIT 1", $host ) );
  503. return $queried[ $host ];
  504. }