Created
April 28, 2014 02:49
-
-
Save anonymous/11360646 to your computer and use it in GitHub Desktop.
Download handler with the following features: 1. Proper direct link protection
2. Lazy referrer checking
3. Makes sure the file is a real file
4. Semi-proper download count generation
5. File path hack protection (can't use "../" to get system files)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class Controller_Dl extends Controller | |
{ | |
public function action_devs() | |
{ | |
$thisIp = Input::ip(); | |
$thisIp = hash('sha256', $thisIp); | |
if (null !== Input::get('dl')) { | |
$dlpath = Input::get('dl'); | |
if (!empty($dlpath)) { | |
// make sure we received the session uid marker | |
if (null !== Input::get('dluid')) { | |
// the get var is there, is it empty? | |
$sessionUid = Input::get('dluid'); | |
if (empty($sessionUid)) { | |
// it is empty, so throw a 404 | |
Response::redirect('/devs'); | |
} else { | |
// it is not empty, move along | |
$fullpath = DOCROOT . "uploads/devs/$dlpath"; | |
if (strpos($fullpath, '../') !== false) { | |
// we captured a hacking attempt! | |
Response::redirect('/devs'); | |
} else { | |
// ok this is a legitimate request | |
if (file_exists($fullpath)) { | |
// its a real file, so let's validate the session uid marker | |
$sessionUidMarker = Session::get('dluid'); | |
if ($sessionUid != $sessionUidMarker) { | |
// they don't match, throw a 404 error | |
Response::redirect('/devs'); | |
} else { | |
$referrer = Input::referrer(); | |
// they do match, hand over the requested data | |
if (strpos($referrer, 'basketbuild.com') !== false) { | |
// ^ lazy referrer checking, only checks if basketbuild.com is somewhere in the string | |
/* | |
* checking for dupe downloads | |
* | |
* | |
* how it works: | |
* | |
* We first fetch any entries in the database that match both the originating | |
* IP address and the exact matching file path that is being requested. | |
* | |
* If there are any matching entries: | |
* Check the timestamp. Was the last download over 30 seconds ago? If so, | |
* then we can add a new entry. This also fixes a bug where Android | |
* generates dupe download requests; one from the browser, and one from the | |
* Download activity. If the last download was 30 seconds or under ago, then | |
* we hand over the requested data without adding anything to the database. | |
* | |
* If there are not any matching entries: | |
* This is obviously the first time this IP has attempted to download this | |
* file, so we add a new database entry and hand over the requested data. | |
*/ | |
$dupes = Model_Download::find('all', array( | |
'where' => array( | |
'ip' => $thisIp, | |
'filepath' => $fullpath, | |
), | |
'limit' => 1, | |
)); | |
/* | |
* The above code only selects one matching entry, without the limit | |
* it will generate new entries for all entries in the database. It's | |
* a very nasty bug and there is probably a much better way of doing this | |
* but it works. | |
*/ | |
if (!empty($dupes)) { | |
foreach ($dupes as $dupe) { | |
$currTime = time(); | |
$prevTime = $dupe['created_at']; | |
$timeDilation = $currTime - $prevTime; | |
if ($timeDilation > 30) { | |
/* | |
* It's been more than 30 seconds since the last time this file | |
* was downloaded by this IP, so we add a db entry. | |
*/ | |
$dlM = new Model_Download(); | |
$dlM->filepath = $fullpath; | |
$dlM->ip = $thisIp; | |
$dlM->save(); | |
} | |
} | |
} else { | |
/* | |
* This IP has never downloaded this file, so we add a db entry. | |
*/ | |
$dlM = new Model_Download(); | |
$dlM->filepath = $fullpath; | |
$dlM->ip = $thisIp; | |
$dlM->save(); | |
} | |
File::download($fullpath); | |
} else { | |
// bad referrer string, take this!!! | |
Response::redirect('/devs'); | |
} | |
} | |
} else { | |
// the file doesn't exist, throw a 404 page | |
Response::redirect('/devs'); | |
} | |
} | |
} | |
} else { | |
// the dluid wasn't even given, wtf are you doing? | |
Response::redirect('/devs'); | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment