WordPress 4.5
[autoinstalls/wordpress.git] / wp-includes / class-wp-http-proxy.php
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                  * Filter 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 }