<?php
/*
Plugin Name: WP Minify Fix
Plugin URI: http://wordpress.org/plugins/wp-minify-fixed/
Description: [Fixed] This plugin uses the Minify engine to combine and compress JS and CSS files to improve page load time.
Version: 1.4.1
Author: NodeCode
Author URI: http://nodecode.de
*/

/*
Copyright 2013-2015 NodeCode (email: info@nodecode.de)
Copyright 2009-2011 Thaya Kareeson (email: thaya.kareeson@gmail.com)

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.	If not, see <http://www.gnu.org/licenses/>.
*/

class WPMinify {

	var $author_homepage = 'http://nodecode.de/';
	var $homepage = 'http://wordpress.org/plugins/wp-minify-fixed/';
	var $name = 'wp_minify'; 
	var $name_dashed = 'wp-minify-fix'; 
	var $name_proper = 'WP Minify Fix'; 
	var $required_wp_version = '2.7';
	var $version = '1.4.1';

	var $c = null;
	var $debug = false;
	var $cache_location = 'wp-content/plugins/wp-minify-fix/cache/';
	var $url_len_limit = 2000;
	var $minify_limit = 50;
	var $buffer_started = false;
	var $default_exclude = array();
	
	var $footer_scripts_string = 'abc';

	function WPMinify() {
		// initialize common functions
		$this->c = new WPMinifyCommon($this);

		// load translation
		$this->c->load_text_domain();

		// register admin scripts
		add_action('admin_init', array($this->c, 'a_register_scripts'));
		add_action('admin_init', array($this->c, 'a_register_styles'));

		// check wp version
		add_action('admin_head', array($this->c, 'a_check_version'));

		// load admin menu
		add_action('admin_menu', array($this, 'a_menu'));

		// register ajax handler
		add_action('wp_ajax_wpm', array($this, 'a_ajax_handler'));

		// No need to minify admin stuff
		if (!is_admin() && !defined('XMLRPC_REQUEST')) {
			// Don't minify if if user passes wp-minify-off=1 in GET parameter
			if (!(isset($_GET['wp-minify-off']) && $_GET['wp-minify-off'])) {
				// footer scripts hook
				add_action('wp_footer', array($this, 'footer_placeholder'), 1);
				
				add_action('init', array($this, 'pre_content'), 99999);
				add_action('wp_footer', array($this, 'post_content'), 99999);
			}
			// advertise hook
			add_action('wp_footer', array($this, 'advertise'));
		}
	}

	// admin functions

	function a_default_options() {
		return array(
			'cache_external' => false,
			'cache_interval' => 3600,
			'css_exclude' => array(),
			'css_include' => array(),
			'debug_nominify' => false,
			'debug_firephp' => false,
			'enable_css' => true,
			'enable_js' => true,
			'enable_html' => true,
			'auto_base' => true,
			'extra_minify_options' => '',
			'js_exclude' => array(),
			'js_include' => array(),
			'js_placement' => 'header-footer', // header-footer, header or footer
			'js_async' => false, // Header only, see http://css-tricks.com/async-attribute-scripts-bottom/
			'force_https' => false,
			'pretty_url' => false,
			'show_link' => false,
			'show_advanced' => false,
			'uri_exclude' => array(),
			'version' => $this->version,
			'deprecated' => array(
				'wp_path', 'debug', 'debug_noprettyurl', 'js_in_footer'
			)
		);
	}

	function a_update_options() {
		// new options
		$wpm_new_options = stripslashes_deep($_POST['wpm_options_update']);

		// current options
		$wpm_current_options = get_option($this->name);

		// convert "on" to true and "off" to false for checkbox fields
		// and set defaults for fields that are left blank
		if (isset($wpm_new_options['show_link']) && $wpm_new_options['show_link'] == "on")
			$wpm_new_options['show_link'] = true;
		else
			$wpm_new_options['show_link'] = false;

		if (isset($wpm_new_options['enable_js']))
			$wpm_new_options['enable_js'] = true;
		else
			$wpm_new_options['enable_js'] = false;

		if (isset($wpm_new_options['enable_css']))
			$wpm_new_options['enable_css'] = true;
		else
			$wpm_new_options['enable_css'] = false;

		if (isset($wpm_new_options['enable_html']))
			$wpm_new_options['enable_html'] = true;
		else
			$wpm_new_options['enable_html'] = false;

		if (isset($wpm_new_options['auto_base']))
			$wpm_new_options['auto_base'] = true;
		else
			$wpm_new_options['auto_base'] = false;

		if (isset($wpm_new_options['cache_external']))
			$wpm_new_options['cache_external'] = true;
		else
			$wpm_new_options['cache_external'] = false;

		if (isset($wpm_new_options['js_in_footer']))
			$wpm_new_options['js_in_footer'] = true;
		else
			$wpm_new_options['js_in_footer'] = false;

		if (isset($wpm_new_options['pretty_url']))
			$wpm_new_options['pretty_url'] = true;
		else
			$wpm_new_options['pretty_url'] = false;

		if (isset($wpm_new_options['debug_nominify']))
			$wpm_new_options['debug_nominify'] = true;
		else
			$wpm_new_options['debug_nominify'] = false;

		if (isset($wpm_new_options['debug_firephp']))
			$wpm_new_options['debug_firephp'] = true;
		else
			$wpm_new_options['debug_firephp'] = false;

		$this->a_set_minify_config($wpm_new_options['debug_nominify'], $wpm_new_options['debug_firephp']);
		
		if ( isset($wpm_new_options['js_async']) )
			$wpm_new_options['js_async'] = true;
		else
			$wpm_new_options['js_async'] = false;

		if ( isset($wpm_new_options['force_https']) )
			$wpm_new_options['force_https'] = true;
		else
			$wpm_new_options['force_https'] = false;

		if (strlen(trim($wpm_new_options['js_include'])) > 0)
			$wpm_new_options['js_include'] = $this->array_trim(split(chr(10), str_replace(chr(13), '', $wpm_new_options['js_include'])));
		else
			$wpm_new_options['js_include'] = array();

		if (strlen(trim($wpm_new_options['js_exclude'])) > 0)
			$wpm_new_options['js_exclude'] = $this->array_trim(split(chr(10), str_replace(chr(13), '', $wpm_new_options['js_exclude'])));
		else
			$wpm_new_options['js_exclude'] = array();

		if (strlen(trim($wpm_new_options['css_include'])) > 0)
			$wpm_new_options['css_include'] = $this->array_trim(split(chr(10), str_replace(chr(13), '', $wpm_new_options['css_include'])));
		else
			$wpm_new_options['css_include'] = array();

		if (strlen(trim($wpm_new_options['css_exclude'])) > 0)
			$wpm_new_options['css_exclude'] = $this->array_trim(split(chr(10), str_replace(chr(13), '', $wpm_new_options['css_exclude'])));
		else
			$wpm_new_options['css_exclude'] = array();

		if ( strlen(trim($wpm_new_options['uri_exclude'])) > 0 )
			$wpm_new_options['uri_exclude'] = $this->array_trim(split(chr(10), str_replace(chr(13), '', $wpm_new_options['uri_exclude'])));
		else
			$wpm_new_options['uri_exclude'] = array();

		// Update options
		foreach ($wpm_new_options as $key => $value) {
			$wpm_current_options[$key] = $value;
		}

		update_option($this->name, $wpm_current_options);
	}

	function a_set_advanced_options($val) {
		$wpm_options = get_option($this->name);
		$wpm_options['show_advanced'] = $val;
		update_option($this->name, $wpm_options);
	}

	function a_ajax_handler() {
		check_ajax_referer($this->name);
		if (isset($_POST['wpm_action'])) {
			if (strtolower($_POST['wpm_action']) == 'show_advanced') {
				$this->a_set_advanced_options(true);
			}
			elseif (strtolower($_POST['wpm_action']) == 'hide_advanced') {
				$this->a_set_advanced_options(false);
			}
			else {
				echo 'Invalid wpm_action.';
			}
		}
		exit();
	}

	function a_request_handler() {
		if (isset($_POST['wpm_options_update_submit'])) {
			check_admin_referer($this->name);
			$this->a_update_options();
			add_action('admin_notices', array($this->c, 'a_notify_updated'));
		}
		elseif (isset($_POST['wpm_options_clear_cache_submit'])) {
			// if user wants to regenerate nonce
			check_admin_referer($this->name);
			$this->c->a_clear_cache();
			add_action('admin_notices', array($this->c, 'a_notify_cache_cleared'));
		}
		elseif (isset($_POST['wpm_options_upgrade_submit'])) {
			// if user wants to upgrade options (for new options on version upgrades)
			check_admin_referer($this->name);
			$this->c->a_upgrade_options();
			add_action('admin_notices', array($this->c, 'a_notify_upgraded'));
		}
		elseif (isset($_POST['wpm_options_reset_submit'])) {
			// if user wants to reset all options
			check_admin_referer($this->name);
			$this->c->a_reset_options();
			add_action('admin_notices', array($this->c, 'a_notify_reset'));
		}

		// only check these on plugin settings page
		$this->c->a_check_dir_writable($this->c->get_plugin_dir().'cache/', array($this, 'a_notify_cache_not_writable'));
		$this->c->a_check_orphan_options(array($this, 'a_notify_orphan_options'));
		if ($this->c->a_check_dir_writable($this->c->get_plugin_dir().'min/config.php', array($this, 'a_notify_config_not_writable'))) {
			$this->a_check_minify_config();
		}
	}

	function a_check_minify_config() {
		$fname = $this->c->get_plugin_dir().'min/config.php';
		$fhandle = fopen($fname,'r');
		$content = fread($fhandle,filesize($fname));

		$config_modified = false;
		
		preg_match('/\/\/###WPM-CACHE-PATH-BEFORE###(.*)\/\/###WPM-CACHE-PATH-AFTER###/s', $content, $matches);
		$cache_path_code = $matches[1];
		if (!preg_match('/\$min_cachePath.*?/', $cache_path_code)) {
			$content = preg_replace(
				'/\/\/###WPM-CACHE-PATH-BEFORE###(.*)\/\/###WPM-CACHE-PATH-AFTER###/s',
				"//###WPM-CACHE-PATH-BEFORE###\n".'$min_cachePath = \''.$this->c->get_plugin_dir()."cache/';\n//###WPM-CACHE-PATH-AFTER###",
				$content);
			$config_modified = true;
		}

		preg_match('/\/\/###WPM-CACHE-AGE-BEFORE###(.*)\/\/###WPM-CACHE-AGE-AFTER###/s', $content, $matches);
		$cache_age_code = $matches[1];
		if (!preg_match('/\$min_serveOptions\[\'maxAge\'].*?/', $cache_age_code)) {
			$content = preg_replace(
				'/\/\/###WPM-CACHE-AGE-BEFORE###(.*)\/\/###WPM-CACHE-AGE-AFTER###/s',
				"//###WPM-CACHE-AGE-BEFORE###\n".'$min_serveOptions[\'maxAge\'] = 2592000;'."\n//###WPM-CACHE-AGE-AFTER###",
				$content);
			$config_modified = true;
		}

		if ($config_modified) {
			$this->a_notify_modified_minify_config();
		}
		
		$fhandle = fopen($fname,"w");
		fwrite($fhandle,$content);
		fclose($fhandle);
	}

	function a_set_minify_config($nominify = false, $firephp = false) {
		if ($nominify) {
			$nominify = 'true';
		} else {
			$nominify = 'false';
		}
		if ($firephp) {
			$firephp = 'true';
		} else {
			$firephp = 'false';
		}
		$fname = $this->c->get_plugin_dir().'min/config.php';
		$fhandle = fopen($fname,'r');
		$content = fread($fhandle,filesize($fname));

		$content = preg_replace(
			'/\/\/###WPM-DEBUG-FLAG-BEFORE###(.*)\/\/###WPM-DEBUG-FLAG-AFTER###/s',
			"//###WPM-DEBUG-FLAG-BEFORE###\n".'$min_allowDebugFlag = '.$nominify.";\n//###WPM-DEBUG-FLAG-AFTER###",
			$content);

		$content = preg_replace(
			'/\/\/###WPM-ERROR-LOGGER-BEFORE###(.*)\/\/###WPM-ERROR-LOGGER-AFTER###/s',
			"//###WPM-ERROR-LOGGER-BEFORE###\n".'$min_errorLogger = '.$firephp.";\n//###WPM-ERROR-LOGGER-AFTER###",
			$content);

		$fhandle = fopen($fname,"w");
		fwrite($fhandle,$content);
		fclose($fhandle);
	}

	function a_notify_cache_not_writable() {
		$this->c->a_notify(
			sprintf('%s: %s',
				__('Cache directory is not writable. Please grant your server write permissions to the directory', $this->name),
				$this->c->get_plugin_dir().'cache/'),
			true);
	}

	function a_notify_config_not_writable() {
		$this->c->a_notify(
			sprintf('%s: %s',
				__('Minify Engine config.php is not writable. Please grant your server write permissions to file', $this->name),
				$this->c->get_plugin_dir().'min/config.php'));
	}

	function a_notify_orphan_options() {
		$this->c->a_notify(
			sprintf('%s',
				__('Some option settings are missing (possibly from plugin upgrade).', $this->name)));
	}

	function a_notify_modified_minify_config() {
		$this->c->a_notify(__('Minify Engine config.php was configured automatically.', $this->name));
	}

	function a_menu() {
		$options_page = add_options_page($this->name_proper, $this->name_proper, 'manage_options', 'wp-minify-fix', array($this, 'a_page'));
		add_action('admin_head-'.$options_page, array($this, 'a_request_handler'));
		add_action('admin_print_scripts-'.$options_page, array($this->c, 'a_enqueue_scripts'));
		add_action('admin_print_styles-'.$options_page, array($this->c, 'a_enqueue_styles'));
	}

	function a_page() {
		$wpm_options = get_option($this->name);
		printf('
			<div class="wrap omni_admin_content">
				<h2>%s</h2>
				<div>
					<a href="'.preg_replace('/&wpm-page=[^&]*/', '', $_SERVER['REQUEST_URI']).'">%s</a>&nbsp;|&nbsp;
					<a href="'.$this->homepage.'">%s</a>
				</div>',
			__('WP Minify Options', $this->name),
			__('General Configuration', $this->name),
			__('Documentation', $this->name)
		);
		printf('<div class="omni_admin_main">');
		if (isset($_GET['wpm-page'])) {
			if ($_GET['wpm-page'] || !$_GET['wpm-page']) {
				require_once('options-generic.php');
			}
		}
		else {
			require_once('options-generic.php');
		}
		printf('</div>'); // omni_admin_main
		require_once('options-sidebar.php');
		printf('</div>'); // wrap

	} // admin_page()

	// other functions

	function fetch_and_cache($url, $cache_file) {
		$ch = curl_init();
		$timeout = 5; // set to zero for no timeout
		curl_setopt ($ch, CURLOPT_URL, $url);
		curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
		curl_setopt ($ch, CURLOPT_USERAGENT, 'WP-Minify Fix');
		$content = curl_exec($ch);
		curl_close($ch);
		if ($content) {
			if (is_array($content)) {
				$content = implode($content);
			}

			// save cache file
			$fh = fopen($cache_file, 'w');
			if ($fh) {
				fwrite($fh, $content);
				fclose($fh);
			}
			else {
				// cannot open for write.	 no error b/c something else is probably writing to the file.
			}

			return $content;
		}
		else {
			printf(
				'%s: '.$url.'. %s<br/>',
				__('Error: Could not fetch and cache URL'),
				__('You might need to exclude this file in WP Minify options.')
			);
			return '';
		}
	}

	function refetch_cache_if_expired($url, $cache_file) {
		$wpm_options = get_option($this->name);
		$cache_file_mtime = filemtime($cache_file);
		if ((time() - $cache_file_mtime) > $wpm_options['cache_interval']) {
			$this->fetch_and_cache($url, $cache_file);
		}
	}

	function tiny_filename($str) {
		$f = __FILE__;
		// no fancy shortening for Windows
		return ('/' === $f[0]) ? strtr(base64_encode(md5($str, true)), '+/=', '-_(') : md5($str);
	}

	function array_trim($arr, $charlist=null) {
		foreach ($arr as $key => $value) {
			if (is_array($value)) $result[$key] = array_trim($value, $charlist);
			else $result[$key] = trim($value, $charlist);
		}
		return $result;
	}

	function check_and_split_url($url, $latest_modified = 0) {
		$url_chunk = explode('?f=', $url);
		$base_url = array_shift($url_chunk);
		$files = explode(',', array_shift($url_chunk));
		$num_files = sizeof($files);

		if ($this->url_needs_splitting($url, $files)) {
			$first_half = $this->check_and_split_url($base_url . '?f=' . implode(',', array_slice($files, 0, $num_files/2)), $latest_modified);
			$second_half = $this->check_and_split_url($base_url . '?f=' . implode(',', array_slice($files, $num_files/2)), $latest_modified);
			return $first_half + $second_half;
		}
		else {
			$wpm_options = get_option($this->name);

			// append &debug if we need to
			if ($wpm_options['debug_nominify']) {
				$debug_string = '&debug=true';
			} else {
				$debug_string = '';
			}

			// append base directory if needed
			$base = $this->get_base();
			if ($base != '') {
				$base_string = '&b='.$base;
			} else {
				$base_string = '';
			}

			// get rid of any base directory specification in extra options
			$extra_minify_options = preg_replace('/(&|&amp;|\b)b=[^&]*/', '', trim($wpm_options['extra_minify_options']));
			if (trim($extra_minify_options) != '') {
				$extra_string = '&'.$extra_minify_options;
			} else {
				$extra_string = '';
			}

			// append last modified time
			$latest_modified_string = '&m='.$latest_modified;

			return array($base_url . '?f=' . implode(',', $files) . $debug_string . $base_string . $extra_string . $latest_modified_string);
		}
	}

	function fetch_content($url, $type = '') {
		$cache_file = $this->c->get_plugin_dir().'cache/'.md5($url).$type;
		$content = '';
		if (file_exists($cache_file)) {
			// check cache expiration
			$this->refetch_cache_if_expired($url, $cache_file);

			$fh = fopen($cache_file, 'r');
			if ($fh && filesize($cache_file) > 0) {
				$content = fread($fh, filesize($cache_file));
				fclose($fh);
			}
			else {
				// cannot open cache file so fetch it
				$content = $this->fetch_and_cache($url, $cache_file);
			}
		}
		else {
			// no cache file.	 fetch from internet and save to local cache
			$content = $this->fetch_and_cache($url, $cache_file);
		}
		return $content;
	}

	function local_version($url) {
		$site_url = trailingslashit(get_option('siteurl'));
		$url = str_replace($site_url, '', $url); // relative paths only for local urls
		//$url = preg_replace('/^\//', '', $url); // strip front / if any
		$url = preg_replace('/\?.*/i', '', $url); // throws away parameters, if any
		return $url;
	}

	function is_external($url, $localize=true) {
		if ($localize) {
			$url = $this->local_version($url);
		}

		if (substr($url, 0, 4) != 'http' && substr($url, 0, 2) != '//'
			&& (substr($url, -3, 3) == '.js' || substr($url, -4, 4) == '.css')) {
			return false;
		} else {
			return true;
		}
	}

	function get_js_location($src) {
		if ($this->debug)
			echo 'Script URL:'.$src."<br/>\n";

		$script_path = $this->local_version($src);
		if ($this->is_external($script_path, false)) {
			// fetch scripts if necessary
			$this->fetch_content($src, '.js');
			$location = $this->cache_location . md5($src) . '.js';
			if ($this->debug)
				echo 'External script detected, cached as:'. md5($src) . "<br/>\n";
		} else {
			// if script is local to server
			$location = $script_path;
			if ($this->debug)
				echo 'Local script detected:'.$script_path."<br/>\n";
		}

		return $location;
	}

	function get_css_location($src) {
		if ($this->debug)
			echo 'Style URL:'.$src."<br/>\n";

		$css_path = $this->local_version($src);
		if ($this->is_external($css_path, false)) {
			// fetch scripts if necessary
			$this->fetch_content($src, '.css');
			$location = $this->cache_location . md5($src) . '.css';
			if ($this->debug)
				echo 'External css detected, cached as:'. md5($src) . "<br/>\n";
		} else {
			$location = $css_path;
			// if css is local to server
			if ($this->debug)
				echo 'Local css detected:'.$css_path."<br/>\n";
		}

		return $location;
	}

	function url_needs_splitting($url, $locations) {
		if ($url > $this->url_len_limit || count($locations) > $this->minify_limit) {
			return true;
		} else {
			return false;
		}
	}

	function build_minify_urls($locations, $type) {
		$wpm_options = get_option($this->name);
		$minify_url = $this->c->get_plugin_url().'min/?f=';
		if ($wpm_options['force_https'] && $_SERVER["HTTPS"] == "on") {
			$minify_url = preg_replace('/^http:\/\//', 'https://', $minify_url);
		}
		$minify_url .= implode(',', $locations);
		$latest_modified = $this->get_latest_modified_time($locations);
		$minify_urls = $this->check_and_split_url($minify_url, $latest_modified);

		if ($wpm_options['pretty_url']) {
			return $this->get_cached_minify_urls($minify_urls, $type);
		} else {
			return $minify_urls;
		}
	}
	
	function get_cached_minify_urls($urls, $type) {
		$wpm_options = get_option($this->name);
		$cached_urls = array();
		foreach ($urls as $url) {
			$cache_file = $this->c->get_plugin_dir().'cache/'.md5($url).$type;
			if (file_exists($cache_file)) {
				// check cache expiration
				$this->refetch_cache_if_expired($url, $cache_file);
	
				$fh = fopen($cache_file, 'r');
				if ($fh && filesize($cache_file) > 0) {
					$content = fread($fh, filesize($cache_file));
					fclose($fh);
				} else {
					// cannot open cache file so fetch it
					$this->fetch_and_cache($url, $cache_file);
				}
			} else {
				// no cache file. fetch it
				$this->fetch_and_cache($url, $cache_file);
			}
			$cache_url = $this->c->get_plugin_url().'cache/'.md5($url).$type.'?m='.filemtime($cache_file);
			$cached_urls[] = $cache_url;
		}
		return $cached_urls;
	}

	function get_base_from_minify_args() {
		$wpm_options = get_option($this->name);
		if (!empty($wpm_options['extra_minify_options'])) {
			if (preg_match('/\bb=([^&]*?)(&|$)/', trim($wpm_options['extra_minify_options']), $matches)) {
				return rtrim(trim($matches[1]), '\\/');
			}
		}
		return '';
	}

	function get_base_from_siteurl() {
		$site_url = trailingslashit(get_option('siteurl'));
		return rtrim(preg_replace('/^https?:\/\/.*?\//', '', $site_url), '\\/');
	}

	function get_base() {
		$base_from_min_args = $this->get_base_from_minify_args();
		if ($base_from_min_args != '') {
			return $base_from_min_args;
		}

		$wpm_options = get_option($this->name);
		if ($wpm_options['auto_base']) {
			return $this->get_base_from_siteurl();
		} else {
			return '';
		}
	}

	function get_latest_modified_time($locations = array()) {
		$latest_modified = 0;
		if (!empty($locations)) {
			$base_path = trailingslashit($_SERVER['DOCUMENT_ROOT']);
			$base_path .= trailingslashit($this->get_base());

			foreach ($locations as $location) {
				$path = $base_path.$location;
				$mtime = filemtime($path);
				if ($latest_modified < $mtime) {
					$latest_modified = $mtime;
				}
			}
		}
		return $latest_modified;
	}

	function extract_css($content) {
		$wpm_options = get_option($this->name);
		$css_locations = array();

		preg_match_all('/<link([^>]*?)>/i', $content, $link_tags_match);

		foreach ($link_tags_match[0] as $link_tag) {
			if (strpos(strtolower($link_tag), 'stylesheet')) {
				// check CSS media type
				if (!strpos(strtolower($link_tag), 'media=')
					|| preg_match('/media=["\'](?:["\']|[^"\']*?(all|screen)[^"\']*?["\'])/', $link_tag)
				) {
					preg_match('/href=[\'"]([^\'"]+)/', $link_tag, $href_match);
					if ($href_match[1]) {
						// include it if it is in the include list
						$include = false;
						$inclusions = $wpm_options['css_include'];
						foreach ($inclusions as $include_pat) {
							$include_pat = trim($include_pat);
							if (strlen($include_pat) > 0 && strpos($src_match[1], $include_pat) !== false) {
								$include = true;
								break;
							}
						}

						if (!$include) {
							// support external files?
							if (!$wpm_options['cache_external'] && $this->is_external($href_match[1])) {
								continue; // skip if we don't cache externals and this file is external
							}

							// do not include anything in excluded list
							$skip = false;
							$exclusions = array_merge($this->default_exclude, $wpm_options['css_exclude']);
							foreach ($exclusions as $exclude_pat) {
								$exclude_pat = trim($exclude_pat);
								if (strlen($exclude_pat) > 0 && strpos($href_match[1], $exclude_pat) !== false) {
									$skip = true;
									break;
								}
							}
							if ($skip) continue;
						}

						$content = str_replace($link_tag . '</link>', '', $content);
						$content = str_replace($link_tag, '', $content);
						$css_locations[] = $this->get_css_location($href_match[1]);
					}
				}
			}
		}

		$css_locations = array_unique($css_locations);

		return array($content, $css_locations);
	}

	function inject_css($content, $css_locations) {
		if (count($css_locations) > 0) {
			$wpm_options = get_option($this->name);
			// build minify URLS
			$css_tags = '';
			$minify_urls = $this->build_minify_urls($css_locations, '.css');

			foreach ($minify_urls as $minify_url) {
				$minify_url = apply_filters('wp_minify_css_url', $minify_url); // Allow plugins to modify final minify URL
				$css_tags .= "<link rel='stylesheet' href='$minify_url' type='text/css' media='screen' />";
			}

			$matches = preg_match('/<!-- WP-Minify CSS -->/', $content);

			if ($matches) {
				$content = preg_replace('/<!-- WP-Minify CSS -->/', "$css_tags", $content, 1); // limit 1 replacement
			} else {
				// HTML5 has <header> tags so account for those in regex
				$content = preg_replace('/<head(>|\s[^>]*?>)/', "\\0\n$css_tags", $content, 1); // limit 1 replacement
			}
		}
		return $content;
	}

	function extract_conditionals($content) {
		preg_match_all('/<!--\[if[^\]]*?\]>.*?<!\[endif\]-->/is', $content, $conditionals_match);
		$content = preg_replace('/<!--\[if[^\]]*?\]>.*?<!\[endif\]-->/is', '###WPM-CSS-CONDITIONAL###', $content);

		$conditionals = array();
		foreach ($conditionals_match[0] as $conditional) {
			$conditionals[] = $conditional;
		}

		return array($content, $conditionals);
	}

	function inject_conditionals($content, $conditionals) {
		while (count($conditionals) > 0 && strpos($content, '###WPM-CSS-CONDITIONAL###')) {
			$conditional = array_shift($conditionals);
			$content = preg_replace('/###WPM-CSS-CONDITIONAL###/', $conditional, $content, 1);
		}

		return $content;
	}

	function extract_js($content) {
		$wpm_options = get_option($this->name);
		$js_locations = array();
		
		if ($wpm_options['js_placement'] === 'header-footer') {
			// Header and footer
			$split = explode('</head>', $content); // Head tag required
			preg_match_all('/<script([^>]*?)><\/script>/i', $split[0], $script_tags_match); // Header scripts
			preg_match_all('/<script([^>]*?)><\/script>/i', $split[1], $script_tags_footer_match); // Footer scripts
		} else {
			// Only one placement
			preg_match_all('/<script([^>]*?)><\/script>/i', $content, $script_tags_match);
		}

		foreach ($script_tags_match[0] as $script_tag) {
			preg_match('/src=[\'"]([^\'"]+)/', $script_tag, $src_match);
			if ($src_match[1]) {
				// include it if it is in the include list
				$include = false;
				$inclusions = $wpm_options['js_include'];
				foreach ($inclusions as $include_pat) {
					$include_pat = trim($include_pat);
					if (strlen($include_pat) > 0 && strpos($src_match[1], $include_pat) !== false) {
						$include = true;
						break;
					}
				}

				if (!$include) {
					// support external files?
					if (!$wpm_options['cache_external'] && $this->is_external($src_match[1])) {
						continue; // skip if we don't cache externals and this file is external
					}

					// do not include anything in excluded list
					$skip = false;
					$exclusions = array_merge($this->default_exclude, $wpm_options['js_exclude']);
					foreach ($exclusions as $exclude_pat) {
						$exclude_pat = trim($exclude_pat);
						if (strlen($exclude_pat) > 0 && strpos($src_match[1], $exclude_pat) !== false) {
							$skip = true;
							break;
						}
					}
					if ($skip) continue;
				}

				$content = str_replace($script_tag, '', $content);
				$js_locations[] = $this->get_js_location($src_match[1]);
			}
		}

		$js_locations = array_unique($js_locations);
		
		if ($wpm_options['js_placement'] === 'header-footer') {
			foreach ($script_tags_footer_match[0] as $script_tag) {
				preg_match('/src=[\'"]([^\'"]+)/', $script_tag, $src_match);
				if ($src_match[1]) {
					// include it if it is in the include list
					$include = false;
					$inclusions = $wpm_options['js_include'];
					foreach ($inclusions as $include_pat) {
						$include_pat = trim($include_pat);
						if (strlen($include_pat) > 0 && strpos($src_match[1], $include_pat) !== false) {
							$include = true;
							break;
						}
					}
	
					if (!$include) {
						// support external files?
						if (!$wpm_options['cache_external'] && $this->is_external($src_match[1])) {
							continue; // skip if we don't cache externals and this file is external
						}
	
						// do not include anything in excluded list
						$skip = false;
						$exclusions = array_merge($this->default_exclude, $wpm_options['js_exclude']);
						foreach ($exclusions as $exclude_pat) {
							$exclude_pat = trim($exclude_pat);
							if (strlen($exclude_pat) > 0 && strpos($src_match[1], $exclude_pat) !== false) {
								$skip = true;
								break;
							}
						}
						if ($skip) continue;
					}
	
					$content = str_replace($script_tag, '', $content);
					$js_locations_footer[] = $this->get_js_location($src_match[1]);
				}
			}
	
			if ($js_locations_footer != NULL)
				$js_locations_footer = array_unique($js_locations_footer);
		}

		return array($content, $js_locations, $js_locations_footer);
	}

	function inject_js($content, $js_locations, $js_locations_footer) {
		if (count($js_locations) > 0) {
			$wpm_options = get_option($this->name);
			// build minify URLS
			$js_tags = '';
			$minify_urls = $this->build_minify_urls($js_locations, '.js');
			if ($js_locations_footer) {
				$js_tags_footer = '';
				$minify_urls_footer = $this->build_minify_urls($js_locations_footer, '.js');
			}
			
			$placeholderRemoved = false;

			// Primary placement
			foreach ($minify_urls as $minify_url) {
				echo $minify_url;
				$minify_url = apply_filters('wp_minify_js_url', $minify_url); // Allow plugins to modify final minify URL
				$js_tags .= "<script type=\"text/javascript\" src=\"$minify_url\"". ($wpm_options['js_async'] === true && $wpm_options['js_placement'] !== 'footer' ? ' async' : '') ."></script>";
			}

			$matches = preg_match('/<!-- WP-Minify JS -->/', $content);

			if ($matches) {
				$content = preg_replace('/<!-- WP-Minify JS -->/', "$js_tags", $content, 1); // limit 1 replacement
			} else {
				$wpm_options = get_option($this->name);
				if ($wpm_options['js_placement'] === 'footer') {
					$content = preg_replace('/<!-- WP Minify Footer Placeholder -->/', "$js_tags", $content, 1); // limit 1 replacement
					$placeholderRemoved = true;
				} else {
					// HTML5 has <header> tags so account for those in regex
					$content = preg_replace('/<head(>|\s[^>]*?>)/', "\\0\n$js_tags", $content, 1); // limit 1 replacement
				}
			}
		
			// If separate footer
			if ($js_locations_footer) {
				foreach ($minify_urls_footer as $minify_url) {
					$minify_url = apply_filters('wp_minify_js_url', $minify_url); // Allow plugins to modify final minify URL
					$js_tags_footer .= "<script type='text/javascript' src='$minify_url'></script>";
				}
	
				$matches = preg_match('/<!-- WP-Minify JS Footer -->/', $content);
	
				if ($matches) {
					$content = preg_replace('/<!-- WP-Minify JS Footer -->/', "$js_tags_footer", $content, 1); // limit 1 replacement
				} else {
					$content = preg_replace('/<!-- WP-Minify Footer Placeholder -->/', "$js_tags_footer", $content, 1); // limit 1 replacement
					$placeholderRemoved = true;
				}
			}
			
			// If necessary (custom footer position comment), remove placeholder comment
			if ($placeholderRemoved === false) {
				$content = preg_replace('/<!-- WP-Minify Footer Placeholder -->/', "", $content, 1); // limit 1 replacement
			}
		}
		return $content;
	}

	function pre_content() {
		if ( is_feed() ) return;
		$wpm_options = get_option($this->name);
		if ($wpm_options['uri_exclude'] && count($wpm_options['uri_exclude'])) {
			foreach ($wpm_options['uri_exclude'] as $exclude_pat) {
				$exclude_pat = trim($exclude_pat);
				if (strlen($exclude_pat) > 0 && strpos($_SERVER['REQUEST_URI'], $exclude_pat) !== false) {
					return;
				}
			}
		}

		ob_start(array($this, 'modify_buffer'));

		// variable for sanity checking
		$this->buffer_started = true;
	}

	function modify_buffer($buffer) {
		$wpm_options = get_option($this->name);

		// if we do not want to force http to https then we need to exclude https
		if (!($wpm_options['force_https'] && $_SERVER["HTTPS"] == "on")) {
			$this->default_exclude[] = 'https://';
		}

		// minify JS
		if ($wpm_options['enable_js']) {
			list($buffer, $js_locations, $js_locations_footer) = $this->extract_js($buffer);
			$buffer= $this->inject_js($buffer, $js_locations, $js_locations_footer);
		}

		// minify CSS (make sure to exclude CSS conditionals)
		if ($wpm_options['enable_css']) {
			list($buffer, $conditionals) = $this->extract_conditionals($buffer);
			list($buffer, $css_locations) = $this->extract_css($buffer);
			$buffer = $this->inject_css($buffer, $css_locations);
			$buffer = $this->inject_conditionals($buffer, $conditionals);
		}

		// get rid of empty lines
		$buffer = preg_replace('/\s*(\r?\n)(\r?\n)*/', '$1', $buffer);

		// minify HTML
		if ($wpm_options['enable_html']) {
			if (!class_exists('Minify_HTML')) {
				require_once('min/lib/Minify/HTML.php');
			}
			$buffer = Minify_HTML::minify($buffer);
		}

		$buffer = apply_filters('wp_minify_content', $buffer); // allow plugins to modify buffer

		return $buffer;
	}

	function post_content() {
		if ( is_feed() ) return;
		// sanity checking
		if ($this->buffer_started) {
			ob_end_flush();
		}
	}
	
	function footer_placeholder() {
			printf('<!-- WP-Minify Footer Placeholder -->');
	}

	function advertise() {
		$wpm_options = get_option($this->name);
		if ($wpm_options['show_link']) {
			printf("<p align='center'><small>Page optimized by <a href='$this->homepage' title='$this->name_proper WordPress Plugin' style='text-decoration:none;'>$this->name_proper</a> <a href='$this->author_homepage' title='WordPress Plugin' style='text-decoration:none;'>WordPress Plugin</a></small></p>");
		}
	}

} // class WPMinify

require_once('common.php');
require_once('http_build_url.php');
$wp_minify = new WPMinify();
?>
