Somenath Sinha Somenath Sinha - 3 months ago 9
PHP Question

How does the following code work without the proper action attribute being set?

I have a code, in a file called

service.php
which does as follows:

if ((!empty($_POST)) && ($_POST['action'] == 'addRunner'))
{
// Code to add entry into database
}

function fail($message)
{
die(json_encode(array('status' => 'fail', 'message' => $message)));
}
function success($message)
{
die(json_encode(array('status' => 'success', 'message' => $message)));
}


And the file to send the data via POST method using AJAX is:

$("#btnSave").click(function()
{
var data = $("#addRunner :input").serialize();

$.post($("#addRunner").attr('action'), data, function(json)
{
if(json.status == 'fail')
alert(json.message);

if(json.status == 'success')
{
alert(json.message);
clearInputs();
}
},"json");
});


The action attribute of the form
#addRunner
is:

<form action="service.php" id="addRunner" name="addRunner" method="POST">
<!-- Form Elements -->
</form>


Note that the action attribute for the form element is simply
service.php
instead of
service.php?action=addRunner
. However, the form still works perfectly, and successfully adds new "runner" information into the database. How does this happen?

Shouldn't the condition
($_POST['action'] == 'addRunner')
fail and prevent the code to enter data into the database from running?




For the sake of completeness, the entirity of my code is as below.

My HTML is:

<!DOCTYPE html>
<html>
<head>
<title>2011 Race Finishers</title>
<link href="styles/my_style.css" rel="stylesheet">
</head>
<body>
<header>
<h2>2011 Race Finishers!</h2>
</header>
<div id="main">
<ul class="idTabs">
<li><a href="#male">Male Finishers</a></li>
<li><a href="#female">Female Finishers</a></li>
<li><a href="#all">All Finishers</a></li>
<li><a href="#new">Add New Finishers</a></li>
</ul>
<div id="male">
<h4>Male Finishers</h4>
<ul id="finishers_m"></ul>
</div>
<div id="female">
<h4>Female Finishers</h4>
<ul id="finishers_f"></ul>
</div>
<div id="all">
<h4>All Finishers</h4>
<ul id="finishers_all"></ul>
</div>
<div id="new">
<h4>Add New Finishers</h4>
<form action="service.php" id="addRunner" name="addRunner" method="POST">
First Name: <input type="text" name="txtFirstName" id="txtFirstName"> <br>
Last Name: <input type="text" name="txtLastName" id="txtLastName"> <br>
Gender: <select name="ddlGender" id="ddlGender">
<option value="">--Please Select--</option>
<option value="m">Male</option>
<option value="f">Female</option>
</select> <br>
Finish Time:
<input type="text" id="txtMinutes" name="txtMinutes" size="10" maxlength="2">
<input type="text" id="txtSeconds" name="txtSeconds" size="10" maxlength="2">
<br><br>
<button id="btnSave" type="sumbit" name="btnSave">Add Runner</button>
<input type="hidden" id="action" name="action" value="addRunner">
</form>
</div>
</div>
<footer>
<h4>Congratulations to all our finishers!</h4>
<button id="btnStart">Start Page Updates</button>
<button id="btnStop">Stop Page Updates</button>
<br>
<span id="freq"></span><br><br>
Last Updated: <div id="updatedTime"></div>
</footer>
<script src="scripts/jquery-1.6.2.min.js"></script>
<script src="scripts/my_scripts.js"></script>
<script src="scripts/jquery.idTabs.min.js"></script>
</body>
</html>


My jQuery is:

$(document).ready(function(){

var FREQ = 10000 ;
var repeat = true;

function showFrequency(){
$("#freq").html( "Page refreshes every " + FREQ/1000 + " second(s).");
}

function startAJAXcalls(){

if(repeat){
setTimeout( function() {
getDBRacers();
startAJAXcalls();
},
FREQ
);
}
}

function getXMLRacers(){
$.ajax({
url: "finishers.xml",
cache: false,
dataType: "xml",
success: function(xml){

$('#finishers_m').empty();
$('#finishers_f').empty();
$('#finishers_all').empty();

$(xml).find("runner").each(function() {
var info = '<li>Name: ' + $(this).find("fname").text() + ' ' + $(this).find("lname").text() + '. Time: ' + $(this).find("time").text() + '</li>';
if( $(this).find("gender").text() == "m" ){
$('#finishers_m').append( info );
}else if ( $(this).find("gender").text() == "f" ){
$('#finishers_f').append( info );
}else{ }
$('#finishers_all').append( info );
});

getTimeAjax();
}
});
}

function getDBRacers()
{
$.getJSON("service.php?action=getRunners", function(json)
{
if(json.runners.length > 0)
{
$('#finishers_m').empty();
$('#finishers_f').empty();
$('#finishers_all').empty();

$.each(json.runners, function()
{
var info = '<li>Name: ' + this['fname'] + ' ' + this['lname'] + '. Time: ' + this['time'] + '</li>';
if(this['gender'] == 'm')
{
$('#finishers_m').append(info);
}
else if(this['gender'] == 'f')
{
$('#finishers_f').append(info);
}
else {}

$('#finishers_all').append(info);
});
}
});
getTimeAjax();
}

function getTimeAjax(){
var time = "";
$.ajax({
url: "time.php",
cache: false,
success: function(data){
$('#updatedTime').html(data);
}
});
}

$("#btnStop").click(function(){
repeat = false;
$("#freq").html( "Updates paused." );
});

$("#btnStart").click(function(){
repeat = true;
startAJAXcalls();
showFrequency();
});

showFrequency();
getDBRacers();
startAJAXcalls();

$("#btnSave").click(function()
{
var data = $("#addRunner :input").serialize();

$.post($("#addRunner").attr('action'), data, function(json)
{
if(json.status == 'fail')
alert(json.message);

if(json.status == 'success')
{
alert(json.message);
clearInputs();
}
},"json");
});

function clearInputs()
{
$("#addRunner:input").each(function(){
$(this).val('');
});
}

$("#addRunner").submit(function() {
return false;
});

});


And finally the contents of Service.php is:

<?php

if ((!empty($_POST)) && ($_POST['action'] == 'addRunner'))
{
$fname = htmlspecialchars($_POST['txtFirstName']);
$lname = htmlspecialchars($_POST['txtLastName']);
$gender = htmlspecialchars($_POST['ddlGender']);
$minutes = htmlspecialchars($_POST['txtMinutes']);
$seconds = htmlspecialchars($_POST['txtSeconds']);

if(preg_match('/[^\w\s]/i', $fname) || preg_match('/[^\w\s]/i', $lname))
{
fail('Invalid name provided.');
}
if( empty($fname) || empty($lname) )
{
fail('Please enter a first and last name.');
}
if( empty($gender) )
{
fail('Please select a gender.');
}
if( empty($minutes) || empty($seconds) ) {
fail('Please enter minutes and seconds.');
}

$time = $minutes.":".$seconds;
$query = "INSERT INTO runners SET first_name='$fname', last_name='$lname', gender='$gender', finish_time='$time'";
$result = db_connection($query);

if ($result)
{
$msg = "Runner: ".$fname." ".$lname." added successfully" ;
success($msg);
}
else
{
fail('Insert failed.');
}
exit;
}
else if($_GET['action'] == 'getRunners')
{

$query = "SELECT first_name, last_name, gender, finish_time FROM runners ORDER BY finish_time ASC";
$result = db_connection($query);

$runners = array();

while($row = mysqli_fetch_array($result))
{
array_push($runners, array('fname' => $row['first_name'], 'lname' => $row['last_name'], 'gender' => $row['gender'], 'time' => $row['finish_time']));
}

echo json_encode(array("runners" => $runners));
exit;
}

function db_connection($query)
{
$dbc = mysqli_connect('127.0.0.1','runner_db_user','runner_db_password','race_info')
or die('Error connecting to Database');

return mysqli_query($dbc,$query);
}

function fail($message)
{
die(json_encode(array('status' => 'fail', 'message' => $message)));
}
function success($message)
{
die(json_encode(array('status' => 'success', 'message' => $message)));
}

?>

Answer

It will work reason behind this is action is value of name attribute from hidden field. It is not the action of your form tag. If you want to make it fail for testing purpose you should change the value of hidden field to something else in your form and then check again.

This is your hidden field

<input type="hidden" id="action" name="action" value="addRunner">

You can do like this for testing only

<input type="hidden" id="action" name="action" value="addRunners">

It will not satisfy this if condition

if ((!empty($_POST)) && ($_POST['action'] == 'addRunner'))