wp/wp-includes/Requests/Transport/fsockopen.php
author ymh <ymh.work@gmail.com>
Tue, 15 Oct 2019 11:56:20 +0200
changeset 12 d8a8807227e4
parent 7 cf61fcea0001
child 16 a86126ab1dd4
permissions -rw-r--r--
upgrade portofolio
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
7
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
     1
<?php
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
     2
/**
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
     3
 * fsockopen HTTP transport
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
     4
 *
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
     5
 * @package Requests
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
     6
 * @subpackage Transport
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
     7
 */
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
     8
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
     9
/**
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    10
 * fsockopen HTTP transport
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    11
 *
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    12
 * @package Requests
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    13
 * @subpackage Transport
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    14
 */
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    15
class Requests_Transport_fsockopen implements Requests_Transport {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    16
	/**
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    17
	 * Second to microsecond conversion
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    18
	 *
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    19
	 * @var integer
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    20
	 */
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    21
	const SECOND_IN_MICROSECONDS = 1000000;
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    22
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    23
	/**
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    24
	 * Raw HTTP data
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    25
	 *
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    26
	 * @var string
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    27
	 */
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    28
	public $headers = '';
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    29
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    30
	/**
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    31
	 * Stream metadata
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    32
	 *
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    33
	 * @var array Associative array of properties, see {@see https://secure.php.net/stream_get_meta_data}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    34
	 */
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    35
	public $info;
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    36
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    37
	/**
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    38
	 * What's the maximum number of bytes we should keep?
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    39
	 *
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    40
	 * @var int|bool Byte count, or false if no limit.
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    41
	 */
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    42
	protected $max_bytes = false;
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    43
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    44
	protected $connect_error = '';
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    45
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    46
	/**
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    47
	 * Perform a request
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    48
	 *
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    49
	 * @throws Requests_Exception On failure to connect to socket (`fsockopenerror`)
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    50
	 * @throws Requests_Exception On socket timeout (`timeout`)
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    51
	 *
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    52
	 * @param string $url URL to request
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    53
	 * @param array $headers Associative array of request headers
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    54
	 * @param string|array $data Data to send either as the POST body, or as parameters in the URL for a GET/HEAD
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    55
	 * @param array $options Request options, see {@see Requests::response()} for documentation
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    56
	 * @return string Raw HTTP result
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    57
	 */
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    58
	public function request($url, $headers = array(), $data = array(), $options = array()) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    59
		$options['hooks']->dispatch('fsockopen.before_request');
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    60
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    61
		$url_parts = parse_url($url);
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    62
		if (empty($url_parts)) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    63
			throw new Requests_Exception('Invalid URL.', 'invalidurl', $url);
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    64
		}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    65
		$host = $url_parts['host'];
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    66
		$context = stream_context_create();
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    67
		$verifyname = false;
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    68
		$case_insensitive_headers = new Requests_Utility_CaseInsensitiveDictionary($headers);
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    69
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    70
		// HTTPS support
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    71
		if (isset($url_parts['scheme']) && strtolower($url_parts['scheme']) === 'https') {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    72
			$remote_socket = 'ssl://' . $host;
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    73
			if (!isset($url_parts['port'])) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    74
				$url_parts['port'] = 443;
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    75
			}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    76
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    77
			$context_options = array(
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    78
				'verify_peer' => true,
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    79
				// 'CN_match' => $host,
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    80
				'capture_peer_cert' => true
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    81
			);
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    82
			$verifyname = true;
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    83
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    84
			// SNI, if enabled (OpenSSL >=0.9.8j)
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    85
			if (defined('OPENSSL_TLSEXT_SERVER_NAME') && OPENSSL_TLSEXT_SERVER_NAME) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    86
				$context_options['SNI_enabled'] = true;
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    87
				if (isset($options['verifyname']) && $options['verifyname'] === false) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    88
					$context_options['SNI_enabled'] = false;
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    89
				}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    90
			}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    91
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    92
			if (isset($options['verify'])) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    93
				if ($options['verify'] === false) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    94
					$context_options['verify_peer'] = false;
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    95
				}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    96
				elseif (is_string($options['verify'])) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    97
					$context_options['cafile'] = $options['verify'];
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    98
				}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
    99
			}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   100
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   101
			if (isset($options['verifyname']) && $options['verifyname'] === false) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   102
				$context_options['verify_peer_name'] = false;
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   103
				$verifyname = false;
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   104
			}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   105
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   106
			stream_context_set_option($context, array('ssl' => $context_options));
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   107
		}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   108
		else {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   109
			$remote_socket = 'tcp://' . $host;
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   110
		}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   111
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   112
		$this->max_bytes = $options['max_bytes'];
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   113
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   114
		if (!isset($url_parts['port'])) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   115
			$url_parts['port'] = 80;
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   116
		}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   117
		$remote_socket .= ':' . $url_parts['port'];
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   118
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   119
		set_error_handler(array($this, 'connect_error_handler'), E_WARNING | E_NOTICE);
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   120
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   121
		$options['hooks']->dispatch('fsockopen.remote_socket', array(&$remote_socket));
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   122
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   123
		$socket = stream_socket_client($remote_socket, $errno, $errstr, ceil($options['connect_timeout']), STREAM_CLIENT_CONNECT, $context);
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   124
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   125
		restore_error_handler();
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   126
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   127
		if ($verifyname && !$this->verify_certificate_from_context($host, $context)) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   128
			throw new Requests_Exception('SSL certificate did not match the requested domain name', 'ssl.no_match');
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   129
		}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   130
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   131
		if (!$socket) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   132
			if ($errno === 0) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   133
				// Connection issue
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   134
				throw new Requests_Exception(rtrim($this->connect_error), 'fsockopen.connect_error');
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   135
			}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   136
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   137
			throw new Requests_Exception($errstr, 'fsockopenerror', null, $errno);
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   138
		}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   139
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   140
		$data_format = $options['data_format'];
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   141
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   142
		if ($data_format === 'query') {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   143
			$path = self::format_get($url_parts, $data);
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   144
			$data = '';
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   145
		}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   146
		else {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   147
			$path = self::format_get($url_parts, array());
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   148
		}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   149
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   150
		$options['hooks']->dispatch('fsockopen.remote_host_path', array(&$path, $url));
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   151
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   152
		$request_body = '';
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   153
		$out = sprintf("%s %s HTTP/%.1f\r\n", $options['type'], $path, $options['protocol_version']);
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   154
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   155
		if ($options['type'] !== Requests::TRACE) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   156
			if (is_array($data)) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   157
				$request_body = http_build_query($data, null, '&');
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   158
			}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   159
			else {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   160
				$request_body = $data;
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   161
			}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   162
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   163
			if (!empty($data)) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   164
				if (!isset($case_insensitive_headers['Content-Length'])) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   165
					$headers['Content-Length'] = strlen($request_body);
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   166
				}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   167
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   168
				if (!isset($case_insensitive_headers['Content-Type'])) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   169
					$headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   170
				}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   171
			}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   172
		}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   173
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   174
		if (!isset($case_insensitive_headers['Host'])) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   175
			$out .= sprintf('Host: %s', $url_parts['host']);
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   176
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   177
			if (( 'http' === strtolower($url_parts['scheme']) && $url_parts['port'] !== 80 ) || ( 'https' === strtolower($url_parts['scheme']) && $url_parts['port'] !== 443 )) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   178
				$out .= ':' . $url_parts['port'];
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   179
			}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   180
			$out .= "\r\n";
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   181
		}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   182
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   183
		if (!isset($case_insensitive_headers['User-Agent'])) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   184
			$out .= sprintf("User-Agent: %s\r\n", $options['useragent']);
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   185
		}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   186
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   187
		$accept_encoding = $this->accept_encoding();
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   188
		if (!isset($case_insensitive_headers['Accept-Encoding']) && !empty($accept_encoding)) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   189
			$out .= sprintf("Accept-Encoding: %s\r\n", $accept_encoding);
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   190
		}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   191
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   192
		$headers = Requests::flatten($headers);
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   193
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   194
		if (!empty($headers)) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   195
			$out .= implode($headers, "\r\n") . "\r\n";
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   196
		}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   197
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   198
		$options['hooks']->dispatch('fsockopen.after_headers', array(&$out));
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   199
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   200
		if (substr($out, -2) !== "\r\n") {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   201
			$out .= "\r\n";
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   202
		}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   203
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   204
		if (!isset($case_insensitive_headers['Connection'])) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   205
			$out .= "Connection: Close\r\n";
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   206
		}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   207
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   208
		$out .= "\r\n" . $request_body;
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   209
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   210
		$options['hooks']->dispatch('fsockopen.before_send', array(&$out));
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   211
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   212
		fwrite($socket, $out);
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   213
		$options['hooks']->dispatch('fsockopen.after_send', array($out));
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   214
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   215
		if (!$options['blocking']) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   216
			fclose($socket);
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   217
			$fake_headers = '';
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   218
			$options['hooks']->dispatch('fsockopen.after_request', array(&$fake_headers));
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   219
			return '';
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   220
		}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   221
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   222
		$timeout_sec = (int) floor($options['timeout']);
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   223
		if ($timeout_sec == $options['timeout']) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   224
			$timeout_msec = 0;
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   225
		}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   226
		else {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   227
			$timeout_msec = self::SECOND_IN_MICROSECONDS * $options['timeout'] % self::SECOND_IN_MICROSECONDS;
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   228
		}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   229
		stream_set_timeout($socket, $timeout_sec, $timeout_msec);
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   230
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   231
		$response = $body = $headers = '';
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   232
		$this->info = stream_get_meta_data($socket);
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   233
		$size = 0;
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   234
		$doingbody = false;
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   235
		$download = false;
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   236
		if ($options['filename']) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   237
			$download = fopen($options['filename'], 'wb');
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   238
		}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   239
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   240
		while (!feof($socket)) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   241
			$this->info = stream_get_meta_data($socket);
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   242
			if ($this->info['timed_out']) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   243
				throw new Requests_Exception('fsocket timed out', 'timeout');
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   244
			}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   245
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   246
			$block = fread($socket, Requests::BUFFER_SIZE);
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   247
			if (!$doingbody) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   248
				$response .= $block;
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   249
				if (strpos($response, "\r\n\r\n")) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   250
					list($headers, $block) = explode("\r\n\r\n", $response, 2);
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   251
					$doingbody = true;
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   252
				}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   253
			}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   254
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   255
			// Are we in body mode now?
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   256
			if ($doingbody) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   257
				$options['hooks']->dispatch('request.progress', array($block, $size, $this->max_bytes));
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   258
				$data_length = strlen($block);
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   259
				if ($this->max_bytes) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   260
					// Have we already hit a limit?
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   261
					if ($size === $this->max_bytes) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   262
						continue;
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   263
					}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   264
					if (($size + $data_length) > $this->max_bytes) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   265
						// Limit the length
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   266
						$limited_length = ($this->max_bytes - $size);
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   267
						$block = substr($block, 0, $limited_length);
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   268
					}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   269
				}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   270
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   271
				$size += strlen($block);
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   272
				if ($download) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   273
					fwrite($download, $block);
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   274
				}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   275
				else {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   276
					$body .= $block;
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   277
				}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   278
			}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   279
		}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   280
		$this->headers = $headers;
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   281
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   282
		if ($download) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   283
			fclose($download);
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   284
		}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   285
		else {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   286
			$this->headers .= "\r\n\r\n" . $body;
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   287
		}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   288
		fclose($socket);
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   289
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   290
		$options['hooks']->dispatch('fsockopen.after_request', array(&$this->headers, &$this->info));
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   291
		return $this->headers;
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   292
	}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   293
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   294
	/**
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   295
	 * Send multiple requests simultaneously
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   296
	 *
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   297
	 * @param array $requests Request data (array of 'url', 'headers', 'data', 'options') as per {@see Requests_Transport::request}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   298
	 * @param array $options Global options, see {@see Requests::response()} for documentation
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   299
	 * @return array Array of Requests_Response objects (may contain Requests_Exception or string responses as well)
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   300
	 */
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   301
	public function request_multiple($requests, $options) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   302
		$responses = array();
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   303
		$class = get_class($this);
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   304
		foreach ($requests as $id => $request) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   305
			try {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   306
				$handler = new $class();
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   307
				$responses[$id] = $handler->request($request['url'], $request['headers'], $request['data'], $request['options']);
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   308
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   309
				$request['options']['hooks']->dispatch('transport.internal.parse_response', array(&$responses[$id], $request));
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   310
			}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   311
			catch (Requests_Exception $e) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   312
				$responses[$id] = $e;
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   313
			}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   314
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   315
			if (!is_string($responses[$id])) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   316
				$request['options']['hooks']->dispatch('multiple.request.complete', array(&$responses[$id], $id));
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   317
			}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   318
		}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   319
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   320
		return $responses;
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   321
	}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   322
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   323
	/**
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   324
	 * Retrieve the encodings we can accept
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   325
	 *
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   326
	 * @return string Accept-Encoding header value
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   327
	 */
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   328
	protected static function accept_encoding() {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   329
		$type = array();
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   330
		if (function_exists('gzinflate')) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   331
			$type[] = 'deflate;q=1.0';
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   332
		}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   333
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   334
		if (function_exists('gzuncompress')) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   335
			$type[] = 'compress;q=0.5';
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   336
		}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   337
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   338
		$type[] = 'gzip;q=0.5';
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   339
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   340
		return implode(', ', $type);
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   341
	}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   342
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   343
	/**
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   344
	 * Format a URL given GET data
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   345
	 *
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   346
	 * @param array $url_parts
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   347
	 * @param array|object $data Data to build query using, see {@see https://secure.php.net/http_build_query}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   348
	 * @return string URL with data
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   349
	 */
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   350
	protected static function format_get($url_parts, $data) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   351
		if (!empty($data)) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   352
			if (empty($url_parts['query'])) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   353
				$url_parts['query'] = '';
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   354
			}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   355
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   356
			$url_parts['query'] .= '&' . http_build_query($data, null, '&');
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   357
			$url_parts['query'] = trim($url_parts['query'], '&');
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   358
		}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   359
		if (isset($url_parts['path'])) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   360
			if (isset($url_parts['query'])) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   361
				$get = $url_parts['path'] . '?' . $url_parts['query'];
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   362
			}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   363
			else {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   364
				$get = $url_parts['path'];
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   365
			}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   366
		}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   367
		else {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   368
			$get = '/';
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   369
		}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   370
		return $get;
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   371
	}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   372
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   373
	/**
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   374
	 * Error handler for stream_socket_client()
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   375
	 *
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   376
	 * @param int $errno Error number (e.g. E_WARNING)
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   377
	 * @param string $errstr Error message
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   378
	 */
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   379
	public function connect_error_handler($errno, $errstr) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   380
		// Double-check we can handle it
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   381
		if (($errno & E_WARNING) === 0 && ($errno & E_NOTICE) === 0) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   382
			// Return false to indicate the default error handler should engage
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   383
			return false;
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   384
		}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   385
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   386
		$this->connect_error .= $errstr . "\n";
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   387
		return true;
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   388
	}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   389
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   390
	/**
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   391
	 * Verify the certificate against common name and subject alternative names
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   392
	 *
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   393
	 * Unfortunately, PHP doesn't check the certificate against the alternative
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   394
	 * names, leading things like 'https://www.github.com/' to be invalid.
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   395
	 * Instead
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   396
	 *
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   397
	 * @see https://tools.ietf.org/html/rfc2818#section-3.1 RFC2818, Section 3.1
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   398
	 *
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   399
	 * @throws Requests_Exception On failure to connect via TLS (`fsockopen.ssl.connect_error`)
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   400
	 * @throws Requests_Exception On not obtaining a match for the host (`fsockopen.ssl.no_match`)
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   401
	 * @param string $host Host name to verify against
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   402
	 * @param resource $context Stream context
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   403
	 * @return bool
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   404
	 */
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   405
	public function verify_certificate_from_context($host, $context) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   406
		$meta = stream_context_get_options($context);
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   407
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   408
		// If we don't have SSL options, then we couldn't make the connection at
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   409
		// all
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   410
		if (empty($meta) || empty($meta['ssl']) || empty($meta['ssl']['peer_certificate'])) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   411
			throw new Requests_Exception(rtrim($this->connect_error), 'ssl.connect_error');
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   412
		}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   413
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   414
		$cert = openssl_x509_parse($meta['ssl']['peer_certificate']);
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   415
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   416
		return Requests_SSL::verify_certificate($host, $cert);
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   417
	}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   418
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   419
	/**
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   420
	 * Whether this transport is valid
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   421
	 *
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   422
	 * @codeCoverageIgnore
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   423
	 * @return boolean True if the transport is valid, false otherwise.
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   424
	 */
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   425
	public static function test($capabilities = array()) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   426
		if (!function_exists('fsockopen')) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   427
			return false;
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   428
		}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   429
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   430
		// If needed, check that streams support SSL
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   431
		if (isset($capabilities['ssl']) && $capabilities['ssl']) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   432
			if (!extension_loaded('openssl') || !function_exists('openssl_x509_parse')) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   433
				return false;
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   434
			}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   435
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   436
			// Currently broken, thanks to https://github.com/facebook/hhvm/issues/2156
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   437
			if (defined('HHVM_VERSION')) {
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   438
				return false;
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   439
			}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   440
		}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   441
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   442
		return true;
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   443
	}
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
diff changeset
   444
}