PHP Dataurifier : Convert CSS Images to data URI

This little php script should handle expiry dates, compression and check for browser support with transparent fallback, automatically "dataurify" images in CSS files. It will encode everything that needs to be encoded. According to my own browser stats, browser support for data:uri at this time (Dec 6 2009) is over 50%. Use it as you like, just credit if you can and, more important, comment here any issue, question, idea, improvement, etc. please, I spent some time on it and that´s the least I can ask.

How to use it:

Save the code below in a .php file, name it for instance "css.php" and link it from your (X)HTML:


<link href="css.php" rel ="stylesheet" type="text/css" />


Include your current css file(s) in the proper spot inside css.php (Read comments in code).


That's it!

The Code:


<?php
define
( 'CSS_BROWSER_CACHE' , 60 * 60 * 24 * 7 ); ### SECONDS, CLIENT CACHE
define ( 'CONTENT_CRUNCH' , true ); ### Set to 0 or false if you DO not want your CSS text to be crunched.
#############################################################################
################### COMPRESSION #########################
#############################################################################
if ((isset( $_SERVER [ 'HTTP_ACCEPT_ENCODING' ]) && strstr ( $_SERVER [ 'HTTP_ACCEPT_ENCODING' ], 'gzip' )) && extension_loaded ( 'zlib' )) {
$_zlib_included = strtolower ( ini_get ( 'zlib.output_compression' ));
if (empty(
$_zlib_included ) || $_zlib_included == 'off' ) {
ini_set ( 'zlib.output_compression_level' , 6 );
ob_start ( 'ob_gzhandler' );
}
}
#############################################################################
################### READY, SET, GO! #########################
#############################################################################
ob_start ( '_process_css' );
#############################################################################
################### CSS FILES #########################
#############################################################################
# In your CSS text you DO need to use complete absolute server image paths,
# i.e.: url(/path/to/image/file.jpg) and NOT url(../../file.jpg). With or without quotes.
#
# Include here all the css files you want to send, one by one
# as with any other php include file path must be absolute or relative
# to this file. If css text files are in the same folder, you do not need
# to specify path.
# i.e.:
# include(path/to/css/file/file.css);
# include(path/to/css/file/another_file.css);
include( 'cssfile.css' );
# That's all! Happy CSSing.
#############################################################################
#############################################################################
#############################################################################
#############################################################################
################### RESPONSE HEADERS #########################
#############################################################################
header ( 'Content-Type: text/css; charset=utf-8' );
header ( 'Expires: ' . gmdate ( 'D, d M Y H:i:s' , time ()+ abs ( CSS_BROWSER_CACHE ) ) . ' GMT' );
header ( 'Cache-Control: max-age=' . abs ( CSS_BROWSER_CACHE ). ', must-revalidate' );
header ( 'X-Robots-Tag: noindex' );
exit;
#############################################################################
#############################################################################
################### FUNCTIONS #########################
#############################################################################
function _process_css ( $contents ) {
if (
dataURIsupported ()) {
$contents = dataURIfy_CSS ( $contents );
}
if (
CONTENT_CRUNCH ) {
$contents = preg_replace (array( '/[nrt]/' , '/ss+/' ), array( '' , ' ' ), $contents );
}
return
$contents ;
}
function
produce_dataURI ( $file ){
### $file should be an absolute root path address "/media/more/evenmore/file.png"
$string = str_replace (array( '"' , "'" ), '' , $file );
$file_path = $_SERVER [ 'DOCUMENT_ROOT' ]. $string ;
if (
is_file ( $file_path )){
$type = end ( explode ( '.' , $string ));
$type = $type == 'jpg' ? 'jpeg' : $type ;
$content = base64_encode ( file_get_contents ( $file_path ));
$string = "data:image/" . $type . ';base64,' . $content ;
}
return
"url('" . $string . "')" ;
}

function
dataURIfy_CSS ( $css_text ) {
return
preg_replace ( '¬url((.*))¬e' , "produce_dataURI('$1')" , $css_text );
}
/*
Browsers that support data URIs:
* Firefox 2+
* Opera 7.2+ - data URIs must not be longer than 4100 characters (Mensonge!)
* Chrome (all versions)
* Safari (all versions), Of course safari and chrome, chrome is just a copy of konqueror and safari.
* Internet Explorer 8+ - data URIs must be smaller than 32k
*/
function dataURIsupported (){
$supported = false ;
$browser = what_browser ();
if (
$browser [ 'name' ] == 'ie' && $browser [ 'ver' ]> 7.9 ) {
$supported = true ;
}
elseif(
$browser [ 'name' ] == 'AppleWebKit' ) {
$supported = true ;
}
elseif( (
$browser [ 'name' ] == 'firefox' && $browser [ 'ver' ]> 2 ) || ( $browser [ 'name' ] == 'opera' && $browser [ 'ver' ]> 8 ) || ( $browser [ 'name' ] == 'netscape' && $browser [ 'ver' ]> 7 )) {
$supported = true ;
}
return
$supported ;
}
function
what_browser ( $user_agent = '' ){
### THIS IS A SIMPLIFIED VERSION FITTED FOR THIS USE
if (! function_exists ( 'stripos' )) {
function
stripos ( $haystack , $needle , $offset = 0 ) {
return
strpos ( strtolower ( $haystack ), strtolower ( $needle ), $offset );
}
}
$user_agent = empty( $user_agent ) ? $_SERVER [ 'HTTP_USER_AGENT' ] : $user_agent ;
$browser = array( 'name' => 'default' , 'ver' => 0 );
if (
stripos ( $user_agent , 'Opera' ) !== false ) {
$browser [ 'name' ] = 'opera' ;
if(
stripos ( $user_agent , 'Version' ) !== false ) { # Opera/9.80 (X11; Linux x86_64; U; en) Presto/2.2.15 Version/10.00
$browser [ 'ver' ] = trim ( current ( explode ( ' ' , end ( explode ( 'version/' , strtolower ( $user_agent ))))));
}
else {
$browser [ 'ver' ] = trim ( current ( explode ( ' ' , substr ( $user_agent , ( stripos ( $user_agent , 'opera' ) + strlen ( 'opera' ) + 1 )))));
}
}
elseif (
stripos ( $user_agent , 'MSIE' ) !== false ) {
$browser [ 'name' ] = 'ie' ;
$browser [ 'ver' ] = rtrim ( current ( explode ( ' ' , trim ( end ( explode ( 'msie' , strtolower ( $user_agent )))))), ';' );
}
## Webkit (Safari/Chrome)
elseif ( stripos ( $user_agent , 'AppleWebKit' ) !== false ) {
$browser [ 'name' ] = 'applewebkit' ;
$browser [ 'ver' ] = trim ( current ( explode ( ' ' , substr ( $user_agent , ( stripos ( $user_agent , 'applewebkit' ) + strlen ( 'AppleWebKit' ) + 1 )))));
}
## Gecko/Netscape/Firefox/Flock/Mozilla/Camino/SeaMonkey
elseif ( stripos ( $user_agent , 'Gecko' ) !== false && stripos ( $user_agent , 'like Gecko' ) === false ) {
if (
stripos ( $user_agent , 'Navigator' ) !== false ) { ##Netscape 9+
$browser [ 'name' ] = 'netscape' ;
$browser [ 'ver' ] = trim ( current ( explode ( ' ' , end ( explode ( 'navigator/' , strtolower ( $user_agent ))))));
}
elseif (
stripos ( $user_agent , 'Firefox' ) !== false ) { ## Firefox 0.10 +
$browser [ 'name' ] = 'firefox' ;
$browser [ 'ver' ] = trim ( current ( explode ( ' ' , end ( explode ( 'firefox/' , strtolower ( $user_agent ))))));
}
elseif(
stripos ( $user_agent , 'Netscape6' ) !== false ){ #Netscape 6
$browser [ 'name' ] = 'netscape' ;
$browser [ 'ver' ] = trim ( current ( explode ( ' ' , end ( explode ( 'netscape6/' , strtolower ( $user_agent ))))));
}
elseif(
stripos ( $user_agent , 'Netscape' ) !== false ){ ## Netscape 7-9
$browser [ 'name' ] = 'netscape' ;
$browser [ 'ver' ] = trim ( current ( explode ( ' ' , end ( explode ( 'netscape/' , strtolower ( $user_agent ))))));
}
}
elseif(
stripos ( $user_agent , 'Googlebot' ) !== false ){ ## Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)
$browser [ 'name' ] = 'googlebot' ;
$browser [ 'ver' ] = trim ( current ( explode ( ' ' , end ( explode ( 'googlebot/' , strtolower ( $user_agent ))))), ';' );
}
elseif(
stripos ( $user_agent , 'msnbot' ) !== false ){ ## msnbot/1.0 (+http://search.msn.com/msnbot.htm)
$browser [ 'name' ] = 'msnbot' ;
$browser [ 'ver' ] = trim ( current ( explode ( ' ' , end ( explode ( 'msnbot/' , strtolower ( $user_agent ))))), ';' );
}
elseif(
stripos ( $user_agent , 'Yahoo! Slurp' ) !== false ){ ## Mozilla/5.0 (compatible; Yahoo! Slurp; http://help.yahoo.com/help/us/ysearch/slurp)
$browser [ 'name' ] = 'yahoo' ;
$browser [ 'ver' ] = 1 ;
}
$browser [ 'ver' ] = (float) $browser [ 'ver' ];
return
$browser ;
}
?>

Related Links:

Why you should use something like this - Yahoo

Post in WebmasterWorld

WebsiteOptimization.com

ravelrumba