Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.919
diff -u -r1.919 common.inc
--- includes/common.inc	6 Jun 2009 16:05:26 -0000	1.919
+++ includes/common.inc	7 Jun 2009 16:07:49 -0000
@@ -2296,13 +2296,16 @@
  *   - 'inline': A string of CSS that should be placed in the given scope. Note
  *     that it is better practice to use 'module' or 'theme' stylesheets, rather
  *     than 'inline' as the CSS would then be aggregated and cached.
+ *   - 'external': Include an external CSS file that is not hosted on the local
+ *     server. These files will not be aggregated if CSS aggregation is
+ *     enabled.
  *
  * @param $options
  *   (optional) A string defining the 'type' of CSS that is being added in the
- *   $data parameter ('module', 'theme' or 'inline'), or an associative array of
- *   additional options, with the following keys:
+ *   $data parameter ('module', 'theme', 'external' or 'inline'), or an
+ *   associative array of additional options, with the following keys:
  *   - 'type': The type of stylesheet that is being added. Types are: 'module',
- *     'theme' or 'inline'. Defaults to 'module'.
+ *     'theme', 'external' or 'inline'. Defaults to 'module'.
  *   - 'media': The media type for the stylesheet, e.g., all, print, screen.
  *     Defaults to 'all'.
  *   - 'preprocess': Allows the CSS to be aggregated and compressed if the
@@ -2314,7 +2317,8 @@
  *     files into one file that is then compressed by removing all extraneous
  *     white space. Note that preprocessed inline stylesheets will not be
  *     aggregated into this single file, instead it will just be compressed
- *     when being output on the page.
+ *     when being output on the page. External stylesheets will not be
+ *     aggregated at all.
  *
  *     The reason for merging the CSS files is outlined quite thoroughly here:
  *     http://www.die.net/musings/page_load_time/
@@ -2364,7 +2368,7 @@
     $css[$media][$type][$data] = $options['preprocess'];
 
     // If the current language is RTL, add the CSS file with RTL overrides.
-    if ($type != 'inline' && $language->direction == LANGUAGE_RTL) {
+    if (($type == 'module' || $type == 'theme') && $language->direction == LANGUAGE_RTL) {
       $rtl_path = str_replace('.css', '-rtl.css', $data);
       if (file_exists($rtl_path)) {
         $css[$media][$type][$rtl_path] = $options['preprocess'];
@@ -2438,6 +2442,18 @@
         // Include inline stylesheets.
         if ($type == 'inline') {
           $no_inline_preprocess .= drupal_load_stylesheet_content($data, $preprocess);
+          // Unset the inline CSS to prevent it from being considered for inclusion
+          // when CSS aggregation is enabled.
+          unset($types[$type][$data]);
+        }
+        // Include external stylesheets.
+        elseif ($type == 'external') {
+          // Validate the external CSS address by passing it through url().
+          $url = url($data, array('absolute' => TRUE, 'external' => TRUE));
+          $output .= '<link type="text/css" rel="stylesheet" media="' . $media . '" href="' . $url . '" />' . "\n";
+          // Unset the external file to prevent it from being considered for
+          // inclusion when CSS aggregation is enabled.
+          unset($types[$type][$data]);
         }
         // Only include the stylesheet if it exists.
         elseif (file_exists($data)) {
@@ -2922,8 +2938,10 @@
         break;
 
       case 'external':
+        // Validate the external JavaScript address by passing it through url().
+        $url = url($item['data'], array('absolute' => TRUE, 'external' => TRUE));
         // Preprocessing for external JavaScript files is ignored.
-        $output .= '<script type="text/javascript"' . ($item['defer'] ? ' defer="defer"' : '') . ' src="' . $item['data'] . "\"></script>\n";
+        $output .= '<script type="text/javascript"' . ($item['defer'] ? ' defer="defer"' : '') . ' src="' . $url . "\"></script>\n";
         break;
     }
   }
Index: modules/simpletest/tests/common.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/common.test,v
retrieving revision 1.45
diff -u -r1.45 common.test
--- modules/simpletest/tests/common.test	6 Jun 2009 15:43:05 -0000	1.45
+++ modules/simpletest/tests/common.test	7 Jun 2009 16:07:52 -0000
@@ -215,6 +215,15 @@
   }
 
   /**
+   * Tests adding an external stylesheet.
+   */
+  function testAddExternal() {
+    $path = 'http://example.com/style.css';
+    $css = drupal_add_css($path, 'external');
+    $this->assertEqual($css['all']['external'][$path], TRUE, t('Adding an external CSS file caches it properly.'));
+  }
+
+  /**
    * Makes sure that reseting the CSS empties the cache.
    */
   function testReset() {
@@ -232,6 +241,15 @@
   }
 
   /**
+   * Tests rendering an external stylesheet.
+   */
+  function testRenderExternal() {
+    $css = 'http://example.com/style.css';
+    drupal_add_css($css, 'external');
+    $this->assertTrue(strpos(drupal_get_css(), 'href="' . $css) > 0, t('Rendering an external CSS file.'));
+  }
+
+  /**
    * Tests rendering inline stylesheets with preprocessing on.
    */
   function testRenderInlinePreprocess() {
