Created
May 11, 2009 19:49
-
-
Save jaylib/110142 to your computer and use it in GitHub Desktop.
base64 Plugin for CSS Cacheer with support for IE6+
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /****************************************************************************** | |
| Prevent direct access | |
| ******************************************************************************/ | |
| if (!defined('CSS_CACHEER')) { header('Location:/'); } | |
| $plugin_class = 'Base64Plugin'; | |
| class Base64Plugin extends CacheerPlugin | |
| { | |
| function Base64Plugin() | |
| { | |
| if (isset($_SERVER['HTTP_USER_AGENT'])) | |
| { | |
| $ua = $this->parse_user_agent($_SERVER['HTTP_USER_AGENT']); | |
| // Safari (WebKit), Firefox & Opera are known to support data: urls so embed base64-encoded images | |
| if | |
| ( | |
| ($ua['browser'] == 'applewebkit' && $ua['version'] >= 125) || // Safari and ilk | |
| ($ua['browser'] == 'firefox') || // Firefox et al | |
| ($ua['browser'] == 'opera' && $ua['version'] >= 7.2) || // quell vociferous Opera evangelists | |
| ($ua['browser'] == 'ie' && $ua['version'] >= 6.0) | |
| ) | |
| { | |
| $this->flags['Base64'] = true; | |
| } | |
| } | |
| } | |
| function post_process($css) | |
| { | |
| global $prepend_css; | |
| $ua = $this->parse_user_agent($_SERVER['HTTP_USER_AGENT']); | |
| if (isset($this->flags['Base64'])) | |
| { | |
| global $requested_dir; | |
| $root_dir = $_SERVER['DOCUMENT_ROOT']; | |
| $images = array(); | |
| if (preg_match_all('#url\(([^\)]+)\)#i', $css, $matches)) | |
| { | |
| foreach($matches[1] as $relative_img) | |
| { | |
| if (!preg_match('#\.(gif|jpg|png)$#', $relative_img, $ext)) | |
| { | |
| continue; | |
| } | |
| $images[$relative_img] = $ext[1]; | |
| } | |
| } | |
| if ($ua['browser']!="ie") { | |
| foreach($images as $relative_img => $img_ext) | |
| { | |
| $up = substr_count($relative_img, '../'); | |
| $absolute_img = $root_dir.preg_replace('#([^/]+/){'.$up.'}(\.\./){'.$up.'}#', '', $requested_dir.'/'.$relative_img); | |
| if (file_exists($absolute_img)) | |
| { | |
| $img_raw = file_get_contents($absolute_img); | |
| $img_data = 'data:image/'.$img_ext.';base64,'.base64_encode($img_raw); | |
| $css = str_replace("url({$relative_img})", "url({$img_data})", $css); | |
| } | |
| } | |
| } | |
| else if ($ua['browser']=="ie") { | |
| $full_request_uri = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; // absolute url for the requested css file | |
| $delimiter = "DELIMITER_STRING"; // Delimiter for each base64 encoded image declaration | |
| $prepend_css .="/*\n".'Content-Type: multipart/related; boundary="'.$delimiter.'"'."\n\n"; // set the required Content-Type for mhtml | |
| foreach($images as $relative_img => $img_ext) | |
| { | |
| $up = substr_count($relative_img, '../'); | |
| $absolute_img = $root_dir.preg_replace('#([^/]+/){'.$up.'}(\.\./){'.$up.'}#', '', $requested_dir.'/'.$relative_img); | |
| if (file_exists($absolute_img)) | |
| { | |
| $img_raw = file_get_contents($absolute_img); | |
| $img_data = trim(base64_encode($img_raw)); | |
| // Content-Location: .... | |
| $content_location = str_replace(array("/", "."), "", $relative_img); | |
| // url(mhtlm:http://......) | |
| $mhtml_uri = "mhtml:".$full_request_uri."!".$content_location; | |
| $css = str_replace("url({$relative_img})", "url({$mhtml_uri})", $css); | |
| // insert base64 encoded images into the css-file | |
| $prepend_css .= "--".$delimiter."\n"; | |
| $prepend_css .= "Content-Location:".$content_location."\n"; | |
| $prepend_css .= "Content-Transfer-Encoding:base64\n\n"; | |
| $prepend_css .= $img_data."\n\n"; | |
| } | |
| } | |
| $prepend_css .= "*/\n\n"; // Close comment for the mhtml part | |
| } | |
| } | |
| return $css; | |
| } | |
| // really simple (read: imperfect) rendering engine detection | |
| function parse_user_agent($user_agent) | |
| { | |
| $ua['browser'] = ''; | |
| $ua['version'] = 0; | |
| if (preg_match('/(firefox|opera|applewebkit)(?: \(|\/|[^\/]*\/| )v?([0-9.]*)/i', $user_agent, $m)) | |
| { | |
| $ua['browser'] = strtolower($m[1]); | |
| $ua['version'] = $m[2]; | |
| } | |
| else if (preg_match('/MSIE ?([0-9.]*)/i', $user_agent, $v) && !preg_match('/(bot|(?<!mytotal)search|seeker)/i', $user_agent)) | |
| { | |
| $ua['browser'] = 'ie'; | |
| $ua['version'] = $v[1]; | |
| } | |
| return $ua; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| error_reporting(0); | |
| /****************************************************************************** | |
| Used to prevent direct access to CSS Cacheer files | |
| ******************************************************************************/ | |
| define('CSS_CACHEER', true); | |
| /****************************************************************************** | |
| Received request from mod_rewrite | |
| ******************************************************************************/ | |
| // absolute path to requested file, eg. /css/nested/sample.css | |
| $requested_file = isset($_GET['cssc_request']) ? $_GET['cssc_request'] : ''; | |
| // absolute path to directory containing requested file, eg. /css/nested | |
| $requested_dir = preg_replace('#/[^/]*$#', '', $requested_file); | |
| // absolute path to css directory, eg. /css | |
| $css_dir = preg_replace('#/[^/]*$#', '', (isset($_SERVER['PHP_SELF'])) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_URL']); | |
| /****************************************************************************** | |
| Limit processing to existing css files within this and nested directories | |
| ******************************************************************************/ | |
| if | |
| ( | |
| substr($requested_file, -4) != '.css' || | |
| substr($requested_file, 0, strlen($css_dir)) != $css_dir || | |
| !file_exists(substr($requested_file, strlen($css_dir) + 1)) | |
| ) | |
| { | |
| echo '/* Invalid Request */'; | |
| exit(); | |
| } | |
| /****************************************************************************** | |
| Load plugins | |
| ******************************************************************************/ | |
| include('css-cacheer/plugin.php'); | |
| $flags = array(); | |
| $plugins = array(); | |
| $plugin_path = 'css-cacheer/plugins'; | |
| if (is_dir($plugin_path)) | |
| { | |
| if ($dir_handle = opendir($plugin_path)) | |
| { | |
| while (($plugin_file = readdir($dir_handle)) !== false) | |
| { | |
| if (substr($plugin_file, 0, 1) == '.' || substr($plugin_file, 0, 1) == '-') | |
| { | |
| continue; | |
| } | |
| include($plugin_path.'/'.$plugin_file); | |
| if (isset($plugin_class) && class_exists($plugin_class)) | |
| { | |
| $plugins[$plugin_class] = new $plugin_class($flags); | |
| $flags = array_merge($flags, $plugins[$plugin_class]->flags); | |
| } | |
| } | |
| closedir($dir_handle); | |
| } | |
| } | |
| /****************************************************************************** | |
| Create hash of query string to allow variables to be cached | |
| ******************************************************************************/ | |
| $isIE = eregi("MSIE", $_SERVER['HTTP_USER_AGENT']); | |
| $isIEOnVista = $isIE && eregi("Windows NT 6.0", $_SERVER['HTTP_USER_AGENT']); | |
| $recache = isset($_GET['recache']); | |
| $args = $flags; | |
| ksort($args); | |
| $checksum = md5(serialize($args.$isIE.)); // Gives two different checksums for IE and non-IE Browsers | |
| /****************************************************************************** | |
| Determine relative and cache paths | |
| ******************************************************************************/ | |
| $cssc_cache_dir = 'css-cacheer/cache/'; | |
| // path to requested file, relative to css directory, eg. nested/sample.css | |
| $relative_file = substr($requested_file, strlen($css_dir) + 1); | |
| // path to directory containing requested file, relative to css directory, eg. nested | |
| $relative_dir = (strpos($relative_file, '/') === false) ? '' : preg_replace("/\/[^\/]*$/", '', $relative_file); | |
| // path to cache of requested file, relative to css directory, eg. css-cacheer/cache/nested/sample.css | |
| $cached_file = $cssc_cache_dir.preg_replace('#(.+)(\.css)$#i', "$1-{$checksum}$2", $relative_file); | |
| // path to directory containing cache of requested CSS file, relative from the directory containing cache.php, eg. cache/nested | |
| $cached_dir = $cssc_cache_dir.$relative_dir; | |
| /****************************************************************************** | |
| Delete file cache | |
| ******************************************************************************/ | |
| if ($recache && file_exists($cached_file)) | |
| { | |
| unlink($cached_file); | |
| } | |
| /****************************************************************************** | |
| Get modified time for requested file and if available, its cache | |
| ******************************************************************************/ | |
| $requested_mod_time = filemtime($relative_file); | |
| $cached_mod_time = (int) @filemtime($cached_file); | |
| // cache may not exist, silence error with @ | |
| /****************************************************************************** | |
| Recreate the cache if stale or nonexistent | |
| ******************************************************************************/ | |
| if ($cached_mod_time < $requested_mod_time) | |
| { | |
| include_once('css-cacheer/index.php'); | |
| } | |
| /****************************************************************************** | |
| Or send 304 header if appropriate | |
| ******************************************************************************/ | |
| else if | |
| ( | |
| isset($_SERVER['HTTP_IF_MODIFIED_SINCE'], $_SERVER['SERVER_PROTOCOL']) && | |
| $requested_mod_time <= strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) | |
| ) | |
| { | |
| header("{$_SERVER['SERVER_PROTOCOL']} 304 Not Modified"); | |
| exit(); | |
| } | |
| /****************************************************************************** | |
| Send cached file to browser, Due to security restrictions on Windows Vista, a | |
| MHTML document has to have the MIME type 'text/plain'. | |
| ******************************************************************************/ | |
| if ($isIEOnVista) | |
| { | |
| header('Content-type: text/plain'); | |
| } | |
| else | |
| { | |
| header('Content-type: text/css'); | |
| } | |
| header("Vary: User-Agent, Accept"); | |
| header('Last-Modified: '.gmdate('D, d M Y H:i:s', $requested_mod_time).' GMT'); | |
| @include($cached_file); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /****************************************************************************** | |
| Prevent direct access | |
| ******************************************************************************/ | |
| if (!defined('CSS_CACHEER')) { header('Location:/'); } | |
| /****************************************************************************** | |
| Grab the modified CSS file | |
| ******************************************************************************/ | |
| $css = file_get_contents($relative_file); | |
| $prepend_css = ""; // prepend to css before caching | |
| // Pre-process for importers | |
| foreach($plugins as $plugin) | |
| { | |
| $css = $plugin->pre_process($css); | |
| } | |
| // Process for heavy lifting | |
| foreach($plugins as $plugin) | |
| { | |
| $css = $plugin->process($css); | |
| } | |
| // Post-process for formatters | |
| foreach($plugins as $plugin) | |
| { | |
| $css = $plugin->post_process($css); | |
| } | |
| /******************************************************************************/ | |
| $header = '/* Processed and cached by Shaun Inman\'s CSS Cacheer'; | |
| $header .= ' (with '.str_replace('Plugin', '', preg_replace('#,([^,]+)$#', " &$1", join(', ', array_keys($plugins)))).' enabled)'; | |
| $header .= ' on '.gmdate('r').' <http://shauninman.com/search/?q=cacheer> */'."\r\n"; | |
| $css = $prepend_css.$header.$css; | |
| /****************************************************************************** | |
| Make sure the target directory exists | |
| ******************************************************************************/ | |
| if ($cached_file != $cached_dir && !is_dir($cached_dir)) | |
| { | |
| $path = $cssc_cache_dir; | |
| $dirs = explode('/', $relative_dir); | |
| foreach ($dirs as $dir) | |
| { | |
| $path .= '/'.$dir; | |
| mkdir($path, 0777); | |
| } | |
| } | |
| /****************************************************************************** | |
| Cache parsed CSS | |
| ******************************************************************************/ | |
| $css_handle = fopen($cached_file, 'w'); | |
| fwrite($css_handle, $css); | |
| fclose($css_handle); | |
| chmod($cached_file, 0777); | |
| touch($cached_file, $requested_mod_time); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment