How to prevent people from spamming an ajax form [closed] - javascript

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
My problem is I have a vote system similar to the one of Stack Overflow. My problem is that a person can spam the vote up button which makes it glitch and make it submit more times than it’s supposed to. For example, if there are 10 up votes on a post, I could repeatedly click the vote up button and the it would add two or three up votes instead of one. Similarly I could do this with the down vote button. How do I prevent this?
Index.php:
<?php
session_start();
require('db.php');
$pid = 2;
$uid = $_SESSION['id'];
$sql = mysqli_query($con, "SELECT * FROM posts WHERE pid = '$pid'"); //check to see how many likes the post has
$r = mysqli_fetch_assoc($sql);
$body = $r['body'];
$likes = $r['likes'];
$sql2 = mysqli_query($con, "SELECT * FROM likes WHERE pid = '$pid' AND uid = '$uid'"); //check to see if user has voted
$n = mysqli_num_rows($sql2);
if ($n == 0) {
//user hasn't liked or down vote anything yet
$liked = "no";
} else {
if ($n > 1) {
//like scammed
echo "<script>alert('Stop spamming for votes. You are banned for spam.')</script>";
exit("You have been banned for spam");
//This isn't fool proof though, and I don't want to ban people for this. It would be best if I could just prevent the vote scam in the first place
}
$r = mysqli_fetch_assoc($sql2);
$type = $r['like_type'];
if ($type == '0') {
$liked = "liked";
} else {
$liked = "disliked";
}
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<script src="//code.jquery.com/jquery-latest.min.js"></script>
<style>
.selected {
color: red;
}
</style>
</head>
<body>
<div class="post">
<p><?php echo $body; ?></p>
</div>
<div class="likes">
Upvote
<span id="votes-<?php echo $pid; ?>"><?php echo $likes; ?></span>
Downvote
</div>
</body>
Javascript vote() function
function vote(type, pid, uid, id, voteId) {
var vote = $('#'+ id);
if (vote.hasClass('selected')) {
//user voted for this
$.post("vote.php", {pid: pid, uid: uid, type: type, vote: 'reset'}, function(d) {
if (d == '0' || d == '1') {
vote.removeClass('selected');
var votes = $('#' + voteId);
var num = votes.text();
if (d == '1') {
votes.text(++num);
} else {
votes.text(--num);
}
} else {
alert('An error occurred')
}
});
} else {
var upVoteId = $('#up-' + pid);
var downVoteId = $('#down-' + pid);
if (upVoteId.hasClass('selected') || downVoteId.hasClass('selected')) {
//user wants to switch votes
$.post('vote.php', {pid: pid, uid: uid, type: type, vote: 'switch'}, function(data) {
var votes = $('#' + voteId);
var num = votes.text();
if (data == '1') {
//downvote successful
votes.text(parseInt(num) - 2);
vote.addClass('selected');
upVoteId.removeClass('selected');
}
if (data == '0') {
//upvote successful
votes.text(parseInt(num) + 2);
vote.addClass('selected');
downVoteId.removeClass('selected');
}
if (d == 'error') {
alert('error');
}
});
} else {
$.post('test2.php', {type: type, pid: pid, uid: uid}, function(d) {
if (d == "1") {
//everything good
$('#' + type + '-<?php echo $pid; ?>').addClass('selected');
var votes = $("#" + voteId).text();
if (type == 'down') {
//downvote
votes = --votes;
$('#' + voteId).text(votes);
} else {
votes = ++votes;
$('#' + voteId).text(votes);
}
} else {
alert('failed');
}
});
}
}
}
}
Vote.php
<?php
session_start();
require('db.php');
if (!isset($_SESSION['id'], $_SESSION['un'])) {
//not logged in
header('Location: index.php');
exit;
} else {
if (!isset($_POST['uid'], $_POST['pid'], $_POST['type'], $_POST['vote'])) {
//form not submitted
header('Location: home.php');
exit;
} else {
$uid = (int)$_SESSION['id'];
$pid = (int)$_POST['pid'];
$type = preg_replace('#[^a-z]#', '', $_POST['type']);
$vote = preg_replace('#[^a-z]#', '',$_POST['vote']); //vote type
if ($vote == 'reset') {
//initiate vote reset
if ($type == 'down') {
//downvote
$sql = mysqli_query($con, "DELETE FROM likes WHERE like_type = '1' AND pid = '$pid' AND uid = '$uid'"); //delete the downvote
$sql2 = mysqli_query($con, "UPDATE posts SET likes = likes + 1 WHERE pid = '$pid'");
if ($sql) {
echo "1"; // 1
exit;
} else {
echo "error";
exit;
}
} else {
//upvote
$sql = mysqli_query($con, "DELETE FROM likes WHERE like_type = '0' AND pid = '$pid' AND uid = '$uid'"); //delete upvote
$sql2 = mysqli_query($con, "UPDATE posts SET likes = likes - 1 WHERE pid = '$pid'");
if ($sql) {
echo "0"; // 0
exit;
} else {
echo "error";
exit;
}
}
}
if ($vote == 'switch') {
//user wanted to switch vote
if ($type == 'down') {
//user had voted up but wants to vote down now
$sql = mysqli_query($con, "DELETE FROM likes WHERE like_type = '0' AND pid = '$pid' AND uid = '$uid'"); //delete the previous vote
$sql2 = mysqli_query($con, "INSERT INTO likes (pid, uid, like_type, date_liked) VALUES ('$pid', '$uid', '1', now())"); //insert new vote
$sql3 = mysqli_query($con, "UPDATE posts SET likes = likes - 2 WHERE pid = '$pid'");
if ($sql AND $sql2 AND $sql3) {
//all three queries were successful
echo "1";
exit;
} else {
echo "error";
exit;
}
} else {
//user had voted down but wants to vote up now
$sql = mysqli_query($con, "DELETE FROM likes WHERE like_type = '1' AND pid = '$pid' AND uid = '$uid'") or die(mysqli_error($con)); //delete the previous vote
$sql2 = mysqli_query($con, "INSERT INTO likes (pid, uid, like_type, date_liked) VALUES ('$pid', '$uid', '0', now())"); //insert new vote
$sql3 = mysqli_query($con, "UPDATE posts SET likes = likes + 2 WHERE pid = '$pid'");
if ($sql AND $sql2 AND $sql3) {
//all three queries were successful
echo "0";
exit;
} else {
echo "error";
exit;
}
}
}
}
}
Test2.php
<?php
require('db.php');
$pid = $_POST['pid'];
$uid = $_POST['uid'];
$type = $_POST['type'];
if ($type == "down") {
//downvote
$type = 1;
$sql = mysqli_query($con, "INSERT INTO likes (uid, pid, like_type, date_liked) VALUES ('$uid', '$pid', '$type', now())");
$sql2 = mysqli_query($con, "UPDATE posts SET likes = likes - 1 WHERE pid = '$pid'");
if ($sql) {
echo '1';
exit;
}
} else {
//upvote
$type = 0;
$sql = mysqli_query($con, "INSERT INTO likes (uid, pid, like_type, date_liked) VALUES ('$uid', '$pid', '$type', now())");
$sql2 = mysqli_query($con, "UPDATE posts SET likes = likes + 1 WHERE pid = '$pid'");
if ($sql) {
echo '1';
exit;
}
}
These are my pages that are currently used. I plan on moving test2.php to vote.php.
In my database I have two tables, one to store all the post details including the number of votes. The second table is to store who voted for what post and if it was an upvote or down.
If I could make my system more efficient, please give me tips or recommendations.

Quick SQL hack: make a unique index on pid,uid so that a user can only ever vote once on a post.
ex: ALTER TABLE vote ADD UNIQUE INDEX pid_uid (pid, uid);
Quick JS hack: set a variable on submit that you don't clear until the response; if the variable is set, you don't submit the form. Thus, spam clicking will do nothing, since every click after the first will be ignored.
ex:
var submitting = false;
function submit_form()
{
if (!submitting)
{
submitting = true;
// example; insert actual arguments for it to work
$.post(
url,
postData,
function (data, textStatus)
{
submitting = false;
// handle data here
},
"json"
);
}
}

Well, there is a lot of improvement to be done.
First you are running open to SQL injection queries. Move that to prepared statement.
Then you can, before insert, check if user already voted for that type, as you already have uid, pid, and like_type. This is server-side.
Client-side your JavaScript could disable clicked button to prevent double click. This will prevent user's to send many requests to the server.
The goal here is let server, PHP, handle the verification if the user already voted to that post, as client -ide is easily manipulated in this case.
Don't forget, move those SQL queries to something safe.

Ultimately, you can only hope to control multiple voting using server-side validation.
Stack Overflow requires the user to sign in to a known account in order to vote, which makes it more difficult (but of course not impossible) for multiple votes.
If you do not require that, the best solution depends on your specific requirements.
A simple, client-only solution is to set a cookie indicating the user has voted. Disable the appropriate UI element if that cookie is set. Someone who clears cookies or uses InPrivate style browsing will easily bypass that. Someone can also write their own client that ignores the cookie. Perhaps it is sufficient for your requirements.
A naive server-side solution is to allow only one vote per IP address. I do not recommend this, but include it so you understand why. Unfortunately, a single user can have multiple IP addresses (just drive down the road on your mobile device and see how many IPs you get), or a single IP can represent multiple physical computers (proxy server).
A solid server-side solution would combine the IP address, user agent, and various aspects of the device to yield a device fingerprint. This is a complex solution, beyond the needs of most websites (but if you need it, there are a few companies out there that offer device fingerprinting). Check out https://panopticlick.eff.org/
Summary
If you can require the user to log in to vote (like StackOverflow), that will often be the best solution.
If you cannot require that, use device fingerprinting if it is in your budget, otherwise rely on a cookie. If you do the latter, it may still be worth logging the IP address and user agent of voters so that you can keep an eye out for blatant cheating.

I'd consider storing a voter's IP address in a mysql table as an INT once they have voted.
After that either just show them the tally, or provide them the option to undo their vote by voting up/down.
Check out the PHP function ip2long:
http://www.php.net/manual/en/function.ip2long.php
Use that to convert the IP address into INT format and store it in your mysql to reference against.
Other Resources:
http://www.php.net/manual/en/function.long2ip.php
http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_inet-aton

Related

PHP unlink not working when using PHP and Javascript

I have a process for deleting post entries in a PHP app. I want to delete the image associated with the post, if an image exists.
The post itself is deleted from the database successfully, but the image is not deleted from the image folder.
Here's delete_post.php:
if (isset($_GET['post_id'])) {
$post_id = $_GET['post_id'];
if (isset($_POST['result'])) {
if ($_POST['result'] == 'true') {
$delete_img = $pdo->prepare("SELECT image FROM posts WHERE id = ?");
$delete_img->execute([$post_id]);
$img_row = $delete_img->fetch();
$img = $img_row['image'];
if (file_exists($img)) {
unlink($img);
}
$sql = "DELETE FROM posts WHERE id = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute([$post_id]);
}
}
}
...the form handler
<?php include '../../inc/config.php';
if (isset($_GET['post_id'])) {
$post_id = $_GET['post_id'];
if (isset($_POST['result'])) {
if ($_POST['result'] == 'true') {
$delete_img = $pdo->prepare("SELECT * FROM posts WHERE id = ?");
$delete_img->execute([$post_id]);
$img_row = $delete_img->fetch();
$filename = $_SERVER['DOCUMENT_ROOT']. '/' .$img_row['image'];
if (file_exists($filename)) {
unlink($filename);
}
$get_gallery_img = $pdo->prepare("SELECT * FROM files WHERE post_id = ?");
$get_gallery_img->execute([$post_id]);
while ($row = $get_gallery_img->fetch()) {
$galleryName = $_SERVER['DOCUMENT_ROOT'] . '/' . $row['file_name'];
unlink($galleryName);
}
$delete_gallery = "DELETE FROM files WHERE post_id = ?";
$stmt = $pdo->prepare($delete_gallery);
$stmt->execute([$post_id]);
$sql = "DELETE FROM posts WHERE id = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute([$post_id]);
}
}
}
...and the Javascript that executes the form handler.
<script>
$(document).ready(function() {
$('#post<?=$id?>').on('click', function() {
bootbox.confirm("Are you sure you want to delete this post?", function(result){
$.post("inc/form_handlers/delete_post.php?post_id=<?=$id?>", {result:result});
if(result) {
location.reload();
}
});
});
});
</script>
I've tried moving the statement for deleting the image to just below the $_GET['post_id'] if statement, as well as just below the the $_POST['result'] if statement. I know it needs to be above the delete post statement since the path to the image is in the image column of the database - neither worked.
I have tried the unlink statement in another PHP file to make sure that it works - it does. So far I haven't found where I am going wrong, but I continue to look.
Since I'm still new to both PHP I am not sure where I should focus, or more to the point, what I am missing.
In case it helps someone else it was a path issue. Here's the final PHP:
if (isset($_GET['post_id'])) {
$post_id = $_GET['post_id'];
if (isset($_POST['result'])) {
if ($_POST['result'] == 'true') {
$delete_img = $pdo->prepare("SELECT * FROM posts WHERE id = ?");
$delete_img->execute([$post_id]);
$img_row = $delete_img->fetch();
$filename = $_SERVER['DOCUMENT_ROOT']. '/' .$img_row['image'];
unlink($filename);
$sql = "DELETE FROM posts WHERE id = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute([$post_id]);
}
}
}
The part to note is $filename = $_SERVER['DOCUMENT_ROOT']. '/' .$img_row['image']; - using document root was the missing link.
I hope this helps any with a similar issue.

Ajax database insert isnt working

I am trying to insert values from an input field into a database with ajax as part of a conversation system.I am using an input form as follows.
<input data-statusid="' .$statuscommentid. '" id="reply_'.$statusreplyid.'" class="inputReply" placeholder="Write a comment..."/>
with the following jquery I carry out a function when the enter key is pressed by the user.
$(document).ready(function(){
$('.inputReply').keyup(function (e) {
if (e.keyCode === 13) {
replyToStatus($(this).attr('data-statusid'), '1',$(this).attr("id"));
}
});
});
within this function is where I am having the problem ,I have no problems calling the function with jquery but I have done something wrong with the ajax and I don't know what?
$.ajax({ type: "POST", url: $(location).attr('href');, data: dataString, cache: false, success: function(){ $('#'+ta).val(""); } });
Additionally this is the php I am using to insert into the database
<?php //status reply input/insert
//action=status_reply&osid="+osid+"&user="+user+"&data="+data
if (isset($_POST['action']) && $_POST['action'] == "status_reply"){
// Make sure data is not empty
if(strlen(trim($_POST['data'])) < 1){
mysqli_close($db_conx);
echo "data_empty";
exit();
}
// Clean the posted variables
$osid = preg_replace('#[^0-9]#', '', $_POST['sid']);
$account_name = preg_replace('#[^a-z0-9]#i', '', $_POST['user']);
$data = htmlentities($_POST['data']);
$data = mysqli_real_escape_string($db_conx, $data);
// Make sure account name exists (the profile being posted on)
$sql = "SELECT COUNT(userid) FROM user WHERE userid='$userid' LIMIT 1";
$query = mysqli_query($db_conx, $sql);
$row = mysqli_fetch_row($query);
if($row[0] < 1){
mysqli_close($db_conx);
echo "$account_no_exist";
exit();
}
// Insert the status reply post into the database now
$sql = "INSERT INTO conversation(osid, userid, postuserid, type, pagetext, postdate)
VALUES('$osid','$userid','$postuserid','b','$pagetext',now())";
$query = mysqli_query($db_conx, $sql);
$id = mysqli_insert_id($db_conx);
// Insert notifications for everybody in the conversation except this author
$sql = "SELECT authorid FROM conversation WHERE osid='$osid' AND postuserid!='$log_username' GROUP BY postuserid";///change log_username
$query = mysqli_query($db_conx, $sql);
while ($row = mysqli_fetch_array($query, MYSQLI_ASSOC)) {
$participant = $row["postuserid"];
$app = "Status Reply";
$note = $log_username.' commented here:<br />Click here to view the conversation';
mysqli_query($db_conx, "INSERT INTO notifications(username, initiator, app, note, date_time)
VALUES('$participant','$log_username','$app','$note',now())");
}
mysqli_close($db_conx);
echo "reply_ok|$id";
exit();
}
?>
Thanks in advance for any help it will be much appreciated
Why didn't you set the proper URL for Ajax calls instead of using location.href?
var ajax = ajaxObj("POST", location.href);
In additional, I guess ajaxObj is not defined or well coded. You are using, jQuery, why don't you try jQuery ajax?
http://api.jquery.com/jquery.ajax/
var ajax = ajaxObj("POST", location.href);
ajax.onreadystatechange = function() {
if(ajaxReturn(ajax) == true) {
var datArray = ajax.responseText.split("|");
if(datArray[0] == "reply_ok"){
var rid = datArray[1];
data = data.replace(/</g,"<").replace(/>/g,">").replace(/\n/g,"<br />").replace(/\r/g,"<br />");
_("status_"+sid).innerHTML += '<div id="reply_'+rid+'" class="reply_boxes"><div><b>Reply by you just now:</b><span id="srdb_'+rid+'">remove</span><br />'+data+'</div></div>';
_("replyBtn_"+sid).disabled = false;
_(ta).value = "";
alert("reply ok!");
} else {
alert(ajax.responseText);
}
ajax.send("action=status_reply_ok&sid="+sid+"&user="+user+"&data="+data);
}
}

Preventing Multiple Unintended PHP Form Submissions

I run a website for a youth sports program that features schedules, standings, and score reporting using simple PHP scripts that manipulate data stored in a MySQL database.
After a game is played, the winning coach will access the score reporting form for that particular game, enter the information, and click submit to update the schedule and standings accordingly. They are then automatically redirected to the schedule page that they came from.
However, several times a season, a coach will unintentionally duplicate a score submission (sometimes creating as many as three or four instances) which does not affect the result posted on the schedule, but does throw the data in the standings out of whack. I'm not sure how exactly this is being accomplished, but I'm trying to fix the problem.
I've been reading up as much as possible on here and the web and believe that I need to implement some sort of token system to the reporting script, but I'm unsure how to exactly write the code? Any advice here would be GREATLY appreciated. Here is the script itself:
<?php
// Connect to the database:
require ('../mysqli_connect.php');
// Validate the school:
if (empty($_POST['school'])) {
echo "You forgot to enter your school.<br>";
$validate = 'false';
} elseif ($_POST['school'] != $_POST['away_team'] && $_POST['school'] != $_POST['home_team']) {
echo "Your school does not match one of the two on file for this game.<br>";
$validate = 'false';
} else {
$school = mysqli_real_escape_string($db, trim($_POST['school']));
$validate = 'true';
}
// Validate the password:
if (empty($_POST['pass'])) {
echo "You forgot to enter your password.<br>";
$validate = 'false';
} else {
$pass = mysqli_real_escape_string($db, trim($_POST['pass']));
$validate = 'true';
}
// Validate the away score:
if (!isset($_POST['away_score'])) {
echo "You forgot to enter the away score.<br>";
$validate = 'false';
} elseif (!is_numeric($_POST['away_score'])) {
echo "You entered an invalid score for the away team.<br>";
$validate = 'false';
} else {
$away_score_confirm = mysqli_real_escape_string($db, trim($_POST['away_score']));
$validate = 'true';
}
// Validate the home score:
if (!isset($_POST['away_score'])) {
echo "You forgot to enter the home score.<br>";
$validate = 'false';
} elseif (!is_numeric($_POST['$home_score']) && $_POST['$home_score'] < 0 ) {
echo "You entered an invalid score for the home team.<br>";
$validate = 'false';
} else {
$home_score_confirm = mysqli_real_escape_string($db, trim($_POST['home_score']));
$validate = 'true';
}
// Determine the winner and loser, and set variables:
if ($_POST['away_score'] > $_POST['home_score']) {
$winner = mysqli_real_escape_string($db, trim($_POST['away_team']));
$winner_score = mysqli_real_escape_string($db, trim($_POST['away_score']));
$loser = mysqli_real_escape_string($db, trim($_POST['home_team']));
$loser_score = mysqli_real_escape_string($db, trim($_POST['home_score']));
$tie = 'no';
} else if ($_POST['away_score'] < $_POST['home_score']) {
$winner = mysqli_real_escape_string($db, trim($_POST['home_team']));
$winner_score = mysqli_real_escape_string($db, trim($_POST['home_score']));
$loser = mysqli_real_escape_string($db, trim($_POST['away_team']));
$loser_score = mysqli_real_escape_string($db, trim($_POST['away_score']));
$tie = 'no';
} else if ($_POST['away_score'] == $_POST['home_score']) {
$tie = 'yes';
$tie1 = mysqli_real_escape_string($db, trim($_POST['away_team']));
$tie2 = mysqli_real_escape_string($db, trim($_POST['home_team']));
$tie_score = mysqli_real_escape_string($db, trim($_POST['away_score']));
}
// Declare remaining hidden inputs as variables:
$league = $_POST['league'];
$table = mysqli_real_escape_string($db, $_POST['table']);
$game_id = mysqli_real_escape_string($db, $_POST['game_id']);
$sport = $_POST['sport'];
// Declare remaining hidden inputs as variables:
$standings_league = $table . "_standings";
// If all conditions are met, process the form:
if ($validate != 'false') {
$q1 = "SELECT school_id FROM user_schools WHERE (school_name='$school' AND pass='$pass')";
$r1 = mysqli_query($db, $q1);
$num = mysqli_num_rows($r1);
if ($num == 1) {
// Get the game ID:
$q2 = "SELECT $game_id FROM $table";
$r2 = mysqli_query($db, $q2);
// Get the row for the game ID:
$row = mysqli_fetch_array($r2, MYSQLI_NUM);
// Perform an UPDATE query to modify the game scores:
$q3 = "UPDATE $table SET home_score='$home_score_confirm', away_score='$away_score_confirm' WHERE game_id=$row[0]";
$r3 = mysqli_query($db, $q3);
if (mysqli_affected_rows($db) == 1) {
$confirm = 'true';
} else {
$confirm = 'false';
}
// Update the winning team in the standings:
$q4 = "SELECT school_id FROM $standings_league WHERE school_name='$winner'";
$r4 = mysqli_query($db, $q4);
// Get the row for the school:
$row2 = mysqli_fetch_array($r4, MYSQLI_NUM);
$q5 = "UPDATE $standings_league SET games=games + 1, win=win + 1, pts_for=pts_for + '$winner_score', pts_against=pts_against + '$loser_score' WHERE school_id=$row2[0]";
$r5 = mysqli_query($db, $q5);
$q6 = "UPDATE $standings_league SET pct=(win / games), avg_for=(pts_for / games), avg_against=(pts_against / games) WHERE school_id=$row2[0]";
$r6 = mysqli_query($db, $q6);
// Update the losing team in the standings:
$q7 = "SELECT school_id FROM $standings_league WHERE school_name='$loser'";
$r7 = mysqli_query($db, $q7);
// Get the row for the school:
$row3 = mysqli_fetch_array($r7, MYSQLI_NUM);
$q8 = "UPDATE $standings_league SET games=games + 1, loss=loss+1, pts_for=pts_for + '$loser_score', pts_against=pts_against + '$winner_score' WHERE school_id=$row3[0]";
$r8 = mysqli_query($db, $q8);
$q9 = "UPDATE $standings_league SET pct=(win / games), avg_for=(pts_for / games), avg_against=(pts_against / games) WHERE school_id=$row3[0]";
$r9 = mysqli_query($db, $q9);
if ($confirm != 'false') {
header('Location: schedules_' . $sport . '_' . $league . '.html?league=' . $league .'&table=' . $table);
} else {
echo "The scores could not be reported due to a system error. Apologies for the inconvenience. If this problem continues, please contact us directly.";
}
} else {
echo "Your school and password combination do not match those on file for this game.";
}
}
mysqli_close($db);
?>
My guess is that these coaches are simply clicking the submit button multiple times while the form is waiting for a response from the server. You could use JS to disable (or hide) the button after the first click:
var button = document.querySelector('input[type=submit]'); // Use whatever selector is appropriate here
button.addEventListener('click', function(ev) {
if (!button.classList.contains('submitting')) { // If this is our first click...
button.className += ' submitting';
} else { // Otherwise prevent submission
ev.preventDefault();
}
});
If you have jQuery available to you, you could also just handle the entire submission process via JS and block it there.
You should be aware of presenting some sort of feedback onto the screen to let the user know that a submission is currently in progress, that'll help alleviate some button mashing as well.
One solution is to add a unique value to the form and when its submitted, add the value to a session. If they hit submit button more than once ( probably what is happening ), it will accept only one submition
Example:
<form>
<input type="hidden" name="submit_id" value="<?php echo mt_rand(); ?>">
// rest of the form
</form>
Php file recieving:
<?php
session_start();
if ( isset( $_POST['submit_id'] ) ) {
if ( !isset( $_SESSION['submit_id'] ) ) {
$_SESSION['submit_id'] = array();
}
if ( !in_array( $_POST['submit_id'], $_SESSION['submit_id'] ) ) {
// validate posted values
// when data is valid, register form as submitted
$_SESSION['submit_id'][] = $_POST['submit_id'];
// add the submitted form data to database
}
else {
echo 'Your data has already been submitted';
}
}
I don't want to read your code so I'll suggest a strategy.
I agree with #relic. Your coach is probably double-clicking the button.
If you can assume that different users will never submit two forms in the same second, then you can "filter" your table to accept only one entry for any given second. Make an index for the (new) seconds column, and make it unique. This will prevent insertions of rows to that table if an entry already exits for that second.
If this leads to conflicts, you can introduce restrictions that enforce every entry to be unique for a combination of other fields in the table. This is called compound keys (SQL). You formulate something like, for this game and user, there can only be one score registration.
MySQL:
create table scores (game_id int, user_id int, score int );
alter table scores add unique index uniq_gus (game_id, user_id, score);
insert into scores (game_id, user_id, score) values (1, 1, 10);
insert into scores (game_id, user_id, score) values (1, 1, 10);
ERROR 1062 (23000): Duplicate entry '1-1-10' for key 'uniq_gus'
In addition, you may want to prevent double-submissions (assuming jQuery):
(function($){
var btn = $('button[type="submit"]');
btn.click(function(event){
event.preventDefault();
btn.attr('disabled','disabled');
$.ajax({
url: 'http://foo.bar/form-endpoint.php',
success: function (data, status, xhr) {
btn.removeAttr('disabled');
},
})
})
})(jQuery);

Getting UserID when posting to MySQL

I'm looking to get other information when logging into my database. I'm looking to get the TechID of the tech that has successfully signed in and store it within "output" in the second section. Wondering if you could help.
PHP:
$myusername=$_POST['username'];
$mypassword=$_POST['password'];
$myusername = stripslashes($myusername);
$mypassword = stripslashes($mypassword);
$myusername = mysql_real_escape_string($myusername);
$mypassword = mysql_real_escape_string($mypassword);
$sql="SELECT TechNo, TechName, TechUser,TechPass FROM $tbl_name
WHERE TechUser='$myusername' and TechPass='$mypassword'";
$result=mysql_query($sql);
$count=mysql_num_rows($result);
if($count==1)
{
echo "***TechID goes here";
}
else
{
echo 'false';
}
Post Method:
function checkEvents()
{
var username = $("#username").val();
var password = $("#pass").val();
$.post('checklogin.php', {username: username, password: password},
function(output){
if(output == 'false')
{
Win('#geteventslogin', 0);
popupcetion('#loginfailed', 1);
}
else
{
Win('#geteventslogin', 0);
alert(output); ///output = TechID number.
popupcetion('#getevents', 1);
}
});
}
What im trying to do is display a list of jobs from another database, each tech is assigned jobs and i want only to display the correct jobs for that tech. This question has probably been asked before. If you could point me towards a post or answer my question, i would be much appreciative.
Thanks in advance.
I think your code should look like this
$sql="SELECT TechID FROM $tbl_name
WHERE TechUser='".$myusername."' and TechPass='".$mypassword."'";
$result=mysql_query($sql);
$count=mysql_num_rows($result);
if($count==1)
{
$row = mysql_fetch_assoc($result);
echo $row['TechID'];
}
else
{
echo 'false';
}
Hope it will help.
I think you should take more care about stripslashes and echoing variables:
$myusername=$_POST['username'];
$mypassword=$_POST['password'];
$myusername = get_magic_quotes_gpc() ? stripslashes($myusername) : $myusername;
$mypassword = get_magic_quotes_gpc() ? stripslashes($mypassword) : $myusername;
$myusername = mysql_real_escape_string($myusername);
$mypassword = mysql_real_escape_string($mypassword);
$sql="SELECT TechNo, TechName, TechUser,TechPass FROM $tbl_name
WHERE TechUser='$myusername' and TechPass='$mypassword'";
$result=mysql_query($sql);
if( mysql_num_rows($result) )
{
$fields = mysql_fetch_assoc($result);
echo "TechID = ". htmlspecialchars($fields['TechNo']); // or 'TechID' !?
}
else
{
echo 'false';
}
;)

Check if user exists with AJAX and PHP

I am trying to create a signup form that checks if the user exists in the database, I inserted a sample user and when I tried signing up with that user it didn't say its already been taken. What have I done wrong?
The JavaScript:
function formSubmit()
{
document.getElementById('email_valid').innerHTML = '';
var temail=document.forms["signup_form"]["temail"].value.replace(/^\s+|\s+$/g, '');
var atpos=temail.indexOf("#");
var dotpos=temail.lastIndexOf(".");
if (atpos<1 || dotpos<atpos+2 || dotpos+2>=temail.length)
{
//alert("Not a valid e-mail address");
setTimeout(function(){document.getElementById('email_valid').innerHTML = '<br/>Email must be valid...';},1000);
var temailsub=0;
}
else
{
$.post('/resources/forms/signup/email.php',{email: temail}, function(data){
document.getElementById('email_valid').innetHTML = data;
if(data.exists){
document.getElementById('email_valid').innetHTML = '<br/>The email address you entered is already in use.';
var temailsub=0;
}else{
var temailsub=1;
}
}, 'JSON');
}
if(temailsub==1e)
{
setTimeout(function(){document.getElementById("signup_form").submit();},1000);
}
else
{
return false;
}
}
The PHP file (email.php):
<?php
header('content-type: text/json');
require_once $_SERVER['DOCUMENT_ROOT']."/resources/settings.php";
$query = $pdo->prepare("SELECT * FROM users WHERE email=:email");
$query->execute(array(
":email"=> $_POST['email']
));
echo json_encode(array('exists' => $query->rowCount() > 0));
?>
I have checked and double checked the code, I still cannot see why its not detecting that the email has already been used... what do i need to do to fix this and avoid this in the future?
The problem is that PDOStatement::rowCount() returns the number of rows affected by the last SQL statement. You are performing a SELECT so this value will always be 0. SELECT does not affect any rows. Instead you need to count the number of rows:
$query = $pdo->prepare("SELECT COUNT(*) FROM users WHERE email=:email");
$query->execute(array(
":email"=> $_POST['email']
));
$rows = $query->fetchColumn();
echo json_encode(array('exists' => $rows);
Also from jtheman's comment above, you should replace innetHTML with innerHTML in your JavaScript.

Categories

Resources