Example #1
0
 /**
  * Make API request
  *
  * @param string  $url
  * @return string
  */
 function _request($url)
 {
     $request_url = Util_Environment::url_format(W3TC_PAGESPEED_API_URL, array('url' => $url, 'key' => $this->key));
     $response = Util_Http::get($request_url, array('timeout' => 120));
     if (!is_wp_error($response) && $response['response']['code'] == 200) {
         return $response['body'];
     }
     return false;
 }
 /**
  * Check
  *
  * @throws Util_WpFile_FilesystemOperationException
  * @throws FileOperationException
  */
 public function get_ip_ranges()
 {
     $data = array();
     $response = Util_Http::get('https://www.cloudflare.com/ips-v4');
     if (!is_wp_error($response)) {
         $ip4_data = $response['body'];
         $ip4_data = explode("\n", $ip4_data);
         $data['ip4'] = $ip4_data;
     }
     $response = Util_Http::get('https://www.cloudflare.com/ips-v6');
     if (!is_wp_error($response)) {
         $ip6_data = $response['body'];
         $ip6_data = explode("\n", $ip6_data);
         $data['ip6'] = $ip6_data;
     }
     return $data;
 }
 /**
  * Makes get requests to url specific to a post, its permalink
  *
  * @param unknown $post_id
  * @return boolean returns true on success
  */
 public function prime_post($post_id)
 {
     $post_urls = Util_PageUrls::get_post_urls($post_id);
     // Make HTTP requests and prime cache
     foreach ($post_urls as $url) {
         $result = Util_Http::get($url, array('user-agent' => ''));
         if (is_wp_error($result)) {
             return false;
         }
     }
     return true;
 }
 /**
  * Perform rewrite test
  *
  * @param string  $url
  * @return boolean
  */
 private function test_rewrite($url)
 {
     $key = sprintf('w3tc_rewrite_test_%s', substr(md5($url), 0, 16));
     $result = get_site_transient($key);
     if ($result != 'ok') {
         $response = Util_Http::get($url);
         $is_ok = !is_wp_error($response) && $response['response']['code'] == 200 && trim($response['body']) == 'OK';
         if ($is_ok) {
             $result = 'ok';
         } else {
             $result = is_wp_error($response) ? $response->get_error_message() : implode(' ', $response['response']);
         }
         set_site_transient($key, $result, 30);
     }
     return $result;
 }
 /**
  * Pre-caches external file
  *
  * @param string  $url
  * @param string  $type
  * @return string
  */
 function _precache_file($url, $type)
 {
     $lifetime = $this->_config->get_integer('minify.lifetime');
     $cache_path = sprintf('%s/minify_%s.%s', Util_Environment::cache_blog_dir('minify'), md5($url), $type);
     if (!file_exists($cache_path) || @filemtime($cache_path) < time() - $lifetime) {
         if (!@is_dir(dirname($cache_path))) {
             Util_File::mkdir_from(dirname($cache_path), W3TC_CACHE_DIR);
         }
         Util_Http::download($url, $cache_path);
     }
     return file_exists($cache_path) ? $this->_get_minify_source($cache_path, $url) : false;
 }
Example #6
0
 /**
  * Returns theme recommendations
  *
  * @param string  $theme_name
  * @return array
  */
 function get_theme_recommendations($theme_name)
 {
     $urls = $this->get_theme_urls($theme_name);
     $js_groups = array();
     $css_groups = array();
     @set_time_limit($this->_config->get_integer('timelimit.minify_recommendations'));
     foreach ($urls as $template => $url) {
         /**
          * Append theme identifier
          */
         $url .= (strstr($url, '?') !== false ? '&' : '?') . 'w3tc_theme=' . urlencode($theme_name);
         /**
          * If preview mode enabled append w3tc_preview
          */
         if ($this->_config->is_preview()) {
             $url .= '&w3tc_preview=1';
         }
         /**
          * Get page contents
          */
         $response = Util_Http::get($url);
         if (!is_wp_error($response) && ($response['response']['code'] == 200 || $response['response']['code'] == 404 && $template == '404')) {
             $js_files = $this->get_recommendations_js($response['body']);
             $css_files = $this->get_recommendations_css($response['body']);
             $js_groups[$template] = $js_files;
             $css_groups[$template] = $css_files;
         }
     }
     $js_groups = $this->get_theme_recommendations_by_groups($js_groups);
     $css_groups = $this->get_theme_recommendations_by_groups($css_groups);
     $recommendations = array($js_groups, $css_groups);
     return $recommendations;
 }
 function w3tc_errors($errors)
 {
     $c = Dispatcher::config();
     $state = Dispatcher::config_state();
     $cdn_engine = $c->get_string('cdn.engine');
     if (Cdn_Util::is_engine_push($cdn_engine)) {
         /**
          * Show notification if upload queue is not empty
          */
         try {
             if (!($error = get_transient('w3tc_cdn_error')) && !$this->_is_queue_empty()) {
                 $errors['cdn_unsuccessful_queue'] = sprintf(__('The %s has unresolved errors. Empty the queue to restore normal operation.', 'w3-total-cache'), Util_Ui::button_popup(__('unsuccessful transfer queue', 'w3-total-cache'), 'cdn_queue'));
             } elseif ($error) {
                 $errors['cdn_generic'] = $error;
             }
         } catch (\Exception $ex) {
             $errors[] = $ex->getMessage();
             set_transient('w3tc_cdn_error', $ex->getMessage(), 30);
         }
         /**
          * Check upload settings
          */
         $upload_info = Util_Http::upload_info();
         if (!$upload_info) {
             $upload_path = get_option('upload_path');
             $upload_path = trim($upload_path);
             if (empty($upload_path)) {
                 $upload_path = WP_CONTENT_DIR . '/uploads';
                 $errors['cdn_uploads_folder_empty'] = sprintf(__('The uploads directory is not available. Default WordPress directories will be created: <strong>%s</strong>.', 'w3-total-cache'), $upload_path);
             }
             if (!Util_Environment::is_wpmu()) {
                 $errors['cdn_uploads_folder_not_found'] = sprintf(__('The uploads path found in the database (%s) is inconsistent with the actual path. Please manually adjust the upload path either in miscellaneous settings or if not using a custom path %s automatically to resolve the issue.', 'w3-total-cache'), $upload_path, Util_Ui::button_link(__('update the path', 'w3-total-cache'), Util_Ui::url(array('w3tc_config_update_upload_path' => 'y'))));
             }
         }
     }
     /**
      * Check CDN settings
      */
     $error = '';
     switch (true) {
         case $cdn_engine == 'ftp' && !count($c->get_array('cdn.ftp.domain')):
             $errors['cdn_ftp_empty'] = __('A configuration issue prevents <acronym title="Content Delivery Network">CDN</acronym> from working:
                                     The <strong>"Replace default hostname with"</strong>
                                     field cannot be empty. Enter <acronym
                                     title="Content Delivery Network">CDN</acronym>
                                     provider hostname <a href="?page=w3tc_cdn#configuration">here</a>.
                                     <em>(This is the hostname used in order to view objects
                                     in a browser.)</em>', 'w3-total-cache');
             break;
         case $cdn_engine == 's3' && ($c->get_string('cdn.s3.key') == '' || $c->get_string('cdn.s3.secret') == '' || $c->get_string('cdn.s3.bucket') == ''):
             $error = __('The <strong>"Access key", "Secret key" and "Bucket"</strong> fields cannot be empty.', 'w3-total-cache');
             break;
         case $cdn_engine == 'cf' && ($c->get_string('cdn.cf.key') == '' || $c->get_string('cdn.cf.secret') == '' || $c->get_string('cdn.cf.bucket') == '' || $c->get_string('cdn.cf.id') == '' && !count($c->get_array('cdn.cf.cname'))):
             $error = __('The <strong>"Access key", "Secret key", "Bucket" and "Replace default hostname with"</strong> fields cannot be empty.', 'w3-total-cache');
             break;
         case $cdn_engine == 'cf2' && ($c->get_string('cdn.cf2.key') == '' || $c->get_string('cdn.cf2.secret') == '' || $c->get_string('cdn.cf2.id') == '' && !count($c->get_array('cdn.cf2.cname'))):
             $error = __('The <strong>"Access key", "Secret key" and "Replace default hostname with"</strong> fields cannot be empty.', 'w3-total-cache');
             break;
         case $cdn_engine == 'rscf' && ($c->get_string('cdn.rscf.user') == '' || $c->get_string('cdn.rscf.key') == '' || $c->get_string('cdn.rscf.container') == ''):
             $error = __('The <strong>"Username", "API key", "Container" and "Replace default hostname with"</strong> fields cannot be empty.', 'w3-total-cache');
             break;
         case $cdn_engine == 'azure' && ($c->get_string('cdn.azure.user') == '' || $c->get_string('cdn.azure.key') == '' || $c->get_string('cdn.azure.container') == ''):
             $error = __('The <strong>"Account name", "Account key" and "Container"</strong> fields cannot be empty.', 'w3-total-cache');
             break;
         case $cdn_engine == 'mirror' && !count($c->get_array('cdn.mirror.domain')):
             $error = __('The <strong>"Replace default hostname with"</strong> field cannot be empty.', 'w3-total-cache');
             break;
         case $cdn_engine == 'netdna':
             $fields = array();
             if ($c->get_string('cdn.netdna.authorization_key') == '') {
                 $fields[] = '"' . __('Authorization key', 'w3-total-cache') . '"';
             }
             if (!count($c->get_array('cdn.netdna.domain'))) {
                 $fields[] = '"' . __('Replace default hostname with', 'w3-total-cache') . '"';
             }
             if ($fields) {
                 $error = sprintf(__('The <strong>%s</strong> field(s) cannot be empty.', 'w3-total-cache'), implode(__(' and ', 'w3-total-cache'), $fields));
             }
             if ($c->get_string('cdn.netdna.authorization_key') != '' && sizeof(explode('+', $c->get_string('cdn.netdna.authorization_key'))) != 3) {
                 $error .= __('The <strong>"Authorization key"</strong> is not correct.', 'w3-total-cache');
             } elseif ($c->get_integer('cdn.netdna.zone_id', 0) <= 0) {
                 $error .= __('You need to select / create a pull zone.', 'w3-total-cache');
             }
             break;
         case $cdn_engine == 'maxcdn':
             $fields = array();
             if ($c->get_string('cdn.maxcdn.authorization_key') == '') {
                 $fields[] = '"' . __('Authorization key', 'w3-total-cache') . '"';
             }
             if (!count($c->get_array('cdn.maxcdn.domain'))) {
                 $fields[] = '"' . __('Replace default hostname with', 'w3-total-cache') . '"';
             }
             if ($fields) {
                 $error = sprintf(__('The <strong>%s</strong> field(s) cannot be empty.', 'w3-total-cache'), implode(__(' and ', 'w3-total-cache'), $fields));
             }
             if ($c->get_string('cdn.maxcdn.authorization_key') != '' && sizeof(explode('+', $c->get_string('cdn.maxcdn.authorization_key'))) != 3) {
                 $error .= __('The <strong>"Authorization key"</strong> is not correct.', 'w3-total-cache');
             } elseif ($c->get_integer('cdn.maxcdn.zone_id', 0) <= 0) {
                 $error .= __('You need to select / create a pull zone.', 'w3-total-cache');
             }
             break;
         case $cdn_engine == 'cotendo' && !count($c->get_array('cdn.cotendo.domain')):
             $error = __('The <strong>"Replace default hostname with"</strong> field cannot be empty.', 'w3-total-cache');
             break;
         case $cdn_engine == 'edgecast' && !count($c->get_array('cdn.edgecast.domain')):
             $error = __('The <strong>"Replace default hostname with"</strong> field cannot be empty.', 'w3-total-cache');
             break;
         case $cdn_engine == 'att' && !count($c->get_array('cdn.att.domain')):
             $error = __('The <strong>"Replace default hostname with"</strong> field cannot be empty.', 'w3-total-cache');
             break;
         case $cdn_engine == 'akamai' && !count($c->get_array('cdn.akamai.domain')):
             $error = 'The <strong>"Replace default hostname with"</strong> field cannot be empty.';
             break;
     }
     if ($error) {
         $errors['cdn_not_configured'] = __('A configuration issue prevents <acronym title="Content Delivery Network">CDN</acronym> from working: ', 'w3-total-cache') . $error . __(' <a href="?page=w3tc_cdn#configuration">Specify it here</a>.', 'w3-total-cache');
     }
     return $errors;
 }
 /**
  * Show plugin changes
  *
  * @return void
  */
 function in_plugin_update_message()
 {
     $response = Util_Http::get(W3TC_README_URL);
     if (is_wp_error($response) || $response['response']['code'] != 200) {
         return;
     }
     $matches = null;
     $regexp = '~==\\s*Changelog\\s*==\\s*=\\s*[0-9.]+\\s*=(.*)(=\\s*' . preg_quote(W3TC_VERSION) . '\\s*=|$)~Uis';
     $body = $response['body'];
     if (!preg_match($regexp, $body, $matches)) {
         return;
     }
     $changelog = (array) preg_split('~[\\r\\n]+~', trim($matches[1]));
     echo '<div style="color: #f00;">' . __('Take a minute to update, here\'s why:', 'w3-total-cache') . '</div><div style="font-weight: normal;height:300px;overflow:auto">';
     $ul = false;
     foreach ($changelog as $index => $line) {
         if (preg_match('~^\\s*\\*\\s*~', $line)) {
             if (!$ul) {
                 echo '<ul style="list-style: disc; margin-left: 20px;margin-top:0;">';
                 $ul = true;
             }
             $line = preg_replace('~^\\s*\\*\\s*~', '', htmlspecialchars($line));
             echo '<li style="width: 50%; margin: 0; float: left; ' . ($index % 2 == 0 ? 'clear: left;' : '') . '">' . $line . '</li>';
         } else {
             if ($ul) {
                 echo '</ul><div style="clear: left;"></div>';
                 $ul = false;
             }
         }
     }
     if ($ul) {
         echo '</ul><div style="clear: left;"></div>';
     }
     echo '</div>';
 }
 /**
  * Rename domain
  *
  * @param array   $names
  * @param integer $limit
  * @param integer $offset
  * @param integer $count
  * @param integer $total
  * @param integer $results
  * @return void
  */
 function rename_domain($names, $limit, $offset, &$count, &$total, &$results)
 {
     global $wpdb;
     @set_time_limit($this->_config->get_integer('timelimit.domain_rename'));
     $count = 0;
     $total = 0;
     $results = array();
     $upload_info = Util_Http::upload_info();
     foreach ($names as $index => $name) {
         $names[$index] = str_ireplace('www.', '', $name);
     }
     if ($upload_info) {
         $sql = sprintf('SELECT
     		ID,
     		post_content,
     		post_date
         FROM
             %sposts
         WHERE
             post_status = "publish"
             AND (post_type = "post" OR post_type = "page")
             AND (post_content LIKE "%%src=%%"
             	OR post_content LIKE "%%href=%%")
    		', $wpdb->prefix);
         if ($limit) {
             $sql .= sprintf(' LIMIT %d', $limit);
             if ($offset) {
                 $sql .= sprintf(' OFFSET %d', $offset);
             }
         }
         $posts = $wpdb->get_results($sql);
         if ($posts) {
             $count = count($posts);
             $total = $this->get_rename_posts_count();
             $names_quoted = array_map(array('\\W3TC\\Util_Environment', 'preg_quote'), $names);
             foreach ($posts as $post) {
                 $matches = null;
                 $post_content = $post->post_content;
                 $regexp = '~(href|src)=[\'"]?(https?://(www\\.)?(' . implode('|', $names_quoted) . ')' . Util_Environment::preg_quote($upload_info['baseurlpath']) . '([^\'"<>\\s]+))[\'"]~';
                 if (preg_match_all($regexp, $post_content, $matches, PREG_SET_ORDER)) {
                     foreach ($matches as $match) {
                         $old_url = $match[2];
                         $new_url = sprintf('%s/%s', $upload_info['baseurl'], $match[5]);
                         $post_content = str_replace($old_url, $new_url, $post_content);
                         $results[] = array('old' => $old_url, 'new' => $new_url, 'result' => true, 'error' => 'OK');
                     }
                 }
                 if ($post_content != $post->post_content) {
                     wp_update_post(array('ID' => $post->ID, 'post_content' => $post_content));
                 }
             }
         }
     }
 }
Example #10
0
 /**
  * Normalizes attachment file
  *
  * @param string  $file
  * @return string
  */
 function normalize_attachment_file($file)
 {
     $upload_info = Util_Http::upload_info();
     if ($upload_info) {
         $file = ltrim(str_replace($upload_info['basedir'], '', $file), '/\\');
         $matches = null;
         if (preg_match('~(\\d{4}/\\d{2}/)?[^/]+$~', $file, $matches)) {
             $file = $matches[0];
         }
     }
     return $file;
 }
 /**
  * Returns server info
  *
  * @return array
  */
 private function get_server_info()
 {
     global $wp_version, $wp_db_version, $wpdb;
     $wordpress_plugins = get_plugins();
     $wordpress_plugins_active = array();
     foreach ($wordpress_plugins as $wordpress_plugin_file => $wordpress_plugin) {
         if (is_plugin_active($wordpress_plugin_file)) {
             $wordpress_plugins_active[$wordpress_plugin_file] = $wordpress_plugin;
         }
     }
     $mysql_version = $wpdb->get_var('SELECT VERSION()');
     $mysql_variables_result = (array) $wpdb->get_results('SHOW VARIABLES', ARRAY_N);
     $mysql_variables = array();
     foreach ($mysql_variables_result as $mysql_variables_row) {
         $mysql_variables[$mysql_variables_row[0]] = $mysql_variables_row[1];
     }
     $server_info = array('w3tc' => array('version' => W3TC_VERSION, 'server' => !empty($_SERVER['SERVER_SOFTWARE']) ? $_SERVER['SERVER_SOFTWARE'] : 'Unknown', 'dir' => W3TC_DIR, 'cache_dir' => W3TC_CACHE_DIR, 'blog_id' => Util_Environment::blog_id(), 'home_domain_root_url' => Util_Environment::home_domain_root_url(), 'home_url_maybe_https' => Util_Environment::home_url_maybe_https(), 'site_path' => Util_Environment::site_path(), 'document_root' => Util_Environment::document_root(), 'site_root' => Util_Environment::site_root(), 'site_url_uri' => Util_Environment::site_url_uri(), 'home_url_host' => Util_Environment::home_url_host(), 'home_url_uri' => Util_Environment::home_url_uri(), 'network_home_url_uri' => Util_Environment::network_home_url_uri(), 'host_port' => Util_Environment::host_port(), 'host' => Util_Environment::host(), 'wp_config_path' => Util_Environment::wp_config_path()), 'wp' => array('version' => $wp_version, 'db_version' => $wp_db_version, 'abspath' => ABSPATH, 'home' => get_option('home'), 'siteurl' => get_option('siteurl'), 'email' => get_option('admin_email'), 'upload_info' => (array) Util_Http::upload_info(), 'theme' => Util_Theme::get_current_theme(), 'wp_cache' => defined('WP_CACHE') && WP_CACHE ? 'true' : 'false', 'plugins' => $wordpress_plugins_active), 'mysql' => array('version' => $mysql_version, 'variables' => $mysql_variables));
     return $server_info;
 }
Example #12
0
 private function fill_regexps()
 {
     $regexps = array();
     $site_path = Util_Environment::site_url_uri();
     $domain_url_regexp = Util_Environment::home_domain_root_url_regexp();
     $site_domain_url_regexp = false;
     if ($domain_url_regexp != Util_Environment::get_url_regexp(Util_Environment::url_to_host(site_url()))) {
         $site_domain_url_regexp = Util_Environment::get_url_regexp(Util_Environment::url_to_host(site_url()));
     }
     if ($this->_config->get_boolean('cdn.uploads.enable')) {
         $upload_info = Util_Http::upload_info();
         if ($upload_info) {
             $baseurl = $upload_info['baseurl'];
             if (defined('DOMAIN_MAPPING') && DOMAIN_MAPPING) {
                 $parsed = @parse_url($upload_info['baseurl']);
                 $baseurl = home_url() . $parsed['path'];
             }
             $regexps = $this->make_uploads_regexes($domain_url_regexp, $baseurl, $upload_info, $regexps);
             if ($site_domain_url_regexp) {
                 $regexps = $this->make_uploads_regexes($site_domain_url_regexp, $baseurl, $upload_info, $regexps);
             }
         }
     }
     if ($this->_config->get_boolean('cdn.includes.enable')) {
         $mask = $this->_config->get_string('cdn.includes.files');
         if ($mask != '') {
             $regexps[] = '~(["\'(=])\\s*((' . $domain_url_regexp . ')?(' . Util_Environment::preg_quote($site_path . WPINC) . '/(' . Cdn_Util::get_regexp_by_mask($mask) . ')([^"\'() >]*)))~i';
             if ($site_domain_url_regexp) {
                 $regexps[] = '~(["\'(=])\\s*((' . $site_domain_url_regexp . ')?(' . Util_Environment::preg_quote($site_path . WPINC) . '/(' . Cdn_Util::get_regexp_by_mask($mask) . ')([^"\'() >]*)))~i';
             }
         }
     }
     if ($this->_config->get_boolean('cdn.theme.enable')) {
         $theme_dir = preg_replace('~' . $domain_url_regexp . '~i', '', get_theme_root_uri());
         $mask = $this->_config->get_string('cdn.theme.files');
         if ($mask != '') {
             $regexps[] = '~(["\'(=])\\s*((' . $domain_url_regexp . ')?(' . Util_Environment::preg_quote($theme_dir) . '/(' . Cdn_Util::get_regexp_by_mask($mask) . ')([^"\'() >]*)))~i';
             if ($site_domain_url_regexp) {
                 $theme_dir2 = preg_replace('~' . $site_domain_url_regexp . '~i', '', get_theme_root_uri());
                 $regexps[] = '~(["\'(=])\\s*((' . $site_domain_url_regexp . ')?(' . Util_Environment::preg_quote($theme_dir) . '/(' . Cdn_Util::get_regexp_by_mask($mask) . ')([^"\'() >]*)))~i';
                 $regexps[] = '~(["\'(=])\\s*((' . $site_domain_url_regexp . ')?(' . Util_Environment::preg_quote($theme_dir2) . '/(' . Cdn_Util::get_regexp_by_mask($mask) . ')([^"\'() >]*)))~i';
             }
         }
     }
     if ($this->_config->get_boolean('cdn.custom.enable')) {
         $masks = $this->_config->get_array('cdn.custom.files');
         $masks = array_map(array('\\W3TC\\Cdn_Util', 'replace_folder_placeholders'), $masks);
         $masks = array_map(array('\\W3TC\\Util_Environment', 'parse_path'), $masks);
         if (count($masks)) {
             $mask_regexps = array();
             foreach ($masks as $mask) {
                 if ($mask != '') {
                     $mask = Util_Environment::normalize_file($mask);
                     $mask_regexps[] = Cdn_Util::get_regexp_by_mask($mask);
                 }
             }
             $regexps[] = '~(["\'(=])\\s*((' . $domain_url_regexp . ')?(' . Util_Environment::preg_quote($site_path) . '(' . implode('|', $mask_regexps) . ')([^"\'() >]*)))~i';
             if ($site_domain_url_regexp) {
                 $regexps[] = '~(["\'(=])\\s*((' . $site_domain_url_regexp . ')?(' . Util_Environment::preg_quote($site_path) . '(' . implode('|', $mask_regexps) . ')([^"\'() >]*)))~i';
             }
         }
     }
     $this->_regexps = $regexps;
 }
Example #13
0
 function _request($varnish_server, $url)
 {
     $parse_url = @parse_url($url);
     if (!$parse_url || !isset($parse_url['host'])) {
         return new \WP_Error('http_request_failed', 'Unrecognized URL format ' . $url);
     }
     $host = $parse_url['host'];
     $port = isset($parse_url['port']) ? (int) $parse_url['port'] : 80;
     $path = !empty($parse_url['path']) ? $parse_url['path'] : '/';
     $query = isset($parse_url['query']) ? $parse_url['query'] : '';
     $request_uri = $path . ($query != '' ? '?' . $query : '');
     if (strpos($varnish_server, ':')) {
         list($varnish_host, $varnish_port) = explode(':', $varnish_server);
     } else {
         $varnish_host = $varnish_server;
         $varnish_port = 80;
     }
     // if url host is the same as varnish server - we can use regular
     // wordpress http infrastructure, otherwise custom request should be
     // sent using fsockopen, since we send request to other server than
     // specified by $url
     if ($host == $varnish_host && $port == $varnish_port) {
         return Util_Http::request($url, array('method' => 'PURGE'));
     }
     $request_headers_array = array(sprintf('PURGE %s HTTP/1.1', $request_uri), sprintf('Host: %s', $host), sprintf('User-Agent: %s', W3TC_POWERED_BY), 'Connection: close');
     $request_headers = implode("\r\n", $request_headers_array);
     $request = $request_headers . "\r\n\r\n";
     // log what we are about to do
     $this->_log($url, sprintf('Connecting to %s ...', $varnish_host));
     $this->_log($url, sprintf('PURGE %s HTTP/1.1', $request_uri));
     $this->_log($url, sprintf('Host: %s', $host));
     $errno = null;
     $errstr = null;
     $fp = @fsockopen($varnish_host, $varnish_port, $errno, $errstr, 10);
     if (!$fp) {
         return new \WP_Error('http_request_failed', $errno . ': ' . $errstr);
     }
     @stream_set_timeout($fp, 60);
     @fputs($fp, $request);
     $response = '';
     while (!@feof($fp)) {
         $response .= @fgets($fp, 4096);
     }
     @fclose($fp);
     list($response_headers, $contents) = explode("\r\n\r\n", $response, 2);
     $matches = null;
     if (preg_match('~^HTTP/1.[01] (\\d+)~', $response_headers, $matches)) {
         $code = (int) $matches[1];
         $a = explode("\n", $response_headers);
         $status = count($a) >= 1 ? $a[0] : '';
         $return = array('response' => array('code' => $code, 'status' => $status));
         return $return;
     }
     return new \WP_Error('http_request_failed', 'Unrecognized response header' . $response_headers);
 }