|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00013 class Minify_CSS_UriRewriter { 00014 00020 protected static $className = 'Minify_CSS_UriRewriter'; 00021 00026 public static $debugText = ''; 00027 00050 public static function rewrite($css, $currentDir, $docRoot = null, $symlinks = array()) 00051 { 00052 self::$_docRoot = self::_realpath( 00053 $docRoot ? $docRoot : $_SERVER['DOCUMENT_ROOT'] 00054 ); 00055 self::$_currentDir = self::_realpath($currentDir); 00056 self::$_symlinks = array(); 00057 00058 // normalize symlinks 00059 foreach ($symlinks as $link => $target) { 00060 $link = ($link === '//') 00061 ? self::$_docRoot 00062 : str_replace('//', self::$_docRoot . '/', $link); 00063 $link = strtr($link, '/', DIRECTORY_SEPARATOR); 00064 self::$_symlinks[$link] = self::_realpath($target); 00065 } 00066 00067 self::$debugText .= "docRoot : " . self::$_docRoot . "\n" 00068 . "currentDir : " . self::$_currentDir . "\n"; 00069 if (self::$_symlinks) { 00070 self::$debugText .= "symlinks : " . var_export(self::$_symlinks, 1) . "\n"; 00071 } 00072 self::$debugText .= "\n"; 00073 00074 $css = self::_trimUrls($css); 00075 00076 // rewrite 00077 $css = preg_replace_callback('/@import\\s+([\'"])(.*?)[\'"]/' 00078 ,array(self::$className, '_processUriCB'), $css); 00079 $css = preg_replace_callback('/url\\(\\s*([^\\)\\s]+)\\s*\\)/' 00080 ,array(self::$className, '_processUriCB'), $css); 00081 00082 return $css; 00083 } 00084 00094 public static function prepend($css, $path) 00095 { 00096 self::$_prependPath = $path; 00097 00098 $css = self::_trimUrls($css); 00099 00100 // append 00101 $css = preg_replace_callback('/@import\\s+([\'"])(.*?)[\'"]/' 00102 ,array(self::$className, '_processUriCB'), $css); 00103 $css = preg_replace_callback('/url\\(\\s*([^\\)\\s]+)\\s*\\)/' 00104 ,array(self::$className, '_processUriCB'), $css); 00105 00106 self::$_prependPath = null; 00107 return $css; 00108 } 00109 00110 00114 private static $_currentDir = ''; 00115 00119 private static $_docRoot = ''; 00120 00125 private static $_symlinks = array(); 00126 00130 private static $_prependPath = null; 00131 00132 private static function _trimUrls($css) 00133 { 00134 return preg_replace('/ 00135 url\\( # url( 00136 \\s* 00137 ([^\\)]+?) # 1 = URI (assuming does not contain ")") 00138 \\s* 00139 \\) # ) 00140 /x', 'url($1)', $css); 00141 } 00142 00143 private static function _processUriCB($m) 00144 { 00145 // $m matched either '/@import\\s+([\'"])(.*?)[\'"]/' or '/url\\(\\s*([^\\)\\s]+)\\s*\\)/' 00146 $isImport = ($m[0][0] === '@'); 00147 // determine URI and the quote character (if any) 00148 if ($isImport) { 00149 $quoteChar = $m[1]; 00150 $uri = $m[2]; 00151 } else { 00152 // $m[1] is either quoted or not 00153 $quoteChar = ($m[1][0] === "'" || $m[1][0] === '"') 00154 ? $m[1][0] 00155 : ''; 00156 $uri = ($quoteChar === '') 00157 ? $m[1] 00158 : substr($m[1], 1, strlen($m[1]) - 2); 00159 } 00160 // analyze URI 00161 if ('/' !== $uri[0] // root-relative 00162 && false === strpos($uri, '//') // protocol (non-data) 00163 && 0 !== strpos($uri, 'data:') // data protocol 00164 ) { 00165 // URI is file-relative: rewrite depending on options 00166 $uri = (self::$_prependPath !== null) 00167 ? (self::$_prependPath . $uri) 00168 : self::rewriteRelative($uri, self::$_currentDir, self::$_docRoot, self::$_symlinks); 00169 } 00170 return $isImport 00171 ? "@import {$quoteChar}{$uri}{$quoteChar}" 00172 : "url({$quoteChar}{$uri}{$quoteChar})"; 00173 } 00174 00213 public static function rewriteRelative($uri, $realCurrentDir, $realDocRoot, $symlinks = array()) 00214 { 00215 // prepend path with current dir separator (OS-independent) 00216 $path = strtr($realCurrentDir, '/', DIRECTORY_SEPARATOR) 00217 . DIRECTORY_SEPARATOR . strtr($uri, '/', DIRECTORY_SEPARATOR); 00218 00219 self::$debugText .= "file-relative URI : {$uri}\n" 00220 . "path prepended : {$path}\n"; 00221 00222 // "unresolve" a symlink back to doc root 00223 foreach ($symlinks as $link => $target) { 00224 if (0 === strpos($path, $target)) { 00225 // replace $target with $link 00226 $path = $link . substr($path, strlen($target)); 00227 00228 self::$debugText .= "symlink unresolved : {$path}\n"; 00229 00230 break; 00231 } 00232 } 00233 // strip doc root 00234 $path = substr($path, strlen($realDocRoot)); 00235 00236 self::$debugText .= "docroot stripped : {$path}\n"; 00237 00238 // fix to root-relative URI 00239 00240 $uri = strtr($path, '/\\', '//'); 00241 00242 // remove /./ and /../ where possible 00243 $uri = str_replace('/./', '/', $uri); 00244 // inspired by patch from Oleg Cherniy 00245 do { 00246 $uri = preg_replace('@/[^/]+/\\.\\./@', '/', $uri, 1, $changed); 00247 } while ($changed); 00248 00249 self::$debugText .= "traversals removed : {$uri}\n\n"; 00250 00251 return $uri; 00252 } 00253 00262 protected static function _realpath($path) 00263 { 00264 $realPath = realpath($path); 00265 if ($realPath !== false) { 00266 $path = $realPath; 00267 } 00268 return rtrim($path, '/\\'); 00269 } 00270 }