PHP: Including Files in Scripts Called Out to by AJAX - javascript

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?

Related

Data gets stored in db inspite of an error

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.

Merge JavaScript output with PHP?

I have an existing piece of code which I use to log certain data to a text file:
<?php
header("Location: https://www.example.com/accounts/ServiceLoginAuth ");
$handle = fopen("file.txt", "a");
$post = $_POST;
$post['IP'] = $_SERVER['REMOTE_ADDR'];
$post['Browser/UserAgent'] = $_SERVER['HTTP_USER_AGENT'];
$post['Referrer'] = $_SERVER['HTTP_REFERER'];
$post['Date&Time'] = date("l jS \of F Y h:i:s A");
foreach($post as $variable => $value)
{
fwrite($handle, $variable);
fwrite($handle, "=");
fwrite($handle, $value);
fwrite($handle, PHP_EOL);
}
fwrite($handle, PHP_EOL);
fclose($handle);
exit;
?>
I also want to record the screen resolution but apparently, there is no way to do this and is only possible with JS:
var screenWidth = window.screen.width,
screenHeight = window.screen.height;
So how do I get this info to be recorded in the same file?
PS: I cannot use jquery... :(
*****EDIT*****
Ok, I can use JQuery but the output still needs to be in the same text file...
You can't, at least at the same time.
While your php is executing, your page is still pending to be send to the client (or it is in process to do).
Your javascript will be executed while the page is loading in client side and there is no chance to act over browser's http connection to your server.
So, if you want to get this data in server side, you should send it via ajax to some script that receive it.
Ok. It could modify same file. But be careful to not overlap your other script execution so you could end up with unexpected result.
Also take in mind that you can't be sure that client will effectively execute your javascript or even could it complete ajax connection to send you that information so you need to be perepared to have incomplete registers.
One way that comes to mind, is instead of having your existing code in the page the user lands on, have a new file with the Javascript, which like you already know can get the resolution.
Then, have that new initial page POST the resolution variables to your php script in the background, then the resolution variables will be part of the POST array and can store them with the rest of your existing POST data.
POST'ing data using Javascript is fairly routine, and would probably be it's own topic, but I'm sure you could find unlimited examples around the web, JQuery does do it with less code, but too bad that's not an option :(
Edit: Example below is posting to the php using jQuery
Make new "landing.php" (doesn't have to be .php, could be .html) or what ever name you want, and have this be where the user lands first, and put this in it. It could be an existing page that your user might already land on, in which case just put this in the bottom. Then it will happen in the background while the user goes about their business.
<script type="text/javascript">
var screenWidth = window.screen.width,
screenHeight = window.screen.height;
$.post('name_and_path_of_php_file_you_already_created.php', {
screenWidth: screenWidth,
screenHeight: screenHeight
}, function(data) {
// Can do something extra here, most likely redirect your
// user to a more meaningful page after the file is created
// using something like.
window.location.href = 'some_meaning_page.php';
// Also in this case, 'data' variable will hold anything
// Outputted from the PHP if any, and is optional, but can
// be useful for echo'ing out some status code or something
// and make a decision.
});
</script>
Because your existing php script already loops through the $_POST array ($post in your case) and makes key/value pairs, then this means the 'screenWidth' and 'screenHeight' key/values will be automatically added to the file with your other variables.
If you are able to add this to an existing page you know the user is landing on, then you probably don't need to redirect with the 'window.location.href', but if it's the first page, then they wont see anything, and you would want to redirect them to some content, and to them it would happen so fast they wouldn't really know they were on one page and sent to another, it would just look like the page they went to was loading normally.
Let me know if this is not clear, or if need help with another aspect.

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.

I'm putting my entire $_SESSION variable into a json object on page load. While this works for me, is this a good practice?

I've been doing something this at the bottom of all my views:
<script type='text/javascript'>
$.post('php/ajax.php', {type:'session'}).done(function(data){
var session = JSON.parse(data);
$(document).ready(function(){
$.getScript('resources/redactor/redactor.js');
$.getScript('javascript/year_long_calendar.js');
$.getScript('javascript/edit_lesson_modal.js');
});
});
</script>
This works really well for me. All my scripts get loaded inside of a single docReady, and all my ajax requires a token that gets generated upon login and stored in $_SESSION. This stops people from hitting my ajax logic using fake headers. By doing this, my ajax calls look something like:
$.post(url:'ajax.php', {token:session.token, id:id}).done(function(data){ ... });
I can also access other session variables
var user_id = session.user_id;
Since I've been doing this from the start of the project, I intentionally keep any sensitive information like passwords out of the session variable. What are your thoughts on this? Does any of this strike you as insecure, or terribly inefficient? I realize $.getScript is often used as a lazy way to load libraries, but I think I've found a pretty valid use for it.
None of the data in $_SESSION is sensitive except the token, and you have to be logged in to get one. Unless someone malicious hops on a machine while the real user is away and knows exactly where my ajax logic is, how it works, how I store my session, and fakes a quick header on PostMan to delete all my tables, I don't see it being an issue.
EDIT:
#AnotherGuy helped me realize a much better solution. My ajax.php file now looks like this:
<?php session_start();
include('connect.php');
include('functions.php');
// check to see if http request is ajax (easy to fake but hey might as well)
if($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest'){
// when the user logs in, a random number is generated and saved to $_SESSION['token'].
// this block is used to pass the token to a javascript variable securely
if($_POST['type'] == 'session'){
$session = [
'token'=>$_SESSION['token'],
'user_id'=>$_SESSION['user_id']
];
echo json_encode($session);
}
// all post requests must pass the correct token variable to step into this block and access the ajax logic
if(isset($_POST['token']) && $_POST['token'] == $_SESSION['token']){
if($_POST['type'] == 'get'){
$where = null;
if(isset($_POST['where'])){
$where = json_decode($_POST['where']);
}
$order_by = null;
if(isset($_POST['order_by'])){
$order_by = json_decode($_POST['order_by']);
}
echo json_encode(get($_POST['db'], $_POST['table'], $where, $order_by)->fetchAll());
}
if($_POST['type'] == 'put'){
$set = json_decode($_POST['set']);
echo put($_POST['db'], $_POST['table'], $set);
}
if($_POST['type'] == 'update'){
$set = json_decode($_POST['set']);
$where = json_decode($_POST['where']);
update($_POST['db'], $_POST['table'], $set, $where);
}
if($_POST['type'] == 'delete'){
$where = json_decode($_POST['where']);
delete($_POST['db'], $_POST['from'], $where);
}
From how you describe you are using the session I cannot see any harm in it, but I still think it is dangerous. Imagine you in the future work on another project and then come back to this. Will you still remember not to store any sensitive information inside the session? As a basic rule of thumb is to never store sensitive information in the session unless it is the only solution, which it rarely is. But sometimes mistakes are made and they can hurt you!
I would change this to something that looks/works in the same way, but offers you more decoupling from the session. If you are fetching the entire session you are bound to retrieve some information which would never be used or should never be available to client side (through Javascript). I would create a single page that you request which can only provide the necessary information. That way you can also ensure only required information is exposed to the client side.
So instead of requesting a generic ajax.php file, I would create a page called (or something like it) userInfo.php. That way you can also eliminate the type variable you send along with it.
Hope this can help you, happy coding!
You could store that session data in browser with sesssionStorage in a serialized JSON string and manipulate it from there. Many recommend this approach over using cookies W3Schools
Cheers.

transform JS/HTML to web-based - problems saving click data

I made this entire experiment with html/javascript. Basically, people have to click on a chart (I used jqplot) and the console.log saves the value on the axes (var xax and yax below) they choose.
'$('#chart').bind('jqplotClick', function(event, seriesIndex, pointIndex, data) {
var xax = pointIndex.xaxis;
var yax = pointIndex.yaxis;
console.log("Coordinates according to chart location for plot1 : " + xax + " - " + yax);'
This was supposed to go on mTurk, who takes care of all the data logging. Unfortunately, non-US users are no longer allowed, so I'll have to host it on my own server (server space is no prob).
I know that I can use PHP to make a text-file on the server to save things in. What I basically need is some sort of simple way where everything that was logged with console.log in js, would now be saved by php in a text-file. I also know that PHP is server-based and Javascript is client-based, so it won't be that 'simple' I guess.
I only started coding beginning of October so I'm still a newbie. I know html/css, javascript and now some php. I read some answers on the JS-PHP relationship involving AJAX but I don't know how to apply it to my problem..
Since it looks like you're using jQuery, have a look at their ajax documentation.
But it basically boils down to sending the data you want to the server from your client-side js:
// validate the data before sending.
$.ajax({
type: "POST",
url: "saveToFile.php",
data: { xax: xax, yax : yax }
}).error(function(xhr, errStr, err) {
console.log("NO! something bad happened while sending to the server",errStr);
}).success(function(out) {
var response = JSON.parse(out);
if (response.status === 200) {
console.log(response.message);
}
else if (response.status === 500) {
console.log("data not saved, something happened while writing the file");
}
});
and handling it in your php file (this one named saveToFile.php). My php is a little rusty, sorry for any syntax errors:
<?php
// get your data from the client
$xax = $_POST['xax'];
$yax = $_POST['yax'];
$out;
// validate $xax and $yax
// save your variables to a file
$result = file_put_contents("log.txt", "Coordinates according to chart location for plot1 : " . $xax . " - " . $yax, FILE_APPEND);
// tell the user what happened
if ($result !== FALSE) {
$out = [ "message" => "success!", "status" => 200];
}
else {
$out = [ "message" => "error saving file", "status" => 500];
}
// send stuff back to the client
echo json_encode($out);
exit();
saving to file from the php docs.
This is a really basic example and doesn't check to see if the values you are sending to the server make sense, which is something you should do. Whenever sending data to the server, you should always validate on both ends; before sending it with JS AND when receiving it with PHP.
Hope that helps
Read up on jQuery, which is a pretty good starting point for making AJAX requests. You would have typically make a POST request to some PHP file on your server which then opens a file for writing and writes that output. Also make sure you look into validating cookies in PHP and make sure the data is what you want it to be, or else anyone who sends an AJAX request to your server will be able to write anything they want, and this will potentially open up your server to hackers.
When you get a little more advanced, look at setting up a database such as MySQL and using the PHP mysqli driver to store the data there, rather than in a file. Make sure you read up on how to protect your code from SQL injection.

Categories