Commit f394a34c by Scott

Allow cache files inside web root

Cache files now use PHP to avoid being readable. We also prevent access with .htaccess (for the common Apache setup).
parent 618a5039
# Ignore config file in development # Ignore config file in development
qa-config.php qa-config.php
qa-cache/*/
# Other files # Other files
.DS_Store .DS_Store
...@@ -9,5 +10,4 @@ qa-config.php ...@@ -9,5 +10,4 @@ qa-config.php
.Trashes .Trashes
ehthumbs.db ehthumbs.db
Thumbs.db Thumbs.db
.idea/ .idea/
...@@ -86,10 +86,10 @@ ...@@ -86,10 +86,10 @@
*/ */
/* /*
If you wish to use caching, you must define QA_CACHE_DIRECTORY to store the cache files. The If you wish to use file-based caching, you must define QA_CACHE_DIRECTORY to store the cache
directory must be writable by the web server. It also must be OUTSIDE the public root. For files. The directory must be writable by the web server. For maximum security it's STRONGLY
example if your site resides in '/var/www/yoursite/public_html', then the cache directory could recommended to place the folder outside of the web root (so they can never be accessed via a
be '/var/www/yoursite/qa-cache', but it cannot be '/var/www/yoursite/public_html/qa-cache'. web browser).
define('QA_CACHE_DIRECTORY', '/path/to/writable_cache_directory/'); define('QA_CACHE_DIRECTORY', '/path/to/writable_cache_directory/');
*/ */
......
...@@ -30,6 +30,8 @@ class Q2A_Storage_FileCacheDriver implements Q2A_Storage_CacheDriver ...@@ -30,6 +30,8 @@ class Q2A_Storage_FileCacheDriver implements Q2A_Storage_CacheDriver
private $error; private $error;
private $cacheDir; private $cacheDir;
private $phpProtect = '<?php header($_SERVER[\'SERVER_PROTOCOL\'].\' 404 Not Found\'); die; ?>';
/** /**
* Creates a new FileCache instance and checks we can write to the cache directory. * Creates a new FileCache instance and checks we can write to the cache directory.
* @param array $config Configuration data, including cache storage directory. * @param array $config Configuration data, including cache storage directory.
...@@ -46,12 +48,8 @@ class Q2A_Storage_FileCacheDriver implements Q2A_Storage_CacheDriver ...@@ -46,12 +48,8 @@ class Q2A_Storage_FileCacheDriver implements Q2A_Storage_CacheDriver
if (isset($config['dir'])) { if (isset($config['dir'])) {
$this->cacheDir = realpath($config['dir']); $this->cacheDir = realpath($config['dir']);
if (!is_writable($this->cacheDir)) { if (!is_writable($this->cacheDir)) {
$this->error = qa_lang_html_sub('admin/caching_dir_error', $config['dir']); $this->error = qa_lang_html_sub('admin/caching_dir_error', $config['dir']);
} elseif (strpos($this->cacheDir, realpath($_SERVER['DOCUMENT_ROOT'])) === 0 || strpos($this->cacheDir, realpath(QA_BASE_DIR)) === 0) {
// check the folder is outside the public root - checks against server root and Q2A root, in order to handle symbolic links
$this->error = qa_lang_html_sub('admin/caching_dir_public', $config['dir']);
} }
} else { } else {
$this->error = qa_lang_html('admin/caching_dir_missing'); $this->error = qa_lang_html('admin/caching_dir_missing');
...@@ -77,6 +75,7 @@ class Q2A_Storage_FileCacheDriver implements Q2A_Storage_CacheDriver ...@@ -77,6 +75,7 @@ class Q2A_Storage_FileCacheDriver implements Q2A_Storage_CacheDriver
if (is_readable($file)) { if (is_readable($file)) {
$lines = file($file, FILE_IGNORE_NEW_LINES); $lines = file($file, FILE_IGNORE_NEW_LINES);
$skipLine = array_shift($lines);
$actualKey = array_shift($lines); $actualKey = array_shift($lines);
// double check this is the correct data // double check this is the correct data
...@@ -114,7 +113,7 @@ class Q2A_Storage_FileCacheDriver implements Q2A_Storage_CacheDriver ...@@ -114,7 +113,7 @@ class Q2A_Storage_FileCacheDriver implements Q2A_Storage_CacheDriver
if ($this->enabled && $ttl > 0) { if ($this->enabled && $ttl > 0) {
$encData = serialize($data); $encData = serialize($data);
$expiry = time() + ($ttl * 60); $expiry = time() + ($ttl * 60);
$cache = $fullKey . "\n" . $expiry . "\n" . $encData; $cache = $this->phpProtect . "\n" . $fullKey . "\n" . $expiry . "\n" . $encData;
$file = $this->getFilename($fullKey); $file = $this->getFilename($fullKey);
$dir = dirname($file); $dir = dirname($file);
...@@ -279,6 +278,6 @@ class Q2A_Storage_FileCacheDriver implements Q2A_Storage_CacheDriver ...@@ -279,6 +278,6 @@ class Q2A_Storage_FileCacheDriver implements Q2A_Storage_CacheDriver
private function getFilename($fullKey) private function getFilename($fullKey)
{ {
$filename = sha1($fullKey); $filename = sha1($fullKey);
return $this->cacheDir . '/' . substr($filename, 0, 1) . '/' . substr($filename, 1, 2) . '/' . $filename; return $this->cacheDir . '/' . substr($filename, 0, 1) . '/' . substr($filename, 1, 2) . '/' . $filename . '.php';
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment