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