Skip to content

Commit

Permalink
Allow cache files inside web root
Browse files Browse the repository at this point in the history
Cache files now use PHP to avoid being readable. We also prevent access with .htaccess (for the common Apache setup).
  • Loading branch information
svivian committed Dec 22, 2017
1 parent 618a503 commit f394a34
Show file tree
Hide file tree
Showing 4 changed files with 11 additions and 11 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Ignore config file in development
qa-config.php
qa-cache/*/

# Other files
.DS_Store
Expand All @@ -9,5 +10,4 @@ qa-config.php
.Trashes
ehthumbs.db
Thumbs.db

.idea/
1 change: 1 addition & 0 deletions qa-cache/.htaccess
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Deny from all
8 changes: 4 additions & 4 deletions qa-config-example.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,10 @@
*/

/*
If you wish to use caching, you must define QA_CACHE_DIRECTORY to store the cache files. The
directory must be writable by the web server. It also must be OUTSIDE the public root. For
example if your site resides in '/var/www/yoursite/public_html', then the cache directory could
be '/var/www/yoursite/qa-cache', but it cannot be '/var/www/yoursite/public_html/qa-cache'.
If you wish to use file-based caching, you must define QA_CACHE_DIRECTORY to store the cache
files. The directory must be writable by the web server. For maximum security it's STRONGLY
recommended to place the folder outside of the web root (so they can never be accessed via a
web browser).
define('QA_CACHE_DIRECTORY', '/path/to/writable_cache_directory/');
*/
Expand Down
11 changes: 5 additions & 6 deletions qa-include/Q2A/Storage/FileCacheDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ class Q2A_Storage_FileCacheDriver implements Q2A_Storage_CacheDriver
private $error;
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.
* @param array $config Configuration data, including cache storage directory.
Expand All @@ -46,12 +48,8 @@ public function __construct($config)

if (isset($config['dir'])) {
$this->cacheDir = realpath($config['dir']);

if (!is_writable($this->cacheDir)) {
$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 {
$this->error = qa_lang_html('admin/caching_dir_missing');
Expand All @@ -77,6 +75,7 @@ public function get($key)

if (is_readable($file)) {
$lines = file($file, FILE_IGNORE_NEW_LINES);
$skipLine = array_shift($lines);
$actualKey = array_shift($lines);

// double check this is the correct data
Expand Down Expand Up @@ -114,7 +113,7 @@ public function set($key, $data, $ttl)
if ($this->enabled && $ttl > 0) {
$encData = serialize($data);
$expiry = time() + ($ttl * 60);
$cache = $fullKey . "\n" . $expiry . "\n" . $encData;
$cache = $this->phpProtect . "\n" . $fullKey . "\n" . $expiry . "\n" . $encData;

$file = $this->getFilename($fullKey);
$dir = dirname($file);
Expand Down Expand Up @@ -279,6 +278,6 @@ private function deleteFile($file)
private function getFilename($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';
}
}

0 comments on commit f394a34

Please sign in to comment.