So I'm trying to block voting for 24hours after a user has already voted, and I've been stuck for a while now. I tried working off this earlier post but I haven't had any luck. I was able to echo the ip address but not the vote_time
I have a database with a table named voterlist that has two columns: submission_ip and vote_time. (the time is formatted like this date("Y-m-d H:i:s",time()) )
My php looks like this:
<?php
$ip = mysql_real_escape_string($_SERVER['REMOTE_ADDR']);
$query = "SELECT vote_time FROM voterlist WHERE submission_ip ='$ip'";
$result = mysql_query($query);
if(mysql_num_rows($result) < date('Y-m-d H:i:s',strtotime('-24 hour'))) {
echo 'you can vote again in 24 hours';
}else {
echo 'vote now';
}
?>
Any help with this query would be greatly appreciated.
In your line
if(mysql_num_rows($result) < date('Y-m-d H:i:s',strtotime('-24 hour'))) {
What are you trying to do here exactly?
The first term, mysql_num_rows($result) is the amount of rows the query returned. The second term, date('Y-m-d H:i:s',strtotime('-24 hour')) is some date string, like 2015-01-25 22:47:00. You're comparing them, why?
Instead, check for the date in the query:
SELECT vote_time FROM voterlist WHERE submission_ip ='$ip' AND `vote_time` > timestampadd(day, -1, now())
Then, if mysql_num_rows($result) gives you 1 or more, that means there is a record, so there has been a vote in the last 24 hours. If the number of rows is 0, there has not been a vote in the last 24 hours.
Besides that, blocking by IP is a bad idea. Do you want to block a whole company after one employee has voted? You could use authentication with some OpenID provider to ensure people only vote once, however, privacy may be an issue. If you have a list of the people who are allowed to vote (and it's not 'everyone') you could look into systems as RIES, which was used in some elections in the Netherlands a few years ago. (In 2008 the software was released and shown to have extensive security problems.)
Also note that the mysql_* functions have been deprecated (docs) in favour of PDO_MySQL and mysqli_*.
Related
I am trying to convert three separate database columns into a date (day,month,year) and calculate the age so only users over the age of 15 or 18 can purchase certain products. The code below doesnt work as it echoes '0 days, 0 months, 0 years' and still adds the product to the basket. Which means the age calculation doesnt work, and my first if statement doesnt work either.
<?php
$username = $_SESSION['solentuser'];
echo "$username's account!<br>";
$conn = new PDO("mysql:host=localhost;dbname=u;","u","p");
$productID= htmlentities($_GET['ID']);
//startdate
$result=$conn->prepare("SELECT * FROM users WHERE username=:username");
$result->bindParam(":username",$username);
$result->execute();
$row=$result->fetch();
$birthdate = $row['yearofbirth'] . $row['monthofbirth'] . $row['dayofbirth'];
$presentdate = date('Ymd');
$birthday = new DateTime($birthdate);
$currentdate = new DateTime($presentdate);
$age = $birthday->diff($currentdate);
echo $age->format('<br>%d Days %m Months %y Years<br>');
//enddate
$results=$conn->prepare("SELECT * FROM products where ID=:productID");
$results->bindParam(":productID",$productID);
$results->execute();
$row=$results->fetch();
if($row['agelimit'] <= $age){
if($row['stocklevel'] >= 1){
$result=$conn->prepare("INSERT INTO basket(productID,username,qty) values(:productID,:username,1)");
$result->bindParam(":productID",$productID);
$result->bindParam(":username",$username);
$result->execute();
$result=$conn->prepare("UPDATE products SET stocklevel=stocklevel-1 WHERE ID=:productID");
$result->bindParam(":productID",$productID);
$result->execute();
echo "You have successfully added this product to your basket!";
}
else{
echo "This product is out of stock!";
}
}
else{
echo "You are not old enough to purchase this product!";
}
//print_r($conn->errorInfo());
?>
any suggestions as to where the error is? i have read that it is possible to write an if statement inside an if statement, so why does this one not work?
thank you!
I'd echo out $birthdate and verify there's a valid date there. (We aren't getting back single digits, a date of 2009-05-04 getting represented as '2009', '5' and '4' such that when we concatenate them, we get 200954, or maybe extra spaces. (We're not seeing the datatypes of the three separate columns.)
We might try adding some delimiters in there, so we'd get 2009-5-4, likely we could get that converted into a DateTime, using the correct format string.
If I had separate values for month, day and year, I would use PHP mktime, and then create a DateTime object from that.
(MySQL does provide a DATE datatype that allows for a very large range of valid dates, and doesn't allow invalid dates to be stored. Storing three separate columns to represent a single date just smells like the wrong way to do it. (If I actually needed the separate month and day columns (to allow indexing for some queries), I would add those in addition to the birthdate DATE column, not in place of it, with triggers to keep the values in sync with the birthdate column.)
Also, $age is a DateInterval object. You seem to be aware that we can use the format method to extract integer number of years.
$age_yrs = $age->format('%y');
We're guessing that the database column age_limit is integer years.
if( $row['agelimit'] <= $age_yrs ) {
Right before that if statement, we can confirm that what we think to be true is actually true...
echo " age_yrs=" . $age_yrs;
echo " row_age_limit=" . $row['age_limit'];
Looking closely at the debugging output helps us identify if the problem is before the if statement or after, so we aren't chasing down a problem in a section of code where there isn't a problem, the problem is somewhere else, on a preceding line.
I encourage you to develop the skills needed to debug programs that you write. It seems like you are making some (wrong) assumptions about what the variables are containing.
Adding echo and var_dump during development is a first step in verifying that what you think to be true is actually true.
I'd go as far as recommending that you look at every line of code you write as possibly going wrong, especially in edge cases.
https://ericlippert.com/2014/03/05/how-to-debug-small-programs/
(StackOverflow is a question/answer community, not a debugging service.)
I am providing 24 hours trial membership in my android application. I do not know more about PHP. I want check user registration time and want disable trial membership if 24 hours got passed. I have made little PHP file for that.
$sql = "SELECT id, email, registration_time FROM user WHERE trial = 1";
$result = $conn->query($sql);
if($result) {
while($row = $result->fetch_row()) {
$id = $row[0];
$email = $row[1];
$registrationTime = strtotime($row[2]);
$currentTime = strtotime("-1 day");
if($currentTime > $registrationTime) {
$update = "UPDATE user SET trial = 0 WHERE email = '$email'";
$conn->query($update);
$update = "UPDATE number_list SET disable = 1 WHERE user_id = $id";
$conn->query($update);
}
}
}
Its not providing any result even I have one user which time passed more than 48 hours.
How can I solve this issue?
try this and check
$currentTime=date('m-d-Y',strtotime($registrationTime . "-1 days"))
You should use a prepared statement to update the database for all the users with the same email (your first update query). Also see the documentation.
If someone registers with an e-mail address like test'; DROP ALL TABLES; --#gmail.com1 this code will dutifully remove your database. Never put user data into code directly like that.
Now let's look at the example code;
$sql = "SELECT id, email, registration_time FROM user WHERE trial = 1";
$result = $conn->query($sql);
if($result) {
while($row = $result->fetch_row()) {
You're saying there is no result at all. I assume that you've tested the output with a debug statement. E.g. putting echo 'users exist'; in between here. The first thing to do would be to check your user table if there are any rows. Does this SQL query produce results?
Assuming that it does, there doesn't appear to be anything wrong with the SQL statement. Assuming you have a table called user with four columns id, email, registration_time, and trial it should produce results.
Next, what you want to do is read the query function documentation. As you can see there, when a query fails, for whatever reason, it returns FALSE. Try writing an 'else' code block and logging the error that occurs. You can fetch it using the error function mysqli::error. Try appending this code;
} else {
echo "MySQL Error: " . $conn->error;
}
Where you can replace the echo with your error handling of choice.
It's probably a good idea to write a wrapper for mysqli if you're going to execute more than a few queries in your application. That way, you can write error handlers in your wrapper class for what your application should do if a query or database connection fails.
What could also be the case is that, while your initial query succeeds and fetches some rows, the time check fails. You may want to do some stricter date/time parsing than using strtotime and hoping for the best. Assuming you're using a TIMESTAMP column to store the data, you can use this:
function readDatabaseTimestampValue($value) {
$dateTime = date_create_from_format("Y-m-d H:i:s", $value);
$timestamp = $dateTime->getTimestamp();
return $timestamp;
}
Check the exact time data returned from your database. Dates and times are complicated, and if things are reinterpreted, say the day number in SQL may become the year in the PHP app, which can cause strange bugs. E.g. you can do this by doing say:
echo "24 hours ago: " . strtotime("-1 day") . ", user data: " . $row[2];
Next, you probably have some bugs in the logic. '24 hours ago' is better done by doing this, as using '-1 day' will cause weird issues when people mess with the calendar:
$timestamp = time() - 86400;
There's 86,400 seconds in a day (well, excluding DST and leap seconds, but you want 24 hours of subscription time, not 23 hours around the 21st of March).
Finally, there's problems if the same E-mail address is present more than once in the table. You will set 'trial' to 0 for one user, but may set the 'disable' flag for another if two users register within the same 24-hour period with the same e-mail. If the latter is guaranteed to be unique then this is no issue. Otherwise, you may want to update by id in both tables.
Next, we can look at some optimization. Right now, you fetch everything from the database. But you can do much better/faster by having an index on registrationTime, and using the database's sorting features. E.g. let's say we know the exact date/time of 24 hours ago as $yesterday in PHP we can write a query like:
SELECT id, email, registration_time FROM user WHERE trial = 1 AND registration_time > ?
Bind the $yesterday variable to the parameter. Now you no longer need the if() statement; the database does it for you. Also, as your database grows, you're not checking the old records one-by-one every time the code runs.
1Note, that may not be a legal e-mail address, but there's probably ways to do evil things even with a legal mail address.
I'm trying to make a booking system and I came across a mistake.
I have a starting date and a ending date, if I enter a date start en end that falls between a booking already made the system is saying that is not possible, however if I enter before and after a already occupied period the system accepts the booking
this how I check now
`$db_check_result1 = mysql_query("SELECT * FROM ms_bookings WHERE ms_bookings_calid = '$propertyId' AND '$convertedstartdate' BETWEEN ms_bookings_startdate AND ms_bookings_enddate") or die(mysql_error());
if the result is greater than 0 then booking date is not possible and I do the samen with the departure date
$db_check_result2 = mysql_query("SELECT * FROM ms_bookings WHERE ms_bookings_calid = '$propertyId' AND '$convertedenddate' BETWEEN ms_bookings_startdate AND ms_bookings_enddate") or die(mysql_error());
again if the result is greater than 0 then booking is not possible
it works fine if new request falls within a already entered booking but when arrivaldate and departure date is before and after existing date the systems accepts
how can I solve this?
To get it out of the way:
Don't use mysql_* functions in any new code. The mysql extension has been removed from current PHP versions (starting with PHP 7.0). Use mysqli (note the "i") or pdo_mysql instead.
Don't put any user data directly into your queries. This will lead to security problems in the future (SQL injection). Use placeholders instead.
That said, the third check you want is
SELECT * FROM ms_bookings
WHERE ms_bookings_calid = :propertyId
AND (ms_bookings_startdate BETWEEN :convertedstartdate AND :convertedenddate
OR ms_bookings_enddate BETWEEN :convertedstartdate AND :convertedenddate)
However, you can combine all checks into a single simpler query:
SELECT * FROM ms_bookings
WHERE ms_bookings_calid = :propertyId
AND :convertedstartdate <= ms_bookings_enddate
AND :convertedenddate >= ms_bookings_startdate
In order to not overlap, the new booking has to either start after the existing booking ends (:convertedstartdate <= ms_bookings_enddate will be false then), or it has to end before the existing booking starts (:convertedenddate >= ms_booking_startdate is false).
hello all i am trying to find the recent birthday of the registered members on the site and also store the result of query into session so that next time the query need not to be executed so to reduce the page load time and also server load
i am having this code
if(!isset($_SESSION['dob']) || $_SESSION['dob'] =='' ){
$frndlist=$_SESSION['friendlist']; //comma seperated list of friends
$CurrMOnth= date('m'); // this month
$BirthDLAST0n=date('d', strtotime(' - 7 day'));
$BirthDGRATEn=date('d', strtotime(' + 7 day'));
$GEttheBIrthdaYS=mysqli_query($connection,"select id,name,dob from members
where (id IN ($frndlist)) and (MONTH(dob) = '$CurrMOnth') and
(DAY(dob) > '$BirthDLAST0n' and DAY(dob) < '$BirthDGRATEn' )
order by dob desc limit 10");
$_SESSION['dob']=$GEttheBIrthdaYS;}else{
$GEttheBIrthdaYS=$_SESSION['dob'];
}
while($theBdaYSreYAr90=mysqli_fetch_array($GEttheBIrthdaYS)){ //print }
but the problem here is result of query is stored into session but it is never accepted by the mysqli_fetch_array it says error.
this is problem because i am trying to store object onto session
is there any alternative to store the result into something so that the same query need not to be executed gain again ....
and also the birthday script is not good it dosent displays the birthday of people whose DOB is at the last or begning of months.
please let me know how to store the result of query into session or cookie
as cookie stores very less size i dont think cookie is good option.
Looks like you're trying to put a whole array into the session var, just break it up.
$result = mysql_fetch_array($GettheBIrthdaYS);
$_SESSION['dob'] = $result['dob'];
Also make your limit 1, unless you want more than 1 record, which if you do then you will need to change everything.
I found the exact same question here.
But it isn't working for me. I've modified it a bit, manipulated it, and I can't figure it out. I'm trying to remove rows that are over a day old. Here is my code:
if (isset($_POST['prune'])) {
$sql = "DELETE FROM logs WHERE time < date('now', '-1 days')";
mysql_query($sql);
echo 'Logs older than one day removed.';
}
Fairly simple question I suppose, but its bugging the hell out of me. I would appreciate any help.
In case it makes a difference, the column is a TIMESTAMP type.
EDIT: Apparently I'm an idiot. The question I linked you to relates to SQLite3. So now my question is, how can I do this in MySQL?
You can subtract an interval:
DELETE FROM logs WHERE time < now() - interval 1 day
That answer was IIRC for SQLite3. You're using MySQL which does not support this syntax.
You want to use DATE_ADD() function (example below not tested but should work):
DELETE FROM logs WHERE time < TIMESTAMPADD(DAY,-1,NOW());
In my case, only the
timestampadd
in positive direction works when running through an asc ordered date calendar:
if (urldecode ($aUrl['Select']) == '>')
$this-> db-> where ('konzertdatum >', 'TIMESTAMPADD(DAY, 1, "'. $id . '") ', false) ;
else
$this-> db-> where ('konzertdatum < ', 'TIMESTAMPADD(DAY, -1, "'. $id . '") ', false) ;
In negative direction (-1), the timestamp goes back to the very first entry. I also tried not to use CodeIgniter, but the same consequence.
Summing up, +1 as parameter for timestampadd works, -1 works for the second lowest entry (then jumping back to the first one. But it fails when I step further away from the first date.