post throttling using php mysql and an epoch timestamp not functioning - php

I'm trying to throttle posts by users via php, mysql, and an epoch timestamp in my database stored in the row timestamp (ex: 1406059107).
My script executes as intended the first time and throttles the user for 60 seconds, but after that I can literally flood the server with posts since the throttling stops functioning.
I tried using ASC instead of DESC without success.
$sql = "SELECT timestamp FROM phpbb_schedule WHERE username = " . (int) $user->data['user_id'] . " ORDER BY timestamp DESC";
$result = $db->sql_query_limit($sql, 1);
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
if (time() - $row['timestamp'] < 60)
{
header( 'Location: someurl.php' );
die ('Your can only input one request every 60 seconds.');
}
else
{
echo 'success some other code goes here that inputs the data into the db and redirects this to another page';
}
Note: The issue has been resolved I didn't use ORDER by timestamp and a syntax error had occurred (see comments).

Related

How would I go about timing between status changes in php?

When the status changes to prepare/preparing, the timer begins. I then want to stop the timer and calculate the difference when the status changes to ready, and store it as time in the database. Ive tried various ways but can't seem to get it working, what am I doing wrong? Thanks
if(isset($_POST['prepare'])){
$_SESSION['startTime'] = time();
$question2="UPDATE `order` SET orderStatus='Preparing', idEmployee='$_SESSION[id]' WHERE idorder='$_POST[id]'";
$sth = $db->prepare($question2);
$sth->execute();
}
if(isset($_POST['ready'])){
$total = time() - $_SESSION['startTime'];
echo date('h:i:s', $total);
$question2="UPDATE `order` SET orderStatus='Completed', timeCompleted='$total' WHERE idorder='$_POST[id]'";
$sth = $db->prepare($question2);
$sth->execute();
}
edit: I overcame the issues I was having by simply using a method within the DateTime class. I began by recording the time from when the order was taken, I also recorded the time of when the order was completed. I then used the method diff() to calculate the difference between the 2 recorded times and stored the results in my db.
if(isset($_POST['prepare'])){
$_SESSION['startTime'] = new DateTime();
$question2="UPDATE `order` SET orderStatus='Preparing', idEmployee='$_SESSION[id]' WHERE idorder='$_POST[prepare]'";
$sth = $db->prepare($question2);
$sth->execute();
}
if(isset($_POST['ready'])){
$endTime = new DateTime();
$i = $_SESSION['startTime']->diff($endTime);
$end = $i->format('%h:%i:%s');
$question2="UPDATE `order` SET orderStatus='Completed', timeCompleted='$end' WHERE idorder='$_POST[ready]'";
$sth = $db->prepare($question2);
$sth->execute();
}
Replace $total = time() - $_SESSION['startTime'] with $total = time() - strtotime($_SESSION['startTime'])
And add session_start(); to the top of your code if you didn't
Then it will work.
If both prepare and ready are actioned on the same machine by the same person (within the same session) - this code should work. If you believe all this to be true - I would check to make sure the session variables are being set print_r($_SESSION)
However, I would recommend when you update orderStatus to 'Preparing', creating a new column called timeStarted and update that to time(), then when you are updating to 'Completed' set timecompleted also to time()
You can then easily work out the difference, as currently (if this code did work timeCompleted is actually timeTaken) - for which you could even add a 3rd column which is the difference between the two for easy reporting.
Doing it this way means if it takes longer than the session or the computer restarts / re login the startTime is not lost

php !isset and empty not working

Pulling my hair out on this, it has to be obvious, but I can't see it today.
I built a small monitoring tool for an app we have. I want to do a check in the DB to make sure the backend scripts are working and the data isn't stale by more than 15 min. When no records are returned in a certain timeframe it should pop up a message saying to check the script. If they are not returned it should be an empty dataset and I should get a message on it.
Problem is, I can't get empty() or !isset to work. Actually regardless of whether I use !empty(), empty(), isset() or !isset(), my $tripped variable never gets tripped. I have this working for other alerts, but this one seems to be stubborn and I don't see what I'm missing.
PS I know mysql_ is out of date.
The relevant piece of code:
$ldap_check = mysql_query("SELECT
*
FROM ldap_conns
WHERE DATETIME > DATE_SUB(NOW(), INTERVAL 15 MINUTE)
order by DATETIME DESC
LIMIT 1");
while($row = mysql_fetch_array($ldap_check))
{
if (empty($row['DATETIME']))
{
echo '<b><font color=blue>Stale Data: </font> <font color=red>LDAP data is old, check script!</font><br>' . $row['DATETIME'];
$tripped='Yes';
}
}
if ($tripped!='Yes')
{
echo '<b><font color=blue>Stale Data: ' . $row['DATETIME'] . '</font></b> <font color=green> No Problems Found<br></font>';
}
You are doing it wrong... Want just check if there exists any old items? Use count! There is no reason for selectin g ALL fields from ALL records from the table. This is wrong using of database! Use count, and make index on DATETIME field!
$result = mysql_query("SELECT
count(*) old_items
FROM
ldap_conns
WHERE
DATETIME < DATE_SUB(NOW(), INTERVAL 15 MINUTE)");
$row = mysql_fetch_row($result);
if ($row['old_items']) {
echo 'There is '.$row['old_items'].' old items!';
}
You have this condition in your query:
WHERE DATETIME > DATE_SUB(NOW(), INTERVAL 15 MINUTE)
So I don't see how $row['DATETIME'] could ever be empty for any of the rows fetched (although you are actually only fetching one row...).

PHP: Online Offline Status

Hi since 3 hour I am trying to make this work but not getting the result as I want. I want to display user list with online and offline status.
Here is the table
and here what I tried to get status result.
$loggedtime = time() - 300; // 5 minutes
$query = 'SELECT userid, handle FROM ^users WHERE loggedin = '.$loggedtime.' ORDER BY userid ASC';
// below are scripts function qa_ pleses refer this http://www.question2answer.org/functions.php
$result = qa_db_query_sub($query);
$users = qa_db_read_all_assoc($result);
$row = mysql_fetch_array($result);
if($row['userid'] > $loggedtime){
echo $row['handle'].' is online';
} else {
echo $row['handle'].' is offline';
}
NOT THIS TOO
foreach($users as $user){
if($user['userid'] > $loggedtime){
echo $user['handle']. ' is online';
} else {
echo $row['handle'].' is offline';
}
}
None of above code working. I am new to MYSQL and PHP just know basic so please help me to solve this.
EDIT:
I have tried now this but not working
foreach($users as $user){
if($user['loggedin'] > $loggedtime){
echo $user['handle']. ' is online';
} else {
echo $row['handle'].' is offline';
}
}
EDIT 2
$query = "SELECT
userid, handle,
CASE
WHEN TIMESTAMPDIFF(SECOND, loggedin, NOW()) < 300
THEN 'Online'
ELSE 'Offline'
END AS 'status'
FROM ^users
ORDER BY userid";
$result = qa_db_query_sub($query);
while($user = mysql_fetch_array($result)){
echo $user['handle'] . '<BR/>';
}
NEW APPROACH
Please check this for new approach User online offline status - offline status issue
Since you fixed the user id comparison, let's address the next issue..
You're trying to compare a string DATE versus a unix timestamp. Let's make them the same type and compare:
foreach($users as $user)
{
$user_time = strtotime($user['loggedin']);
if($user_time > $loggedtime)
{
echo $user['handle']. ' is online';
} else {
echo $row['handle'].' is offline';
}
}
Overall not the best way to approach this problem, but it might get this working for you. The database solution above is probably best.
Your structure looks funny to answer the question. Your loggedin field actually looks more like a "the last time they logged in". Just because you know when they logged in doesn't necessarily mean they are "online".
The reason your query isn't working is because you are comparing a UNIX timestamp to a mysql datetime. In addition, you are using = so unless they logged in EXACTLY five minutes ago, this will not work.
At minimum.
SELECT userid, handle FROM ^users WHERE loggedin > '.date('Y-m-d h:i:s', time()-300).'ORDER BY....
Why not just check on the database side?
SELECT
userid, handle,
CASE
WHEN TIMESTAMPDIFF(SECOND, loggedin, NOW()) < 300
THEN 'Online'
ELSE 'Offline'
END AS 'status'
FROM ^users
ORDER BY userid
You can use TIMESTAMPDIFF(unit,datetime_expr1,datetime_expr2) to return datetime_expr2 – datetime_expr1, where datetime_expr1 and datetime_expr2 are date or datetime expressions. One expression may be a date and the other a datetime; a date value is treated as a datetime having the time part '00:00:00' where necessary. The unit for the result (an integer) is given by the unit argument. The legal values for unit are the same as those listed in the description of the TIMESTAMPADD() function.
Take a look at the MySQL Date and Time Functions.
Also, I strongly advise using reserved words for table names.

Preventing the same IP from executing an action for 24 hours

So I've been programming this thing that allows a user to click a button once every 24 hours and is blocked to do so in the meantime. The concrete example is a vote script that should only allow a vote every 24 hours (albeit a user can vote for the same thing again).
So what I did was create a timelimit table in MySql
CREATE TABLE IF NOT EXISTS `timelimit` (
`ipaddress` VARCHAR(50) NOT NULL ,
`ipdate` DATETIME NOT NULL ,
PRIMARY KEY (`ipaddress`) )
ENGINE = MyIsam;
The IP-address is a string because I was too lazy to convert it to a proper integer format and it should allow for IPv6 addresses, too. Also there's no 128 bit integer, is there?
I'll leave the other table that saves the votings out, I don't think it's in the scope of this question.
So my issue is... random. Some people couldnt vote for days straight, for example. Also we saw a rapid increase (a few hundred) in one day once. We suppose though that was the work of a bot, since this script doesn't yet have any security in terms of verifying if that actually was a click by a user (and it's pointless, because everything can be done by bots. Just a matter of making it harder).
I just voted today and tried again, the program told me I can vote again in... 0 hours and 59 minutes... It should rather be 23 hours and 59 minutes!
Something is so wrong here and I can't put my finger on it. At all!
$oneday = 86400;
$ip = trim($_SERVER['REMOTE_ADDR']);
require_once "config.php";
$conn = mysql_connect($mysql_host, $mysql_user, $mysql_pass);
mysql_select_db($mysql_db);
//I apologize for still using mysql_
if (!$conn) {
die("Connection error!");
}
mysql_query("SET time_zone='+0:00';"); // This helped me fix some issues because the field is DateTime
$res = mysql_query("SELECT COUNT(*) FROM `timelimit` WHERE ipdate <= DATE_ADD(NOW(), INTERVAL 1 DAY) AND `ipaddress` = '$ip';");
/* supposed to count if there is any entry corresponding
to the IP address wihich is in the blocked timeframe.
Could be the source of an error, but I can't put my finger on it... */
if (mysql_result($res,0) > 0) {
$res2 = mysql_query("SELECT UNIX_TIMESTAMP(ipdate) as ipdate FROM timelimit WHERE ipaddress = '$ip';");
$lastvote = mysql_result($res2, 0, "ipdate");
$nextvote = $lastvote + $oneday;
$timebetween = time() - $lastvote;
$timetonext = $nextvote - time();
//Some calculations done for the sake of output.
die("You can only vote once a day. You can vote again in " . date("H", $timetonext) . " hours and " . date("i", $timetonext) . " minutes");
} else {
if (isset($_REQUEST['postid'])) {
$postid = $_REQUEST['postid'];
$postid = mysql_real_escape_string($postid);
if (!is_numeric($postid)) {
die("post id not valid");
} //The input would be sanitized by now (I hope?)
//VOTE IS VALID
//*SNIP* voting logic (increases the counter with an UPDATE table SET votes = votes + 1)
//Done with the voting, time limit logic again:
mysql_query("DELETE FROM `timelimit` WHERE ipaddress = '$ip';");
mysql_query("INSERT INTO `timelimit` (`ipaddress`, `ipdate`) VALUES ('$ip', UTC_TIMESTAMP);");
// Could probably be combined into an INSERT and ON EXIST UPDATE query.
}
Use PEAR FloodControl it does everything for you.
Example taken from http://www.tozalakyan.com/fc/index.php#db
CREATE TABLE fc_logs (
unique_id varchar(32) NOT NULL,
data text NOT NULL,
access int UNSIGNED NOT NULL,
PRIMARY KEY (unique_id)
)
.
require_once 'HTTP/FloodControl.php';
try {
$ip = HTTP_FloodControl::getUserIP();
} catch (HTTP_FloodControl_Exception $e) {
die($e);
}
try {
$fc =& new HTTP_FloodControl();
$fc->setContainer('MDB2', array(
'dsn' => 'mysql://username:password#localhost/dbname',
'table' => 'fc_logs',
'autooptimize' => true
));
$limits = array (
86400 => 10 // maximum 10 requests in 24 h
);
if (!$fc->check($limits, $ip)) {
die('Too many requests. Please try later.');
}
} catch (HTTP_FloodControl_Exception $e) {
die($e);
}
// Your code...
Requirements and Dependencies:
PHP 5
PEAR::Exception
PEAR::DB (optional)
PEAR::MDB (optional)
PEAR::MDB2 (optional)

Allowing users to bump an input they submitted every hour?

I want people to be able to "bump" what they've wrote in my database but at the same time only allow the input to be in the table ONCE at a time.
For Example:
Jim's code is 5555. Jim enters his code and it shoots to the very bottom of the table. After 34 minutes he tries to enter his code in again (Because various other people have inputted their code between now and then) but gets a display error letting him know he has 26 minutes to wait still.
Joe inputs his code and waits an hour and five minutes and is able to push his code back to the bottom again.
Basically, I'm displaying data from the bottom up in my table.
Is there any way to easily do this?
function some_more_custom_content() {
$output="<BR>";
ob_start();
if ($_REQUEST['code'] != "") {
$code = $_REQUEST['code'];
$query="INSERT INTO `fc` (`code`,`datetime`) values ('" . mysql_real_escape_string($code) . "', now())";
$result=mysql_query($query);
$entry['datetime'] = strtotime($entry['datetime']);
while ($fetch_array = mysql_fetch_array($result)) {
$seconds = time() - strtotime($fetch_array["datetime"]);
if ((time() - $entry['datetime']) < 60*60) {
echo ("The code " . htmlentities($code) ." was updated less than an hour ago.");
} else {
echo ("Inserted " . htmlentities($code) ." into the top.");
}
}
?>
I get a syntax error. Any idea where it is?
UPDATE: Getting error of:
Parse error: syntax error, unexpected $end
you should create a table with a unique index on the code field and then use a query like:
INSERT INTO CODES (code)
VALUES (555)
ON DUPLICATE KEY UPDATE lastUpdated =
case when NOW() - INTERVAL 5 MINUTE > lastUpdated
then NOW()
else lastUpdated end
this will update the lastUpdated field only in cases when it's older than 5 minutes
Not that hard:
Use a timestamp for the last "bump time".
When a code is entered, check if it already exists in the database.
If it doesn't, insert it and set the bump timestamp to now().
If it does exist, check if the timestamp was within the hour.
If it was, display error.
If it wasn't, reset it to now().
Sort your display data by bump timestamp.
EDIT:
$entry = /* get entry from database, assuming the case where it already exists */;
// depending on the format of timestamp you get from the database,
// you may have to convert it to a UNIX timestamp:
$entry['timestamp'] = strtotime($entry['timestamp']);
if ((time() - $entry['timestamp']) < 60*60) { // 60*60 is one hour in seconds
// display error
} else {
// reset bump
}

Categories