Reputation: 4478
Sorry for the vague, title! I have a website with a lot of PDF files and limited monthly bandwith. What i would like to achieve (in PHP) is a way to limit each user ($_SESSION
?) to a certain limit - say 50MB, and beyond that when they clicked to download another file they would be redirected to a webpage denying any further downloads (for the next 24 hours, say).
Is this possible? I'm not sure if my download "counter" can only count .pdf
files (I dont want vistors to be blocked from browsing the site if they reach the limit). Any psuedo code would be greatly appreciated.
Upvotes: 3
Views: 4622
Reputation: 594
Create a table to store count downloads
CREATE TABLE IF NOT EXISTS `downloaded` (
`ip` varchar(200) NOT NULL,
`count` int(11) NOT NULL DEFAULT '0',
`last_access` datetime DEFAULT NULL,
UNIQUE KEY `ip` (`ip`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
<?php
/*
$limit => Number of Downloads Allowed
$period => In minutes
*/
function UserHasReachedLimit($limit, $period) {
$ip = addslashes($_SERVER['REMOTE_ADDR']);
$dl = false;
$sql = sprintf("SELECT UNIX_TIMESTAMP(last_access) last_time, count FROM downloaded WHERE ip = '%s' ORDER BY last_access DESC", $ip);
$res = mysql_query($sql);
if (mysql_num_rows($res) > 0) { // There is a registered IP already
$last_xs = mysql_result($res, 0, 'last_time');
$last_xs += $last_xs+$period * 60;
$count = mysql_result($res, 0, 'count'); // number of downloads by this ip
if ($count == $limit && $last_xs > time()) { // we check if downloads reached in this period
$dl = true;
} else {
$sql = sprintf("UPDATE downloaded SET count = CASE WHEN count >= %s THEN 0 ELSE count+1 END, last_access=now() WHERE ip ='%s'", $limit+1, $ip); // we just update download count + 1
mysql_query($sql);
}
} else { // There is not a registered IP and we create it
$sql = sprintf("INSERT INTO downloaded VALUES ('%s', '0', NOW());", $ip); mysql_query($sql);
}
return $dl;
}
/*
Usage
*/
$limit = 2;
$period = 2;
if(UserHasReachedLimit($limit, $period) == true) {
// User reached number of 2 downloads in 2 minutes
} else {
// Continue downloading
}
?>
Upvotes: 0
Reputation: 5705
I think you are trying to avoid forcing user to register in your site, while you are trying to track per visitor bandwidth with is unpractical with the common ways(cookies, ip ...). So, the best way(in my opinion, of course there are many improved solutions) is to make a simple registration form, say name, password and email, put an activation system per email to protect your site from of user, now each user logged in and tried to download a file, you process his request in the following steps:
1) user request for file name.pdf (check its availability and size(important)).
2) check user bandwidth:
$query = sql_query("SELECT Bandwidth, LastDownload FROM Users, Stats WHERE USER_ID=5");
$result = sql_fetch($query);
if ($result['Bandwidth'] < 50M)
showDownloadLink();
else if($result['LastDownload'] - currentTime() !=0)
echo "please wait to the next 24h";
Database should be like this: Users:
ID_U int(key, auto increment), Name varchar(25), email varchar(255), password varchar(32), Bandwith float
Stats:
ID_S int(key, auto increment), LastDownload time, ID_U integer
Note: Each time user download a file, you update Bandwidth row for the right user, so later you can check if particular user reach its limit or not. You have also to reset it after each 24H.
This is a generic solution and many thinks have to be checked, like the counter bandwidth must be reset every 24H.
Upvotes: 0
Reputation: 29434
If you already have a user system, I would recommend to store all information within the users profile.
So there's no problem if he deletes all his cookies and relogins!
And for guests, I would recommend captchas and session or IP based restrictions.
// Pseudo code
// download.php
function UserHasReachedLimit($file)
{
$info = $Database->QueryUserInfo('limit');
$max = $Database->GetLimitForFile($file);
if ( $info[$file] > $max )
return false;
else
return true;
}
if ( IsUser() )
{
if ( UserHasReachedLimit() )
error();
else
download();
}
else // guest
{
// session or IP based restrictions...
}
Upvotes: 2
Reputation: 19999
I'd probably stay away from sessions for this. Sessions are volatile and susceptible to various browser behavior. For example, in Firefox if a session is initialized, I can close Firefox, visit the same site, and session is still active. However in IE if I open up multiple tabs and visit the same site, each tabbed instance gets a new session id.
I'd recommend setting up an account system where a user has to log into your site. Then you can track their download amount at the account level, which will persist between multiple sessions.
Upvotes: 0
Reputation: 3627
If you have all of your downloads go through a single php script:
<a href="download.php?file='filename.pdf'" />
You can do pretty much whatever you want. That php file can deliver all of your files (keeping them out of the webroot), write to your _SESSION, and it can perform your redirect. Enjoy.
Upvotes: 5