diff --git a/.htaccess.sample b/.htaccess.sample
index d6ad2fdfb4baddc26a432bc6df73fb6464f00a6e..e60c87bfb9f5d3cc749bd3ca3916069e91a0c468 100644
--- a/.htaccess.sample
+++ b/.htaccess.sample
@@ -113,6 +113,13 @@ DirectoryIndex index.php index.html index.htm
   # uncomment the following line:
   # RewriteBase /
 
+  # Allow public files to be accessed without the sites/<site_dir>/files prefix
+  # The following line must be added to your apache configuration for this context:
+  # RewriteMap drupal prg:<DRUPAL_ROOT>/rewrite.php
+  # Do not uncomment the previous line.  Only the next two.
+  # RewriteCond %{REQUEST_FILENAME} !-f
+  # RewriteRule (.*) ${drupal:%{HTTP_HOST};delim;%{REQUEST_URI};delim;$1}
+
   # Pass all requests not referring directly to files in the filesystem to
   # index.php. Clean URLs are handled in drupal_environment_initialize().
   RewriteCond %{REQUEST_FILENAME} !-f
diff --git a/README-UNL.txt b/README-UNL.txt
index 8c82f47ba0f8519c20bbfd52fd9aaf3b4c808306..831fed24b93e69eb008eb42ed398396b451f2f5a 100644
--- a/README-UNL.txt
+++ b/README-UNL.txt
@@ -11,3 +11,8 @@ function drush_core_site_install_version()
  * UNL change! Setting this to FALSE because we don't want them and they're hard coded.
 
 ------------------------------------
+
+rewrite.php
+used to allow public files to be accessed without the sites/<site_dir>/files prefix
+
+------------------------------------
diff --git a/rewrite.php b/rewrite.php
new file mode 100755
index 0000000000000000000000000000000000000000..a7fe56ebbc4064186dd071dad85384698528d91d
--- /dev/null
+++ b/rewrite.php
@@ -0,0 +1,89 @@
+#!/usr/bin/php
+<?php
+
+define('DRUPAL_ROOT', getcwd());
+
+require_once DRUPAL_ROOT . '/includes/unl_bootstrap.inc';
+require_once DRUPAL_ROOT . '/includes/bootstrap.inc';
+
+$stdin = fopen('php://stdin', 'r');
+$cache = new RewriteCache();
+
+// Each mapping request is on its own line.
+while ($line = fgets($stdin)) {
+  // Remove the trailing newline
+  $line = trim($line, "\n");
+  
+  // Check for this result in the cache
+  if (!($output = $cache->get($line))) {
+  
+    // Parse the 3 fields.
+    list($host, $uri, $path) = explode(';delim;', $line);
+    
+    // Get the base path of the drupal install
+    $base_path = substr($uri, 0, strlen($uri) - strlen($path));
+    
+    // Set up some _SERVER variables as if this was a HTTP request.
+    $_SERVER['SCRIPT_NAME'] = $base_path . 'index.php';
+    $_SERVER['SCRIPT_FILENAME'] = DRUPAL_ROOT . '/index.php';
+    $_SERVER['REQUEST_URI'] = $uri;
+    $_SERVER['HTTP_HOST'] = $host;
+    
+    // Call the UNL bootstrap to fix conf_path and SCRIPT_NAME
+    unl_bootstrap();
+    $site_dir = conf_path();
+    $base_path = substr($_SERVER['SCRIPT_NAME'], 0, -9);
+    // Now we fix the drupal path.
+    $drupal_path = substr($uri, strlen($base_path));
+    
+    // Finally, generate the path to the file we might be accessing
+    $file_path = $site_dir . '/files/' . $drupal_path;
+    
+    // If that file exists, return the correct path to it, otherwise, return what we were given. 
+    if (is_file($file_path)) {
+      $output = $file_path;
+    }
+    else {
+      $output = 'NULL';
+    }
+    
+    $cache->set($line, $output);
+  }
+  
+  echo $output . PHP_EOL;
+}
+
+
+// A basic in-memory cache that with a Least Recently Used expiration policy with a limitted number of entries.
+class RewriteCache {
+  protected $_storage;
+  protected $_cache_size;
+  protected $_lifetime;
+  
+  function __construct($cache_size = 1000, $lifetime = 30) {
+    $this->_storage = array();
+    $this->_cache_size = $cache_size;
+    $this->_lifetime = $lifetime;
+  }
+  
+  function get($key) {
+    if (isset($this->_storage[$key])) {
+      $entry = $this->_storage[$key];
+      unset($this->_storage[$key]);
+      
+      // If the entry isn't expired, promote it to the front and return it.
+      if ($entry['time'] + $this->_lifetime > time()) {
+        $this->_storage[$key] = $entry;
+        return $entry['data'];
+      }
+    }
+    return FALSE;
+  }
+  
+  function set($key, $value) {
+    if (count($this->_storage) >= $this->_cache_size) {
+      array_shift($this->_storage);
+    }
+    $this->_storage[$key] = array('time' => time(), 'data' => $value);
+  }
+}
\ No newline at end of file