/** * 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; }
/** * 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)); } } } } }
/** * 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; }
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; }
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); }