From 5e08e5ed806ec1adb3164d05fa30c4cee55bd7df Mon Sep 17 00:00:00 2001 From: Mikael Roos Date: Mon, 19 Jan 2015 00:00:54 +0100 Subject: [PATCH] Enable in config to disallow hotlinking/leeching #46 --- CImage.php | 2 +- README.md | 1 + webroot/img.php | 77 ++++++++++++++++++++++++++++++++++-------- webroot/img_config.php | 22 ++++++++++++ 4 files changed, 86 insertions(+), 16 deletions(-) diff --git a/CImage.php b/CImage.php index 47da6f0..137e700 100644 --- a/CImage.php +++ b/CImage.php @@ -2158,7 +2158,7 @@ class CImage $res = link($this->cacheFileName, $alias); if ($res) { - $this->log("Created an alias to the cachefile: $alias"); + $this->log("Created an alias as: $alias"); } else { $this->log("Failed to create the alias: $alias"); } diff --git a/README.md b/README.md index 7beca2a..d1cef60 100644 --- a/README.md +++ b/README.md @@ -280,6 +280,7 @@ Revision history v0.6.x (latest) +* Disallow hotlinking/leeching by configuration #46. * Alias-name is without extension #47. * Option `alias` now requires `password` to work #47. * Support for option `password, pwd` to protect usage of `alias` and remote download. diff --git a/webroot/img.php b/webroot/img.php index f165a01..137371d 100644 --- a/webroot/img.php +++ b/webroot/img.php @@ -143,6 +143,68 @@ $verbose = getDefined(array('verbose', 'v'), true, false); +/** + * Check if passwords are configured, used and match. + * Options decide themself if they require passwords to be used. + */ +$pwdConfig = getConfig('password', false); +$pwd = get(array('password', 'pwd'), null); + +// Check if passwords match, if configured to use passwords +$passwordMatch = null; +if ($pwdConfig && $pwd) { + $passwordMatch = ($pwdConfig == $pwd); +} + +verbose("password match = $passwordMatch"); + + + +/** + * Prevent hotlinking, leeching, of images by controlling who access them + * from where. + * + */ +$allowHotlinking = getConfig('allow_hotlinking', true); +$hotlinkingWhitelist = getConfig('hotlinking_whitelist', array()); + +$serverName = isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : null; +$referer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : null; +$refererHost = parse_url($referer, PHP_URL_HOST); + +if (!$allowHotlinking) { + if ($passwordMatch) { + ; // Always allow when password match + } else if ($passwordMatch === false) { + errorPage("Hotlinking/leeching not allowed when password missmatch."); + } else if (!$referer) { + errorPage("Hotlinking/leeching not allowed and referer is missing."); + } else if (strcmp($serverName, $refererHost) == 0) { + ; // Allow when serverName matches refererHost + } else if (!empty($hotlinkingWhitelist)) { + + $allowedByWhitelist = false; + foreach ($hotlinkingWhitelist as $val) { + if (preg_match($val, $refererHost)) { + $allowedByWhitelist = true; + } + } + + if (!$allowedByWhitelist) { + errorPage("Hotlinking/leeching not allowed by whitelist."); + } + + } else { + errorPage("Hotlinking/leeching not allowed."); + } +} + +verbose("allow_hotlinking = $allowHotlinking"); +verbose("referer = $referer"); +verbose("referer host = $refererHost"); + + + /** * Get the source files. */ @@ -165,21 +227,6 @@ $img->setVerbose($verbose); -/** - * Check if passwords are configured, used and match. - * Options decide themself if they require passwords to be used. - */ -$pwdConfig = getConfig('password', false); -$pwd = get(array('password', 'pwd'), null); - -// Check if passwords match, if configured to use passwords -$passwordMatch = null; -if ($pwdConfig) { - $passwordMatch = ($pwdConfig == $pwd); -} - - - /** * Allow or disallow remote download of images from other servers. * Passwords apply if used. diff --git a/webroot/img_config.php b/webroot/img_config.php index 5bd3c55..e4e0b1b 100644 --- a/webroot/img_config.php +++ b/webroot/img_config.php @@ -164,6 +164,28 @@ return array( */ + + /** + * Prevent leeching of images by controlling who can access them from where. + * Default it to allow hotlinking. + * Password apply when hotlinking is disallowed, use password to allow. + * The whitelist is an array of regexpes for allowed hostnames that can + * hotlink images. + * + * Default values. + * allow_hotlinking: true + * hotlinking_whitelist: array() + */ + /* + 'allow_hotlinking' => false, + 'hotlinking_whitelist' => array( + '#^localhost$#', + '#^dbwebb\.se$#', + ), + */ + + + /** * Create custom shortcuts for more advanced expressions. *