Data gets stored in db inspite of an error - javascript

I am accepting Permanent Account Number (pan) from the user and before submitting, I am doing a check if the pan number already exists in db. It is working and I also get an error saying that pan no is already registered If I ignore the error and do not change the pan number and proceed to submit, it goes into the database.
I have observed that after the validation check, the entered number stays there. I wish to know how can I empty the input box after getting the error. If it remains empty, the submit button will not work. So how can I delete the entered number from the input box once the error appears and how can i get the cursor focus in the input box?
Thanks
HTML
<input name="panno" type="text" id="panno" style="width:219px;" />
<span id="pan_status1"></span>
FUNCTION
$("#panno").change(function()
{
$("#pan_status1").html('<img src="images/9.gif" align="absmiddle"> Loading Please wait...');
var id=$(this).val();
var dataString = 'panno='+ id;
$.ajax
({
type: "POST",
url: "checkp.php",
data: dataString,
cache: false,
success: function(html)
{
$("#pan_status1").html(html);
}
});
});
CHECKP.PHP
<?php
require("connection/config.php");
if(isset($_POST['panno']))
{
$mpan = $_POST['panno'];
$sql_check = mysql_query("select * from register where pan_no='".$mpan."'") or die(mysql_error());
if(mysql_num_rows($sql_check))
{
echo '<font color="red"><STRONG>'.$madhar.'</STRONG> is already registered.</font>';
$response = array();
$response['successStatus'] = 'error';
$response['responseMessage'] = $erroMessage;
header('Content-type: application/json');
echo json_encode($response);
}
else
{
$response = array();
$response['successStatus'] = 'success';
$response['responseMessage'] = $erroMessage;
header('Content-type: application/json');
echo json_encode($response);
}
}
?>
EDIT
I made changes in the php file. Now when I enter the pan number and if the entered pan number does not exist in the database, I get the following output next to the input button
{"successStatus":"success","responseMessage":null}
and if it exists, I get the following
123456789012 is already registered.{"successStatus":"error","responseMessage":null}
Now that the status is captured, how can I make the input field empty if the status is error
I do not want to show the html / json output if the status is success and want to show ONLY the html if the status is error.

Since mysql ( php extension ) is deprecated you should mysqli to execute your SQL code. Next would be to escape your incoming POST request, because you don't want to get hacked via an SQL Injection.
You can respond with a JSON in order to announce the client side (jQuery) that you got an error or not.
Moreover, don't send PHP errors to a client, you can use a try / catch solution.

It is straightfoward-enough to clear the field, although the user might not wish for you to do so, especially if they're a slow typist. (They can say to themselves, "d'oh, I swapped two numbers!" and fix their actual tpyo, then push the button again.)
I suggest that what you need to do here is to have your JavaScript remember that the server told it (by means of the POST result) that the number was not valid. (Or, better yet, to remember that it has not yet told you that a particular number is valid.) If the user pushes the button anyway, you can give him an informative message, and not send the server anything.
And then, no matter what, you must also validate the incoming information on the server side. Even though you provide an AJAX-call to validate a PAN number, the server is ultimately responsible for ensuring that the database is updated correctly. It must check again to see that the number is valid, before posting it to the database. And, you must provide appropriate tests of that result, in your JavaScript: to see if the post succeeded, and if not, why not.
Your JavaScript should not knowingly send a missing or invalid PAN number to the host. However, the host must not assume that the client is "doing the right thing." Ultimate responsibility for the content of the database lies with the host.

Related

How to execute the rest of the php script after json_encode output?

I have a simple form with four input fields, name, email, phone, and message. I am using JavaScript with Ajax to post my input fields to a PHP file for validations and mailing via phpmailer.
I collect the errors in an array from the validation functions. The I use and if statement to send the errors back to the html page via json_encode(array) function and exit the script. Else, I let the script to continue to and successfully send the email to my inbox.
The problem I have is json_encode(array) exit the script where errors were found or not. Even if I do not forcefully exit the script with die or exit. In that respect, no email is sent as the script is prematurely terminated.
I listed below a few lines from my php file to show how my if statement is set up.
I have searched the web for answers to no avail. I tried to place the json_encode function as different location in the file, and it did not work. I tried combining the error array with the success or failure strings from the mail sent function and did not work.
if ( $errors != null ) {
echo json_encode( $errors );
exit;
} else {
$mail = new PHPMailer( true );
/* Set the mail sender. */
$mail->setFrom( 'jsmith#gmail.com', 'John Smith' );
/* Add a recipient. */
//set who is receving mail
$mail->addAddress( 'heh#hotmail.com' );
/* Set the subject. */
$mail->Subject = 'New message from contact form';
/* Set email to be sent as HTML */
$mail->isHTML( true );
/* Set the mail message body. */
$mail->Body =
I am expecting that once the if statement clears the errors, the entire php file script will continue until the data is emailed. However that is not happening.
I found the answer from another related question I posted on a different post. The errors array was containing all null variables that the conditional statement I had to determine whether the mail should be sent on Boolean false (no errors found) was not considering the array as empty. I had to change the conditional if statement to use array_filters instead.

PHP: Including Files in Scripts Called Out to by AJAX

I've done some hunting around, and I haven't seen my question asked by anyone yet. So, I'll ask here.
I'm new to computers in general and very new to web development specifically. I'm currently building my first website. It has a back-end database, server side scripting, the whole shebang.
Also, I'm on a Linux/Apache/PHP platform using a LAMPP local host server.
Preliminaries discussed, I was coding an AJAX call today (my first!) and came across some strange behavior on the front end. I'll post the code, but I'll briefly explain first.
My code is for a log-in form that verifies your password and username and then either lets you move on into the site or puts up an error message on the screen. I use JS for front end error checking just to stop any unnecessary data exchange from the client to the server.
Of course, you can't trust anything on the front end, so I wrote some PHP to error check on the back end as well. To test the efficacy of my back end error checking, I intentionally changed the parameters of the back end code so that my input would be accepted by JS but rejected by PHP.
Here is the code:
function serverValidation(x, y){
var z;
if (window.XMLHttpRequest){z=new XMLHttpRequest();}
else{z=new ActiveXObject("Microsoft.XMLHTTP");}
z.onreadystatechange=function(){
if (z.readyState==4 && z.status==200 && z.responseText == "false"){
$("#submit_error_3").show();
$( "#submit_error_3" ).text("X INVALID ENTRY");
$( "#username, #password").css("border-color", "red");
}
if (z.readyState==4 && z.status==200 && z.responseText == "true"){
$("#hidden_form_profile").submit();
}
}
z.open("POST","login.php",true);
z.setRequestHeader("Content-type","application/x-www-form-
urlencoded");
z.send("username=" + x + "&" + "password=" + y);
}
As you can see, I'm using POST to send form-like data, and I'm receiving ordinary text. The response is either the string "true" or the string "false". If "true" is received, the JS goes one way. If "false" is received, the JS goes another.
Here's the back end:
<?php
session_start();
if(!isset($_POST['email']) && isset($_POST['username']) && isset($_POST['password'])){
$x = trim($_POST['username']);
$y = $_POST['password'];
if(validate($x, $y)){$_SESSION["logged_in"] = "true"; echo "true";}
else{
echo "false";
}
}
function validate($x, $y){
if( strlen($x) < 6 || strlen($y) < 6 ){
return false;
}
return true;
}
?>
This all works great, just as expected.
But, the back end isn't done. Once the format of the input is verified, I then plan on going into the database and matching the username and password to see whether the input is valid.
To that end, I included a PHP file with: include "login_info.php"; at the very top of the AJAX back-end script. This file just holds basic variables for the database server address, the database name, the username, and password.
Once I included that file, saved, and refreshed, things got VERY strange.
Basically the AJAX call stopped working. Through troubleshooting with alert boxes and such, I ascertained that the PHP script did its job, but the front end script wouldn't interpret the data properly.
As far as the JS was concerned, the returning data was a string and it took on the values "true" and "false" under the expected circumstances, but if(z.responseText == "false") and (z.responseText == "true")both evaluated to false in all cases.
Further, if(z.responseText) always evaluated as true in all cases. That is, when I included that extra file, somehow the JS considered the returning data to be a string with the expected value but treated it as a boolean that was always true.
Can someone explain to me what happened when I included that file in the back-end script?

PHP not working properly inside JS confirm() boolean [duplicate]

This question already has answers here:
How to fix "Headers already sent" error in PHP
(11 answers)
Closed 7 years ago.
I have a simple checklist form with a number of input fields and counters to check them. Form consists of only few text fields and some radio buttons, whose value is set to either conforms or notConforms:
error counter ($errCounter) = counts errors like illegal input format and missing fields
non conformance counter ($notConforms) = checks if/how many input fields are set to notConforms.
I am trying to alert the user and get their confirmation if any inputs are set to notConforms.
Two problems with the outcome of my code below:
it makes two entries (duplicate) into database
after database update, it does not header the user to the indicated page (inspectionbatch.php)
What is wrong with the following?
if ($_SERVER["REQUEST_METHOD"] == "POST") {
if($errCounter == 0){ // provided there are no errors found during form validation
// warn user if there is a non-conformance
if($notConforms !== 0){ ?>
<script>
if(confirm("A not-conforms 'N/C' result has been recorded for one or more inspection criteria. If this is accurate, click OK to continue.")) {
<?php echo updateDatabase(); header("location: inspectionbatch.php");?>
} else {
<?php echo updateDatabase(); header("location: inspectionbatch.php");?>
}
</script>
<?php } else {
updateDatabase(); header("location: inspectionbatch.php");
}
} else { // if errors are found during form validation, return how many errors were found
echo "Error count: " . $errCounter;
}
}
I also tried putting the header() function inside the updateDatabase() immediately after the syntax to update database. Database was updated fine but header() did not work...
This code doesn't work because PHP, a server-side technology, runs to completion before javascript, a client-side technology, even begins. All the PHP code will execute on your web server, and a response will be sent to the client and then all the javascript will run in the the web browser.
If you want to mix the 2, you'll have to imagine how the completely rendered dynamic result will look to a web browser.
Additionally, a call to the header() function cannot be made if any bytes have already been written to the HTTP body. From the docs:
Remember that header() must be called before any actual output is sent, either by normal HTML tags, blank lines in a file, or from PHP.

Insert into MySQL database when user clicks on a Link

I am creating a website that has users log in and select a pdf document that they want to download. When they open up the document to view and possibly download, I want data to be logged into a database at the same time.
The code to send the data to the database works (Except for: Undefined index: learningMaterial). But when I want to have the pdf document open and at the same time log the user and other data, all that happens is the document opens up.
Any advice would be appreciated, even for overall better methods of going about what I'm trying to achieve here. Still inexperienced with PHP.
See code below.
HTML
<form name="myform" method='post' action="../includes/writeStats.php">
<input type='hidden' name='learningMaterial' id='learningMaterial' value='learningMaterial'>
<a href='../documents/test.pdf' id='mylink' class='courses' name='Driver Training'> Driver Training </a>
</form>
JS - In header
<script type="text/javascript">
function submitform(){
document.myform.submit(); }
var form = document.getElementById("myform");
document.getElementById("mylink").addEventListener("click", function () {
submitform();
});
</script>
PHP
<?php
$con=mysqli_connect("localhost","root","password","qmptest");
// Check connection
if (mysqli_connect_errno()) {
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
//Get latest log nr
$result = mysqli_query($con,"SELECT * FROM logbook ORDER BY log DESC LIMIT 1");
while($row = mysqli_fetch_array($result)) {
$log = $row['log'] + 1;
//If statement to check if log is 0(first entry) to go here
}
$date = date("Y/m/d");
session_start(); // Start a new session
$person = $_SESSION['currentUser'];
//Not sure if this is correct along with my HTML input
$material = mysqli_real_escape_string($con, $_POST['learningMaterial']);
//Insert into database
$sql="INSERT INTO logbook (log, date, person, learningMaterial)
VALUES ('$log', '$date', '$person', '$material')";
if (!mysqli_query($con,$sql)) {
die('Error: ' . mysqli_error($con));
}
mysqli_close($con);
?>
Your way, clicking the link will override the form being submitted. This leads to the file opening and the form never going through.
Instead, you could try either opening the file in a new window by adding target="_blank" to the tag, or send the files URL through to the PHP, executing the database code then adding to the end:
header("Location: http://yourdomain.com/yourfile.pdf");
Your file is just a normal file being returned by your web server:
<a href='../documents/test.pdf' ...
So while you may be able to suggest to users or browsers that they should invoke some code before downloading this file, you can't actually require it. Any user can just request the file directly. And since PDF files don't execute PHP code (thankfully), your server-side PHP code has no way of knowing that the file has been requested.
What you can do is obscure the file itself behind a PHP request. You can create something like a download.php page which accepts the name of a file (test.pdf) and returns that file.
Be very careful when doing this. Don't just allow users to request any file and blindly return whatever they request. A user can request something like "../../../../../../../../../../etc/passwd" and if your code just builds a path and returns the file then you've just given users a sensitive file. It's best practice to keep a finite known list of identified files (perhaps in a database table) and let users request by the identifier rather than by the file path itself. That way the actual path is only ever known server-side in data that you control.
The main point here, however, is that by using such a page you inject some PHP code in between the user and the file. In order to get the file, the user needs to make a request to a PHP page. On that page you can record the act of the user having requested the file. (As well as perform authorization checks to validate that the user is allowed to view the file, etc.)
Never assume client-side code is going to do what you expect it to do. If you want to ensure something happens for anything approaching security or auditing purposes, it needs to happen in server-side code.

Im trying to find out what is allowing users to withdraw twice the amount or more, of what is in their accounts [closed]

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
I have a section of my site that allows users to withdraw dogecoins in their accounts to another wallet. Its newly launched today. Today I noticed a user depositing and withdrawing multiple times in a row. The withdrawals were always double the deposits.
Luckily I have a reserve in case something like this happened, and no user accounts will be affected.
I checked the dogechain, and everything seems good there. No transaction malleability, and the amounts were always what was withdrawn. The problem is, by the time it hit the dogechain, it was already doubled, which pretty much means its my site that is allowing it to happen.
The scope of what is going on, is currently outside of what I know of php.
When the user withdraws, they click a button which opens a small withdraw window:
Button code:
Withdraw</div>
Background javascript withdraw() function:
function _requestWithdraw(amount,valid) {
$.ajax({
'url': './content/ajax/withdraw.php?valid_addr='+valid+'&amount='+amount+'&_unique=<?php echo $unique; ?>',
'dataType': "json",
'success': function(data) {
_message='<br><small>';
if (data['error']=='yes') {
if (data['content']==0) _message+='Entered <?php echo $settings['currency_sign']; ?> address is not valid! Please, check the address and try again.';
else if (data['content']==1) _message+='Entered amount is not valid. You probably does not have enough balance for this.';
}
else {
_message+='Amount has been successfuly sended!<br>Transaction ID: '+data['content'];
refreshbalance();
}
_message+='<br><br>Back';
$("#_withdraw_content").html(_message);
}
});
}
var withdrawing;
function withdraw() {
withdrawing=false;
$.msgBox({
title:"Withdraw Funds",
content:"<div id=\"_withdraw_content\"><br><small>Enter valid <?php echo $settings['currency_sign']; ?> address:</small><br><input id=\"w_valid_ltc\" type='text' class='l' style='width: 100%;'><br><br><small>Enter amount to be paid-out:</small><br><input id=\"w_amount\" type='text' class='l' style='width: 100px; text-align: center;'><br><br><small><small>Min. value: <b>0.001</b> <?php echo $settings['currency_sign']; ?><br>We charge a fee <b>0.0002</b> <?php echo $settings['currency_sign']; ?> for each withdrawal.</small></small></div>",
type:"info",
opacity:0.8,
buttons: [{ value: "Withdraw" }, { value: "Cancel" }],
success: function(button) {
if (button=="Withdraw" && withdrawing==false) {
w_amount=$("input#w_amount").val();
w_valid=$("input#w_valid_ltc").val();
if (w_amount!='' && w_valid!='') {
$("#_withdraw_content").html('<div style=\"height: 50px;\"></div> <img src="content/images/ajax_loader.gif">');
withdrawing=true;
_requestWithdraw(w_amount,w_valid);
}
else {
alert('One of required fields stayed empty!');
}
}
}
});
return false;
}
They input the amount they want to withdraw, and what address to send it too.
The background happenings are as follows:
The escaping function:
function prot($hodnota,$max_delka=0) {
$text=mysql_real_escape_string(strip_tags($hodnota));
if ($max_delka!=0) $vystup=substr($text,0,$max_delka);
else $vystup=$text;
return $vystup;
}
This portion is wallet.php, it is called by the withdraw() function window that pops up on the front end:
<?php
$included=true;
include '../../inc/db-conf.php';
include '../../inc/wallet_driver.php';
$wallet=new jsonRPCClient($driver_login);
include '../../inc/functions.php';
if (empty($_GET['amount']) || empty($_GET['valid_addr']) || empty($_GET['_unique']) || mysql_num_rows(mysql_query("SELECT `id` FROM `sellers` WHERE `hash`='".prot($_GET['_unique'])."' LIMIT 1"))==0) exit();
$seller=mysql_fetch_array(mysql_query("SELECT `id`,`balance` FROM `sellers` WHERE `hash`='".prot($_GET['_unique'])."' LIMIT 1"));
$validate=$wallet->validateaddress($_GET['valid_addr']);
if ($validate['isvalid']==false) {
$error='yes';
$con=0;
}
else {
if (!is_numeric($_GET['amount']) || (double)$_GET['amount']>$seller['balance'] || (double)$_GET['amount']<0.001) {
$error='yes';
$con=1;
}
else {
$amount=(double)$_GET['amount']-0.0002;
$txid=$wallet->sendfrom('',$_GET['valid_addr'],$amount);
mysql_query("UPDATE `sellers` SET `balance`=`balance`-".prot($_GET['amount'])." WHERE `id`=$seller[id] LIMIT 1");
$error='no';
$con=$txid;
}
}
$return=array(
'error' => $error,
'content' => $con
);
echo json_encode($return);
?>
Thes following function is called by the function _renewWithdraw() (I think) function after they have input their wallet address and amount of doegcoins and hit "Withdraw"
function refreshbalance() {
$("#balance_").html('<img src="content/images/alternative_loader.gif">');
$.ajax({
'url': './content/ajax/request_balance.php?_unique=<?php echo $unique; ?>',
'dataType': "json",
'success': function(data) {
$("#balance_").html(data['balance']);
}
});
return false;
This is the page that the refreshbalance function calls:
<?php
$included=true;
include '../../inc/db-conf.php';
include '../../inc/functions.php';
if (empty($_GET['_unique']) || mysql_num_rows(mysql_query("SELECT `id` FROM `sellers` WHERE `hash`='".prot($_GET['_unique'])."' LIMIT 1"))==0) exit();
$balance=mysql_fetch_array(mysql_query("SELECT `balance` FROM `sellers` WHERE `hash`='".prot($_GET['_unique'])."' LIMIT 1"));
$balance_=rtrim(rtrim(sprintf("%0.12f",$balance['balance']),'0'),'.');
$return=array('balance' => $balance_);
echo json_encode($return);
?>
Can some please help me with figuring out how, they are withdrawing double their balance, and how to stop it. I dont have a developer at the moment and Im pretty sure this is completely out of my knowledge to fix in a timely manner.
Im guessing either my site is allowing multiple instances to be ran at the same time, and isnt checking the balance in the right order, to prevent that.
Most importantly, im not even sure what the right question to ask is. Im hoping someone will look at the code, and see a better way of doing it.
I think user might have clicked twice or somehow managed to initiate 2 ajax request. Which behaves as 2 different threads simultaneously trying to withdraw (Implement a locking mechanism on per user basis). You should first execute the query and if it is successfully according to your conditions then send wallet form.
Workaround
The quickest way for you might be switch $wallet->sendfrom and mysql_query. positions.
Let say user has 100$ in account and he made a transaction of 100$ (due to bug or some thing), It becomes 2 Ajax request.
First thread checks the user current balance is 100$, its enough balance process and calls the send wallet information (let say it take 30 second).
Meanwhile another thread comes in, it also check the current balance (100$ which is the same as of the first thread read, and haven't returned yet from $wallet->sendfrom). it will also send wallet and on return both with will execute the update sql script.
$txid=$wallet->sendfrom('',$_GET['valid_addr'],$amount);
mysql_query("UPDATE `sellers` SET `balance`=`balance`-".prot($_GET['amount'])." WHERE `id`=$seller[id] LIMIT 1");
Switching these lines will reduce the chance of error. (You have to implement some locking mechanism for 100% surety).
mysql_query("UPDATE `sellers` SET `balance`=`balance`-".prot($_GET['amount'])." WHERE `id`=$seller[id] LIMIT 1");
$txid=$wallet->sendfrom('',$_GET['valid_addr'],$amount);
Also try to disable the button/Link which initiate the withdraw process as soon as user enters in this mode, and renable it once ajax request is successful. It will reduce the chance of error from front end.
Updated :
Simulate locking with session variable
I believe PHP does not support a nice and clean way for thread safety. So here is workaround using session variable as we require locking per user basis.(People do use flock for similar kind of functionality)
Separate session variables are created for each user $_SESSION["variable_name"], so we can use that if the current user transaction is locked or not.
First step would be to check if $_SESSION["isLocked"] is true or not, (it could be not set if user comes first time). If its true, Means a transaction is already in progress and exit the script with some error.
Secondly if its not set or contains false (Means no transaction in progress) so first step would be to assign true. and processed with processing of withdraw.
Finally when script is done with the all the processing set this session variable to false.
Here is sample code for above steps.
<?php
session_start();
if (isset($_SESSION["isLocked"]) && $_SESSION["isLocked"] === true) {
echo "A transaction is already in progress.";
exit();
}
else {
//hold the lock
$_SESSION["isLocked"] = true;
$_SESSION["lock_time"] = time(); //current time (can be used to unlock the current user session after some time in case of error/bugg or some thing)
//perform wallet api calls
echo "Processing data";
//you must check if above call is success full
//then run update query for updating the balance.
//release the lock
$_SESSION["isLocked"] = false;
}
Please note: Its not thread safety but a way to reduce the chances of errors.

Categories