|
1 <?php |
|
2 /** |
|
3 * HTTP Proxy connection interface |
|
4 * |
|
5 * @package Requests\Proxy |
|
6 * @since 1.6 |
|
7 */ |
|
8 |
|
9 namespace WpOrg\Requests\Proxy; |
|
10 |
|
11 use WpOrg\Requests\Exception\ArgumentCount; |
|
12 use WpOrg\Requests\Exception\InvalidArgument; |
|
13 use WpOrg\Requests\Hooks; |
|
14 use WpOrg\Requests\Proxy; |
|
15 |
|
16 /** |
|
17 * HTTP Proxy connection interface |
|
18 * |
|
19 * Provides a handler for connection via an HTTP proxy |
|
20 * |
|
21 * @package Requests\Proxy |
|
22 * @since 1.6 |
|
23 */ |
|
24 final class Http implements Proxy { |
|
25 /** |
|
26 * Proxy host and port |
|
27 * |
|
28 * Notation: "host:port" (eg 127.0.0.1:8080 or someproxy.com:3128) |
|
29 * |
|
30 * @var string |
|
31 */ |
|
32 public $proxy; |
|
33 |
|
34 /** |
|
35 * Username |
|
36 * |
|
37 * @var string |
|
38 */ |
|
39 public $user; |
|
40 |
|
41 /** |
|
42 * Password |
|
43 * |
|
44 * @var string |
|
45 */ |
|
46 public $pass; |
|
47 |
|
48 /** |
|
49 * Do we need to authenticate? (ie username & password have been provided) |
|
50 * |
|
51 * @var boolean |
|
52 */ |
|
53 public $use_authentication; |
|
54 |
|
55 /** |
|
56 * Constructor |
|
57 * |
|
58 * @since 1.6 |
|
59 * |
|
60 * @param array|string|null $args Proxy as a string or an array of proxy, user and password. |
|
61 * When passed as an array, must have exactly one (proxy) |
|
62 * or three elements (proxy, user, password). |
|
63 * |
|
64 * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed argument is not an array, a string or null. |
|
65 * @throws \WpOrg\Requests\Exception\ArgumentCount On incorrect number of arguments (`proxyhttpbadargs`) |
|
66 */ |
|
67 public function __construct($args = null) { |
|
68 if (is_string($args)) { |
|
69 $this->proxy = $args; |
|
70 } elseif (is_array($args)) { |
|
71 if (count($args) === 1) { |
|
72 list($this->proxy) = $args; |
|
73 } elseif (count($args) === 3) { |
|
74 list($this->proxy, $this->user, $this->pass) = $args; |
|
75 $this->use_authentication = true; |
|
76 } else { |
|
77 throw ArgumentCount::create( |
|
78 'an array with exactly one element or exactly three elements', |
|
79 count($args), |
|
80 'proxyhttpbadargs' |
|
81 ); |
|
82 } |
|
83 } elseif ($args !== null) { |
|
84 throw InvalidArgument::create(1, '$args', 'array|string|null', gettype($args)); |
|
85 } |
|
86 } |
|
87 |
|
88 /** |
|
89 * Register the necessary callbacks |
|
90 * |
|
91 * @since 1.6 |
|
92 * @see \WpOrg\Requests\Proxy\Http::curl_before_send() |
|
93 * @see \WpOrg\Requests\Proxy\Http::fsockopen_remote_socket() |
|
94 * @see \WpOrg\Requests\Proxy\Http::fsockopen_remote_host_path() |
|
95 * @see \WpOrg\Requests\Proxy\Http::fsockopen_header() |
|
96 * @param \WpOrg\Requests\Hooks $hooks Hook system |
|
97 */ |
|
98 public function register(Hooks $hooks) { |
|
99 $hooks->register('curl.before_send', [$this, 'curl_before_send']); |
|
100 |
|
101 $hooks->register('fsockopen.remote_socket', [$this, 'fsockopen_remote_socket']); |
|
102 $hooks->register('fsockopen.remote_host_path', [$this, 'fsockopen_remote_host_path']); |
|
103 if ($this->use_authentication) { |
|
104 $hooks->register('fsockopen.after_headers', [$this, 'fsockopen_header']); |
|
105 } |
|
106 } |
|
107 |
|
108 /** |
|
109 * Set cURL parameters before the data is sent |
|
110 * |
|
111 * @since 1.6 |
|
112 * @param resource|\CurlHandle $handle cURL handle |
|
113 */ |
|
114 public function curl_before_send(&$handle) { |
|
115 curl_setopt($handle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); |
|
116 curl_setopt($handle, CURLOPT_PROXY, $this->proxy); |
|
117 |
|
118 if ($this->use_authentication) { |
|
119 curl_setopt($handle, CURLOPT_PROXYAUTH, CURLAUTH_ANY); |
|
120 curl_setopt($handle, CURLOPT_PROXYUSERPWD, $this->get_auth_string()); |
|
121 } |
|
122 } |
|
123 |
|
124 /** |
|
125 * Alter remote socket information before opening socket connection |
|
126 * |
|
127 * @since 1.6 |
|
128 * @param string $remote_socket Socket connection string |
|
129 */ |
|
130 public function fsockopen_remote_socket(&$remote_socket) { |
|
131 $remote_socket = $this->proxy; |
|
132 } |
|
133 |
|
134 /** |
|
135 * Alter remote path before getting stream data |
|
136 * |
|
137 * @since 1.6 |
|
138 * @param string $path Path to send in HTTP request string ("GET ...") |
|
139 * @param string $url Full URL we're requesting |
|
140 */ |
|
141 public function fsockopen_remote_host_path(&$path, $url) { |
|
142 $path = $url; |
|
143 } |
|
144 |
|
145 /** |
|
146 * Add extra headers to the request before sending |
|
147 * |
|
148 * @since 1.6 |
|
149 * @param string $out HTTP header string |
|
150 */ |
|
151 public function fsockopen_header(&$out) { |
|
152 $out .= sprintf("Proxy-Authorization: Basic %s\r\n", base64_encode($this->get_auth_string())); |
|
153 } |
|
154 |
|
155 /** |
|
156 * Get the authentication string (user:pass) |
|
157 * |
|
158 * @since 1.6 |
|
159 * @return string |
|
160 */ |
|
161 public function get_auth_string() { |
|
162 return $this->user . ':' . $this->pass; |
|
163 } |
|
164 } |