PageRenderTime 69ms CodeModel.GetById 2ms app.highlight 59ms RepoModel.GetById 1ms app.codeStats 0ms

/wp-content/plugins/wp-minify/wp-minify.php

https://github.com/gregoryo/nycga2
PHP | 932 lines | 718 code | 135 blank | 79 comment | 148 complexity | 02903eb5673232f8ea883cf60e98914e MD5 | raw file
  1<?php
  2/*
  3Plugin Name: WP Minify
  4Plugin URI: http://omninoggin.com/wordpress-plugins/wp-minify-wordpress-plugin/
  5Description: This plugin uses the Minify engine to combine and compress JS and CSS files to improve page load time.
  6Version: 1.1.8
  7Author: Thaya Kareeson
  8Author URI: http://omninoggin.com
  9*/
 10
 11/*
 12Copyright 2009-2011 Thaya Kareeson (email : thaya.kareeson@gmail.com)
 13
 14This program is free software: you can redistribute it and/or modify
 15it under the terms of the GNU General Public License as published by
 16the Free Software Foundation, either version 3 of the License, or
 17(at your option) any later version.
 18
 19This program is distributed in the hope that it will be useful,
 20but WITHOUT ANY WARRANTY; without even the implied warranty of
 21MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 22GNU General Public License for more details.
 23
 24You should have received a copy of the GNU General Public License
 25along with this program.  If not, see <http://www.gnu.org/licenses/>.
 26*/
 27
 28class WPMinify {
 29
 30  var $author_homepage = 'http://omninoggin.com/';
 31  var $homepage = 'http://omninoggin.com/wordpress-plugins/wp-minify-wordpress-plugin/';
 32  var $name = 'wp_minify'; 
 33  var $name_dashed = 'wp-minify'; 
 34  var $name_proper = 'WP Minify'; 
 35  var $required_wp_version = '2.7';
 36  var $version = '1.1.8';
 37
 38  var $c = null;
 39  var $debug = false;
 40  var $cache_location = 'wp-content/plugins/wp-minify/cache/';
 41  var $url_len_limit = 2000;
 42  var $minify_limit = 50;
 43  var $buffer_started = false;
 44  var $default_exclude = array();
 45
 46  function WPMinify() {
 47    // initialize common functions
 48    $this->c = new WPMinifyCommon($this);
 49
 50    // load translation
 51    $this->c->load_text_domain();
 52
 53    // register admin scripts
 54    add_action('admin_init', array($this->c, 'a_register_scripts'));
 55    add_action('admin_init', array($this->c, 'a_register_styles'));
 56
 57    // check wp version
 58    add_action('admin_head', array($this->c, 'a_check_version'));
 59
 60    // load admin menu
 61    add_action('admin_menu', array($this, 'a_menu'));
 62
 63    // register ajax handler
 64    add_action('wp_ajax_wpm', array($this, 'a_ajax_handler'));
 65
 66    // No need to minify admin stuff
 67    if (!is_admin() && !is_feed() && !defined('XMLRPC_REQUEST')) {
 68      // Don't minify if if user passes wp-minify-off=1 in GET parameter
 69      if (!(isset($_GET['wp-minify-off']) && $_GET['wp-minify-off'])) {
 70        add_action('init', array($this, 'pre_content'), 99999);
 71        add_action('wp_footer', array($this, 'post_content'));
 72      }
 73      // advertise hook
 74      add_action('wp_footer', array($this, 'advertise'));
 75    }
 76  }
 77
 78  // admin functions
 79
 80  function a_default_options() {
 81    return array(
 82      'cache_external' => false,
 83      'cache_interval' => 900,
 84      'css_exclude' => array(),
 85      'css_include' => array(),
 86      'debug_nominify' => false,
 87      'debug_firephp' => false,
 88      'enable_css' => true,
 89      'enable_js' => true,
 90      'enable_html' => true,
 91      'auto_base' => true,
 92      'extra_minify_options' => '',
 93      'js_exclude' => array(),
 94      'js_include' => array(),
 95      'js_in_footer' => false,
 96      'force_https' => false,
 97      'pretty_url' => false,
 98      'show_link' => true,
 99      'show_advanced' => false,
100      'uri_exclude' => array(),
101      'version' => $this->version,
102      'deprecated' => array(
103        'wp_path', 'debug', 'debug_noprettyurl'
104      )
105    );
106  }
107
108  function a_update_options() {
109    // new options
110    $wpm_new_options = stripslashes_deep($_POST['wpm_options_update']);
111
112    // current options
113    $wpm_current_options = get_option($this->name);
114
115    // convert "on" to true and "off" to false for checkbox fields
116    // and set defaults for fields that are left blank
117    if (isset($wpm_new_options['show_link']) && $wpm_new_options['show_link'] == "on")
118      $wpm_new_options['show_link'] = true;
119    else
120      $wpm_new_options['show_link'] = false;
121
122    if (isset($wpm_new_options['enable_js']))
123      $wpm_new_options['enable_js'] = true;
124    else
125      $wpm_new_options['enable_js'] = false;
126
127    if (isset($wpm_new_options['enable_css']))
128      $wpm_new_options['enable_css'] = true;
129    else
130      $wpm_new_options['enable_css'] = false;
131
132    if (isset($wpm_new_options['enable_html']))
133      $wpm_new_options['enable_html'] = true;
134    else
135      $wpm_new_options['enable_html'] = false;
136
137    if (isset($wpm_new_options['auto_base']))
138      $wpm_new_options['auto_base'] = true;
139    else
140      $wpm_new_options['auto_base'] = false;
141
142    if (isset($wpm_new_options['cache_external']))
143      $wpm_new_options['cache_external'] = true;
144    else
145      $wpm_new_options['cache_external'] = false;
146
147    if (isset($wpm_new_options['js_in_footer']))
148      $wpm_new_options['js_in_footer'] = true;
149    else
150      $wpm_new_options['js_in_footer'] = false;
151
152    if (isset($wpm_new_options['pretty_url']))
153      $wpm_new_options['pretty_url'] = true;
154    else
155      $wpm_new_options['pretty_url'] = false;
156
157    if (isset($wpm_new_options['debug_nominify']))
158      $wpm_new_options['debug_nominify'] = true;
159    else
160      $wpm_new_options['debug_nominify'] = false;
161
162    if (isset($wpm_new_options['debug_firephp']))
163      $wpm_new_options['debug_firephp'] = true;
164    else
165      $wpm_new_options['debug_firephp'] = false;
166
167    $this->a_set_minify_config($wpm_new_options['debug_nominify'], $wpm_new_options['debug_firephp']);
168
169    if ( isset($wpm_new_options['force_https']) )
170      $wpm_new_options['force_https'] = true;
171    else
172      $wpm_new_options['force_https'] = false;
173
174    if (strlen(trim($wpm_new_options['js_include'])) > 0)
175      $wpm_new_options['js_include'] = $this->array_trim(split(chr(10), str_replace(chr(13), '', $wpm_new_options['js_include'])));
176    else
177      $wpm_new_options['js_include'] = array();
178
179    if (strlen(trim($wpm_new_options['js_exclude'])) > 0)
180      $wpm_new_options['js_exclude'] = $this->array_trim(split(chr(10), str_replace(chr(13), '', $wpm_new_options['js_exclude'])));
181    else
182      $wpm_new_options['js_exclude'] = array();
183
184    if (strlen(trim($wpm_new_options['css_include'])) > 0)
185      $wpm_new_options['css_include'] = $this->array_trim(split(chr(10), str_replace(chr(13), '', $wpm_new_options['css_include'])));
186    else
187      $wpm_new_options['css_include'] = array();
188
189    if (strlen(trim($wpm_new_options['css_exclude'])) > 0)
190      $wpm_new_options['css_exclude'] = $this->array_trim(split(chr(10), str_replace(chr(13), '', $wpm_new_options['css_exclude'])));
191    else
192      $wpm_new_options['css_exclude'] = array();
193
194    if ( strlen(trim($wpm_new_options['uri_exclude'])) > 0 )
195      $wpm_new_options['uri_exclude'] = $this->array_trim(split(chr(10), str_replace(chr(13), '', $wpm_new_options['uri_exclude'])));
196    else
197      $wpm_new_options['uri_exclude'] = array();
198
199    // Update options
200    foreach ($wpm_new_options as $key => $value) {
201      $wpm_current_options[$key] = $value;
202    }
203
204    update_option($this->name, $wpm_current_options);
205  }
206
207  function a_set_advanced_options($val) {
208    $wpm_options = get_option($this->name);
209    $wpm_options['show_advanced'] = $val;
210    update_option($this->name, $wpm_options);
211  }
212
213  function a_ajax_handler() {
214    check_ajax_referer($this->name);
215    if (isset($_POST['wpm_action'])) {
216      if (strtolower($_POST['wpm_action']) == 'show_advanced') {
217        $this->a_set_advanced_options(true);
218      }
219      elseif (strtolower($_POST['wpm_action']) == 'hide_advanced') {
220        $this->a_set_advanced_options(false);
221      }
222      else {
223        echo 'Invalid wpm_action.';
224      }
225    }
226    exit();
227  }
228
229  function a_request_handler() {
230    if (isset($_POST['wpm_options_update_submit'])) {
231      check_admin_referer($this->name);
232      $this->a_update_options();
233      add_action('admin_notices', array($this->c, 'a_notify_updated'));
234    }
235    elseif (isset($_POST['wpm_options_clear_cache_submit'])) {
236      // if user wants to regenerate nonce
237      check_admin_referer($this->name);
238      $this->c->a_clear_cache();
239      add_action('admin_notices', array($this->c, 'a_notify_cache_cleared'));
240    }
241    elseif (isset($_POST['wpm_options_upgrade_submit'])) {
242      // if user wants to upgrade options (for new options on version upgrades)
243      check_admin_referer($this->name);
244      $this->c->a_upgrade_options();
245      add_action('admin_notices', array($this->c, 'a_notify_upgraded'));
246    }
247    elseif (isset($_POST['wpm_options_reset_submit'])) {
248      // if user wants to reset all options
249      check_admin_referer($this->name);
250      $this->c->a_reset_options();
251      add_action('admin_notices', array($this->c, 'a_notify_reset'));
252    }
253
254    // only check these on plugin settings page
255    $this->c->a_check_dir_writable($this->c->get_plugin_dir().'cache/', array($this, 'a_notify_cache_not_writable'));
256    $this->c->a_check_orphan_options(array($this, 'a_notify_orphan_options'));
257    if ($this->c->a_check_dir_writable($this->c->get_plugin_dir().'min/config.php', array($this, 'a_notify_config_not_writable'))) {
258      $this->a_check_minify_config();
259    }
260  }
261
262  function a_check_minify_config() {
263    $fname = $this->c->get_plugin_dir().'min/config.php';
264    $fhandle = fopen($fname,'r');
265    $content = fread($fhandle,filesize($fname));
266
267    $config_modified = false;
268    
269    preg_match('/\/\/###WPM-CACHE-PATH-BEFORE###(.*)\/\/###WPM-CACHE-PATH-AFTER###/s', $content, $matches);
270    $cache_path_code = $matches[1];
271    if (!preg_match('/\$min_cachePath.*?/', $cache_path_code)) {
272      $content = preg_replace(
273        '/\/\/###WPM-CACHE-PATH-BEFORE###(.*)\/\/###WPM-CACHE-PATH-AFTER###/s',
274        "//###WPM-CACHE-PATH-BEFORE###\n".'$min_cachePath = \''.$this->c->get_plugin_dir()."cache/';\n//###WPM-CACHE-PATH-AFTER###",
275        $content);
276      $config_modified = true;
277    }
278
279    preg_match('/\/\/###WPM-CACHE-AGE-BEFORE###(.*)\/\/###WPM-CACHE-AGE-AFTER###/s', $content, $matches);
280    $cache_age_code = $matches[1];
281    if (!preg_match('/\$min_serveOptions\[\'maxAge\'].*?/', $cache_age_code)) {
282      $content = preg_replace(
283        '/\/\/###WPM-CACHE-AGE-BEFORE###(.*)\/\/###WPM-CACHE-AGE-AFTER###/s',
284        "//###WPM-CACHE-AGE-BEFORE###\n".'$min_serveOptions[\'maxAge\'] = 2592000;'."\n//###WPM-CACHE-AGE-AFTER###",
285        $content);
286      $config_modified = true;
287    }
288
289    if ($config_modified) {
290      $this->a_notify_modified_minify_config();
291    }
292    
293    $fhandle = fopen($fname,"w");
294    fwrite($fhandle,$content);
295    fclose($fhandle);
296  }
297
298  function a_set_minify_config($nominify = false, $firephp = false) {
299    if ($nominify) {
300      $nominify = 'true';
301    } else {
302      $nominify = 'false';
303    }
304    if ($firephp) {
305      $firephp = 'true';
306    } else {
307      $firephp = 'false';
308    }
309    $fname = $this->c->get_plugin_dir().'min/config.php';
310    $fhandle = fopen($fname,'r');
311    $content = fread($fhandle,filesize($fname));
312
313    $content = preg_replace(
314      '/\/\/###WPM-DEBUG-FLAG-BEFORE###(.*)\/\/###WPM-DEBUG-FLAG-AFTER###/s',
315      "//###WPM-DEBUG-FLAG-BEFORE###\n".'$min_allowDebugFlag = '.$nominify.";\n//###WPM-DEBUG-FLAG-AFTER###",
316      $content);
317
318    $content = preg_replace(
319      '/\/\/###WPM-ERROR-LOGGER-BEFORE###(.*)\/\/###WPM-ERROR-LOGGER-AFTER###/s',
320      "//###WPM-ERROR-LOGGER-BEFORE###\n".'$min_errorLogger = '.$firephp.";\n//###WPM-ERROR-LOGGER-AFTER###",
321      $content);
322
323    $fhandle = fopen($fname,"w");
324    fwrite($fhandle,$content);
325    fclose($fhandle);
326  }
327
328  function a_notify_cache_not_writable() {
329    $this->c->a_notify(
330      sprintf('%s: %s',
331        __('Cache directory is not writable. Please grant your server write permissions to the directory', $this->name),
332        $this->c->get_plugin_dir().'cache/'),
333      true);
334  }
335
336  function a_notify_config_not_writable() {
337    $this->c->a_notify(
338      sprintf('%s: %s',
339        __('Minify Engine config.php is not writable. Please grant your server write permissions to file', $this->name),
340        $this->c->get_plugin_dir().'min/config.php'));
341  }
342
343  function a_notify_orphan_options() {
344    $this->c->a_notify(
345      sprintf('%s',
346        __('Some option settings are missing (possibly from plugin upgrade).', $this->name)));
347  }
348
349  function a_notify_modified_minify_config() {
350    $this->c->a_notify(__('Minify Engine config.php was configured automatically.', $this->name));
351  }
352
353  function a_menu() {
354    $options_page = add_options_page($this->name_proper, $this->name_proper, 'manage_options', 'wp-minify', array($this, 'a_page'));
355    add_action('admin_head-'.$options_page, array($this, 'a_request_handler'));
356    add_action('admin_print_scripts-'.$options_page, array($this->c, 'a_enqueue_scripts'));
357    add_action('admin_print_styles-'.$options_page, array($this->c, 'a_enqueue_styles'));
358  }
359
360  function a_page() {
361    $wpm_options = get_option($this->name);
362    printf('
363      <div class="wrap omni_admin_content">
364        <h2>%s</h2>
365        <div>
366          <a href="'.preg_replace('/&wpm-page=[^&]*/', '', $_SERVER['REQUEST_URI']).'">%s</a>&nbsp;|&nbsp;
367          <a href="'.$this->homepage.'">%s</a>
368        </div>',
369      __('WP Minify Options', $this->name),
370      __('General Configuration', $this->name),
371      __('Documentation', $this->name)
372    );
373    printf('<div class="omni_admin_main">');
374    if (isset($_GET['wpm-page'])) {
375      if ($_GET['wpm-page'] || !$_GET['wpm-page']) {
376        require_once('options-generic.php');
377      }
378    }
379    else {
380      require_once('options-generic.php');
381    }
382    printf('</div>'); // omni_admin_main
383    require_once('options-sidebar.php');
384    printf('</div>'); // wrap
385
386  } // admin_page()
387
388  // other functions
389
390  function fetch_and_cache($url, $cache_file) {
391    $ch = curl_init();
392    $timeout = 5; // set to zero for no timeout
393    curl_setopt ($ch, CURLOPT_URL, $url);
394    curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
395    curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
396    curl_setopt ($ch, CURLOPT_USERAGENT, 'WP-Minify');
397    $content = curl_exec($ch);
398    curl_close($ch);
399    if ($content) {
400      if (is_array($content)) {
401        $content = implode($content);
402      }
403
404      // save cache file
405      $fh = fopen($cache_file, 'w');
406      if ($fh) {
407        fwrite($fh, $content);
408        fclose($fh);
409      }
410      else {
411        // cannot open for write.  no error b/c something else is probably writing to the file.
412      }
413
414      return $content;
415    }
416    else {
417      printf(
418        '%s: '.$url.'. %s<br/>',
419        __('Error: Could not fetch and cache URL'),
420        __('You might need to exclude this file in WP Minify options.')
421      );
422      return '';
423    }
424  }
425
426  function refetch_cache_if_expired($url, $cache_file) {
427    $wpm_options = get_option($this->name);
428    $cache_file_mtime = filemtime($cache_file);
429    if ((time() - $cache_file_mtime) > $wpm_options['cache_interval']) {
430      $this->fetch_and_cache($url, $cache_file);
431    }
432  }
433
434  function tiny_filename($str) {
435    $f = __FILE__;
436    // no fancy shortening for Windows
437    return ('/' === $f[0]) ? strtr(base64_encode(md5($str, true)), '+/=', '-_(') : md5($str);
438  }
439
440  function array_trim($arr, $charlist=null) {
441    foreach ($arr as $key => $value) {
442      if (is_array($value)) $result[$key] = array_trim($value, $charlist);
443      else $result[$key] = trim($value, $charlist);
444    }
445    return $result;
446  }
447
448  function check_and_split_url($url, $latest_modified = 0) {
449    $url_chunk = explode('?f=', $url);
450    $base_url = array_shift($url_chunk);
451    $files = explode(',', array_shift($url_chunk));
452    $num_files = sizeof($files);
453
454    if ($this->url_needs_splitting($url, $files)) {
455      $first_half = $this->check_and_split_url($base_url . '?f=' . implode(',', array_slice($files, 0, $num_files/2)), $latest_modified);
456      $second_half = $this->check_and_split_url($base_url . '?f=' . implode(',', array_slice($files, $num_files/2)), $latest_modified);
457      return $first_half + $second_half;
458    }
459    else {
460      $wpm_options = get_option($this->name);
461
462      // append &debug if we need to
463      if ($wpm_options['debug_nominify']) {
464        $debug_string = '&amp;debug=true';
465      } else {
466        $debug_string = '';
467      }
468
469      // append base directory if needed
470      $base = $this->get_base();
471      if ($base != '') {
472        $base_string = '&amp;b='.$base;
473      } else {
474        $base_string = '';
475      }
476
477      // get rid of any base directory specification in extra options
478      $extra_minify_options = preg_replace('/(&|&amp;|\b)b=[^&]*/', '', trim($wpm_options['extra_minify_options']));
479      if (trim($extra_minify_options) != '') {
480        $extra_string = '&amp;'.$extra_minify_options;
481      } else {
482        $extra_string = '';
483      }
484
485      // append last modified time
486      $latest_modified_string = '&amp;m='.$latest_modified;
487
488      return array($base_url . '?f=' . implode(',', $files) . $debug_string . $base_string . $extra_string . $latest_modified_string);
489    }
490  }
491
492  function fetch_content($url, $type = '') {
493    $cache_file = $this->c->get_plugin_dir().'cache/'.md5($url).$type;
494    $content = '';
495    if (file_exists($cache_file)) {
496      // check cache expiration
497      $this->refetch_cache_if_expired($url, $cache_file);
498
499      $fh = fopen($cache_file, 'r');
500      if ($fh && filesize($cache_file) > 0) {
501        $content = fread($fh, filesize($cache_file));
502        fclose($fh);
503      }
504      else {
505        // cannot open cache file so fetch it
506        $content = $this->fetch_and_cache($url, $cache_file);
507      }
508    }
509    else {
510      // no cache file.  fetch from internet and save to local cache
511      $content = $this->fetch_and_cache($url, $cache_file);
512    }
513    return $content;
514  }
515
516  function local_version($url) {
517    $site_url = trailingslashit(get_option('siteurl'));
518    $url = str_replace($site_url, '', $url); // relative paths only for local urls
519    $url = preg_replace('/^\//', '', $url); // strip front / if any
520    $url = preg_replace('/\?.*/i', '', $url); // throws away parameters, if any
521    return $url;
522  }
523
524  function is_external($url, $localize=true) {
525    if ($localize) {
526      $url = $this->local_version($url);
527    }
528
529    if (substr($url, 0, 4) != 'http'
530      && (substr($url, -3, 3) == '.js' || substr($url, -4, 4) == '.css')) {
531      return false;
532    } else {
533      return true;
534    }
535  }
536
537  function get_js_location($src) {
538    if ($this->debug)
539      echo 'Script URL:'.$src."<br/>\n";
540
541    $script_path = $this->local_version($src);
542    if ($this->is_external($script_path, false)) {
543      // fetch scripts if necessary
544      $this->fetch_content($src, '.js');
545      $location = $this->cache_location . md5($src) . '.js';
546      if ($this->debug)
547        echo 'External script detected, cached as:'. md5($src) . "<br/>\n";
548    } else {
549      // if script is local to server
550      $location = $script_path;
551      if ($this->debug)
552        echo 'Local script detected:'.$script_path."<br/>\n";
553    }
554
555    return $location;
556  }
557
558  function get_css_location($src) {
559    if ($this->debug)
560      echo 'Style URL:'.$src."<br/>\n";
561
562    $css_path = $this->local_version($src);
563    if ($this->is_external($css_path, false)) {
564      // fetch scripts if necessary
565      $this->fetch_content($src, '.css');
566      $location = $this->cache_location . md5($src) . '.css';
567      if ($this->debug)
568        echo 'External css detected, cached as:'. md5($src) . "<br/>\n";
569    } else {
570      $location = $css_path;
571      // if css is local to server
572      if ($this->debug)
573        echo 'Local css detected:'.$css_path."<br/>\n";
574    }
575
576    return $location;
577  }
578
579  function url_needs_splitting($url, $locations) {
580    if ($url > $this->url_len_limit || count($locations) > $this->minify_limit) {
581      return true;
582    } else {
583      return false;
584    }
585  }
586
587  function build_minify_urls($locations, $type) {
588    $wpm_options = get_option($this->name);
589    $minify_url = $this->c->get_plugin_url().'min/?f=';
590    if ($wpm_options['force_https'] && $_SERVER["HTTPS"] == "on") {
591      $minify_url = preg_replace('/^http:\/\//', 'https://', $minify_url);
592    }
593    $minify_url .= implode(',', $locations);
594    $latest_modified = $this->get_latest_modified_time($locations);
595    $minify_urls = $this->check_and_split_url($minify_url, $latest_modified);
596
597    if ($wpm_options['pretty_url']) {
598      return $this->get_cached_minify_urls($minify_urls, $type);
599    } else {
600      return $minify_urls;
601    }
602  }
603  
604  function get_cached_minify_urls($urls, $type) {
605    $wpm_options = get_option($this->name);
606    $cached_urls = array();
607    foreach ($urls as $url) {
608      $cache_file = $this->c->get_plugin_dir().'cache/'.md5($url).$type;
609      if (file_exists($cache_file)) {
610        // check cache expiration
611        $this->refetch_cache_if_expired($url, $cache_file);
612  
613        $fh = fopen($cache_file, 'r');
614        if ($fh && filesize($cache_file) > 0) {
615          $content = fread($fh, filesize($cache_file));
616          fclose($fh);
617        } else {
618          // cannot open cache file so fetch it
619          $this->fetch_and_cache($url, $cache_file);
620        }
621      } else {
622        // no cache file. fetch it
623        $this->fetch_and_cache($url, $cache_file);
624      }
625      $cache_url = $this->c->get_plugin_url().'cache/'.md5($url).$type.'?m='.filemtime($cache_file);
626      $cached_urls[] = $cache_url;
627    }
628    return $cached_urls;
629  }
630
631  function get_base_from_minify_args() {
632    $wpm_options = get_option($this->name);
633    if (!empty($wpm_options['extra_minify_options'])) {
634      if (preg_match('/\bb=([^&]*?)(&|$)/', trim($wpm_options['extra_minify_options']), $matches)) {
635        return rtrim(trim($matches[1]), '\\/');
636      }
637    }
638    return '';
639  }
640
641  function get_base_from_siteurl() {
642    $site_url = trailingslashit(get_option('siteurl'));
643    return rtrim(preg_replace('/^https?:\/\/.*?\//', '', $site_url), '\\/');
644  }
645
646  function get_base() {
647    $base_from_min_args = $this->get_base_from_minify_args();
648    if ($base_from_min_args != '') {
649      return $base_from_min_args;
650    }
651
652    $wpm_options = get_option($this->name);
653    if ($wpm_options['auto_base']) {
654      return $this->get_base_from_siteurl();
655    } else {
656      return '';
657    }
658  }
659
660  function get_latest_modified_time($locations = array()) {
661    $latest_modified = 0;
662    if (!empty($locations)) {
663      $base_path = trailingslashit($_SERVER['DOCUMENT_ROOT']);
664      $base_path .= trailingslashit($this->get_base());
665
666      foreach ($locations as $location) {
667        $path = $base_path.$location;
668        $mtime = filemtime($path);
669        if ($latest_modified < $mtime) {
670          $latest_modified = $mtime;
671        }
672      }
673    }
674    return $latest_modified;
675  }
676
677  function extract_css($content) {
678    $wpm_options = get_option($this->name);
679    $css_locations = array();
680
681    preg_match_all('/<link([^>]*?)>/i', $content, $link_tags_match);
682
683    foreach ($link_tags_match[0] as $link_tag) {
684      if (strpos(strtolower($link_tag), 'stylesheet')) {
685        // check CSS media type
686        if (!strpos(strtolower($link_tag), 'media=')
687          || preg_match('/media=["\'](?:["\']|[^"\']*?(all|screen)[^"\']*?["\'])/', $link_tag)
688        ) {
689          preg_match('/href=[\'"]([^\'"]+)/', $link_tag, $href_match);
690          if ($href_match[1]) {
691            // include it if it is in the include list
692            $include = false;
693            $inclusions = $wpm_options['css_include'];
694            foreach ($inclusions as $include_pat) {
695              $include_pat = trim($include_pat);
696              if (strlen($include_pat) > 0 && strpos($src_match[1], $include_pat) !== false) {
697                $include = true;
698                break;
699              }
700            }
701
702            if (!$include) {
703              // support external files?
704              if (!$wpm_options['cache_external'] && $this->is_external($href_match[1])) {
705                continue; // skip if we don't cache externals and this file is external
706              }
707
708              // do not include anything in excluded list
709              $skip = false;
710              $exclusions = array_merge($this->default_exclude, $wpm_options['css_exclude']);
711              foreach ($exclusions as $exclude_pat) {
712                $exclude_pat = trim($exclude_pat);
713                if (strlen($exclude_pat) > 0 && strpos($href_match[1], $exclude_pat) !== false) {
714                  $skip = true;
715                  break;
716                }
717              }
718              if ($skip) continue;
719            }
720
721            $content = str_replace($link_tag . '</link>', '', $content);
722            $content = str_replace($link_tag, '', $content);
723            $css_locations[] = $this->get_css_location($href_match[1]);
724          }
725        }
726      }
727    }
728
729    $css_locations = array_unique($css_locations);
730
731    return array($content, $css_locations);
732  }
733
734  function inject_css($content, $css_locations) {
735    if (count($css_locations) > 0) {
736      $wpm_options = get_option($this->name);
737      // build minify URLS
738      $css_tags = '';
739      $minify_urls = $this->build_minify_urls($css_locations, '.css');
740
741      foreach ($minify_urls as $minify_url) {
742        $minify_url = apply_filters('wp_minify_css_url', $minify_url); // Allow plugins to modify final minify URL
743        $css_tags .= "<link rel='stylesheet' href='$minify_url' type='text/css' media='screen' />";
744      }
745
746      $matches = preg_match('/<!-- WP-Minify CSS -->/', $content);
747
748      if ($matches) {
749        $content = preg_replace('/<!-- WP-Minify CSS -->/', "$css_tags", $content, 1); // limit 1 replacement
750      } else {
751        // HTML5 has <header> tags so account for those in regex
752        $content = preg_replace('/<head(>|\s[^>]*?>)/', "\\0\n$css_tags", $content, 1); // limit 1 replacement
753      }
754    }
755    return $content;
756  }
757
758  function extract_conditionals($content) {
759    preg_match_all('/<!--\[if[^\]]*?\]>.*?<!\[endif\]-->/is', $content, $conditionals_match);
760    $content = preg_replace('/<!--\[if[^\]]*?\]>.*?<!\[endif\]-->/is', '###WPM-CSS-CONDITIONAL###', $content);
761
762    $conditionals = array();
763    foreach ($conditionals_match[0] as $conditional) {
764      $conditionals[] = $conditional;
765    }
766
767    return array($content, $conditionals);
768  }
769
770  function inject_conditionals($content, $conditionals) {
771    while (count($conditionals) > 0 && strpos($content, '###WPM-CSS-CONDITIONAL###')) {
772      $conditional = array_shift($conditionals);
773      $content = preg_replace('/###WPM-CSS-CONDITIONAL###/', $conditional, $content, 1);
774    }
775
776    return $content;
777  }
778
779  function extract_js($content) {
780    $wpm_options = get_option($this->name);
781    $js_locations = array();
782
783    preg_match_all('/<script([^>]*?)><\/script>/i', $content, $script_tags_match);
784
785    foreach ($script_tags_match[0] as $script_tag) {
786      if (strpos(strtolower($script_tag), 'text/javascript') !== false) {
787        preg_match('/src=[\'"]([^\'"]+)/', $script_tag, $src_match);
788        if ($src_match[1]) {
789          // include it if it is in the include list
790          $include = false;
791          $inclusions = $wpm_options['js_include'];
792          foreach ($inclusions as $include_pat) {
793            $include_pat = trim($include_pat);
794            if (strlen($include_pat) > 0 && strpos($src_match[1], $include_pat) !== false) {
795              $include = true;
796              break;
797            }
798          }
799
800          if (!$include) {
801            // support external files?
802            if (!$wpm_options['cache_external'] && $this->is_external($src_match[1])) {
803              continue; // skip if we don't cache externals and this file is external
804            }
805
806            // do not include anything in excluded list
807            $skip = false;
808            $exclusions = array_merge($this->default_exclude, $wpm_options['js_exclude']);
809            foreach ($exclusions as $exclude_pat) {
810              $exclude_pat = trim($exclude_pat);
811              if (strlen($exclude_pat) > 0 && strpos($src_match[1], $exclude_pat) !== false) {
812                $skip = true;
813                break;
814              }
815            }
816            if ($skip) continue;
817          }
818
819          $content = str_replace($script_tag, '', $content);
820          $js_locations[] = $this->get_js_location($src_match[1]);
821        }
822      }
823    }
824
825    $js_locations = array_unique($js_locations);
826
827    return array($content, $js_locations);
828  }
829
830  function inject_js($content, $js_locations) {
831    if (count($js_locations) > 0) {
832      // build minify URLS
833      $js_tags = '';
834      $minify_urls = $this->build_minify_urls($js_locations, '.js');
835
836      foreach ($minify_urls as $minify_url) {
837        $minify_url = apply_filters('wp_minify_js_url', $minify_url); // Allow plugins to modify final minify URL
838        $js_tags .= "<script type='text/javascript' src='$minify_url'></script>";
839      }
840
841      $matches = preg_match('/<!-- WP-Minify JS -->/', $content);
842
843      if ($matches) {
844        $content = preg_replace('/<!-- WP-Minify JS -->/', "$js_tags", $content, 1); // limit 1 replacement
845      } else {
846        $wpm_options = get_option($this->name);
847        if ($wpm_options['js_in_footer']) {
848          $content = preg_replace('/<\/body>/', "$js_tags\n</body>", $content, 1); // limit 1 replacement
849        } else {
850          // HTML5 has <header> tags so account for those in regex
851          $content = preg_replace('/<head(>|\s[^>]*?>)/', "\\0\n$js_tags", $content, 1); // limit 1 replacement
852        }
853      }
854    }
855    return $content;
856  }
857
858  function pre_content() {
859    $wpm_options = get_option($this->name);
860    if ($wpm_options['uri_exclude'] && count($wpm_options['uri_exclude'])) {
861      foreach ($wpm_options['uri_exclude'] as $exclude_pat) {
862        $exclude_pat = trim($exclude_pat);
863        if (strlen($exclude_pat) > 0 && strpos($_SERVER['REQUEST_URI'], $exclude_pat) !== false) {
864          return;
865        }
866      }
867    }
868
869    ob_start(array($this, 'modify_buffer'));
870
871    // variable for sanity checking
872    $this->buffer_started = true;
873  }
874
875  function modify_buffer($buffer) {
876    $wpm_options = get_option($this->name);
877
878    // if we do not want to force http to https then we need to exclude https
879    if (!($wpm_options['force_https'] && $_SERVER["HTTPS"] == "on")) {
880      $this->default_exclude[] = 'https://';
881    }
882
883    // minify JS
884    if ($wpm_options['enable_js']) {
885      list($buffer, $js_locations) = $this->extract_js($buffer);
886      $buffer= $this->inject_js($buffer, $js_locations);
887    }
888
889    // minify CSS (make sure to exclude CSS conditionals)
890    if ($wpm_options['enable_css']) {
891      list($buffer, $conditionals) = $this->extract_conditionals($buffer);
892      list($buffer, $css_locations) = $this->extract_css($buffer);
893      $buffer = $this->inject_css($buffer, $css_locations);
894      $buffer = $this->inject_conditionals($buffer, $conditionals);
895    }
896
897    // get rid of empty lines
898    $buffer = preg_replace('/\s*(\r?\n)(\r?\n)*/', '$1', $buffer);
899
900    // minify HTML
901    if ($wpm_options['enable_html']) {
902      if (!class_exists('Minify_HTML')) {
903        require_once('min/lib/Minify/HTML.php');
904      }
905      $buffer = Minify_HTML::minify($buffer);
906    }
907
908    $buffer = apply_filters('wp_minify_content', $buffer); // allow plugins to modify buffer
909
910    return $buffer;
911  }
912
913  function post_content() {
914    // sanity checking
915    if ($this->buffer_started) {
916      ob_end_flush();
917    }
918  }
919
920  function advertise() {
921    $wpm_options = get_option($this->name);
922    if ($wpm_options['show_link']) {
923      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>");
924    }
925  }
926
927} // class WPMinify
928
929require_once('common.php');
930require_once('http_build_url.php');
931$wp_minify = new WPMinify();
932?>