Ticket #8927: 8927.diff
File 8927.diff, 16.2 KB (added by , 16 years ago) |
---|
-
http.php
228 228 static $working_transport, $blocking_transport, $nonblocking_transport; 229 229 230 230 if ( is_null($working_transport) ) { 231 if ( true === WP_Http_ExtHttp::test() && apply_filters('use_http_extension_transport', true)) {231 if ( true === WP_Http_ExtHttp::test() ) { 232 232 $working_transport['exthttp'] = new WP_Http_ExtHttp(); 233 233 $blocking_transport[] = &$working_transport['exthttp']; 234 } else if ( true === WP_Http_Curl::test() && apply_filters('use_curl_transport', true)) {234 } else if ( true === WP_Http_Curl::test() ) { 235 235 $working_transport['curl'] = new WP_Http_Curl(); 236 236 $blocking_transport[] = &$working_transport['curl']; 237 } else if ( true === WP_Http_Streams::test() && apply_filters('use_streams_transport', true)) {237 } else if ( true === WP_Http_Streams::test() ) { 238 238 $working_transport['streams'] = new WP_Http_Streams(); 239 239 $blocking_transport[] = &$working_transport['streams']; 240 } else if ( true === WP_Http_Fopen::test() && apply_filters('use_fopen_transport', true) &&( isset($args['ssl']) && !$args['ssl'] ) ) {240 } else if ( true === WP_Http_Fopen::test() && ( isset($args['ssl']) && !$args['ssl'] ) ) { 241 241 $working_transport['fopen'] = new WP_Http_Fopen(); 242 242 $blocking_transport[] = &$working_transport['fopen']; 243 } else if ( true === WP_Http_Fsockopen::test() && apply_filters('use_fsockopen_transport', true) &&( isset($args['ssl']) && !$args['ssl'] ) ) {243 } else if ( true === WP_Http_Fsockopen::test() && ( isset($args['ssl']) && !$args['ssl'] ) ) { 244 244 $working_transport['fsockopen'] = new WP_Http_Fsockopen(); 245 245 $blocking_transport[] = &$working_transport['fsockopen']; 246 246 } … … 279 279 static $working_transport, $blocking_transport, $nonblocking_transport; 280 280 281 281 if ( is_null($working_transport) ) { 282 if ( true === WP_Http_ExtHttp::test() && apply_filters('use_http_extension_transport', true)) {282 if ( true === WP_Http_ExtHttp::test() ) { 283 283 $working_transport['exthttp'] = new WP_Http_ExtHttp(); 284 284 $blocking_transport[] = &$working_transport['exthttp']; 285 } else if ( true === WP_Http_Curl::test() && apply_filters('use_curl_transport', true)) {285 } else if ( true === WP_Http_Curl::test() ) { 286 286 $working_transport['curl'] = new WP_Http_Curl(); 287 287 $blocking_transport[] = &$working_transport['curl']; 288 } else if ( true === WP_Http_Streams::test() && apply_filters('use_streams_transport', true)) {288 } else if ( true === WP_Http_Streams::test() ) { 289 289 $working_transport['streams'] = new WP_Http_Streams(); 290 290 $blocking_transport[] = &$working_transport['streams']; 291 } else if ( true === WP_Http_Fsockopen::test() && apply_filters('use_fsockopen_transport', true) &&( isset($args['ssl']) && !$args['ssl'] ) ) {291 } else if ( true === WP_Http_Fsockopen::test() && ( isset($args['ssl']) && !$args['ssl'] ) ) { 292 292 $working_transport['fsockopen'] = new WP_Http_Fsockopen(); 293 293 $blocking_transport[] = &$working_transport['fsockopen']; 294 294 } … … 376 376 377 377 $arrURL = parse_url($url); 378 378 379 if ( $this->block_request( $url ) ) 380 return new WP_Error('http_request_failed', 'User has blocked requests through HTTP.'); 381 379 382 // Determine if this is a https call and pass that on to the transport functions 380 383 // so that we can blacklist the transports that do not support ssl verification 381 384 if ( $arrURL['scheme'] == 'https' || $arrURL['scheme'] == 'ssl' ) … … 400 403 $r['user-agent'] = $r['headers']['user-agent']; 401 404 unset($r['headers']['user-agent']); 402 405 } 403 406 404 407 // Construct Cookie: header if any cookies are set 405 408 WP_Http::buildCookieHeader( $r ); 406 409 … … 514 517 /** 515 518 * Transform header string into an array. 516 519 * 517 * If an array is given then it is assumed to be raw header data with 518 * numeric keys with the headers as the values. No headers must be passed 519 * that were already processed. 520 * If an array is given then it is assumed to be raw header data with numeric keys with the 521 * headers as the values. No headers must be passed that were already processed. 520 522 * 521 523 * @access public 522 524 * @static … … 564 566 565 567 /** 566 568 * Takes the arguments for a ::request() and checks for the cookie array. 567 * If it's found, then it's assumed to contain WP_Http_Cookie objects, which568 * are each parsed into strings and added to the Cookie: header (within the569 * arguments array). Edits the array by reference.570 569 * 570 * If it's found, then it's assumed to contain WP_Http_Cookie objects, which are each parsed 571 * into strings and added to the Cookie: header (within the arguments array). Edits the array by 572 * reference. 573 * 571 574 * @access public 575 * @version 2.8.0 572 576 * @static 573 577 * 574 578 * @param array $r Full array of args passed into ::request() … … 583 587 $r['headers']['cookie'] = $cookies_header; 584 588 } 585 589 } 586 590 587 591 /** 588 592 * Decodes chunk transfer-encoding, based off the HTTP 1.1 specification. 589 593 * … … 630 634 } 631 635 } 632 636 } 637 638 /** 639 * Block requests through the proxy. 640 * 641 * Those who are behind a proxy and want to prevent access to certain hosts may do so. This will 642 * prevent plugins from working and core functionality, if you don't include api.wordpress.org. 643 * 644 * You block external URL requests by defining WP_HTTP_BLOCK_EXTERNAL in your wp-config.php file 645 * and this will only allow localhost and your blog to make requests. The constant 646 * WP_ACCESSABLE_HOSTS will allow additional hosts to go through for requests. 647 * 648 * @since unknown 649 * @link http://core.trac.wordpress.org/ticket/8927 Allow preventing external requests. 650 * 651 * @param string $uri URI of url. 652 * @return bool True to block, false to allow. 653 */ 654 function block_request($uri) { 655 // We don't need to block requests, because nothing is blocked. 656 if ( ! defined('WP_HTTP_BLOCK_EXTERNAL') || ( defined('WP_HTTP_BLOCK_EXTERNAL') && WP_HTTP_BLOCK_EXTERNAL == false ) ) 657 return false; 658 659 // parse_url() only handles http, https type URLs, and will emit E_WARNING on failure. 660 // This will be displayed on blogs, which is not reasonable. 661 $check = @parse_url($uri); 662 663 /* Malformed URL, can not process, but this could mean ssl, so let through anyway. 664 * 665 * This isn't very security sound. There are instances where a hacker might attempt 666 * to bypass the proxy and this check. However, the reason for this behavior is that 667 * WordPress does not do any checking currently for non-proxy requests, so it is keeps with 668 * the default unsecure nature of the HTTP request. 669 */ 670 if ( $check === false ) 671 return false; 672 673 $home = parse_url( get_bloginfo('site_url') ); 674 675 if ( $uri == 'localhost' || $uri == $home['host'] ) 676 return false; 677 678 if ( defined('WP_ACCESSABLE_HOSTS') && is_array( WP_ACCESSABLE_HOSTS ) && in_array( $check['host'], WP_ACCESSABLE_HOSTS ) ) { 679 return false; 680 } 681 682 return true; 683 } 633 684 } 634 685 635 686 /** … … 798 849 if ( false !== ($option = get_option( 'disable_fsockopen' )) && time()-$option < 43200 ) // 12 hours 799 850 return false; 800 851 801 if ( function_exists( 'fsockopen' ) )852 if ( function_exists( 'fsockopen' ) && apply_filters('use_fsockopen_transport', true) ) 802 853 return true; 803 854 804 855 return false; … … 911 962 if ( ! function_exists('fopen') || (function_exists('ini_get') && true != ini_get('allow_url_fopen')) ) 912 963 return false; 913 964 914 return true;965 return apply_filters('use_fopen_transport', true); 915 966 } 916 967 } 917 968 … … 955 1006 $r['user-agent'] = $r['headers']['user-agent']; 956 1007 unset($r['headers']['user-agent']); 957 1008 } 958 1009 959 1010 // Construct Cookie: header if any cookies are set 960 1011 WP_Http::buildCookieHeader( $r ); 961 1012 … … 984 1035 'header' => $strHeaders, 985 1036 'timeout' => $r['timeout'], 986 1037 'ssl' => array( 987 988 989 1038 'verify_peer' => apply_filters('https_ssl_verify', $r['sslverify']), 1039 'verify_host' => apply_filters('https_ssl_verify', $r['sslverify']) 1040 ) 990 1041 ) 991 1042 ); 992 1043 … … 1049 1100 if ( version_compare(PHP_VERSION, '5.0', '<') ) 1050 1101 return false; 1051 1102 1052 return true;1103 return apply_filters('use_streams_transport', true); 1053 1104 } 1054 1105 } 1055 1106 … … 1099 1150 // Construct Cookie: header if any cookies are set 1100 1151 WP_Http::buildCookieHeader( $r ); 1101 1152 1153 // Construct Cookie: header if any cookies are set 1154 WP_Http::buildCookieHeader( $r ); 1155 1102 1156 switch ( $r['method'] ) { 1103 1157 case 'POST': 1104 1158 $r['method'] = HTTP_METH_POST; … … 1133 1187 else 1134 1188 $strResponse = http_request($r['method'], $url, $r['body'], $options, $info); //Emits warning level notices for max redirects and timeouts 1135 1189 1136 if ( false === $strResponse || ! empty($info['error']) ) //Error may still be set, Response may return headers or partial document, and error contains a reason the request was aborted, eg, timeout expired or max-redirects reached 1190 // Error may still be set, Response may return headers or partial document, and error 1191 // contains a reason the request was aborted, eg, timeout expired or max-redirects reached. 1192 if ( false === $strResponse || ! empty($info['error']) ) 1137 1193 return new WP_Error('http_request_failed', $info['response_code'] . ': ' . $info['error']); 1138 1194 1139 1195 if ( ! $r['blocking'] ) … … 1168 1224 * @return boolean False means this class can not be used, true means it can. 1169 1225 */ 1170 1226 function test() { 1171 if ( function_exists('http_request') )1227 if ( function_exists('http_request') && apply_filters('use_http_extension_transport', true) ) 1172 1228 return true; 1173 1229 1174 1230 return false; … … 1185 1241 * @since 2.7 1186 1242 */ 1187 1243 class WP_Http_Curl { 1244 1188 1245 /** 1189 1246 * Send a HTTP request to a URI using cURL extension. 1190 1247 * … … 1212 1269 $r['user-agent'] = $r['headers']['user-agent']; 1213 1270 unset($r['headers']['user-agent']); 1214 1271 } 1215 1272 1216 1273 // Construct Cookie: header if any cookies are set 1217 1274 WP_Http::buildCookieHeader( $r ); 1218 1275 … … 1320 1377 * @return boolean False means this class can not be used, true means it can. 1321 1378 */ 1322 1379 function test() { 1323 if ( function_exists('curl_init') && function_exists('curl_exec') )1380 if ( function_exists('curl_init') && function_exists('curl_exec') && apply_filters('use_curl_transport', true) ) 1324 1381 return true; 1325 1382 1326 1383 return false; … … 1329 1386 1330 1387 1331 1388 /** 1332 * Internal representation of a cookie.1389 * Internal representation of a single cookie. 1333 1390 * 1334 1391 * Returned cookies are represented using this class, and when cookies are 1335 1392 * set, if they are not already a WP_Http_Cookie() object, then they are turned 1336 1393 * into one. 1337 1394 * 1395 * @todo The WordPress convention is to use underscores instead of camelCase for function and method 1396 * names. Need to switch to use underscores instead for the methods. 1397 * 1338 1398 * @package WordPress 1339 1399 * @subpackage HTTP 1400 * @since 2.8.0 1401 * @author Beau Lebens 1340 1402 */ 1341 1403 class WP_Http_Cookie { 1342 var $name, 1343 $value, 1344 $expires, 1345 $path, 1346 $domain; 1347 1404 1348 1405 /** 1349 * PHP4 style Constructor - Calls PHP5 Style Constructor 1406 * Cookie name. 1407 * 1408 * @since 2.8.0 1409 * @var string 1350 1410 */ 1411 var $name; 1412 1413 /** 1414 * Cookie value. 1415 * 1416 * @since 2.8.0 1417 * @var string 1418 */ 1419 var $value; 1420 1421 /** 1422 * When the cookie expires. 1423 * 1424 * @since 2.8.0 1425 * @var string 1426 */ 1427 var $expires; 1428 1429 /** 1430 * Cookie URL path. 1431 * 1432 * @since 2.8.0 1433 * @var string 1434 */ 1435 var $path; 1436 1437 /** 1438 * Cookie Domain. 1439 * 1440 * @since 2.8.0 1441 * @var string 1442 */ 1443 var $domain; 1444 1445 /** 1446 * PHP4 style Constructor - Calls PHP5 Style Constructor. 1447 * 1448 * @access public 1449 * @since 2.8.0 1450 * @param string|array $data Raw cookie data. 1451 */ 1351 1452 function WP_Http_Cookie( $data ) { 1352 return$this->__construct( $data );1453 $this->__construct( $data ); 1353 1454 } 1354 1455 1355 1456 /** 1356 1457 * Sets up this cookie object. 1357 1458 * 1459 * The parameter $data should be either an associative array containing the indices names below 1460 * or a header string detailing it. 1461 * 1462 * If it's an array, it should include the following elements: 1463 * <ol> 1464 * <li>Name</li> 1465 * <li>Value - should NOT be urlencoded already.</li> 1466 * <li>Expires - (optional) String or int (UNIX timestamp).</li> 1467 * <li>Path (optional)</li> 1468 * <li>Domain (optional)</li> 1469 * </ol> 1470 * 1358 1471 * @access public 1472 * @since 2.8.0 1359 1473 * 1360 * @param mixed $data Either an associative array describing the cookie, or a header-string detailing it. 1361 * If it's an array, it should include the following elements: 1362 * - name 1363 * - value [should NOT be urlencoded already] 1364 * - expires (optional) String or int (UNIX timestamp) 1365 * - path (optional) 1366 * - domain (optional) 1474 * @param string|array $data Raw cookie data. 1367 1475 */ 1368 1476 function __construct( $data ) { 1369 1477 if ( is_string( $data ) ) { 1370 1478 // Assume it's a header string direct from a previous request 1371 1479 $pairs = explode( ';', $data ); 1372 1480 1373 1481 // Special handling for first pair; name=value. Also be careful of "=" in value 1374 1482 $name = trim( substr( $pairs[0], 0, strpos( $pairs[0], '=' ) ) ); 1375 1483 $value = substr( $pairs[0], strpos( $pairs[0], '=' ) + 1 ); 1376 1484 $this->name = $name; 1377 1485 $this->value = urldecode( $value ); 1378 1486 array_shift( $pairs ); //Removes name=value from items. 1379 1487 1380 1488 // Set everything else as a property 1381 1489 foreach ( $pairs as $pair ) { 1382 1490 if ( empty($pair) ) //Handles the cookie ending in ; which results in a empty final pair 1383 1491 continue; 1492 1384 1493 list( $key, $val ) = explode( '=', $pair ); 1385 1494 $key = strtolower( trim( $key ) ); 1386 1495 if ( 'expires' == $key ) … … 1390 1499 } else { 1391 1500 if ( !isset( $data['name'] ) ) 1392 1501 return false; 1393 1502 1394 1503 // Set properties based directly on parameters 1395 1504 $this->name = $data['name']; 1396 1505 $this->value = isset( $data['value'] ) ? $data['value'] : ''; 1397 1506 $this->path = isset( $data['path'] ) ? $data['path'] : ''; 1398 1507 $this->domain = isset( $data['domain'] ) ? $data['domain'] : ''; 1508 1399 1509 if ( isset( $data['expires'] ) ) 1400 1510 $this->expires = is_int( $data['expires'] ) ? $data['expires'] : strtotime( $data['expires'] ); 1401 1511 else 1402 1512 $this->expires = null; 1403 1513 } 1404 1514 } 1405 1515 1406 1516 /** 1407 1517 * Confirms that it's OK to send this cookie to the URL checked against. 1408 1518 * 1409 1519 * Decision is based on RFC 2109/2965, so look there for details on validity. 1410 1520 * 1411 1521 * @access public 1522 * @since 2.8.0 1412 1523 * 1413 1524 * @param string $url URL you intend to send this cookie to 1414 1525 * @return boolean TRUE if allowed, FALSE otherwise. … … 1417 1528 // Expires - if expired then nothing else matters 1418 1529 if ( time() > $this->expires ) 1419 1530 return false; 1420 1531 1421 1532 // Get details on the URL we're thinking about sending to 1422 1533 $url = parse_url( $url ); 1423 1534 $url['port'] = isset( $url['port'] ) ? $url['port'] : 80; 1424 1535 $url['path'] = isset( $url['path'] ) ? $url['path'] : '/'; 1425 1426 1536 1537 // Values to use for comparison against the URL 1427 1538 $path = isset( $this->path ) ? $this->path : '/'; 1428 1539 $port = isset( $this->port ) ? $this->port : 80; 1429 1540 $domain = isset( $this->domain ) ? strtolower( $this->domain ) : strtolower( $url['host'] ); 1430 1541 if ( false === stripos( $domain, '.' ) ) 1431 1542 $domain .= '.local'; 1432 1543 1433 1544 // Host - very basic check that the request URL ends with the domain restriction (minus leading dot) 1434 1545 $domain = substr( $domain, 0, 1 ) == '.' ? substr( $domain, 1 ) : $domain; 1435 1546 if ( substr( $url['host'], -strlen( $domain ) ) != $domain ) 1436 1547 return false; 1437 1548 1438 1549 // Port - supports "port-lists" in the format: "80,8000,8080" 1439 1550 if ( !in_array( $url['port'], explode( ',', $port) ) ) 1440 1551 return false; 1441 1552 1442 1553 // Path - request path must start with path restriction 1443 1554 if ( substr( $url['path'], 0, strlen( $path ) ) != $path ) 1444 1555 return false; 1445 1556 1446 1557 return true; 1447 1558 } 1448 1559 1560 /** 1561 * Convert cookie name and value back to header string. 1562 * 1563 * @access public 1564 * @since 2.8.0 1565 * 1566 * @return string Header encoded cookie name and value. 1567 */ 1449 1568 function getHeaderValue() { 1450 1569 if ( empty( $this->name ) || empty( $this->value ) ) 1451 1570 return ''; 1452 1571 1453 1572 return $this->name . '=' . urlencode( $this->value ); 1454 1573 } 1455 1574 1575 /** 1576 * Retrieve cookie header for usage in the rest of the WordPress HTTP API. 1577 * 1578 * @access public 1579 * @since 2.8.0 1580 * 1581 * @return string 1582 */ 1456 1583 function getFullHeader() { 1457 1584 return 'Cookie: ' . $this->getHeaderValue(); 1458 1585 }