I have a PHP quiz page which posts answer data on clicking the answer by a function called answer() via ajax then loads the question and answer contents if the answer is correct by loadQuestion() function also via ajax. Here is a part of my code:
<ul class="choices">
<li><span id="a0"><?php echo $questionDetail['a'.$answerOrder[0]]; ?></span></li>
<li><span id="a1"><?php echo $questionDetail['a'.$answerOrder[1]]; ?></span></li>
</ul>
<div id="countdown"><div class="saniyeLoading" style="display: none;"></div></div>
<ul>
<li><span id="a2"><?php echo $questionDetail['a'.$answerOrder[2]]; ?></span></li>
<li><span id="a3"><?php echo $questionDetail['a'.$answerOrder[3]]; ?></span></li>
</ul>
<script type="text/javascript">
function answer(elm){
countdown.stop();
var answer = $(elm).text();
$.ajax({
type: 'POST',
url: "/soru",
data: {act: 'soru', answer: answer},
success:function (data) {
if(data == "success"){
setTimeout(loadQuestion, 300);
} else {
location.href = "/yanlis";
}
}
});
}
function loadQuestion() {
$.ajax({
type: 'POST',
url: "/",
data: {act: 'ysoru'},
success: function (data) {
try {
data = $.parseJSON(data);
$("#questionDetailQuestion").text(data.questionDetail['question']);
$("#a0").text(data.questionDetail['a0']);
$("#a1").text(data.questionDetail['a1']);
$("#a2").text(data.questionDetail['a2']);
$("#a3").text(data.questionDetail['a3']);
$('.saniyeLoading').hide();
countdown.start();
} catch (e) {
}
}
});
}
</script>
My problem here is that people can manipulate the answer() function by writing a simple for loop in the browser developer console. Something like this:
for(i = 1 ; i <= 4; i ++ ) {
$.ajax({
type: 'POST',
url: "/soru",
data: {act: 'soru', answer: $('#a' + i).text()},
success:function (data) {
if(data == "success"){
loadQuestion();
}
}
});
}
I have found a temporary solution by removing onclick="answer(this);" and replacing answer() function with $('.choices a').click(). Then I'm validating if there is a click event in my PHP page by sending the event via my ajax page.
Would there be a better solution to this problem? I've tried tokens but the problem is as I'm loading questions via ajax, I will have to save the token in an hidden input etc, they can get also get the token and send it.
While there is no way you can stop user from using console to manipulate your code. I can suggest following:
You can put server side limit on number of Ajax requests accepted from single user.
Adding captcha code, if you see unusual activity
Obfuscate your code and AJAX call format, so it requires more effort from user to analyze code and will stop most of people
Use dynamically generated image with answers "radio buttons" located at random locations and submitting back x and y position of user click event and use server-side logic to match click position with answer option
Use sessions on the server-side to track each user's correct and incorrect guesses, and enforce the rules.
As long as you rely on the client side to "play nice", you're exposing your application to the will of the end user.
Related
I posted this question ealier today, however I recieved a fix (thank you) that works great against my RequestBin endpoint for testing, however when submitting to my AJAX script, its a different story.
Problem: I cant submit my jQuery toggle values to my PHP AJAX script because there is no form name associated with the POST request (so db never updates). I proven this by making a HTML form with the field names and the database updated right away. However this is not the case with this JS toggle method.
jQuery code
$(document).ready(function() {
$('.switch').click(function() {
var $this = $(this).toggleClass("switchOn");
$.ajax({
type: "POST",
url: "https://--------.x.pipedream.net/",
data: {
value: $this.hasClass("switchOn") ? 'pagination' : 'infinite'
},
success: function(data) {
console.log(data);
}
});
});
});
HTML
<div class="wrapper-toggle" align="center">
<label>
<div class="switch"></div>
<div class="switch-label">Use <b>Paged</b> results instead (Current: <b>Infinite</b>)</div>
</label>
</div>
PHP AJAX script
if (array_key_exists('pagination', $_POST)) {
$stmt = $conn->prepare("UPDATE users SET browse_mode = 'pagination' WHERE user_id = 1");
//$stmt->bindParam(":user_id", $account->getId(), PDO::PARAM_INT);
$stmt->execute();
} else if (array_key_exists('infinite', $_POST)) {
$stmt = $conn->prepare("UPDATE users SET browse_mode = 'infinite' WHERE user_id = 1");
//$stmt->bindParam(":user_id", $account->getId(), PDO::PARAM_INT);
$stmt->execute();
}
I cant figure out how to assign a field name to this, as it is not a traditional post form. This is driving me nuts. So the previous solution was applying hasClass() and calling var $this outside of $ajax(), great (and RequestBin receives both requests), but when submitting to PHP its a dead end (no form names).
Given the code above fixed and revised twice, where do I even start without a form ??
We need:
name="pagination"
name="infinite"
But this toggle JS doesn't allow for this. prop() has been removed to get toggle submitting values over (just not my AJAX script).
Any solution appreciated. Thank you again.
You can set your values as Form Data. So the PHP Function will get it just like a traditional form submission:
$(document).ready(function() {
$('.switch').click(function() {
var $this = $(this).toggleClass("switchOn");
var formdata = new FormData();
$this.hasClass("switchOn") ? formdata.append('pagination', 'name') : formdata.append('infinite', 'name');
$.ajax({
type: "POST",
url: "https://--------.x.pipedream.net/",
data: formdata,
success: function(data) {
console.log(data);
}
});
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
More info on JS Form Data: https://developer.mozilla.org/en-US/docs/Web/API/FormData
I am trying to add a listener to a form so that when the user leaves it, an ajax call is made but nothing seems to be happening. Don't see any errors in firefox and nothing gets console logged when I leave the page which tells me the code is incorrect. Fairly new to jquery (and ajax), hoping someone can show me what I'm doing wrong here.
html: home/folder/index.php
<script>
var rowid = "<?php echo $_SESSION['rowid'] ?>";
var user = "<?php echo $_SESSION['user'] ?>";
</script>
...
<form id="update" method="post" action="index.php?update=1" autocomplete="off">
Jquery: home/scripts/main.js
var end_lock = 0;
$('#update').on('unload', function(){
end_lock = 1;
console.log('error');
});
window.onunload = callAjaxRecordLock;
function callAjaxRecordLock(){
if (end_lock === 1){
$.ajax({
url: 'home/includes/ajax.php',
type: 'POST',
data: {
method: 'ajax_record_lock',
rowid: rowid,
user: user,
endlock: 1
}
});
}
}
php: home/includes/ajax.php
<?php
if (isset($_POST['method'])) {
$_POST['method']();
}
function ajax_record_lock(){
$ajax_rowid = $_POST['rowid'];
$ajax_user = $_POST['user'];
$ajax_endlock = $_POST['endlock'];
if (isset($ajax_rowid) && isset($ajax_user) && isset($ajax_endlock)) {
sp_record_lock($ajax_rowid, $ajax_user, $ajax_endlock);
}
}
Edit:
Found this link https://api.jquery.com/category/events/form-events/ where it appears that beforeunload is not a valid event for a form element. Is there another way to achieve what I need?
You need to make the AJAX call synchronous. If it’s async, it will never execute because the website will, well, unload. With a synchronous request you lock the browser until its made:
async: false
However, I think it’s not a good thing to do. Don’t mess with default client behavior, it’s bad user experience.
I am developing a website for practice, and I would like to know how to use JS to notify the user that the username he picked is already in use, all works fine, if my function(check_username) returns false, the user succesfully registers himself into the site, otherwise the register won't happen.
When the user can't register I would like to know how can I notify the user with a js script.
<?php
//database includes
include_once('../config/init.php');
include_once('../database/users.php');
if(!check_username($_POST['username'])) {
insertUser($_POST['name'], $_POST['username'], $_POST['email'], $_POST['pass']);
}
else header('Location: ../index.php');
?>
One way would be to change your redirect on failure to a javascript message
else
{
echo "<script>alert('Username already exists');</script>";
}
That's a very trivial example to get you started since you mentioned you're learning JS. You can build a lot of improvements on that.
You can set the returns into a javascript variable and use it to display message if the user is not registered.
var x = <?php echo check_username($_POST['username']); ?>;
if(x) {
alert("You are not registered");
}
You can use php ajax for a live notification to users.
<script>
$(document).ready(function() {
$("#InputFieldID").keyup(function (e) {
//removes spaces from username
$(this).val($(this).val().replace(/\s/g, ''));
//Getting value of input field.
var username = $(this).val();
//Check only if the username characters are above 4
if(username.length >= 4){
$("#IndicatorDivID").html('<p style="color:#ffbf25;">Checking..!</p>');
$.ajax({
type: 'POST',
url: 'check_username.php',
data: {"username": username},
dataType: 'json',
success: function (data) {
if(data.response=='true')
alert("Already Exist");
}
});
}
});
});
//Username Checker
</script>
The result fo check_username.php must be in json format.
eg: {"response":"false"}
I m validating email id in php and ajax, and want to return value from php page to html in JSON format.
I want to keep that return value in php variable for the further use.
I'm doing these all in codeigniter, and I want to show .gif image while my AJAX is processing. (Pre loader image)
AJAX/Javascript/jQuery:
function checkEmail(value_email_mobile) {
if (value_email_mobile !== '') {
//alert('te');
$.ajax({
type: "POST",
url: url_check_user_avail_status,
data: "value_email_mobile=" + value_email_mobile,
success: function(msg) {
alert(msg);
//$('#psid').html("<img src='images/spacer.gif'>");
// $('#stat').html(msg);
//
//$('#sid').sSelect({ddMaxHeight: '300px'});
},
error: function() {
//alert('some error has occured...');
},
start: function() {
//alert('ajax has been started...');
}
});
}
}
PHP/Controller:
<?php
function check_email_or_mobile($param)
{
$ci = CI();
$value = $param['email_or_mobile'];
$query = "SELECT user_email , mobile FROM tb_users WHERE user_email = '$value' or mobile = '$value'";
$query = $ci->db->query($query);
if ($query->num_rows() > 0)
{
if (is_numeric($value))
{
return $res = "This mobile number is not registerd";
}
else
{
return $res = "This Email id is not registerd";
}
}
}
This is just to give you an example on how it will work.
First off, (obviously) there must the a preloader image ready inside the document. This must be hidden initially.
Second, before triggering the AJAX request, show the loading animated GIF.
Third, after the request if successful. Hide the image again inside your success: block inside the $.ajax().
Consider this example: Sample Output
PHP:
function check_email_or_mobile($param) {
// your functions, processes, blah blah
// lets say your processes and functions takes time
// lets emulate the processing by using sleep :)
sleep(3); // THIS IS JUST AN EXAMPLE! If your processing really takes time
$data['message'] = 'Process finished!';
// with regarding to storing, use sessions $_SESSION for further use
$_SESSION['your_data'] = $data_that_you_got;
echo json_encode($data); // use this function
exit;
}
// just a simple trigger for that post request (only used in this example)
// you really dont need this since you will access it thru your url
// domain/controller/method
if(isset($_POST['request'])) {
check_email_or_mobile(1);
}
HTML/jQuery/AJAX:
<!-- your animated loading image -->
<img src="http://i600.photobucket.com/albums/tt82/ugmhemhe/preloader.gif" id="loader" style="display: none;" />
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<!-- <script type="text/javascript" src="jquery.min.js"></script> -->
<script type="text/javascript">
$(document).ready(function(){
// before the request, show the GIF
$('#loader').show();
$.ajax({
url: document.URL, // JUST A SAMPLE (url_check_user_avail_status)
type: 'POST',
data: {request: true},
dataType: 'JSON',
// data: "value_email_mobile=" + value_email_mobile,
success: function(response) {
// After a succesful response, hide the GIF
$('#loader').fadeOut();
alert(response.message);
}
});
});
</script>
My assumption is, since this is just a simple email checking, this wont really take a chunk of time. The other way is to fake the loading process.
success: function(response) {
// After a succesful response, hide the GIF
// Fake the loading time, lets say 3 seconds
setInterval(function(){
$('#loader').fadeOut();
alert(response.message);
}, 3000);
}
Let us know what part of your code is not working?
1) Check if the request flow is hitting the function checkEmail? PHP has inbuilt JSON converting utility json_encode. You could start using that.
2) If you want to store this on the server for further use, you could think about usage like
a) Storing it in Database (If really needed based on your requirements. Note: This is always expensive)
b) Session - If you would want this info to be available for all the other users too.
c) Or keep it in the memory like any of the caching mechanisms like memcache etc
3) For displaying the busy display,
// Before the below ajax call, show the busy display
$.ajax({
});
// After the ajax call, hide the busy display.
You could do this using JavaScript / JQuery on your choice.
I remember using
JSON.parse(data)
to convert JSON ino a javascript object.
Jquery has its own JSON parser btw. Something like $.JSONParse(data)
I have a dynamically changing span on a page displaying the number of votes a project has received. On another (target) page i have a list of projects. i want to be able to display that vote count there. i know how to grab the text from the span on the page.
it would be something like this.
<span id="count1"></span>
var prj1c = $("#count1").text;
in know that on the other page i end up using
<?php echo $prj1c(this being after i assign the prj1c var to php somewhere) ?>
i also know i could create a php include page and call it on the target page, though i would like not to create a separate page for each of these instances.
so to sum up: how do i change a JS var to php and call it from another page- remember the text in the span changes (when users vote up or down)?
Try this, use .text() instead of .text
var prj1c = $("#count1").text(); //instead of var prj1c = $("#count1").text;
$.ajax({
type: "POST",
url: "yourpage.php",
data: {count :prj1c},
success: function(response) {
alert("Response "+response);
}
});
in yourpage.php add this <?php echo $_POST['count']; ?>
Update:
$(function(){
$("#count1").click(function(){
window.location='page2.php?count='+$(this).text();
});
});
in page2.php:
<ul>
<li id="projectName">
<img><span>vote count goes HERE: <?php echo $_GET['count']; ?></span>
</li></ul>
You can try with jQuery Ajax request. When user vote up/down you can make an ajax call to the target page.
Eg.
var prj1c = $("#count1").text();
$.ajax({
type: "POST",
url: "targetPage.php",
data: "count="+prj1c,
success: function(response) {
alert("Response "+response);
}
});
Get the prj1c value in targetPage.php
$prj1c = $_REQUEST['count'];
// Follow appropriate steps later in targetPage.php