This is the flow of commands on my login page
User loads page
php checks if the ip address is in the db, if not it adds it
php checks in the ip address is blocked in the db, if not it proceeds
if it is blocked the script will proceed to get the time the ip was blocked at from the db and calculate the amount of time left until the user can try to login again. The blockout time is 15minutes.
However the problem is that if the user was blocked at 45-59 minutes past the hour then 45+15= 00(as 60 doesn't come up on the time) and any number between 45 and 60 excluding 45 and 60 will go past the hour so for example if i get blocked out at 11:48 i will be unblocked at 12:03.
The problem, if you haven't already figured out is how do i code the countdown timer so it goes past the hour and doesn't spazz out when it goes past 59minutes.
Also i want to do this in php as i have no need to actually present the time left in real-time.
The current minute is never an issue. You are concerned with the duration since last blocked, not with "what time was that":
block_user.php:
<?php
$now = new DateTime();
write_block_into_database($ip_address, $now->format('Y-m-d H:i:s'));
?>
check_block.php
<?php
$sql = 'SELECT 1 FROM sometable WHERE ip_address=? AND DATE_ADD(blocked_at, INTERVAL 1 HOURS) >= NOW()';
if(get_result($sql, $ip_address)) {
// this address is blocked
} else {
// no recent block found
}
Or, if you want to do the comparison in PHP:
check_locally.php:
<?php
$sql = "SELECT blocked_at FROM sometable WHERE ip_address=?";
$db_row = get_row($sql,$ip_address);
if ($db_row) {
$blocked = new DateTime($db_row->blocked_at);
$blocked->modify('+1 hour');
$now = new DateTime();
if ($blocked >= $now) {
// still blocked
} else {
// was blocked earlier, no more
}
} else {
// not blocked
}
In other words: "if I take the time the IP was blocked and add one hour, is now still before that point in time?"
Example:
blocked at 12:48
checking at 13:10: 12:48 + 1 hour = 13:48, 13:48 >= 13:10, fail
checking at 15:10: 12:48 + 1 hour = 13:48, 13:48 < 15:10, pass
This is what I managed to come up with
$date = new DateTime();
$currentTime = $date->getTimestamp();
$blockTime = "1453494620";//This value will be taken from the mysql db
$timeElapsed = $currentTime - $blockTime;
echo "Current Time: $currentTime";
echo "<br>Block Time: $blockTime <br>";
if ($timeElapsed < 900){
$leftTime = ((900 - $timeElapsed) / 60) + 1;
$DotPosition = (stripos($leftTime, ".")) + 1;
if($DotPosition == 3 || $DotPosition == 2){
$leftTime = substr($leftTime, 0, $DotPosition - 1);
}
if($leftTime == 1){
$minutesString = "minute";
} else $minutesString = "minutes";
echo "<br>You are blocked from trying to login for too many incorrect tries.
<br>Please try again in $leftTime $minutesString.";
} else {
/*for test purpose, here the user will get unblocked on the mysql by updating the
ips blockout field */
echo "<br>You have been unblocked.";
}
Current Time: 1453495488
Block Time: 1453494620
You are blocked from trying to login for too many incorrect tries.
Please try again in 1 minute.
Thank you guys for telling me about UNIX Timestamps. If I knew about them I wouldn't have asked. :)
Related
So I have a php session timer that works but somehow gets bugged out after awhile... this is the code and the console log I got. I'm looking for a fix to this problem, or possibly a different set of code to achieve the same timer effect (as I'm not sure if using session is the best method for a timer)
session_start();
function timer($time) {
//Set the countdown to 120 seconds.
$_SESSION['countdown'] = $time*60;
//Store the timestamp of when the countdown began.
$_SESSION['time_started'] = time();
$now = time();
$timeSince = $now - $_SESSION['time_started'];
$remainingSeconds = abs($_SESSION['countdown'] - $timeSince);
$counter = 0;
$minutes = $remainingSeconds/60;
echo "$minutes minutes countdown starts.".PHP_EOL;
while($remainingSeconds >= 1) {
$now = time();
$timeSince = $now - $_SESSION['time_started'];
if (($timeSince-$counter) >= 60) {
$remainingSeconds = abs($_SESSION['countdown'] - $timeSince);
$counter = $timeSince;
$minutes = $remainingSeconds/60;
echo "$minutes minutes has passed.".PHP_EOL;
}
}
if($remainingSeconds < 1){
session_abort();
return true;
}
}
if($this->timer(30)) {
// do whatever
echo "$time has passed";
}
Here's what happens in the console:
30 minutes countdown starts.
29 minutes has passed.
.... (continue as per pattern)
16 minutes has passed.
15 minutes has passed. (problem occurs here)
8.7166666666667 minutes has passed.
7.7166666666667 minutes has passed.
6.7166666666667 minutes has passed.
.... (continue as per pattern)
0.71666666666667 minutes has passed.
0.28333333333333 minutes has passed.
1.2833333333333 minutes has passed.
2.2833333333333 minutes has passed.
.... (continue as per pattern all the way)
Extra notes: The session timer doesn't always recur this same pattern, there have been times when it ran through the entire 30minutes and managed to echo "$time has passed"; while the bug only occured later on
I haven't run your, but just from reading it I think there are a few things very wrong with it.
Sessions. You're not using them right.
Session values should only be set once, meaning before you do $_SESSION['countdown'] = $time*60; and $_SESSION['time_started'] = time();, you should check if they already exist or not, and only assign if nonexistent. Your current code resets the clock every time the page is refreshed, which defeats the purpose of sessions.
abs. I think you're not using them right either.
You shouldn't abs the remaining seconds all the time. $remainingSeconds = abs($_SESSION['countdown'] - $timeSince); should be allowed to go into negative. Negative remaining seconds mean your timeout has expired / you've missed it! Calling abs means you're effectively letting it go forever if you by any chance miss the exact time of your event. This is the answer to your main problem. Fix this and your counter will stop going to zero and back up again.
You're relying on your code correctly checking every single second. But it doesn't.
The nasty decimals you're getting happen when for some reason your code gets delayed and doesn't correctly check the 60th second, which means your division by 60 is not perfectly round and you get 8.7166666 minutes.
If you start by removing the abs calls and generally try to simplify your code a bit, I believe you'll quickly get it to work as intended.
// Edit 1
This is a very naive, but simplified approach to your problem. I left two different outputs in there for you to pick one.
function timer($time) {
echo "$time minutes countdown starts." . PHP_EOL;
// Save the date in future when the timer should stop
$endTime = time() + $time * 60;
// Keeps track of last full minute to simplify logs
$lastFullMinute = $time;
while(true) {
$timeRemaining = $endTime - time();
if ($timeRemaining <= 0) {
// Time remaining is less than zero, which means we've gone beyond the end date.
// End the loop
return;
}
// Round up!
$minutesRemaining = ceil($timeRemaining / 60);
if ($minutesRemaining != $lastFullMinute) {
// Current "minute" is different than the previous one, so display a nice message
// If you want to show how many minutes are remainig, use this:
echo "$minutesRemaining minutes remaining." . PHP_EOL;
// If you want to show how many minutes have passed, you have to take mintutesRemaining away from the original time
$minutesPassed = $time - $minutesRemaining;
echo "$minutesPassed minutes passed." . PHP_EOL;
$lastFullMinute = $minutesRemaining;
}
}
}
The main way for you to improve it further would be to use the sleep function http://php.net/manual/en/function.sleep.php. Currently the while loop will hog all the CPU by constantly checking if the timer happened, so you should sleep for a few seconds inside.
What do you think of this solution? referenced from above
function timer($time) {
echo "$time minutes countdown starts." . PHP_EOL;
// Save the date in future when the timer should stop
$endTime = time() + $time*60;
while(true) {
sleep(20);
$secondsRemaining = $endTime - time();
if ($secondsRemaining <= 0) {
echo 'Finished';
return true;
}
}
}
We already know that the following code in PHP will log the user out after 5 mins of inactivity.
$timeout = 5*60; // Set timeout minutes
$logout_redirect_url = "index.php"; // Set logout URL
if (isset($_SESSION['start_time'])) {
$elapsed_time = time() - $_SESSION['start_time'];
if ($elapsed_time >= $timeout) {
session_unset();
session_destroy();
header("Location: $logout_redirect_url");
}
}
$_SESSION['start_time'] = time();
I want to implement a modification of the current code and do something like this:
Assume the user logs out when he had 3 minutes left before automatic logout(assuming the time doesn't restart for him after his inactivity for 2 minutes), we keep track of the time he has left by storing it in a DB (MySQL) and later on start reducing from the same 3 minutes after he logs back in. How can i do this?
Track by the time used, not the currentTime/storedTime. Just use those to figure out the time remaining. This is a quick example. There may be some small errors and improvements that can be made. It should be plenty to help you implement a solution.
User visits page:
if (empty($_SESSION['start_time'])) {
$_SESSION['start-time'] = time();
}
$timeLeft = //get time from db
//if there is a value in the db, that is the time left, otherwise, use the max time allowed (new timer)
$timeLeft = (!empty($timeLeft)) ? $timeLeft : $timeAllowed
$timePassed = time() - $_SESSION['start_time'];
if ($timePassed > $timeAllowed) {
//logout
}
Then, when the user leaves:
$timeLeft = $timeAllowed - (time() - $_SESSION['start_time']);
//Store $timeLeft in the database - should be a value like 180 (3 minutes)
How can I countdown for 7 hours from a variable time (I will get time from my table which is inserted with timestamp), after 7 hours from variable time I will update a table.
I need something like that
$time = 2013-05-18 02:00:00 // comes from database
$target = $time + 7hours // time from database +7hours will be 2013-05-18 09:00:00
$until = $target - $time
I need something like below code
if ($until > 0 ) {
echo "you need to wait for $until hours"
} else {
echo "time is ok"; // i will update a table
}
Convert time into string using strtotime($time)+25200 where 7 hour =60*60*7=25200 sec and then check and also add this file to your cron job.
So, considering that $database_time is the stored time, in your db, and $time_now is your computers time, this message below, just echoed out:
You Must wait 4 hours right, now
It could be done much better, but still calculates the hours from now, to db and tells you how much more, you must wait :)
<?php
$date = date_create();
$database_time = '2013-05-18 22:00:00';
$time_now = date_format($date, 'Y-m-d H:i:s');
$check = $database_time[11];
$check .= $database_time[12];
$check2 = $time_now[11];
$check2 .= $time_now[12];
$time_left = $check - $check2;
So, here is how you can manage your ourputs
if($time_left > 0) {
echo "You Must wait $time_left hours right, now";
}else{
echo "Time is OK";
}
i need a script that automatically add a random number (between 1 and 5) every 24 hours and stores it in a text file, then after 24 hours creates a new random number and adds it to the previous result in the text file, i managed to do something close but still needs a refresh button to take effect, but i want it to automatically do it, so if 1 user visits the page every day, and one visits the page once a month, they should both see the same number (which will be read from the text file).
Here is my code so far:
<?php
$dataFile = "amt.txt";
$date1 = date("H:i:s");
$date2 = date("H:i:s",filemtime("amt.txt"));
$diff = abs(strtotime($date2) - strtotime($date1));
$secs = floor($diff);
if ($diff < 86400) {
echo "$date1 \n";
echo "$date2 \n";
printf($secs);
exit;
}
if (!file_exists($dataFile)) {
$amt = 0;
}
else {
// Otherwise read the previous value from
// the file.
$amt = (int) file_get_contents($dataFile);
}
// Generate the new value...
$Number = rand(1,5);
$total = $amt + $Number;
echo "$". $total ."/-";
// And dump it back into the file.
if (!file_put_contents($dataFile, $total)) {
// If it fails to write to the fle, you'll
// want to know about it...
echo "Failed to save the new total!";
}
?>
basically i want to show a fake number of subscribers which logically should increase with time. So i want to update the number on daily basis, then because i am having this on my website as the number of monthly subscribers, so when a user visits the website any time should see the same figure as any other user visitng the website on that exact time. Hope this is clearer now.
I'd first use time() instead date(xxx) so you get the diff secodns directly. But i don't get the purpose of this and don't know if you want to append the numbers or overwrite them, and also if the number changes every 24h why a user a month later should get the same number.
$date1 = time();
$date2 = filemtime("amt.txt");
$diff = $date1 - $date2;
if ($diff < 86400)
{
echo "$date1 \n";
echo "$date2 \n";
printf($diff);
exit;
}
I'm designing a website where there is a little game going on. Each user that participates has 99 minutes to complete it otherwise we display a game over state. Here is what I managed to do so far using jQuery post.
I've been able to display the timer. In the PHP I've set the target time to 99*60 seconds but I cant set the starting time to 0 as I'll do the difference beteen those to values for the countdown.
Furthermore, as each user is able to quit the page I want to be able to store the time when they left. All I am able to do is store the countdown value, let's say 5845, in the DB when they log off. Though I tried updating the table with each call to the jQuery post, it just makes it worse.
Here is my jQuery:
function countdown() {
var i = (new Date().getTime() / 1000) + (99 * 60);
setTimeout(function () {
$.post(\'countdown.php\',{target:i},function(data){
$('#countdown').html(data);
});
countdown();
},1000);
}
countdown();
Here is the PHP:
if (!empty($resm['Countdown']) || $resm['Countdown'] >= 0) {
$target = (99 * 60);
$countdown = ($target - $current);
$_SESSION['currenttime'] = $countdown;
$hours = floor($countdown / 3600);
$min = floor($countdown / 60);
$r_min = floor(($countdown - ($hours * 3600)) / 60);
$sec = floor($countdown - ($min * 60));
if ($min == 0) {
echo $target.' '.$current.' '.$countdown;
echo '<br/>'.$min.' minutes '.$sec.' seconds left';
} else {
echo 'Time Over';
$sql = "UPDATE bs10000099 SET Upgradedlevel='2',Activated='2',Countdown='5940' WHERE MemberID='$memberid'";
mysql_query($sql);
}
}
I cant figure out how to set the starting time or how to prevent countdown() restart on refresh page.
I'm not sure what kind of security you want, but getting time from Javascript is not really secure since JS gets the time from the computer instead of the server.
With your example, I would be able to play the game, wait until there's 10 minute left, and just roll back time on my desktop and it will reset. Or roll back a year and have 100000 minutes left!
I suggest you use server time.
Here is what I would do:
When the test starts, get the UNIX time + 90 minutes. This will give you the final time.
PHP
if (!isset($_SESSION['end'])) {
$_SESSION['end'] = strtotime("+90 minutes");
}
$remaining = $_SESSION['end'] - time();
if ($remaining > 0) {
echo json_encode(array(
"remaining" => $remaining
));
} else {
// finished! write code here.
}
You can then do a simple $.getJSON() to get the remaining seconds and display it.
Since you kept the "end" time, even if the users leave, the timer will continue.