 includes/file.inc                   |   94 +++++++++++++++++++++--------------
 modules/simpletest/tests/file.test  |    4 ++
 modules/simpletest/tests/theme.test |   22 ++++++++
 3 files changed, 83 insertions(+), 37 deletions(-)

diff --git a/includes/file.inc b/includes/file.inc
index 4188b41..cf56739 100644
--- a/includes/file.inc
+++ b/includes/file.inc
@@ -192,15 +192,23 @@ function file_stream_wrapper_get_class($scheme) {
  * Returns the scheme of a URI (e.g. a stream).
  *
  * @param $uri
- *   A stream, referenced as "scheme://target".
+ *   A URI, in the form 'scheme://target', 'data:target' or 'path/to/file'.
  *
  * @return
  *   A string containing the name of the scheme, or FALSE if none. For example,
- *   the URI "public://example.txt" would return "public".
+ *   the URI 'public://example.txt' would return 'public'.
  *
  * @see file_uri_target()
  */
 function file_uri_scheme($uri) {
+
+  // Because path-only URIs are accepted it is not possible to generically use
+  // ':' as the delimiter (paths can contain this character), so 'data:' is
+  // tested for specifically.
+  if (strpos($uri, 'data:') === 0) {
+    return 'data';
+  }
+
   $position = strpos($uri, '://');
   return $position ? substr($uri, 0, $position) : FALSE;
 }
@@ -235,20 +243,32 @@ function file_stream_wrapper_valid_scheme($scheme) {
  * Returns the part of an URI after the schema.
  *
  * @param $uri
- *   A stream, referenced as "scheme://target".
+ *   A URI, in the form 'scheme://target' or 'data:target'.
  *
  * @return
  *   A string containing the target (path), or FALSE if none.
- *   For example, the URI "public://sample/test.txt" would return
- *   "sample/test.txt".
+ *   For example, the URI 'public://sample/test.txt' would return
+ *   'sample/test.txt'.
  *
  * @see file_uri_scheme()
  */
 function file_uri_target($uri) {
-  $data = explode('://', $uri, 2);
+
+  // Determine the position of the target.
+  if (strpos($uri, 'data:') === 0) {
+    $position = 5;
+  }
+  else {
+    $position = strpos($uri, '://');
+    // If this is not a valid URI return FALSE.
+    if (!$position) {
+      return FALSE;
+    }
+    $position += 3;
+  }
 
   // Remove erroneous leading or trailing, forward-slashes and backslashes.
-  return count($data) == 2 ? trim($data[1], '\/') : FALSE;
+  return trim(substr($uri, $position), '\/');
 }
 
 /**
@@ -381,38 +401,38 @@ function file_create_url($uri) {
   // file server.
   drupal_alter('file_url', $uri);
 
-  $scheme = file_uri_scheme($uri);
+  switch (file_uri_scheme($uri)) {
+    case FALSE:
+      // Allow for:
+      // - root-relative URIs (e.g. /foo.jpg in http://example.com/foo.jpg)
+      // - protocol-relative URIs (e.g. //bar.jpg, which is expanded to
+      //   http://example.com/bar.jpg by the browser when viewing a page over
+      //   HTTP and to https://example.com/bar.jpg when viewing a HTTPS page)
+      // Both types of relative URIs are characterized by a leading slash, hence
+      // we can use a single check.
+      if (drupal_substr($uri, 0, 1) == '/') {
+        return $uri;
+      }
+      else {
+        // If this is not a properly formatted stream, then it is a shipped file.
+        // Therefore, return the urlencoded URI with the base URL prepended.
+        return $GLOBALS['base_url'] . '/' . drupal_encode_path($uri);
+      }
 
-  if (!$scheme) {
-    // Allow for:
-    // - root-relative URIs (e.g. /foo.jpg in http://example.com/foo.jpg)
-    // - protocol-relative URIs (e.g. //bar.jpg, which is expanded to
-    //   http://example.com/bar.jpg by the browser when viewing a page over
-    //   HTTP and to https://example.com/bar.jpg when viewing a HTTPS page)
-    // Both types of relative URIs are characterized by a leading slash, hence
-    // we can use a single check.
-    if (drupal_substr($uri, 0, 1) == '/') {
+    case 'http':
+    case 'https':
+    case 'data':
+      // These URIs are already web-accessible.
       return $uri;
-    }
-    else {
-      // If this is not a properly formatted stream, then it is a shipped file.
-      // Therefore, return the urlencoded URI with the base URL prepended.
-      return $GLOBALS['base_url'] . '/' . drupal_encode_path($uri);
-    }
-  }
-  elseif ($scheme == 'http' || $scheme == 'https') {
-    // Check for http so that we don't have to implement getExternalUrl() for
-    // the http wrapper.
-    return $uri;
-  }
-  else {
-    // Attempt to return an external URL using the appropriate wrapper.
-    if ($wrapper = file_stream_wrapper_get_instance_by_uri($uri)) {
-      return $wrapper->getExternalUrl();
-    }
-    else {
-      return FALSE;
-    }
+
+    default:
+      // Attempt to return an external URL using the appropriate wrapper.
+      if ($wrapper = file_stream_wrapper_get_instance_by_uri($uri)) {
+        return $wrapper->getExternalUrl();
+      }
+      else {
+        return FALSE;
+      }
   }
 }
 
diff --git a/modules/simpletest/tests/file.test b/modules/simpletest/tests/file.test
index 55e3b0a..61d9137 100644
--- a/modules/simpletest/tests/file.test
+++ b/modules/simpletest/tests/file.test
@@ -2396,6 +2396,8 @@ class FileDownloadTest extends FileTestCase {
     $this->checkUrl('public', '', $basename, $base_url . '/' . file_stream_wrapper_get_instance_by_scheme('public')->getDirectoryPath() . '/' . $basename_encoded);
     $this->checkUrl('private', '', $basename, $base_url . '/system/files/' . $basename_encoded);
     $this->checkUrl('private', '', $basename, $base_url . '/?q=system/files/' . $basename_encoded, '0');
+
+    $this->assertEqual(file_create_url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='), 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==', t('URL is data URI.'));
   }
 
   /**
@@ -2726,6 +2728,7 @@ class StreamWrapperTest extends DrupalWebTestCase {
 
     // Test file_uri_target().
     $this->assertEqual(file_uri_target('public://foo/bar.txt'), 'foo/bar.txt', t('Got a valid stream target from public://foo/bar.txt.'));
+    $this->assertEqual(file_uri_target('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='), 'image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==', t('Got a valid stream target from a data URI.'));
     $this->assertFalse(file_uri_target('foo/bar.txt'), t('foo/bar.txt is not a valid stream.'));
 
     // Test file_build_uri() and DrupalLocalStreamWrapper::getDirectoryPath().
@@ -2742,6 +2745,7 @@ class StreamWrapperTest extends DrupalWebTestCase {
    */
   function testGetValidStreamScheme() {
     $this->assertEqual('foo', file_uri_scheme('foo://pork//chops'), t('Got the correct scheme from foo://asdf'));
+    $this->assertEqual('data', file_uri_scheme('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='), t('Got the correct scheme \'data\''));
     $this->assertTrue(file_stream_wrapper_valid_scheme(file_uri_scheme('public://asdf')), t('Got a valid stream scheme from public://asdf'));
     $this->assertFalse(file_stream_wrapper_valid_scheme(file_uri_scheme('foo://asdf')), t('Did not get a valid stream scheme from foo://asdf'));
   }
diff --git a/modules/simpletest/tests/theme.test b/modules/simpletest/tests/theme.test
index d548850..30f641b 100644
--- a/modules/simpletest/tests/theme.test
+++ b/modules/simpletest/tests/theme.test
@@ -305,6 +305,28 @@ class ThemeLinksTest extends DrupalWebTestCase {
 }
 
 /**
+ * Unit tests for theme_image().
+ */
+class ThemeImageUnitTest extends DrupalWebTestCase {
+  public static function getInfo() {
+    return array(
+      'name' => 'Theme image',
+      'description' => 'Test the theme_image() function.',
+      'group' => 'Theme',
+    );
+  }
+
+  /**
+   * Test nested list rendering.
+   */
+  function testDataUri() {
+    $expected = '<img typeof="foaf:Image" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" alt="" />';
+    $output = theme('image', array('path' => 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='));
+    $this->assertIdentical($expected, $output, 'Data URI in image tag.');
+  }
+}
+
+/**
  * Functional test for initialization of the theme system in hook_init().
  */
 class ThemeHookInitUnitTest extends DrupalWebTestCase {
