// // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // This file provides some utilities for dealing with Cascading Style Sheets. // See http://www.w3.org/TR/CSS2/ // css_encode -- Encode arbitrary character string for use as a CSS identifier. // // string css_encode ( string string ) // // Encodes an arbitrary character string for use in a CSS identifier. // // See http://www.w3.org/TR/CSS2/syndata.html#q4 // // This function assumes the latin1 character set. // function css_encode($string) { // Replace all chars that are not alphanumeric and are not U+00A1 and above $string = preg_replace_callback('#([^A-Za-z0-9\xA1-\xFF])#s', '_css_encode__latin1_cb', $string); // Replace leading digit $string = preg_replace_callback('#^([0-9])#s', '_css_encode__latin1_cb', $string); return $string; } function _css_encode__latin1_cb($m) { $charval = ord($m[1]); if (($charval >= 0x21 and $charval <= 0x2f) or ($charval >= 0x3a and $charval <= 0x40) or ($charval >= 0x5b and $charval <= 0x60) or ($charval >= 0x7b and $charval <= 0x7e)) { return "\\".chr($charval); } else { return "\\".str_pad(dechex($charval), 2, '0', STR_PAD_LEFT).' '; } } // css_decode -- Decode a CSS-encoded identifier string. // // string css_decode ( string string ) // // Decodes a character string that has been encoded according to CSS2 // conventions. // // See http://www.w3.org/TR/CSS2/syndata.html#q4 // // This function assumes the latin1 character set. // function css_decode($string) { $cbo = new _css_decode__callbacks(); $cb = array($cbo, 'latin1_cb'); $retval = preg_replace_callback( '#(\\\\\n)|\\\\([0-9A-Fa-f]{1,5})\s?|\\\\([0-9A-Fa-f]{6})|\\\\([^0-9A-Fa-f])#s', $cb, $string); if ($cb->error) { return false; } return $retval; } class _css_decode__callbacks { var $error; function latin1_cb($m) { $this->error = false; if (!empty($m[1])) { // Inside a string, a backslash followed by a newline is ignored. return ''; } else if (!empty($m[4])) { // "\C", where C is a non-hexadecimal character, returns C. return $m[4]; } else if (!empty($m[2]) or !empty($m[3])) { if (!empty($m[2])) { $codepoint = hexdec($m[2]); } else { $codepoint = hexdec($m[3]); } if ($codepoint < 0 or $codepoint > 255) { trigger_error("css_decode: illegal character", E_USER_WARNING); $this->error = true; return FALSE; } return chr($codepoint); } die(__FILE__.":".__LINE__.": BUG: This should never happen."); } } // css_uri_specialchars -- Escape special characters in a CSS URI. // // string css_uri_specialchars ( string uri ) // // css_encode() SHOULD be enough, at least according to my reading of the CSS2 // spec, but instead of treating backslashes as escape characters in "url(...)" // values, MSIE 6 converts backslashes ("\") into path separators ("/"). Argh. // // So, we create a new function that doesn't use backslash-escaping, but // instead just percent-encodes a few known special characters and leaves // everything else alone. // // See http://www.w3.org/TR/CSS2/syndata.html#uri // function css_uri_specialchars($uri) { // Percent-encode all characters except those expected to be in URIs // (Based on code from uri_util.php 0.7) $uri = preg_replace_callback('#([^A-Za-z0-9\-._~:/?\#\[\]@!$&\'()*+,;=%])#s', '_css_uri_specialchars__cb', $uri); // Percent-encode CSS URI special characters: // DQUOTE / "'" / "\" / "(" / ")" $uri = preg_replace_callback("#([\"'\\\\()])#s", '_css_uri_specialchars__cb', $uri); return $uri; } function _css_uri_specialchars__cb($m) { return '%'.strtoupper(bin2hex($m[1])); } /* vim:set ts=4 sw=4 sts=4 expandtab: */