|
1 <?php |
|
2 /** |
|
3 * HTTP API: WP_HTTP_Proxy class |
|
4 * |
|
5 * @package WordPress |
|
6 * @subpackage HTTP |
|
7 * @since 4.4.0 |
|
8 */ |
|
9 |
|
10 /** |
|
11 * Core class used to implement HTTP API proxy support. |
|
12 * |
|
13 * There are caveats to proxy support. It requires that defines be made in the wp-config.php file to |
|
14 * enable proxy support. There are also a few filters that plugins can hook into for some of the |
|
15 * constants. |
|
16 * |
|
17 * Please note that only BASIC authentication is supported by most transports. |
|
18 * cURL MAY support more methods (such as NTLM authentication) depending on your environment. |
|
19 * |
|
20 * The constants are as follows: |
|
21 * <ol> |
|
22 * <li>WP_PROXY_HOST - Enable proxy support and host for connecting.</li> |
|
23 * <li>WP_PROXY_PORT - Proxy port for connection. No default, must be defined.</li> |
|
24 * <li>WP_PROXY_USERNAME - Proxy username, if it requires authentication.</li> |
|
25 * <li>WP_PROXY_PASSWORD - Proxy password, if it requires authentication.</li> |
|
26 * <li>WP_PROXY_BYPASS_HOSTS - Will prevent the hosts in this list from going through the proxy. |
|
27 * You do not need to have localhost and the site host in this list, because they will not be passed |
|
28 * through the proxy. The list should be presented in a comma separated list, wildcards using * are supported, eg. *.wordpress.org</li> |
|
29 * </ol> |
|
30 * |
|
31 * An example can be as seen below. |
|
32 * |
|
33 * define('WP_PROXY_HOST', '192.168.84.101'); |
|
34 * define('WP_PROXY_PORT', '8080'); |
|
35 * define('WP_PROXY_BYPASS_HOSTS', 'localhost, www.example.com, *.wordpress.org'); |
|
36 * |
|
37 * @link https://core.trac.wordpress.org/ticket/4011 Proxy support ticket in WordPress. |
|
38 * @link https://core.trac.wordpress.org/ticket/14636 Allow wildcard domains in WP_PROXY_BYPASS_HOSTS |
|
39 * |
|
40 * @since 2.8.0 |
|
41 */ |
|
42 class WP_HTTP_Proxy { |
|
43 |
|
44 /** |
|
45 * Whether proxy connection should be used. |
|
46 * |
|
47 * @since 2.8.0 |
|
48 * |
|
49 * @use WP_PROXY_HOST |
|
50 * @use WP_PROXY_PORT |
|
51 * |
|
52 * @return bool |
|
53 */ |
|
54 public function is_enabled() { |
|
55 return defined('WP_PROXY_HOST') && defined('WP_PROXY_PORT'); |
|
56 } |
|
57 |
|
58 /** |
|
59 * Whether authentication should be used. |
|
60 * |
|
61 * @since 2.8.0 |
|
62 * |
|
63 * @use WP_PROXY_USERNAME |
|
64 * @use WP_PROXY_PASSWORD |
|
65 * |
|
66 * @return bool |
|
67 */ |
|
68 public function use_authentication() { |
|
69 return defined('WP_PROXY_USERNAME') && defined('WP_PROXY_PASSWORD'); |
|
70 } |
|
71 |
|
72 /** |
|
73 * Retrieve the host for the proxy server. |
|
74 * |
|
75 * @since 2.8.0 |
|
76 * |
|
77 * @return string |
|
78 */ |
|
79 public function host() { |
|
80 if ( defined('WP_PROXY_HOST') ) |
|
81 return WP_PROXY_HOST; |
|
82 |
|
83 return ''; |
|
84 } |
|
85 |
|
86 /** |
|
87 * Retrieve the port for the proxy server. |
|
88 * |
|
89 * @since 2.8.0 |
|
90 * |
|
91 * @return string |
|
92 */ |
|
93 public function port() { |
|
94 if ( defined('WP_PROXY_PORT') ) |
|
95 return WP_PROXY_PORT; |
|
96 |
|
97 return ''; |
|
98 } |
|
99 |
|
100 /** |
|
101 * Retrieve the username for proxy authentication. |
|
102 * |
|
103 * @since 2.8.0 |
|
104 * |
|
105 * @return string |
|
106 */ |
|
107 public function username() { |
|
108 if ( defined('WP_PROXY_USERNAME') ) |
|
109 return WP_PROXY_USERNAME; |
|
110 |
|
111 return ''; |
|
112 } |
|
113 |
|
114 /** |
|
115 * Retrieve the password for proxy authentication. |
|
116 * |
|
117 * @since 2.8.0 |
|
118 * |
|
119 * @return string |
|
120 */ |
|
121 public function password() { |
|
122 if ( defined('WP_PROXY_PASSWORD') ) |
|
123 return WP_PROXY_PASSWORD; |
|
124 |
|
125 return ''; |
|
126 } |
|
127 |
|
128 /** |
|
129 * Retrieve authentication string for proxy authentication. |
|
130 * |
|
131 * @since 2.8.0 |
|
132 * |
|
133 * @return string |
|
134 */ |
|
135 public function authentication() { |
|
136 return $this->username() . ':' . $this->password(); |
|
137 } |
|
138 |
|
139 /** |
|
140 * Retrieve header string for proxy authentication. |
|
141 * |
|
142 * @since 2.8.0 |
|
143 * |
|
144 * @return string |
|
145 */ |
|
146 public function authentication_header() { |
|
147 return 'Proxy-Authorization: Basic ' . base64_encode( $this->authentication() ); |
|
148 } |
|
149 |
|
150 /** |
|
151 * Whether URL should be sent through the proxy server. |
|
152 * |
|
153 * We want to keep localhost and the site URL from being sent through the proxy server, because |
|
154 * some proxies can not handle this. We also have the constant available for defining other |
|
155 * hosts that won't be sent through the proxy. |
|
156 * |
|
157 * @since 2.8.0 |
|
158 * |
|
159 * @staticvar array|null $bypass_hosts |
|
160 * @staticvar array $wildcard_regex |
|
161 * |
|
162 * @param string $uri URI to check. |
|
163 * @return bool True, to send through the proxy and false if, the proxy should not be used. |
|
164 */ |
|
165 public function send_through_proxy( $uri ) { |
|
166 /* |
|
167 * parse_url() only handles http, https type URLs, and will emit E_WARNING on failure. |
|
168 * This will be displayed on sites, which is not reasonable. |
|
169 */ |
|
170 $check = @parse_url($uri); |
|
171 |
|
172 // Malformed URL, can not process, but this could mean ssl, so let through anyway. |
|
173 if ( $check === false ) |
|
174 return true; |
|
175 |
|
176 $home = parse_url( get_option('siteurl') ); |
|
177 |
|
178 /** |
|
179 * Filters whether to preempt sending the request through the proxy server. |
|
180 * |
|
181 * Returning false will bypass the proxy; returning true will send |
|
182 * the request through the proxy. Returning null bypasses the filter. |
|
183 * |
|
184 * @since 3.5.0 |
|
185 * |
|
186 * @param null $override Whether to override the request result. Default null. |
|
187 * @param string $uri URL to check. |
|
188 * @param array $check Associative array result of parsing the URI. |
|
189 * @param array $home Associative array result of parsing the site URL. |
|
190 */ |
|
191 $result = apply_filters( 'pre_http_send_through_proxy', null, $uri, $check, $home ); |
|
192 if ( ! is_null( $result ) ) |
|
193 return $result; |
|
194 |
|
195 if ( 'localhost' == $check['host'] || ( isset( $home['host'] ) && $home['host'] == $check['host'] ) ) |
|
196 return false; |
|
197 |
|
198 if ( !defined('WP_PROXY_BYPASS_HOSTS') ) |
|
199 return true; |
|
200 |
|
201 static $bypass_hosts = null; |
|
202 static $wildcard_regex = array(); |
|
203 if ( null === $bypass_hosts ) { |
|
204 $bypass_hosts = preg_split('|,\s*|', WP_PROXY_BYPASS_HOSTS); |
|
205 |
|
206 if ( false !== strpos(WP_PROXY_BYPASS_HOSTS, '*') ) { |
|
207 $wildcard_regex = array(); |
|
208 foreach ( $bypass_hosts as $host ) |
|
209 $wildcard_regex[] = str_replace( '\*', '.+', preg_quote( $host, '/' ) ); |
|
210 $wildcard_regex = '/^(' . implode('|', $wildcard_regex) . ')$/i'; |
|
211 } |
|
212 } |
|
213 |
|
214 if ( !empty($wildcard_regex) ) |
|
215 return !preg_match($wildcard_regex, $check['host']); |
|
216 else |
|
217 return !in_array( $check['host'], $bypass_hosts ); |
|
218 } |
|
219 } |