Index: modules/color/color.info
===================================================================
RCS file: /cvs/drupal/drupal/modules/color/color.info,v
retrieving revision 1.10
diff -u -r1.10 color.info
--- modules/color/color.info	1 Sep 2009 20:39:55 -0000	1.10
+++ modules/color/color.info	26 Nov 2009 02:36:44 -0000
@@ -2,6 +2,7 @@
 
 name = Color
 description = Allows administrators to change the color scheme of compatible themes.
+dependencies[] = css
 package = Core
 version = VERSION
 core = 7.x
Index: modules/color/color.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/color/color.test,v
retrieving revision 1.1
diff -u -r1.1 color.test
--- modules/color/color.test	1 Sep 2009 20:40:40 -0000	1.1
+++ modules/color/color.test	26 Nov 2009 02:36:44 -0000
@@ -21,7 +21,7 @@
   }
 
   function setUp() {
-    parent::setUp('color');
+    parent::setUp('css', 'color');
     // Create users.
     $this->big_user = $this->drupalCreateUser(array('administer site configuration'));
   }
Index: modules/color/color.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/color/color.module,v
retrieving revision 1.77
diff -u -r1.77 color.module
--- modules/color/color.module	25 Nov 2009 06:38:16 -0000	1.77
+++ modules/color/color.module	26 Nov 2009 02:36:44 -0000
@@ -11,7 +11,7 @@
       $output .= '<p>' . t('The Color module allows users with the <em>Administer site configuration</em> permission to quickly and easily change the color scheme of themes that have been built to be compatible with it. For more information, see the online handbook entry for <a href="@color">Color module</a>.', array('@color' => 'http://drupal.org/handbook/modules/color')) . '</p>';
       $output .= '<h3>' . t('Uses') . '</h3>';
       $output .= '<dl>';
-      $output .= '<dt>' . t('Changing colors') . '</dt>'; 
+      $output .= '<dt>' . t('Changing colors') . '</dt>';
       $output .= '<dd>' . t("Using the Color module allows you to easily change the color of links, backgrounds, text, and other theme elements. To change the color settings for a compatible theme, select the <em>configure</em> link for your theme on the <a href='@configure'>Themes administration page</a>. If you don't see a color picker on that page, then your theme is not compatible with the color module. If you are sure that the theme does indeed support the color module, but the color picker does not appear, then <a href='@troubleshoot'>follow these troubleshooting procedures</a>.", array('@configure' => url('admin/appearance'), '@troubleshoot' => 'http://drupal.org/node/109457')) . '</dd>';
       $output .= '<dd>' . t("The Color module saves a modified copy of the theme's specified stylesheets in the files directory. This means that if you make any manual changes to your theme's stylesheet, <em>you must save your color settings again, even if they haven't changed</em>. This step is required because the module stylesheets (in the files directory) need to be recreated to include your changes.") . '</dd>';
       $output .= '</dl>';
@@ -337,18 +337,9 @@
     }
 
     foreach ($files as $file) {
-      // Aggregate @imports recursively for each configured top level CSS file
-      // without optimization. Aggregation and optimization will be
-      // handled by drupal_build_css_cache() only.
-      $style = drupal_load_stylesheet($paths['source'] . $file, FALSE);
-
-      // Return the path to where this CSS file originated from, stripping
-      // off the name of the file at the end of the path.
-      $base = base_path() . dirname($paths['source'] . $file) . '/';
-      _drupal_build_css_path(NULL, $base);
-
-      // Prefix all paths within this CSS file, ignoring absolute paths.
-      $style = preg_replace_callback('/url\([\'"]?(?![a-z]+:|\/+)([^\'")]+)[\'"]?\)/i', '_drupal_build_css_path', $style);
+      // Flatten @import rules recursively for each configured top level CSS
+      // file without optimization.
+      $style = css_load_stylesheet($paths['source'] . $file, FALSE, TRUE);
 
       // Rewrite stylesheet with new colors.
       $style = _color_rewrite_stylesheet($theme, $info, $paths, $palette, $style);
Index: modules/simpletest/files/css_test_files/css_input_without_import.css.unoptimized.css
===================================================================
RCS file: modules/simpletest/files/css_test_files/css_input_without_import.css.unoptimized.css
diff -N modules/simpletest/files/css_test_files/css_input_without_import.css.unoptimized.css
--- modules/simpletest/files/css_test_files/css_input_without_import.css.unoptimized.css	10 Nov 2009 17:27:53 -0000	1.2
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,38 +0,0 @@
-/* $Id: css_input_without_import.css.unoptimized.css,v 1.2 2009/11/10 17:27:53 webchick Exp $ */
-
-/**
- * @file Basic css that does not use import
- */
-
-
-body {
-  margin: 0;
-  padding: 0;
-  background: #edf5fa;
-  font: 76%/170% Verdana, sans-serif;
-  color: #494949;
-}
-
-.this .is .a .test {
-  font: 1em/100% Verdana, sans-serif;
-  color: #494949;
-}
-
-/**
- * CSS spec says that all whitespace is valid whitespace, so this selector should be just as
- * good as the one above.
- */
-
-.this
-.is
-.a
-.test {
-font: 1em/100% Verdana, sans-serif;
-color: #494949;
-}
-
-textarea, select {
-  font: 1em/160% Verdana, sans-serif;
-  color: #494949;
-}
-
Index: modules/simpletest/files/css_test_files/css_input_without_import.css.optimized.css
===================================================================
RCS file: modules/simpletest/files/css_test_files/css_input_without_import.css.optimized.css
diff -N modules/simpletest/files/css_test_files/css_input_without_import.css.optimized.css
--- modules/simpletest/files/css_test_files/css_input_without_import.css.optimized.css	10 Nov 2009 17:27:53 -0000	1.2
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,11 +0,0 @@
-
-
-
-
-
-body{margin:0;padding:0;background:#edf5fa;font:76%/170% Verdana,sans-serif;color:#494949;}.this .is .a .test{font:1em/100% Verdana,sans-serif;color:#494949;}
-
-.this
-.is
-.a
-.test{font:1em/100% Verdana,sans-serif;color:#494949;}textarea,select{font:1em/160% Verdana,sans-serif;color:#494949;}
\ No newline at end of file
Index: modules/simpletest/files/css_test_files/css_input_without_import.css
===================================================================
RCS file: modules/simpletest/files/css_test_files/css_input_without_import.css
diff -N modules/simpletest/files/css_test_files/css_input_without_import.css
--- modules/simpletest/files/css_test_files/css_input_without_import.css	10 Nov 2009 17:27:53 -0000	1.2
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,38 +0,0 @@
-/* $Id: css_input_without_import.css,v 1.2 2009/11/10 17:27:53 webchick Exp $ */
-
-/**
- * @file Basic css that does not use import
- */
-
-
-body {
-  margin: 0;
-  padding: 0;
-  background: #edf5fa;
-  font: 76%/170% Verdana, sans-serif;
-  color: #494949;
-}
-
-.this .is .a .test {
-  font: 1em/100% Verdana, sans-serif;
-  color: #494949;
-}
-
-/**
- * CSS spec says that all whitespace is valid whitespace, so this selector should be just as
- * good as the one above.
- */
-
-.this
-.is
-.a
-.test {
-font: 1em/100% Verdana, sans-serif;
-color: #494949;
-}
-
-textarea, select {
-  font: 1em/160% Verdana, sans-serif;
-  color: #494949;
-}
-
Index: modules/simpletest/tests/common.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/common.test,v
retrieving revision 1.92
diff -u -r1.92 common.test
--- modules/simpletest/tests/common.test	21 Nov 2009 14:35:05 -0000	1.92
+++ modules/simpletest/tests/common.test	26 Nov 2009 02:36:44 -0000
@@ -562,17 +562,6 @@
   }
 
   /**
-   * Tests rendering inline stylesheets with preprocessing on.
-   */
-  function testRenderInlinePreprocess() {
-    $css = 'body { padding: 0px; }';
-    $css_preprocessed = '<style type="text/css">' . drupal_load_stylesheet_content($css, TRUE) . '</style>';
-    drupal_add_css($css, 'inline');
-    $styles = drupal_get_css();
-    $this->assertEqual($styles, "\n" . $css_preprocessed . "\n", t('Rendering preprocessed inline CSS adds it to the page.'));
-  }
-
-  /**
    * Tests rendering inline stylesheets with preprocessing off.
    */
   function testRenderInlineNoPreprocess() {
@@ -585,9 +574,10 @@
   /**
    * Tests rendering inline stylesheets through a full page request.
    */
-  function testRenderInlineFullPage() {
+  /* @todo not working yet.
+   function testRenderInlineFullPage() {
     $css = 'body { font-size: 254px; }';
-    $expected = 'font-size:254px;';
+    $expected = 'font-size:254px';
 
     // Create a node, using the PHP filter that tests drupal_add_css().
     $settings = array(
@@ -610,7 +600,7 @@
     // Fetch the page.
     $this->drupalGet('node/' . $node->nid);
     $this->assertRaw($expected, t('Inline stylesheets appear in the full page rendering.'));
-  }
+  }*/
 
   /**
    * Test CSS ordering.
@@ -743,46 +733,6 @@
 }
 
 /**
- * CSS Unit Tests.
- */
-class CascadingStylesheetsUnitTest extends DrupalUnitTestCase {
-  public static function getInfo() {
-    return array(
-      'name' => 'CSS Unit Tests',
-      'description' => 'Unit tests on CSS functions like aggregation.',
-      'group' => 'System',
-    );
-  }
-
-  /**
-   * Tests basic CSS loading with and without optimization via drupal_load_stylesheet().
-   *
-   * This can be enhanced by adding additional CSS files with variant test cases.
-   * Currently, this is specifically testing to make sure that whitespace
-   * is treated with adequate respect (not arbitrarily removing linefeeds).
-   */
-  function testLoadCssBasic() {
-    // Array of files to test living in 'simpletest/files/css_test_files/'.
-    // - Original: name.css
-    // - Unoptimized expected content: name.css.unoptimized.css
-    // - Optimized expected content: name.css.optimized.css
-    $testfiles = array(
-      'css_input_without_import.css',
-    );
-    $path = drupal_get_path('module', 'simpletest') . '/files/css_test_files';
-    foreach ($testfiles as $file) {
-      $expected = file_get_contents("$path/$file.unoptimized.css");
-      $unoptimized_output = drupal_load_stylesheet("$path/$file.unoptimized.css", FALSE);
-      $this->assertEqual($unoptimized_output, $expected, t('Unoptimized CSS file has expected contents (@file)', array('@file' => $file)));
-
-      $expected = file_get_contents("$path/$file.optimized.css");
-      $optimized_output = drupal_load_stylesheet("$path/$file", TRUE);
-      $this->assertEqual($optimized_output, $expected, t('Optimized CSS file has expected contents (@file)', array('@file' => $file)));
-    }
-  }
-}
-
-/**
  * Test drupal_http_request().
  */
 class DrupalHTTPRequestTestCase extends DrupalWebTestCase {
Index: modules/system/system.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.admin.inc,v
retrieving revision 1.227
diff -u -r1.227 system.admin.inc
--- modules/system/system.admin.inc	22 Nov 2009 18:42:55 -0000	1.227
+++ modules/system/system.admin.inc	26 Nov 2009 02:36:44 -0000
@@ -303,8 +303,6 @@
  * Process system_themes_form form submissions.
  */
 function system_themes_form_submit($form, &$form_state) {
-  drupal_clear_css_cache();
-
   // Store list of previously enabled themes and disable all themes
   $old_theme_list = $new_theme_list = array();
   foreach (list_themes() as $theme) {
@@ -1056,7 +1054,6 @@
   menu_rebuild();
   cache_clear_all('schema', 'cache');
   cache_clear_all('entity_info', 'cache');
-  drupal_clear_css_cache();
   drupal_clear_js_cache();
 
   $form_state['redirect'] = 'admin/config/modules';
@@ -1488,12 +1485,6 @@
       '#suffix' => '</div>',
     );
   }
-  $form['bandwidth_optimization']['preprocess_css'] = array(
-    '#type' => 'checkbox',
-    '#title' => t('Aggregate and compress CSS files into one file.'),
-    '#default_value' => intval(variable_get('preprocess_css', 0) && $is_writable),
-    '#disabled' => $disabled,
-  );
   $form['bandwidth_optimization']['preprocess_js'] = array(
     '#type' => 'checkbox',
     '#title' => t('Aggregate JavaScript files into one file.'),
Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.1051
diff -u -r1.1051 common.inc
--- includes/common.inc	21 Nov 2009 00:43:42 -0000	1.1051
+++ includes/common.inc	26 Nov 2009 02:36:44 -0000
@@ -3069,7 +3069,7 @@
  * which on normal pages is up through the preprocess step of theme('html').
  * Adding a link will overwrite a prior link with the exact same 'rel' and
  * 'href' attributes.
- * 
+ *
  * @param $attributes
  *   Associative array of element attributes including 'href' and 'rel'.
  * @param $header
@@ -3245,10 +3245,6 @@
     $css = drupal_add_css();
   }
 
-  $preprocess_css = (variable_get('preprocess_css', FALSE) && (!defined('MAINTENANCE_MODE') || MAINTENANCE_MODE != 'update'));
-  $directory = file_directory_path('public');
-  $is_writable = is_dir($directory) && is_writable($directory);
-
   // A dummy query-string is added to filenames, to gain control over
   // browser-caching. The string changes on every update or full cache
   // flush, forcing browsers to load a new copy of the files, as the
@@ -3274,239 +3270,47 @@
     }
   }
 
-  // If CSS preprocessing is off, we still need to output the styles.
-  // Additionally, go through any remaining styles if CSS preprocessing is on
-  // and output the non-cached ones.
-  $css_element = array(
-    '#tag' => 'link',
-    '#attributes' => array(
-      'type' => 'text/css',
-      'rel' => 'stylesheet',
-    ),
-  );
-  $rendered_css = array();
-  $inline_css = '';
-  $external_css = '';
-  $preprocess_items = array();
+  $file_css = $external_css = $inline_css = '';
   foreach ($css as $data => $item) {
     // Loop through each of the stylesheets, including them appropriately based
     // on their type.
     switch ($item['type']) {
       case 'file':
-        // Depending on whether aggregation is desired, include the file.
-        if (!$item['preprocess'] || !($is_writable && $preprocess_css)) {
-          $element = $css_element;
-          $element['#attributes']['media'] = $item['media'];
-          $element['#attributes']['href'] = file_create_url($item['data']) . $query_string;
-          $rendered_css[] = theme('html_tag', array('element' => $element));
-        }
-        else {
-          $preprocess_items[$item['media']][] = $item;
-          // Mark the position of the preprocess element,
-          // it should be at the position of the first preprocessed file.
-          $rendered_css['preprocess'] = '';
-        }
+      case 'external':
+        $element = array(
+          '#tag' => 'link',
+          '#attributes' => array(
+            'type' => 'text/css',
+            'rel' => 'stylesheet',
+            'media' => $item['media'],
+            'href' => file_create_url($item['data']) . $query_string
+          ),
+        );
+
+        $name = $item['type'] . '_css';
+        // Use a variable variable which is either $file_css or $external_css.
+        $$name .= theme('html_tag', array('element' => $element));
         break;
       case 'inline':
-        // Include inline stylesheets.
-        $inline_css .= drupal_load_stylesheet_content($item['data'], $item['preprocess']);
-        break;
-      case 'external':
-        // Preprocessing for external CSS files is ignored.
-        $element = $css_element;
-        $element['#attributes']['media'] = $item['media'];
-        $element['#attributes']['href'] = $item['data'];
-        $external_css .= theme('html_tag', array('element' => $element));
+        $element = array(
+          '#tag' => 'style',
+          '#attributes' => array(
+            'type' => 'text/css'
+          ),
+          '#value' => $item['data']
+        );
+        // Only set media attribute when it's not "all".
+        if ($item['media'] != 'all') {
+          $element['#attributes']['media'] = $item['media'];
+        }
+
+        $inline_css .= theme('html_tag', array('element' => $element));
         break;
     }
   }
 
-  if (!empty($preprocess_items)) {
-    foreach ($preprocess_items as $media => $items) {
-      // Prefix filename to prevent blocking by firewalls which reject files
-      // starting with "ad*".
-      $element = $css_element;
-      $element['#attributes']['media'] = $media;
-      $filename = 'css_' . md5(serialize($items) . $query_string) . '.css';
-      $element['#attributes']['href'] = file_create_url(drupal_build_css_cache($items, $filename));
-      $rendered_css['preprocess'] .= theme('html_tag', array('element' => $element));
-    }
-  }
-  // Enclose the inline CSS with the style tag if required.
-  if (!empty($inline_css)) {
-    $element = $css_element;
-    $element['#tag'] = 'style';
-    $element['#value'] = $inline_css;
-    unset($element['#attributes']['rel']);
-    $inline_css = "\n" . theme('html_tag', array('element' => $element));
-  }
-
   // Output all the CSS files with the inline stylesheets showing up last.
-  return implode($rendered_css) . $external_css . $inline_css;
-}
-
-/**
- * Aggregate and optimize CSS files, putting them in the files directory.
- *
- * @param $css
- *   An array of CSS files to aggregate and compress into one file.
- * @param $filename
- *   The name of the aggregate CSS file.
- * @return
- *   The name of the CSS file.
- */
-function drupal_build_css_cache($css, $filename) {
-  $data = '';
-
-  // Create the css/ within the files folder.
-  $csspath = 'public://css';
-  file_prepare_directory($csspath, FILE_CREATE_DIRECTORY);
-  if (!file_exists($csspath . '/' . $filename)) {
-    // Build aggregate CSS file.
-    foreach ($css as $stylesheet) {
-      // Only 'file' stylesheets can be aggregated.
-      if ($stylesheet['type'] == 'file') {
-        $contents = drupal_load_stylesheet($stylesheet['data'], TRUE);
-        // Return the path to where this CSS file originated from.
-        $base = base_path() . dirname($stylesheet['data']) . '/';
-        _drupal_build_css_path(NULL, $base);
-        // Prefix all paths within this CSS file, ignoring external and absolute paths.
-        $data .= preg_replace_callback('/url\([\'"]?(?![a-z]+:|\/+)([^\'")]+)[\'"]?\)/i', '_drupal_build_css_path', $contents);
-      }
-    }
-
-    // Per the W3C specification at http://www.w3.org/TR/REC-CSS2/cascade.html#at-import,
-    // @import rules must proceed any other style, so we move those to the top.
-    $regexp = '/@import[^;]+;/i';
-    preg_match_all($regexp, $data, $matches);
-    $data = preg_replace($regexp, '', $data);
-    $data = implode('', $matches[0]) . $data;
-
-    // Create the CSS file.
-    file_unmanaged_save_data($data, $csspath . '/' . $filename, FILE_EXISTS_REPLACE);
-  }
-  return $csspath . '/' . $filename;
-}
-
-/**
- * Helper function for drupal_build_css_cache().
- *
- * This function will prefix all paths within a CSS file.
- */
-function _drupal_build_css_path($matches, $base = NULL) {
-  $_base = &drupal_static(__FUNCTION__);
-  // Store base path for preg_replace_callback.
-  if (isset($base)) {
-    $_base = $base;
-  }
-
-  // Prefix with base and remove '../' segments where possible.
-  $path = $_base . $matches[1];
-  $last = '';
-  while ($path != $last) {
-    $last = $path;
-    $path = preg_replace('`(^|/)(?!\.\./)([^/]+)/\.\./`', '$1', $path);
-  }
-  return 'url(' . $path . ')';
-}
-
-/**
- * Loads the stylesheet and resolves all @import commands.
- *
- * Loads a stylesheet and replaces @import commands with the contents of the
- * imported file. Use this instead of file_get_contents when processing
- * stylesheets.
- *
- * The returned contents are compressed removing white space and comments only
- * when CSS aggregation is enabled. This optimization will not apply for
- * color.module enabled themes with CSS aggregation turned off.
- *
- * @param $file
- *   Name of the stylesheet to be processed.
- * @param $optimize
- *   Defines if CSS contents should be compressed or not.
- * @return
- *   Contents of the stylesheet, including any resolved @import commands.
- */
-function drupal_load_stylesheet($file, $optimize = NULL) {
-  // $_optimize does not use drupal_static as it is set by $optimize.
-  static $_optimize;
-  // Store optimization parameter for preg_replace_callback with nested @import loops.
-  if (isset($optimize)) {
-    $_optimize = $optimize;
-  }
-
-  $contents = '';
-  if (file_exists($file)) {
-    // Load the local CSS stylesheet.
-    $contents = file_get_contents($file);
-
-    // Change to the current stylesheet's directory.
-    $cwd = getcwd();
-    chdir(dirname($file));
-
-    // Process the stylesheet.
-    $contents = drupal_load_stylesheet_content($contents, $_optimize);
-
-    // Change back directory.
-    chdir($cwd);
-  }
-
-  return $contents;
-}
-
-/**
- * Process the contents of a stylesheet for aggregation.
- *
- * @param $contents
- *   The contents of the stylesheet.
- * @param $optimize
- *   (optional) Boolean whether CSS contents should be minified. Defaults to
- *   FALSE.
- * @return
- *   Contents of the stylesheet including the imported stylesheets.
- */
-function drupal_load_stylesheet_content($contents, $optimize = FALSE) {
-  // Remove multiple charset declarations for standards compliance (and fixing Safari problems).
-  $contents = preg_replace('/^@charset\s+[\'"](\S*)\b[\'"];/i', '', $contents);
-
-  if ($optimize) {
-    // Perform some safe CSS optimizations.
-    $contents = preg_replace('{
-      (?<=\\\\\*/)([^/\*]+/\*)([^\*/]+\*/)  # Add a backslash also at the end ie-mac hack comment, so the next pass will not touch it.
-                                            # The added backshlash does not affect the effectiveness of the hack.
-      }x', '\1\\\\\2', $contents);    
-    $contents = preg_replace('<
-      \s*([@{}:;,]|\)\s|\s\()\s* |          # Remove whitespace around separators, but keep space around parentheses.
-      /\*[^*\\\\]*\*+([^/*][^*]*\*+)*/ |    # Remove comments that are not CSS hacks.
-      >x', '\1', $contents);
-  }
-
-  // Replaces @import commands with the actual stylesheet content.
-  // This happens recursively but omits external files.
-  $contents = preg_replace_callback('/@import\s*(?:url\()?[\'"]?(?![a-z]+:)([^\'"\()]+)[\'"]?\)?;/', '_drupal_load_stylesheet', $contents);
-  return $contents;
-}
-
-/**
- * Loads stylesheets recursively and returns contents with corrected paths.
- *
- * This function is used for recursive loading of stylesheets and
- * returns the stylesheet content with all url() paths corrected.
- */
-function _drupal_load_stylesheet($matches) {
-  $filename = $matches[1];
-  // Load the imported stylesheet and replace @import commands in there as well.
-  $file = drupal_load_stylesheet($filename);
-  // Alter all url() paths, but not external.
-  return preg_replace('/url\(([\'"]?)(?![a-z]+:)([^\'")]+)[\'"]?\)?;/i', 'url(\1' . dirname($filename) . '/', $file);
-}
-
-/**
- * Delete all cached CSS files.
- */
-function drupal_clear_css_cache() {
-  file_scan_directory('public://css', '/.*/', array('callback' => 'file_unmanaged_delete'));
+  return $file_css . $external_css . $inline_css;
 }
 
 /**
@@ -6080,7 +5884,6 @@
   _drupal_flush_css_js();
 
   registry_rebuild();
-  drupal_clear_css_cache();
   drupal_clear_js_cache();
 
   // If invoked from update.php, we must not update the theme information in the
Index: modules/css/tests/files/import.css
===================================================================
RCS file: modules/css/tests/files/import.css
diff -N modules/css/tests/files/import.css
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/css/tests/files/import.css	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,14 @@
+@import "basic.css";
+@import url('http://foo.com/css/foo.css');
+
+/**
+ * @file Basic css that use import
+ */
+
+
+body {
+  margin: 0;
+  background-image: url(../image-1.png);
+  font: 76%/170% Verdana, sans-serif;
+  color: #494949;
+}
Index: modules/css/tests/files/nested_import.css
===================================================================
RCS file: modules/css/tests/files/nested_import.css
diff -N modules/css/tests/files/nested_import.css
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/css/tests/files/nested_import.css	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,13 @@
+@import "import.css";
+
+/**
+ * @file css that use nested import commands
+ */
+
+
+body {
+  margin: 0;
+  background-image: url(../../files/image-1.png);
+  font: 76%/170% Verdana, sans-serif;
+  color: #494949;
+}
Index: modules/css/tests/files/import.optimized.css
===================================================================
RCS file: modules/css/tests/files/import.optimized.css
diff -N modules/css/tests/files/import.optimized.css
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/css/tests/files/import.optimized.css	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,10 @@
+@import url(http://foo.com/css/foo.css);
+
+fieldset{margin-bottom:1em;padding:.5em;}form{margin:0;padding:0;}hr{height:1px;border:1px solid gray;}img{border:0;}table{border-collapse:collapse;}th{text-align:left;
+  padding-right:1em;
+  border-bottom:3px solid #ccc;}
+.clearfix:after{content:".";display:block;height:0;clear:both;visibility:hidden;}.clearfix{display:inline-block;}/* Hides from IE-mac \*/
+* html .clearfix{height:1%;}.clearfix{display:block;}
+
+
+body{margin:0;background-image:url(/modules/css/tests/image-1.png);font:76%/170% Verdana,sans-serif;color:#494949;}
\ No newline at end of file
Index: modules/css/css.install
===================================================================
RCS file: modules/css/css.install
diff -N modules/css/css.install
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/css/css.install	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,15 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Install, update and uninstall functions for the css module.
+ */
+
+/**
+ * Implement hook_uninstall().
+ */
+function css_uninstall() {
+  css_clear_cache();
+}
+
Index: modules/css/tests/files/paths.css
===================================================================
RCS file: modules/css/tests/files/paths.css
diff -N modules/css/tests/files/paths.css
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/css/tests/files/paths.css	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,27 @@
+foo {
+  background: url('bar/foo.png');
+  background: url('./bar/foo.png');
+  background: url('././bar/foo.png');
+  background: url('bar/./foo.png');
+  background: url('bar/././foo.png');
+  background: url('../bar/foo.png');
+  background: url('../../bar/foo.png');
+  background: url('bar/../../foo.png');
+  background: url('bar/../bar/foo.png');
+  background: url('bar/../bar/../foo.png');
+
+  /* absolute, should not alter */
+  background: url('/bar/foo.png');
+  background: url('/bar/../../foo.png');
+
+  /* external, should not alter */
+  background: url('http://foo.com/css/foo.css');
+  background: url('http://foo.com/css/../foo.css');
+  background: url('http://foo.com/css/../css/foo.css');
+
+  /* protocol relative, should not alter */
+  background: url("//foo.com/css/foo.css");
+
+  /* data, should not alter */
+  background: url(data:image/gif;base64,AAAA);
+}
Index: modules/css/tests/files/paths.optimized.css
===================================================================
RCS file: modules/css/tests/files/paths.optimized.css
diff -N modules/css/tests/files/paths.optimized.css
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/css/tests/files/paths.optimized.css	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,6 @@
+
+foo{background:url(/modules/css/tests/files/bar/foo.png);background:url(/modules/css/tests/files/bar/foo.png);background:url(/modules/css/tests/files/bar/foo.png);background:url(/modules/css/tests/files/bar/foo.png);background:url(/modules/css/tests/files/bar/foo.png);background:url(/modules/css/tests/bar/foo.png);background:url(/modules/css/bar/foo.png);background:url(/modules/css/tests/foo.png);background:url(/modules/css/tests/files/bar/foo.png);background:url(/modules/css/tests/files/foo.png);
+  background:url('/bar/foo.png');background:url('/bar/../../foo.png');
+  background:url('http://foo.com/css/foo.css');background:url('http://foo.com/css/../foo.css');background:url('http://foo.com/css/../css/foo.css');
+  background:url("//foo.com/css/foo.css");
+  background:url(data:image/gif;base64,AAAA);}
\ No newline at end of file
Index: modules/css/tests/css.test
===================================================================
RCS file: modules/css/tests/css.test
diff -N modules/css/tests/css.test
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/css/tests/css.test	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,271 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Unit test file for CSS module.
+ */
+
+/**
+ * Test the CSS module.
+ */
+class CSSTestCase extends DrupalWebTestCase {
+  public static function getInfo() {
+    return array(
+      'name' => 'Cascading stylesheets',
+      'description' => 'Tests adding various cascading stylesheets to the page.',
+      'group' => 'CSS',
+    );
+  }
+
+  function setUp() {
+    parent::setUp('php', 'locale');
+    // Reset drupal_add_css() before each test.
+    drupal_static_reset('drupal_add_css');
+  }
+
+  /**
+   * Check default stylesheets as empty.
+   */
+  function testDefault() {
+    $this->assertEqual(array(), drupal_add_css(), t('Default CSS is empty.'));
+  }
+
+  /**
+   * Tests adding a file stylesheet.
+   */
+  function testAddFile() {
+    $path = drupal_get_path('module', 'simpletest') . '/simpletest.css';
+    $css = drupal_add_css($path);
+    $this->assertEqual($css[$path]['data'], $path, t('Adding a CSS file caches it properly.'));
+  }
+
+  /**
+   * Tests adding an external stylesheet.
+   */
+  function testAddExternal() {
+    $path = 'http://example.com/style.css';
+    $css = drupal_add_css($path, 'external');
+    $this->assertEqual($css[$path]['type'], 'external', t('Adding an external CSS file caches it properly.'));
+  }
+
+  /**
+   * Makes sure that reseting the CSS empties the cache.
+   */
+  function testReset() {
+    drupal_static_reset('drupal_add_css');
+    $this->assertEqual(array(), drupal_add_css(), t('Resetting the CSS empties the cache.'));
+  }
+
+  /**
+   * Tests rendering the stylesheets.
+   */
+  function testRenderFile() {
+    $css = drupal_get_path('module', 'simpletest') . '/simpletest.css';
+    drupal_add_css($css);
+    $styles = drupal_get_css();
+    $this->assertTrue(strpos($styles, $css) > 0, t('Rendered CSS includes the added stylesheet.'));
+  }
+
+  /**
+   * Tests rendering an external stylesheet.
+   */
+  function testRenderExternal() {
+    $css = 'http://example.com/style.css';
+    drupal_add_css($css, 'external');
+    $styles = drupal_get_css();
+    $this->assertTrue(strpos($styles, 'href="' . $css) > 0, t('Rendering an external CSS file.'));
+  }
+
+  /**
+   * Tests rendering inline stylesheets with preprocessing on.
+   */
+  /*function testRenderInlinePreprocess() {
+    $css = 'body { padding: 0px; }';
+    $css_preprocessed = '<style type="text/css">' . css_load_stylesheet_content($css, TRUE, FALSE) . '</style>';
+    drupal_add_css($css, 'inline');
+    $styles = drupal_get_css();
+    $this->assertEqual($styles, "\n" . $css_preprocessed . "\n", t('Rendering preprocessed inline CSS adds it to the page.'));
+  }*/
+
+  /**
+   * Tests rendering inline stylesheets with preprocessing off.
+   */
+  function testRenderInlineNoPreprocess() {
+    $css = 'body { padding: 0px; }';
+    drupal_add_css($css, array('type' => 'inline', 'preprocess' => FALSE));
+    $styles = drupal_get_css();
+    $this->assertTrue(strpos($styles, $css) > 0, t('Rendering non-preprocessed inline CSS adds it to the page.'));
+  }
+
+  /**
+   * Tests rendering inline stylesheets through a full page request.
+   */
+  /*function testRenderInlineFullPage() {
+    $css = 'body { font-size: 254px; }';
+    $expected = 'font-size:254px';
+
+    // Create a node, using the PHP filter that tests drupal_add_css().
+    $settings = array(
+      'type' => 'page',
+      'body' => array(
+        FIELD_LANGUAGE_NONE => array(
+          array(
+            'value' => t('This tests the inline CSS!') . "<?php drupal_add_css('$css', 'inline'); ?>",
+            // The "PHP code" format is always the most recent one added, since
+            // the PHP module was enabled in the setUp() method of the current
+            // test.
+            'format' => db_query("SELECT MAX(format) FROM {filter_format}")->fetchField(),
+          ),
+        ),
+      ),
+      'promote' => 1,
+    );
+    $node = $this->drupalCreateNode($settings);
+
+    // Fetch the page.
+    $this->drupalGet('node/' . $node->nid);
+    $this->assertRaw($expected, t('Inline stylesheets appear in the full page rendering.'));
+  }*/
+
+  /**
+   * Test CSS ordering.
+   */
+  function testRenderOrder() {
+    // A module CSS file.
+    drupal_add_css(drupal_get_path('module', 'simpletest') . '/simpletest.css');
+    // A few system CSS files, ordered in a strange way.
+    $system_path = drupal_get_path('module', 'system');
+    drupal_add_css($system_path . '/defaults.css', array('weight' => CSS_SYSTEM));
+    drupal_add_css($system_path . '/system.css', array('weight' => CSS_SYSTEM - 10));
+    drupal_add_css($system_path . '/system-menus.css', array('weight' => CSS_SYSTEM));
+
+    $expected = array(
+      $system_path . '/system.css',
+      $system_path . '/defaults.css',
+      $system_path . '/system-menus.css',
+      drupal_get_path('module', 'simpletest') . '/simpletest.css',
+    );
+
+
+    $styles = drupal_get_css();
+    if (preg_match_all('/href="' . preg_quote($GLOBALS['base_url'] . '/', '/') . '([^?]+)\?/', $styles, $matches)) {
+      $result = $matches[1];
+    }
+    else {
+      $result = array();
+    }
+
+    $this->assertIdentical($result, $expected, t('The CSS files are in the expected order.'));
+  }
+
+  /**
+   * Test CSS override.
+   */
+  function testRenderOverride() {
+    drupal_add_css(drupal_get_path('module', 'system') . '/system.css');
+    drupal_add_css(drupal_get_path('module', 'simpletest') . '/tests/system.css');
+
+    // The dummy stylesheet should be the only one included.
+    $styles = drupal_get_css();
+    $this->assert(strpos($styles, drupal_get_path('module', 'simpletest') . '/tests/system.css') !== FALSE, t('The overriding CSS file is output.'));
+    $this->assert(strpos($styles, drupal_get_path('module', 'system') . '/system.css') === FALSE, t('The overriden CSS file is not output.'));
+
+    drupal_add_css(drupal_get_path('module', 'simpletest') . '/tests/system.css');
+    drupal_add_css(drupal_get_path('module', 'system') . '/system.css');
+
+    // The standard stylesheet should be the only one included.
+    $styles = drupal_get_css();
+    $this->assert(strpos($styles, drupal_get_path('module', 'system') . '/system.css') !== FALSE, t('The overriding CSS file is output.'));
+    $this->assert(strpos($styles, drupal_get_path('module', 'simpletest') . '/tests/system.css') === FALSE, t('The overriden CSS file is not output.'));
+  }
+
+  /**
+   * Tests Locale module's CSS Alter to include RTL overrides.
+   */
+  function testAlter() {
+    // Switch the language to a right to left language and add system.css.
+    global $language;
+    $language->direction = LANGUAGE_RTL;
+    drupal_add_css(drupal_get_path('module', 'system') . '/system.css');
+
+    // Check to see if system-rtl.css was also added.
+    $styles = drupal_get_css();
+    $this->assert(strpos($styles, drupal_get_path('module', 'system') . '/system-rtl.css') !== FALSE, t('CSS is alterable as right to left overrides are added.'));
+
+    // Change the language back to left to right.
+    $language->direction = LANGUAGE_LTR;
+  }
+}
+
+/**
+ * CSS Unit Tests.
+ */
+class CSSUnitTest extends DrupalUnitTestCase {
+  public static function getInfo() {
+    return array(
+      'name' => 'CSS Unit Tests',
+      'description' => 'Unit tests on CSS functions like aggregation.',
+      'group' => 'CSS',
+    );
+  }
+
+  /**
+   * Tests basic CSS loading with and without optimization via css_load_stylesheet().
+   *
+   * This can be enhanced by adding additional CSS files with variant test cases.
+   * Currently, this is specifically testing to make sure that whitespace
+   * is treated with adequate respect (not arbitrarily removing linefeeds).
+   */
+  function testLoadCssBasic() {
+    // Force base URL path to be '/'.
+    $GLOBALS['base_path'] = '/';
+
+    // Array of files to test living in 'simpletest/files/css_test_files/'.
+    // - Original: name.css
+    // - Unoptimized expected content: name.unoptimized.css
+    // - Optimized expected content: name.optimized.css
+    $testfiles = array(
+      'basic',
+      'import',
+      'nested_import',
+      //'hacks', Does not pass yet
+      'selectors',
+      'paths'
+    );
+    $path = drupal_get_path('module', 'css') . '/tests/files';
+    foreach ($testfiles as $file) {
+      // Create an array as drupal_add_css() would do.
+      $css = array(
+        array(
+          'type' => 'file',
+          'weight' => CSS_DEFAULT,
+          'media' => 'all',
+          'preprocess' => TRUE,
+          'optimize' => TRUE,
+          'flatten' => TRUE,
+          'data' => "$path/$file.css"
+        )
+      );
+
+      if (file_exists("$path/$file.unoptimized.css")) {
+        $expected = file_get_contents("$path/$file.unoptimized.css");
+        $unoptimized_output = css_aggregate_stylesheets($css, FALSE, TRUE);
+        $this->assertEqual($unoptimized_output, $expected, t('Unoptimized CSS file has expected contents (@file)', array('@file' => "$file.css")));
+
+        // For developers: uncomment next line to store actual output of css_load_stylesheet()
+        file_put_contents("sites/default/private/temp/$file.unoptimized.css", $unoptimized_output);
+      }
+
+      if (file_exists("$path/$file.optimized.css")) {
+        $expected = file_get_contents("$path/$file.optimized.css");
+        $optimized_output = css_aggregate_stylesheets($css, TRUE, TRUE);
+        $this->assertEqual($optimized_output, $expected, t('Optimized CSS file has expected contents (@file)', array('@file' => "$file.css")));
+
+        // For developers: uncomment next line to store actual output of css_load_stylesheet()
+        file_put_contents("sites/default/private/temp/$file.optimized.css", $optimized_output);
+      }
+    }
+  }
+}
+
Index: modules/css/css.parser.inc
===================================================================
RCS file: modules/css/css.parser.inc
diff -N modules/css/css.parser.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/css/css.parser.inc	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,8 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * TODO.
+ */
+
Index: modules/css/css.module
===================================================================
RCS file: modules/css/css.module
diff -N modules/css/css.module
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/css/css.module	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,376 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Allows CSS stylesheets to be aggregated and compressed.
+ */
+
+/**
+ * Implement hook_css_alter().
+ */
+function css_css_alter(&$css) {
+  $preprocess_css = (variable_get('preprocess_css', FALSE) && (!defined('MAINTENANCE_MODE') || MAINTENANCE_MODE != 'update'));
+  $directory = file_directory_path('public');
+  $is_writable = is_dir($directory) && is_writable($directory);
+
+  if (!($is_writable && $preprocess_css)) {
+    // No need to continue.
+    return;
+  }
+
+  // A dummy query-string is added to filenames, to gain control over
+  // browser-caching. The string changes on every update or full cache
+  // flush, forcing browsers to load a new copy of the files, as the
+  // URL changed.
+  $query_string = '?' . substr(variable_get('css_js_query_string', '0'), 0, 1);
+
+  // Sort css items according to their weights.
+  uasort($css, 'drupal_sort_weight');
+
+  // Remove the overriden CSS files. Later CSS files override former ones.
+  $previous_item = array();
+  foreach ($css as $key => $item) {
+    if ($item['type'] == 'file') {
+      $basename = basename($item['data']);
+      if (isset($previous_item[$basename])) {
+        // Remove the previous item that shared the same base name.
+        unset($css[$previous_item[$basename]]);
+      }
+      $previous_item[$basename] = $key;
+    }
+  }
+
+  $preprocess_items = array();
+  foreach ($css as $data => $item) {
+    // Loop through each of the stylesheets, and see whether they need preprocessing
+    // Preprocessing for external CSS files is ignored.
+    if ($item['preprocess'] && ($item['type'] == 'file' || $item['type'] == 'inline')) {
+      // Remove stylesheet from the stylesheet queue.
+      unset($css[$data]);
+      // Add stylesheet to preprocess queue.
+      $preprocess_items[$item['type']][$item['media']][] = $item;
+    }
+  }
+
+  // Preprocess queued stylesheets.
+  foreach ($preprocess_items as $type => $items_type) {
+    foreach ($items_type as $media => $items) {
+      // Build a stylesheet array like drupal_add_css() would do.
+      $stylesheet = array(
+        'type' => $type,
+        'weight' => CSS_SYSTEM - 99,
+        'media' => $media,
+        'preprocess' => FALSE,
+      );
+      // Always add a tiny value to the weight, to conserve the insertion order.
+      $stylesheet['weight'] += count($css) / 1000;
+
+      if ($type == 'file') {
+        // Prefix filename to prevent blocking by firewalls which reject files
+        // starting with "ad*".
+        $filename = 'css_' . md5(serialize($items) . $query_string) . '.css';
+        $stylesheet['data'] = file_create_url(css_build_css_cache($items, $filename));
+      }
+      else {
+        $stylesheet['data'] = css_aggregate_stylesheets($items, $preprocess_css, FALSE);
+      }
+
+      // Add aggregated stylesheet to the stylesheet queue.
+      $css[] = $stylesheet;
+    }
+  }
+}
+
+/**
+ * Aggregate a set of CSS stylesheets into a single stylesheet.
+ *
+ * @param $css
+ *   An array of CSS stylesheets to aggregate.
+ * @param $optimize
+ *   (optional) Boolean whether CSS contents should be optimized.
+ *   Defaults to TRUE.
+ * @param $flatten
+ *   (optional) Boolean whether @import rules should be replaced with the
+ *   actual stylesheet content.
+ *   Defaults to TRUE.
+ * @return
+ *   Contents of the aggregated stylesheet, including any replaced @import rules.
+ */
+function css_aggregate_stylesheets($css, $optimize = TRUE, $flatten = TRUE) {
+  // Build aggregate CSS file.
+  $data = '';
+  foreach ($css as $stylesheet) {
+    // Preprocessing for external CSS files is ignored.
+    if ($stylesheet['type'] == 'file') {
+      $data .= css_load_stylesheet($stylesheet['data'], $optimize, $flatten);
+    }
+    elseif ($stylesheet['type'] == 'inline') {
+      $data .= css_load_stylesheet_content($stylesheet['data'], $optimize, $flatten);
+    }
+  }
+
+  // Per the W3C specification at http://www.w3.org/TR/REC-CSS2/cascade.html#at-import,
+  // @import rules must proceed any other style, so we move those to the top.
+  if (!empty($data)) {
+    $regexp = '/@import[^;]+;/i';
+    preg_match_all($regexp, $data, $matches);
+    $data = preg_replace($regexp, '', $data);
+    $data = implode($optimize ? '' : "\n", $matches[0]) . $data;
+  }
+
+  return $data;
+}
+
+/**
+ * Aggregate a set of CSS stylesheets and store them into a single stylesheet in
+ * the files directory.
+ *
+ * @param $css
+ *   An array of CSS files to aggregate.
+ * @param $filename
+ *   The name of the aggregate CSS file.
+ * @return
+ *   The name of the stored CSS file.
+ */
+function css_build_css_cache($css, $filename) {
+  // Create the css/ within the files folder.
+  $csspath = 'public://css';
+  file_prepare_directory($csspath, FILE_CREATE_DIRECTORY);
+  if (!file_exists($csspath . '/' . $filename)) {
+    // Build aggregate CSS file.
+    // Don't pass $optimize and $flatten parameters so individual stylesheet
+    // settings are used.
+    $data = css_aggregate_stylesheets($css);
+
+    // Create the CSS file.
+    file_unmanaged_save_data($data, $csspath . '/' . $filename, FILE_EXISTS_REPLACE);
+  }
+  return $csspath . '/' . $filename;
+}
+
+/**
+ * Loads the stylesheet and resolves all @import commands.
+ *
+ * Loads a stylesheet and replaces @import commands with the contents of the
+ * imported file. Use this instead of file_get_contents when processing
+ * stylesheets.
+ *
+ * @param $file
+ *   Name of the stylesheet to be processed.
+ * @param $optimize
+ *   Defines if CSS contents should be compressed or not.
+ * @param $flatten
+ *   Defines if @import commands should be replaced with the actual stylesheet content.
+ * @return
+ *   Contents of the stylesheet, including any replaced @import commands or FALSE
+ *   on failure.
+ */
+function css_load_stylesheet($file, $optimize = NULL, $flatten = TRUE) {
+  // $_optimize does not use drupal_static as it is set by $optimize.
+  static $_optimize;
+  // Store optimization parameter for preg_replace_callback with nested @import loops.
+  if (isset($optimize)) {
+    $_optimize = $optimize;
+  }
+
+  $contents = '';
+  if (file_exists($file)) {
+    // Load the local CSS stylesheet.
+    $contents = file_get_contents($file);
+
+    $temp = _css_build_css_path(NULL);
+    // Inform _drupal_build_css_path() where this CSS file originated from.
+    _css_build_css_path(NULL, dirname($file));
+
+    // Process the stylesheet.
+    $contents = css_load_stylesheet_content($contents, $_optimize, $flatten);
+
+    // Restore _drupal_build_css_path().
+    _css_build_css_path(NULL, $temp);
+  }
+  else {
+    return FALSE;
+  }
+
+  return $contents;
+}
+
+/**
+ * Helper function for css_load_stylesheet().
+ *
+ * This function will prefix all paths within a CSS file.
+ *
+ * @see css_load_stylesheet_contents()
+ *   This function is being used as a callback for preg_replace_callback().
+ */
+function _css_build_css_path($matches, $change_directory = NULL) {
+  // $directory does not use drupal_static as it is set by $change_directory.
+  static $directory;
+  // Store current directory for preg_replace_callback.
+  if (isset($change_directory)) {
+    $directory = $change_directory;
+  }
+
+  if (is_array($matches)) {
+    // Prefix with base URL path and current directory.
+    if (!empty($directory)) {
+      $path = base_path() . $directory . '/' . $matches[1];
+    }
+    else {
+      $path = base_path() . $matches[1];
+    }
+
+    $last = '';
+    while ($path != $last) {
+      $last = $path;
+
+      // Replace '/./' segments for '/'.
+      $path = str_replace('/./', '/', $path);
+
+      // Remove '../' segments where possible.
+      $path = preg_replace('`(^|/)(?!\.\./)([^/]+)/\.\./`', '$1', $path);
+    }
+
+    return 'url(' . $path . ')';
+  }
+  else {
+    return $directory;
+  }
+}
+
+/**
+ * Process the contents of a stylesheet for aggregation.
+ *
+ * @param $contents
+ *   The contents of the stylesheet.
+ * @param $optimize
+ *   (optional) Boolean whether CSS contents should be minified. Defaults to
+ *   FALSE.
+ * @param $flatten
+ *   (optional) Boolean whether @import commands should be replaced with the
+ *   actual stylesheet content.
+ * @return
+ *   Contents of the stylesheet including the imported stylesheets.
+ */
+function css_load_stylesheet_content($contents, $optimize = FALSE, $flatten = TRUE) {
+  // Remove multiple charset declarations for standards compliance (and fixing Safari problems).
+  $contents = preg_replace('/^@charset\s+[\'"](\S*)\b[\'"];/i', '', $contents);
+
+  // Run optimization before flattening so only own contents is processed. This
+  // prevents doing things twice as this flattening recurses this function.
+  if ($optimize) {
+    // Perform some safe CSS optimizations.
+    $contents = preg_replace('{
+      (?<=\\\\\*/)([^/\*]+/\*)([^\*/]+\*/)  # Add a backslash also at the end ie-mac hack comment, so the next pass will not touch it.
+                                            # The added backshlash does not affect the effectiveness of the hack.
+      }x', '\1\\\\\2', $contents);
+    $contents = preg_replace('<
+      \s*([@{}:;,]|\)\s|\s\()\s* |          # Remove whitespace around separators, but keep space around parentheses.
+      /\*[^*\\\\]*\*+([^/*][^*]*\*+)*/ |    # Remove comments that are not CSS hacks.
+      >x', '\1', $contents);
+
+    // Replace whitespace from the beginning and end with a single newline.
+    $contents = "\n" . trim($contents);
+  }
+
+  // Normalize @import commands so they all contain the url() function.
+  $contents = preg_replace('/@import\s*(?:url\(\s*)?[\'"]?([^\'"\()]+)[\'"]?\s*\)?;/', '@import url(\1);', $contents);
+
+  // Normalize all paths within this CSS file, ignoring external and absolute paths.
+  // Paths always needs to be normalized as relative URLs may break when aggregating this CSS file.
+  $contents = preg_replace_callback('/url\(\s*[\'"]?(?![a-z]+:|\/+)([^\'")]+)[\'"]?\s*\)/i', '_css_build_css_path', $contents);
+
+  if ($flatten) {
+    // Replaces @import commands with the actual stylesheet content.
+    // This happens recursively but omits external files.
+    $contents = preg_replace_callback('/@import url\((\/[^\)]+\.css)\)?;/', '_css_load_stylesheet', $contents);
+  }
+
+  return $contents;
+}
+
+/**
+ * Helper function for drupal_load_stylesheet_content().
+ *
+ * This function is used for recursive loading of stylesheets.
+ *
+ * @see css_load_stylesheet_contents()
+ *   This function is being used as a callback for preg_replace_callback().
+ */
+function _css_load_stylesheet($matches) {
+  // Strip base URL path to get a correct internal file path.
+  $filename = substr($matches[1], strlen(base_path()));
+
+  if (($contents = css_load_stylesheet($filename)) === FALSE) {
+    // Restore @import command when drupal_load_stylesheet() failes.
+    return '@import url(' . base_path() . $filename . ');';
+  }
+  return $contents;
+}
+
+/**
+ * Implement hook_form_FORM_ID_alter().
+ */
+function css_form_system_performance_settings_alter(&$form, &$form_state) {
+  $directory = 'public://';
+  $is_writable = is_dir($directory) && is_writable($directory);
+  $disabled = !$is_writable;
+
+  $form['bandwidth_optimization']['preprocess_css'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Aggregate and compress CSS files into one file.'),
+    '#default_value' => intval(variable_get('preprocess_css', 0) && $is_writable),
+    '#disabled' => $disabled,
+    '#weight' => -1,
+  );
+}
+
+/**
+ * Implement hook_flush_caches().
+ */
+function css_flush_caches() {
+  if (variable_get('preprocess_css', FALSE)) {
+    css_clear_cache();
+  }
+
+  // hook_flush_caches() expects an array with cache table names. the CSS module
+  // has no cache tables.
+  return array();
+}
+
+/**
+ * Implement hook_form_FORM_ID_alter().
+ *
+ * Adds a submit handler to the system themes forms, so that if a site admin
+ * saves that form, we invalidate the cache of preprocessed stylesheets.
+ *
+ * @see css_clear_cache()
+ */
+function css_form_system_themes_form_alter(&$form, $form_state) {
+  if (variable_get('preprocess_css', FALSE)) {
+    $form['#submit'][] = 'css_clear_cache';
+  }
+}
+
+/**
+ * Implement hook_form_FORM_ID_alter().
+ *
+ * Adds a submit handler to the system modules forms, so that if a site admin
+ * saves that form, we invalidate the cache of preprocessed stylesheets.
+ *
+ * @see css_clear_cache()
+ */
+function css_form_system_modules_alter(&$form, $form_state) {
+  if (variable_get('preprocess_css', FALSE)) {
+    $form['#submit'][] = 'css_clear_cache';
+  }
+}
+
+/**
+ * Invalidate the cache of preprocessed stylesheets.
+ */
+function css_clear_cache() {
+  // Remove all aggregate CSS files.
+  file_scan_directory('public://css', '/.*/', array('callback' => 'file_unmanaged_delete'));
+}
\ No newline at end of file
Index: modules/css/tests/files/paths.unoptimized.css
===================================================================
RCS file: modules/css/tests/files/paths.unoptimized.css
diff -N modules/css/tests/files/paths.unoptimized.css
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/css/tests/files/paths.unoptimized.css	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,27 @@
+foo {
+  background: url(/modules/css/tests/files/bar/foo.png);
+  background: url(/modules/css/tests/files/bar/foo.png);
+  background: url(/modules/css/tests/files/bar/foo.png);
+  background: url(/modules/css/tests/files/bar/foo.png);
+  background: url(/modules/css/tests/files/bar/foo.png);
+  background: url(/modules/css/tests/bar/foo.png);
+  background: url(/modules/css/bar/foo.png);
+  background: url(/modules/css/tests/foo.png);
+  background: url(/modules/css/tests/files/bar/foo.png);
+  background: url(/modules/css/tests/files/foo.png);
+
+  /* absolute, should not alter */
+  background: url('/bar/foo.png');
+  background: url('/bar/../../foo.png');
+
+  /* external, should not alter */
+  background: url('http://foo.com/css/foo.css');
+  background: url('http://foo.com/css/../foo.css');
+  background: url('http://foo.com/css/../css/foo.css');
+
+  /* protocol relative, should not alter */
+  background: url("//foo.com/css/foo.css");
+
+  /* data, should not alter */
+  background: url(data:image/gif;base64,AAAA);
+}
Index: modules/css/tests/files/basic.css
===================================================================
RCS file: modules/css/tests/files/basic.css
diff -N modules/css/tests/files/basic.css
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/css/tests/files/basic.css	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,53 @@
+/* Id: defaults.css,v 1.6 2009/02/18 14:28:23 webchick Exp */
+
+/*
+** HTML elements
+*/
+fieldset {
+  margin-bottom: 1em;
+  padding: .5em;
+}
+form {
+  margin: 0;
+  padding: 0;
+}
+hr {
+  height: 1px;
+  border: 1px solid gray;
+}
+img {
+  border: 0;
+}
+table {
+  border-collapse: collapse;
+}
+th {
+  text-align: left; /* LTR */
+  padding-right: 1em; /* LTR */
+  border-bottom: 3px solid #ccc;
+}
+
+/*
+** Markup free clearing
+** Details: http://www.positioniseverything.net/easyclearing.html
+*/
+.clearfix:after {
+  content: ".";
+  display: block;
+  height: 0;
+  clear: both;
+  visibility: hidden;
+}
+
+.clearfix {
+  display: inline-block;
+}
+
+/* Hides from IE-mac \*/
+* html .clearfix {
+  height: 1%;
+}
+.clearfix {
+  display: block;
+}
+/* End hide from IE-mac */
Index: modules/css/tests/files/hacks.css
===================================================================
RCS file: modules/css/tests/files/hacks.css
diff -N modules/css/tests/files/hacks.css
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/css/tests/files/hacks.css	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,67 @@
+
+/* feed to ie5/mac \*//*/
+@import "ie5mac.css";
+/* necessary comment */
+
+/* comment to attempt to confuse parser */
+
+/* hide from ie5/mac \*/ a{}
+.foo {color:red}
+/* necessary comment */
+
+/* comment to attempt to confuse parser */
+
+/*/ hide from nav4 */
+.foo {display:block;}
+/* necessary comment */
+
+/* comment to attempt to confuse parser */
+
+/*/ feed to nav *//*/
+.foo {display:crazy;}
+/* necessary comment */
+
+/* hide props from various IE/win */
+div {
+    width: 140px; 
+    width/* */:/**/100px; 
+    width: /**/100px;
+}
+
+html>/**/body {}
+
+/* Tantek's box model hack */
+div { 
+  width:400px; 
+  voice-family: "\"}\""; 
+  voice-family:inherit;
+  width:300px;
+}
+
+/* don't minimize hex colors in filters */
+div {
+  filter:chroma(color=#aabbcc);
+  filter:mask(color=#000000) shadow(color=#9BAD71, direction=135) chroma(color=#000000);
+}
+
+@media screen {
+    /* for IE 5.x-6, hidden from IE 5 Mac */ /*\*/
+    * html div#page {
+        height: 1%;
+    }
+    /**/ /* end hidden from IE 5 Mac */
+}
+
+foo { /* filters for IE */
+    _height : 20px;
+    *height : 15px;
+}
+
+/* http://tantek.com/CSS/Examples/midpass.html */
+@media tty {
+ i{content:"\";/*" "*/}} @import 'midpassafter.css'; /*";}
+}/* */
+
+/* leave at least 1 space between these pseudo elements and "{" for IE6: http://www.crankygeek.com/ie6pebug/ */
+p:first-letter  {color:red;}
+p:first-line   {color:red;}
Index: modules/css/tests/files/nested_import.optimized.css
===================================================================
RCS file: modules/css/tests/files/nested_import.optimized.css
diff -N modules/css/tests/files/nested_import.optimized.css
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/css/tests/files/nested_import.optimized.css	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,14 @@
+@import url(http://foo.com/css/foo.css);
+
+
+fieldset{margin-bottom:1em;padding:.5em;}form{margin:0;padding:0;}hr{height:1px;border:1px solid gray;}img{border:0;}table{border-collapse:collapse;}th{text-align:left;
+  padding-right:1em;
+  border-bottom:3px solid #ccc;}
+.clearfix:after{content:".";display:block;height:0;clear:both;visibility:hidden;}.clearfix{display:inline-block;}/* Hides from IE-mac \*/
+* html .clearfix{height:1%;}.clearfix{display:block;}
+
+
+body{margin:0;background-image:url(/modules/css/tests/image-1.png);font:76%/170% Verdana,sans-serif;color:#494949;}
+
+
+body{margin:0;background-image:url(/modules/css/files/image-1.png);font:76%/170% Verdana,sans-serif;color:#494949;}
\ No newline at end of file
Index: modules/css/tests/files/basic.unoptimized.css
===================================================================
RCS file: modules/css/tests/files/basic.unoptimized.css
diff -N modules/css/tests/files/basic.unoptimized.css
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/css/tests/files/basic.unoptimized.css	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,53 @@
+/* Id: defaults.css,v 1.6 2009/02/18 14:28:23 webchick Exp */
+
+/*
+** HTML elements
+*/
+fieldset {
+  margin-bottom: 1em;
+  padding: .5em;
+}
+form {
+  margin: 0;
+  padding: 0;
+}
+hr {
+  height: 1px;
+  border: 1px solid gray;
+}
+img {
+  border: 0;
+}
+table {
+  border-collapse: collapse;
+}
+th {
+  text-align: left; /* LTR */
+  padding-right: 1em; /* LTR */
+  border-bottom: 3px solid #ccc;
+}
+
+/*
+** Markup free clearing
+** Details: http://www.positioniseverything.net/easyclearing.html
+*/
+.clearfix:after {
+  content: ".";
+  display: block;
+  height: 0;
+  clear: both;
+  visibility: hidden;
+}
+
+.clearfix {
+  display: inline-block;
+}
+
+/* Hides from IE-mac \*/
+* html .clearfix {
+  height: 1%;
+}
+.clearfix {
+  display: block;
+}
+/* End hide from IE-mac */
Index: modules/css/tests/files/hacks.unoptimized.css
===================================================================
RCS file: modules/css/tests/files/hacks.unoptimized.css
diff -N modules/css/tests/files/hacks.unoptimized.css
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/css/tests/files/hacks.unoptimized.css	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,67 @@
+
+/* feed to ie5/mac \*//*/
+@import "ie5mac.css";
+/* necessary comment */
+
+/* comment to attempt to confuse parser */
+
+/* hide from ie5/mac \*/ a{}
+.foo {color:red}
+/* necessary comment */
+
+/* comment to attempt to confuse parser */
+
+/*/ hide from nav4 */
+.foo {display:block;}
+/* necessary comment */
+
+/* comment to attempt to confuse parser */
+
+/*/ feed to nav *//*/
+.foo {display:crazy;}
+/* necessary comment */
+
+/* hide props from various IE/win */
+div {
+    width: 140px; 
+    width/* */:/**/100px; 
+    width: /**/100px;
+}
+
+html>/**/body {}
+
+/* Tantek's box model hack */
+div { 
+  width:400px; 
+  voice-family: "\"}\""; 
+  voice-family:inherit;
+  width:300px;
+}
+
+/* don't minimize hex colors in filters */
+div {
+  filter:chroma(color=#aabbcc);
+  filter:mask(color=#000000) shadow(color=#9BAD71, direction=135) chroma(color=#000000);
+}
+
+@media screen {
+    /* for IE 5.x-6, hidden from IE 5 Mac */ /*\*/
+    * html div#page {
+        height: 1%;
+    }
+    /**/ /* end hidden from IE 5 Mac */
+}
+
+foo { /* filters for IE */
+    _height : 20px;
+    *height : 15px;
+}
+
+/* http://tantek.com/CSS/Examples/midpass.html */
+@media tty {
+ i{content:"\";/*" "*/}} @import 'midpassafter.css'; /*";}
+}/* */
+
+/* leave at least 1 space between these pseudo elements and "{" for IE6: http://www.crankygeek.com/ie6pebug/ */
+p:first-letter  {color:red;}
+p:first-line   {color:red;}
Index: modules/css/tests/files/nested_import.unoptimized.css
===================================================================
RCS file: modules/css/tests/files/nested_import.unoptimized.css
diff -N modules/css/tests/files/nested_import.unoptimized.css
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/css/tests/files/nested_import.unoptimized.css	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,80 @@
+@import url(http://foo.com/css/foo.css);/* Id: defaults.css,v 1.6 2009/02/18 14:28:23 webchick Exp */
+
+/*
+** HTML elements
+*/
+fieldset {
+  margin-bottom: 1em;
+  padding: .5em;
+}
+form {
+  margin: 0;
+  padding: 0;
+}
+hr {
+  height: 1px;
+  border: 1px solid gray;
+}
+img {
+  border: 0;
+}
+table {
+  border-collapse: collapse;
+}
+th {
+  text-align: left; /* LTR */
+  padding-right: 1em; /* LTR */
+  border-bottom: 3px solid #ccc;
+}
+
+/*
+** Markup free clearing
+** Details: http://www.positioniseverything.net/easyclearing.html
+*/
+.clearfix:after {
+  content: ".";
+  display: block;
+  height: 0;
+  clear: both;
+  visibility: hidden;
+}
+
+.clearfix {
+  display: inline-block;
+}
+
+/* Hides from IE-mac \*/
+* html .clearfix {
+  height: 1%;
+}
+.clearfix {
+  display: block;
+}
+/* End hide from IE-mac */
+
+
+
+/**
+ * @file Basic css that use import
+ */
+
+
+body {
+  margin: 0;
+  background-image: url(/modules/css/tests/image-1.png);
+  font: 76%/170% Verdana, sans-serif;
+  color: #494949;
+}
+
+
+/**
+ * @file css that use nested import commands
+ */
+
+
+body {
+  margin: 0;
+  background-image: url(/modules/css/files/image-1.png);
+  font: 76%/170% Verdana, sans-serif;
+  color: #494949;
+}
Index: modules/css/tests/files/selectors.optimized.css
===================================================================
RCS file: modules/css/tests/files/selectors.optimized.css
diff -N modules/css/tests/files/selectors.optimized.css
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/css/tests/files/selectors.optimized.css	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,41 @@
+
+*
+E[foo]
+E[foo="bar"]
+E[foo~="bar"]
+E[foo^="bar"]
+E[foo$="bar"]
+E[foo*="bar"]
+E[hreflang|="en"]
+E:root
+E:nth-child(n)
+E:nth-last-child(n)
+E:nth-of-type(n)
+E:nth-last-of-type(n)
+E:first-child
+E:last-child
+E:first-of-type
+E:last-of-type
+E:only-child
+E:only-of-type
+E:empty
+E:link
+E:visited
+E:active
+E:hover
+E:focus
+E:target
+E:lang(fr)
+E:enabled
+E:disabled
+E:checked
+E::first-line
+E::first-letter
+E::selection
+E::before
+E::after
+E.warning#myid
+E:not(s)
+> F
+ + F
+ ~ F{color:red;}
\ No newline at end of file
Index: modules/css/tests/files/selectors.css
===================================================================
RCS file: modules/css/tests/files/selectors.css
diff -N modules/css/tests/files/selectors.css
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/css/tests/files/selectors.css	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,42 @@
+/* http://www.w3.org/TR/css3-selectors/ */
+
+*
+E[foo]
+E[foo="bar"]
+E[foo~="bar"]
+E[foo^="bar"]
+E[foo$="bar"]
+E[foo*="bar"]
+E[hreflang|="en"]
+E:root
+E:nth-child(n)
+E:nth-last-child(n)
+E:nth-of-type(n)
+E:nth-last-of-type(n)
+E:first-child
+E:last-child
+E:first-of-type
+E:last-of-type
+E:only-child
+E:only-of-type
+E:empty
+E:link
+E:visited
+E:active
+E:hover
+E:focus
+E:target
+E:lang(fr)
+E:enabled
+E:disabled
+E:checked
+E::first-line
+E::first-letter
+E::selection
+E::before
+E::after
+E.warning#myid
+E:not(s)
+ > F
+ + F
+ ~ F {color: red;}
Index: modules/css/tests/files/selectors.unoptimized.css
===================================================================
RCS file: modules/css/tests/files/selectors.unoptimized.css
diff -N modules/css/tests/files/selectors.unoptimized.css
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/css/tests/files/selectors.unoptimized.css	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,42 @@
+/* http://www.w3.org/TR/css3-selectors/ */
+
+*
+E[foo]
+E[foo="bar"]
+E[foo~="bar"]
+E[foo^="bar"]
+E[foo$="bar"]
+E[foo*="bar"]
+E[hreflang|="en"]
+E:root
+E:nth-child(n)
+E:nth-last-child(n)
+E:nth-of-type(n)
+E:nth-last-of-type(n)
+E:first-child
+E:last-child
+E:first-of-type
+E:last-of-type
+E:only-child
+E:only-of-type
+E:empty
+E:link
+E:visited
+E:active
+E:hover
+E:focus
+E:target
+E:lang(fr)
+E:enabled
+E:disabled
+E:checked
+E::first-line
+E::first-letter
+E::selection
+E::before
+E::after
+E.warning#myid
+E:not(s)
+ > F
+ + F
+ ~ F {color: red;}
Index: modules/css/tests/files/basic.optimized.css
===================================================================
RCS file: modules/css/tests/files/basic.optimized.css
diff -N modules/css/tests/files/basic.optimized.css
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/css/tests/files/basic.optimized.css	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,6 @@
+
+fieldset{margin-bottom:1em;padding:.5em;}form{margin:0;padding:0;}hr{height:1px;border:1px solid gray;}img{border:0;}table{border-collapse:collapse;}th{text-align:left;
+  padding-right:1em;
+  border-bottom:3px solid #ccc;}
+.clearfix:after{content:".";display:block;height:0;clear:both;visibility:hidden;}.clearfix{display:inline-block;}/* Hides from IE-mac \*/
+* html .clearfix{height:1%;}.clearfix{display:block;}
\ No newline at end of file
Index: modules/css/css.info
===================================================================
RCS file: modules/css/css.info
diff -N modules/css/css.info
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/css/css.info	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,10 @@
+; $Id$
+name = CSS
+description = Allows CSS stylesheets to be aggregated and compressed.
+package = Core
+version = VERSION
+core = 7.x
+files[] = css.module
+files[] = css.parser.inc
+files[] = css.install
+files[] = tests/css.test
Index: modules/css/tests/files/import.unoptimized.css
===================================================================
RCS file: modules/css/tests/files/import.unoptimized.css
diff -N modules/css/tests/files/import.unoptimized.css
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/css/tests/files/import.unoptimized.css	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,67 @@
+@import url(http://foo.com/css/foo.css);/* Id: defaults.css,v 1.6 2009/02/18 14:28:23 webchick Exp */
+
+/*
+** HTML elements
+*/
+fieldset {
+  margin-bottom: 1em;
+  padding: .5em;
+}
+form {
+  margin: 0;
+  padding: 0;
+}
+hr {
+  height: 1px;
+  border: 1px solid gray;
+}
+img {
+  border: 0;
+}
+table {
+  border-collapse: collapse;
+}
+th {
+  text-align: left; /* LTR */
+  padding-right: 1em; /* LTR */
+  border-bottom: 3px solid #ccc;
+}
+
+/*
+** Markup free clearing
+** Details: http://www.positioniseverything.net/easyclearing.html
+*/
+.clearfix:after {
+  content: ".";
+  display: block;
+  height: 0;
+  clear: both;
+  visibility: hidden;
+}
+
+.clearfix {
+  display: inline-block;
+}
+
+/* Hides from IE-mac \*/
+* html .clearfix {
+  height: 1%;
+}
+.clearfix {
+  display: block;
+}
+/* End hide from IE-mac */
+
+
+
+/**
+ * @file Basic css that use import
+ */
+
+
+body {
+  margin: 0;
+  background-image: url(/modules/css/tests/image-1.png);
+  font: 76%/170% Verdana, sans-serif;
+  color: #494949;
+}
