Data not being saved in DB via PHP form - php

I,ve trying to save some data in my DB, but it just don't save, no error thrown, i used the echo query_orcN; to see if the data that was input by the form is valid, and its all fine, the form can input up to 5 services ($servicoN), so the cod is kinda repetetive, as i am new with php and mySql, expect to see some newbie coding.
I also verified and the logic to choose what if statement will be used is working fine too, so i will post just the case with one service:
...
<?php
include('login/conexao.php');
$nome_cli = $_POST['nome_cli'];
$nome_orc = $_POST['nome_orc'];
$obs_trab = $_POST['obs_orc'];
$servico1 = $_POST['serv1'];
$obs_serv1 = $_POST['obs_serv1'];
$total1 = $_POST['total1'];
$servico2 = $_POST['serv2'];
$obs_serv2 = $_POST['obs_serv2'];
$total2 = $_POST['total2'];
$servico3 = $_POST['serv3'];
$obs_serv3 = $_POST['obs_serv3'];
$total3 = $_POST['total3'];
$servico4 = $_POST['serv4'];
$obs_serv4 = $_POST['obs_serv4'];
$total4 = $_POST['total4'];
$servico5 = $_POST['serv5'];
$obs_serv5 = $_POST['obs_serv5'];
$total5 = $_POST['total5'];
//um serviço
if($servico1 != '' && $servico2 == '' && $servico3 == '' && $servico4 == '' && $servico5 == ''){
$query_orc1 = "START TRANSACTION;
SET #cod_cli = (SELECT cod_cliente
FROM CLIENTE
WHERE nome_cliente = '$nome_cli');
INSERT INTO TRABALHO(nome_trabalho, cod_cliente, obs_trabalho, statuspag_trabalho)
VALUES ('$nome_orc', #cod_cli, '$obs_trab', 0);
SET #orc = LAST_INSERT_ID();
SET #cod_serv1 = (SELECT cod_servicos
FROM SERVICOS
WHERE descri_servicos = '$servico1');
INSERT INTO SERV_TRAB(cod_trabalho, cod_servicos, qtt_serv_trab, obs_serv_trab)
VALUES (#orc, #cod_serv1, $total1, '$obs_serv1');
COMMIT;";
if($resultado_query_orc1 = mysqli_multi_query($conexao, $query_orc1))
{
//echo $query_orc1;
header('Location: sucesso_orc.php');
exit();
}
else
{
echo "<h3>Falha </h3>".$valid;
echo $result_msg_cliente;
}}
...
I'm using myawardspace to host my project, and already set de engine of the tables to InnoDB as for what i,ve understood, it's one that can support the TRANSACTION.
Already thanks anyone in advance for any help and attention, its the first time a post a question here, hope it's well structered.

You have two problems.
PROBLEM 1: failure of the script to produce expected results (i.e., the question you asked).
PROBLEM 2: Lack of diagnostic information.
To solve problem 2, put the following three lines at the start of your script:
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
Running the script with this change might produce error messages that will lead to a solution for your script. If not, run simple php with a known error, such as:
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
echo '1' //no semi colon is an error
echo '2';
If this produces no error messages, it means there is something in the php or web server (such as Apache) configuration stopping them. Find error logs for php and and the web server (probably apache). Exact details for accessing logs are available myawardspace.
SOLVING PROBLEM 1 - Your Script
Whenever running sql through php, there are two major steps involved in getting it to work.
STEP 1: Verify the sql is valid.
The first shot at forming sql within a php script very often contains errors. That means an important milestone in the development of every php script interacting with a database is verifying the sql outside php. An easy way to do this is to put the following statement immediately after setting the value of query_orc1:
echo query_orc1;
exit;
This will put onto your screen the sql the script is attempting to running. Use copy/paste to run the sql using phpmyadmin or whatever interface you have for your database. If there are problems with the sql, you will see them here. If the sql runs as expected, then you know the part of your script creating the sql is working.
STEP 2: Fix php errors that are failing to submit sql correctly to the database.
Maybe someone can spot errors in this script without benefit of error messages. That is fantastic if someone can provide you that information. I would focus on getting your system to show you error message before trying to troubleshoot the php.

I have no experience with mysqli, therefore I use PDO.
At first: Maybe you should overthink the first part with servico1 to servico5. There is maybe a better solution.
My Changes:
Switch from mysqli to PDO
add prepare statements
replace two statements with subselects
I hope I have commented on every change.
The altered Code:
<?php
include('login/conexao.php');
// Build an PDO Instance (Documentation: https://www.php.net/manual/en/book.pdo.php)
// $db = new PDO("mysql:host=localhost;dbname=test;charset=UTF8", "username", "password", [
// PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
// ]);
$nome_cli = $_POST['nome_cli'];
$nome_orc = $_POST['nome_orc'];
$obs_trab = $_POST['obs_orc'];
$servico1 = $_POST['serv1'];
$obs_serv1 = $_POST['obs_serv1'];
$total1 = $_POST['total1'];
$servico2 = $_POST['serv2'];
$obs_serv2 = $_POST['obs_serv2'];
$total2 = $_POST['total2'];
$servico3 = $_POST['serv3'];
$obs_serv3 = $_POST['obs_serv3'];
$total3 = $_POST['total3'];
$servico4 = $_POST['serv4'];
$obs_serv4 = $_POST['obs_serv4'];
$total4 = $_POST['total4'];
$servico5 = $_POST['serv5'];
$obs_serv5 = $_POST['obs_serv5'];
$total5 = $_POST['total5'];
// switch from
// ($servico1 != '') to !empty($servico1)
// optional, if you like the syntax more, you could use: ($servico1 !== '')
// tripple equals or !== prevents type juggeling
// #see https://www.php.net/manual/en/language.types.type-juggling.php
if (!empty($servico1) && empty($servico2) && empty($servico3) && empty($servico4) && empty($servico5)) {
// Prepared statment to prevent sqlinjection
$stmt = $db->prepare("INSERT INTO TRABALHO (
nome_trabalho,
cod_cliente,
obs_trabalho,
statuspag_trabalho
) VALUES (
:nome_orc,
(SELECT cod_cliente FROM CLIENTE WHERE nome_cliente = :nome_cli ), -- with subselects we can remove unnecessary sql statments
:obs_trab,
0
)
");
try {
// Execute the query and bind the named paraments
// All variables a treated as string
$stmt->execute([
'nome_orc' => $nome_orc,
'nome_cli' => $nome_cli,
'obs_trab' => $obs_trab
]);
} catch (Exception $e) {
// #todo handle exception
echo $e->getMessage();
exit;
}
$stmt = $db->prepare("INSERT INTO SERV_TRAB (
cod_trabalho,
cod_servicos,
qtt_serv_trab,
obs_serv_trab
) VALUES (
:orc,
(SELECT cod_servicos FROM SERVICOS WHERE descri_servicos = :servico1),
$total1,
:obs_serv1
)
");
try {
// get last inserted id with pdo: $db->lastInsertId()
$stmt->execute([
'orc' => $db->lastInsertId(),
'servico1' => $servico1,
'obs_serv1' => $obs_serv1
]);
} catch (Exception $e) {
// #todo handle exception
echo $e->getMessage();
exit;
}
// we don't need an if at this point because if an error occures it will throw an exception
// and the try / catch will catch and handle it
header('Location: sucesso_orc.php');
exit;
}

Related

Query isn't inserting into database [duplicate]

This question already has answers here:
Can I mix MySQL APIs in PHP?
(4 answers)
Closed 6 years ago.
I am attempting to implement a click count system. I am using the following code in this link Click here to see code, but changing it to modern standards. Initially I received errors for the msqli_real_escape_ string, but I believed I resolved it(no errors). Now, I am not receiving any errors at all, but the query is not sending into my database. I am using ini_set('display_errors', 1);
error_reporting(E_ALL); for error checking. Also I have my $con and session in and ini file that I call, so the session and connection are not issues.
Does anyone see what I am doing wrong or is there a good way I can check to see what isn't working?
//create current page constant
$curPage = mysqli_real_escape_string($con,htmlspecialchars($_SERVER['PHP_SELF']));
//set number of clicks variable to 0
$clicks = 0;
//do not recount if page currently loaded
if($_SESSION['page'] != $curPage) {
//set current page as session variable
$_SESSION['page'] = $curPage;
$click_sql = "
SELECT *
FROM click_count
WHERE page_url = ?
";
if (!$click_stmt = $con->prepare($click_sql)) {
$click_stmt->bind_param("s", $curPage);
$click_stmt->execute();
$num_rows = $click_stmt->fetchColumn();
if (!$click_stmt->errno) {
// Handle error here
}
$stmt->bind_result($click_id, $page_url, $page_count);
} elseif ($num_rows == 0) {
//try to create new record and set count for new page to 1
//output error message if problem encountered
$click_insert_stmt = "
INSERT INTO click_count
(page_url, page_count)
VALUES(?, ?)";
if(!$click_stmt = $con->prepare($click_insert_stmt)) {
$click_insert_stmt->execute(array('$curPage',1));
echo "Could not create new click counter.";
}
else {
$clicks= 1;
}
} else {
//get number of clicks for page and add 1 fetch(PDO::FETCH_BOTH)
while($click_row = $click_insert_stmt->fetch(PDO::FETCH_BOTH)) {
$clicks = $row['page_count'] + 1;
//update click count in database;
//report error if not updated
$click_update_stmt = "
UPDATE click_count
SET page_count = ?
WHERE page_url = ?
";
if(!$click_stmt = $con->prepare("$click_update_stmt")) {
$click_update_stmt->execute(array('$clicks', '$curPage'));
echo "Could not save new click count for this page.";
}
}
}
}
Edit: New Updated Code
// ********Page count************
//create current page constant
$curPage = mysqli_real_escape_string($con,($_SERVER['PHP_SELF']));
//set number of clicks variable to 0
$clicks = 0;
//do not recount if page currently loaded
if($_SESSION['page'] != $curPage) {
//set current page as session variable
$_SESSION['page'] = $curPage;
$click_sql = "
SELECT *
FROM click_count
WHERE page_url = ?
";
if (!$click_stmt = $con->prepare($click_sql)) {
$click_stmt->bind_param("s", $_SERVER['PHP_SELF']);
$click_stmt->execute();
$num_rows = $click_stmt->fetchColumn();
if (!$click_stmt->errno) {
// Handle error here
}
$stmt->bind_result($click_id, $page_url, $page_count);
} elseif ($num_rows == 0) {
//try to create new record and set count for new page to 1
//output error message if problem encountered
$click_insert_stmt = "
INSERT INTO click_count
(page_url, page_count)
VALUES(?, ?)";
if(!$click_stmt = $con->prepare($click_insert_stmt)) {
$click_insert_stmt->execute(array($curPage,1));
echo "Could not create new click counter.";
}
else {
$clicks= 1;
}
} else {
//get number of clicks for page and add 1 fetch(PDO::FETCH_BOTH)
while($click_row = $click_insert_stmt->fetch(PDO::FETCH_BOTH)) {
$clicks = $row['page_count'] + 1;
//update click count in database;
//report error if not updated
$click_update_stmt = "
UPDATE click_count
SET page_count=page_count+1
WHERE page_url = ?
";
if(!$click_stmt = $con->prepare("$click_update_stmt")) {
$click_update_stmt->execute(array($curPage));
echo "Could not save new click count for this page.";
}
}
}
}
It looks like you're doing a lot of stuff like this:
$click_update_stmt->execute(array('$clicks', '$curPage'));
I'm not sure where you picked up this habit of quoting variables as strings, but you need to drop it. '$x' and $x are two hugely different things. In the first case it's literally '$x' and in the second case it's whatever the $x variable happens to represent.
Fix it like this:
$click_update_stmt->execute(array($clicks, $curPage));
Also since you're using prepared statements, which by the way is great, you do not need to and should not manually escape your values. Applying them to placeholders with bind_param is the safe way of doing it. Doing any other escaping mangles the data.
Just bind directly to the source:
$click_stmt->bind_param("s", $_SERVER['PHP_SELF']);
Don't arbitrarily run things like htmlspecialchars on input out of paranoia or because you're doing cargo-cult programming and you saw it done in a YouTube tutorial somewhere. That function is intended to be used to display values only, not store them. Data in your database should be as raw as possible.
There's a lot of problems with this code, and one of them that has me confused is why there's so much code. Remember SELECT * and then binding results to arbitrary variables is trouble, your schema might change and then your code is out of sync. Whenever possible fetch rows as an associative array if doing this, then all you have to worry about is renamed ore removed columns.
The biggest problem is this is subject to race conditions because it doesn't use an atomic increment. When writing counters, always do your updates as operations that are a single statement:
UPDATE click_count SET page_count=page_count+1 WHERE page_url=?
Your approach of reading the count, incrementing it, and then writing it back into the database means that you're inviting problems if another operation runs concurrently, something very likely on click-counter code.

Write to online SQL Database using PHP script

I need to save the data from android into an online SQL database. I made a PHP file for doing the task. I am trying to save the data using GET in a PHP file but it always returns false. Kindly have a look at my code and please help. The file is called using an android application. Tried testing though REST add-ons for browsers.
EDIT : Problem - When I send the data using HTTP GET all I get in return is the JSON result {"result":false}. This means my SQL query does not run properly. I tried running the same code directly in phpMyAdmin and it works.
EDIT : Code corrected.
<?php
$con = new mysqli("HOST","USERNAME","PASSWORD","DATABASE");
$rrequest_status = $_GET['request_status'];
$rstudent_name = $_GET['student_name'];
$rrequest_to = $_GET['request_to'];
$renrollment_no = $_GET['enrollment_no'];
$rout_date = $_GET['out_date'];
$rout_time = $_GET['out_time'];
$rin_date = $_GET['in_date'];
$rin_time = $_GET['in_time'];
$rrequest_time = $_GET['request_time'];
$rapproved_time = $_GET['approved_time'];
$rvisit_place = $_GET['visit_place'];
$rvisit_type = $_GET['visit_type'];
$rcontact_number = $_GET['contact_number'];
$squery = "INSERT INTO `gatepass_requests` (
`gatepass_number` ,
`request_status` ,
`student_name` ,
`request_to` ,
`enrollment_no` ,
`out_date` ,
`out_time` ,
`in_date` ,
`in_time` ,
`request_time` ,
`approved_time` ,
`approved_by` ,
`visit_place` ,
`visit_type` ,
`contact_number`
)
VALUES (
NULL ,
'".$rrequest_status."',
'".$rstudent_name."',
'".$rrequest_to."',
'".$renrollment_no."',
'".$rout_date."',
'".$rout_time."',
'".$rin_date."',
'".$rin_time."',
'".$rrequest_time."',
NULL,
'".$rapproved_by."',
'".$rvisit_place."',
'".$rvisit_type."',
'".$rcontact_number."',
)";
if(mysqli_query($con,$squery)){
$result['result'] = true;
}else{
$result['result'] = false;
}
echo json_encode($result);
mysqli_close($con);
?>
To set the record straight for future readers.
The fact of the matter here is that you have different/undefined variables for the following used in your VALUES:
$rrequest_status
$rrequest_to
$rrequest_time
But have declared them as, and with an extra "r" and assuming that is your real code and not just a bad paste in your question:
Sidenote: Assuming the GET requests as opposed to POST.
$request_status = $_GET['request_status'];
$request_to = $_GET['request_to'];
$request_time = $_GET['request_time'];
And error reporting would have have signaled undefined variables notices but failed to mention that.
http://php.net/manual/en/function.error-reporting.php
Then you stated this comment in an answer given:
"Thank You so much for your reply, I removed it for the time being, but it is not the problem. PHP does allow to have trailing commas so it doesn't matter. – Pradumn Kumar Mahanta"
Maybe for certain PHP operations, but we're dealing with MySQL here and that alone would have thrown you an exception about the trailing comma for:
'".$rcontact_number."', <<<
In regards to the SQL injection you're open to, use a prepared statement:
References:
https://en.wikipedia.org/wiki/Prepared_statement
http://www.php.net/manual/en/mysqli.quickstart.prepared-statements.php (MySQLi_)
http://php.net/pdo.prepared-statements (PDO)
Error checking references:
http://php.net/manual/en/function.error-reporting.php (PHP)
http://php.net/manual/en/mysqli.error.php (MySQLi)
As you used $con = new mysqli("HOST","USERNAME","PASSWORD","DATABASE");. So you are following Object oriented style. So, you need to follow Object oriented style for executing query. Right now you mixed Object oriented style & Procedural style
Change
if(mysqli_query($con,$squery)){
$result['result'] = true;
}else{
$result['result'] = false;
}
To
if($con->query($squery)){
$result['result'] = true;
}else{
$result['result'] = false;
}
For more info, please have a look here Object Oriented Style & Procedural Style
Remove extra , from the insert query.
'".$rcontact_number."', <-- this one
To check what error comes, do following:
if(mysqli_query($con,$squery)) {
$result['result'] = true;
} else {
$result['result'] = mysqli_error($con); // instead of false, use mysqli_error($con)
}

Creating a dynamic MySQL query from URL paramaters

I am really trying to wrap my head around this and failing miserably. What I want to do it build a MySQL query based on the URL parameters passed by the URL. I am trying to create a re usable dynamic script that can do what it needs to do based on the URL parameter.
This is what I have come up with, and it appears that it does what it is supposed to do (no errors or anything) but nothing actually gets inserted in the database. I know somewhere I have made a dumb mistake (or thought something out wrong) so hopefully one of you guys can point me in the right direction.
Thanks!
//List all possible variables you can expect the script to receive.
$expectedVars = array('name', 'email', 'score', 'age', 'date');
// This is used for the second part of the query (WHERE, VALUES, ETC)
$fields = array('uName','uEmail','uScore','uAge','uDate');
// Make sure some fields are actually populated....
foreach ($expectedVars as $Var)
{
if (!empty($_GET[$Var]))
{
$fields[] = sprintf("'%s' = '%s'", $Var, mysql_real_escape_string($_GET[$Var]));
}
}
if (count($fields) > 0)
{
// Construct the WHERE Clause
$whereClause = "VALUES " . implode(",",$fields);
//Create the SQL query itself
$sql = ("INSERT INTO $mysql_table ($fields) . $whereClause ");
echo "1"; //It worked
mysql_close($con);
}
else
{
// Return 0 if query failed.
echo "0";
}
?>
You missed mysql_query($sql):
if(!mysql_query($sql)){
//die(mysql_error());
}
Please consider to use PDO or My SQLi using parametrize query because mysl_* function depreciated.
Your SQL is all wrong. You're using the field = value syntax for an INSERT, then you're concatenating an array as if it were a string ($fields), and you're missing a couple of parentheses around the values.
a couple of things: i've found for php <-> mysql its important to see what's going into mysql and experiement directly with those queries in phpmyadmin when i get stuck.
1 - in my code I output mysql_error() when the query fails or when a debug flag is set. this usually explains the sql issue in a way that can point me to a misspelled field name etc...
2 - this way i can feed that mysql query directly into phpmyadmin and tweak it until it gives me the results i want. (while i'm there i can also use explain to see if i need to optimize the table)
specifics in your code. unlike C languages sprintf is implied. here's how i'd write your code:
// List all possible variables you can expect the script to receive.
$expectedvars = array('name', 'email', 'score', 'age', 'date');
// This is used for the second part of the query (WHERE, VALUES, ETC)
// $fields = array('uName','uEmail','uScore','uAge','uDate');
$fields = array();
// Set only the variables that were populated ...
foreach ($expectedvars as $var) {
if (!empty($_GET[$var])) {
$name = "u" + ucwords($var); // convert var into mysql field names
$fields[] = "{$name} = " . mysql_real_escape_string($_GET[$var]);
}
}
// only set those fields which are passed in, let the rest use the mysql default
if (count($fields) > 0) {
// Create the SQL query itself
$sql = "INSERT INTO {$mysql_table} SET " . implode("," , $fields);
$ret = mysql_query($sql);
if (!$ret) {
var_dump('query_failed: ', $sql, $ret);
echo "0"; // Query failed
} else {
echo "1"; // It worked
}
} else {
// Return 0 if nothing to do
echo "0";
}
mysql_close($con);

Replacing $_HTTP_GET_VARS with $_GET

This is a question about setting up variables in an array for a personal memory aid project analogous to the old paper-based flash cards, which I now want to dust off. A PHP programmer at my old work 5 years ago helped write the page - alas I have long since lost contact, and my PHP skills are rudimentary at best.
Current Code (PHP4)
<?php
# Setting up Variables
reset($HTTP_GET_VARS);
while(list($key,$value) = each($HTTP_GET_VARS))
{
$$key = $value;
}
#set query string, current_id and current_index
$query_string = "sound=$sound&hint=$hint&type=$type";
if(!isset($current_id)) $current_id = "";
if(!isset($current_index)) $current_index = "";
#connect to MySQL
$conn = #mysql_connect( "localhost","xxxx","xxxx" )
or die( "Sorry - could not connect to MySQL" );
#select the specified database
$rs = #mysql_select_db( "xxx", $conn )
or die( "Sorry - could not connect to specified Db" );
# create the query to select the records and then …
Attempts to find solution
Initially I tried a simple substitution as recommended elsewhere. But in the case of this page's code it did not work. I also looked at Replaced $HTTP_GET_VARS with $_GET, but not working and it too did not solve the issue (see below attempt)
Attempted New Code (PHP5)
Assuming a single table Db, with multiple columns, say 'alpha', 'bravo' and 'charlie', then rows of data in the table cells. The now depreciated $HTTP_GET_VARS used to work fine:
<?php
# Setting up Variables
unset($alpha, $bravo, $charlie);
while(list($key,$values) = each($alpha = $_GET['alpha'], $bravo = $_GET['bravo'], $charlie = $_GET['charlie']))
{
$$key = $value;
}
#set query string, current_id and current_index
$query_string = "sound=$sound&hint=$hint&type=$type";
if(!isset($current_id)) $current_id = "";
if(!isset($current_index)) $current_index = "";
#connect to MySQL
$conn = #mysql_connect( "localhost","xxxx","xxxx" )
or die( "Sorry - could not connect to MySQL" );
#select the specified database
$rs = #mysql_select_db( "xxx", $conn )
or die( "Sorry - could not connect to specified Db" );
# create the query to select the records and then...
The error I get with this code is: Notice: Undefined index: alpha in C:\wamp\www\page2.php on line 4
that is not an error, it is a notice - telling you some $_GET array index might not exist where you use it. You might look into php's error_reporting() and possibly set it to error_reporting(E_ERROR) at the very beginngin of the script to avoid notices - in your case that would probably suffice.
http://php.net/manual/en/function.error-reporting.php
4) If you want to have the keys available as local variables and (correctly) have register_globals disabled, what's wrong with extract($_GET);? – DaveRandom
From:
<?php
# Setting up Variables
unset($alpha, $bravo, $charlie);
while(list($key,$values) = each($alpha = $_GET['alpha'], $bravo = $_GET['bravo'], $charlie = $_GET['charlie']))
{
$$key = $value;
}
To:
# Setting up Variables
unset($alpha, $bravo, $charlie);
extract($_GET);
Seems to have done the trick.
Thanks DaveRandom
Because you unset variables that aren't set yet
I think you have in php4 register_globals on and in php 5 off
register_globals is a bad thing so don't put it on

php service executing sql commands using jquery ajax

<?php
header('Cache-Control: no-cache, must-revalidate');
header('Content-type: application/json');
$mysql = mysql_connect('corte.no-ip.org', 'hostcorte', 'xxxx');
mysql_select_db('fotosida');
if((isset($_POST['GetPersons'])))
{
if(isset($_POST['ID'])) {
$query = sprintf("SELECT * FROM persons WHERE id='%s'",
mysql_real_escape_string($_POST['ID']));
} else {
$query = "SELECT * FROM persons";
}
$res = mysql_query($query);
while ($row = mysql_fetch_assoc($res)) {
for ($i=0; $i < mysql_num_fields($res); $i++) {
$info = mysql_fetch_field($res, $i);
$type = $info->type;
if ($type == 'real')
$row[$info->name] = doubleval($row[$info->name]);
if ($type == 'int')
$row[$info->name] = intval($row[$info->name]);
}
$rows[] = $row;
}
echo json_encode($rows);
}
mysql_close($mysql);
?>
This works ok for generating a json object based on a database query. Im not very familiar with PHP, so i would like some feedback from you before i proceed with this. Is this a good way of calling the database using ajax? Other alternatives? Frameworks maybe?Are there any security problems when passing database queries like UPDATE, INSERT, SELECT etc using an ajax HTTPPOST? Thanks
To simplify CRUD operations definitely give REST a read.
As mentioned, stop using the # (AKA "shut-up") operator in favor of more robust validation:
if(isset($_GET['key'])){
$value = $_GET['key'];
}
Or some such equivalent.
Using JavaScript/AJAX, aggregate and send your request data, such as IDs and other parameters, from the form fields into a JSON object. Not the built query. The only time the client should be allowed to manipulate directly executed SQL is if you're creating an web based SQL client. Architect your URLs meaninfully (RESTful URLs) so that your HTTP request can be formed as:
GET users/?id=123
DELETE photos/?id=456
Or alternatively:
GET users/?id=123
GET photos/?method=delete&id=456
Server-side, you're going to receive these requests and based on parameters from the session, the request, etc., you can proceed by firing parametrized queries:
switch($method){
case 'get':
$sql = 'SELECT * FROM `my_table` WHERE `id` = :id';
break;
case 'delete':
$sql = 'DELETE FROM `my_table` WHERE `id` = :id';
break;
default:
// unsupported
}
// interpolate data from $_GET['id'] and fire using your preferred
// database API, I suggest the PDO wrapper.
See PDO
Generate output as necessary, and output. Capture on client-side and display.
Always validate and filter user input. Never send and execute raw SQL queries, or concatenate raw user input into SQL queries.
With regard to your question, here's a possible snippet:
(Note -- I haven't tested it, nor rigorously reviewed it, but it should still serve as a guide -- there is a lot of room for improvement, such as refactoring much of this logic into reusable parts; functions, classes, includes, etc.)
header('Cache-Control: no-cache, must-revalidate');
header('Content-type: application/json');
$error = array();
// get action parameter, or use default
if(empty($_POST['action']))
{
$action = 'default_action';
}
else
{
$action = $_POST['action'];
}
// try to connect, on failure push to error
try
{
$pdo = new PDO('mysql:dbname=fotosida;host=corte.no-ip.org', 'hostcorte', 'xxxx');
}
catch(Exception $exception)
{
$error[] = 'Error: Could not connect to database.';
}
// if no errors, then check action against supported
if(empty($error))
{
switch($action)
{
// get_persons action
case 'get_persons':
try
{
if(!isset($_POST['id']))
{
$sql = 'SELECT * FROM `persons`';
$stm = $pdo->prepare($sql);
$stm->execute();
}
else
{
$sql = 'SELECT * FROM `persons` WHERE `id` = :id';
$stm = $pdo->prepare($sql);
$stm->execute(array(
'id' => (int) $_POST['id'],
));
}
$rows = array();
foreach($stm->fetchAll() as $row)
{
$rows[] = $row;
}
}
catch(Exception $exception)
{
$error[] = 'Error: ' . $exception->getMessage();
}
break;
// more actions
case 'some_other_action':
// ...
break;
// unsupported action
default:
$error[] = 'Error: Unsupported action';
break;
}
}
// if errors not empty, dump errors
if(!empty($error))
{
exit(json_encode($error));
}
// otherwise, dump data
if(!empty($rows))
{
exit(json_encode($rows));
}
You can't do that. Sending database queries from the client is a huge security risk! What if he sends DROP TABLE fotosida as query?
You should always validate and sanitize data coming from the client before you do anything with it. Identify your use-cases and provide access to them with a clearly defined interface.
Update: To elaborate a bit about the interface you define. Say you're creating a gallery. Let's assume you have several use-cases:
Get a list of all images
Delete an image from the gallery
Upload an image to the gallery
There are different ways to do this, but the simplest way (for a beginner in PHP programming) is proably to have a PHP script for every case.
So you'll have:
imageList.php?gallery=1 that will return a list of all images in the gallery with ID 1
deleteImage.php?image=46 will delete the image with ID 46
uploadImage.php parameters will be passed via multipart POST and should be a uploaded file and the ID of the gallery where the image should be added to.
All these scripts need to make sure that they are receiving valid parameters. Eg. the ID should be a number, uploaded file needs to be checked for validity etc.
Only expose the needed functionality via your interface. This makes it much more secure and also better understandable for other users.
Like the other answers above, i agree that this is just asking for an injection attack (and probably other types). Some things that you can do to prevent that and enhance security in other ways could be the following:
1 Look for something suspicious with your response handler.
Lack of a query variable in the post, for instance, doesn't make sense, so it should just kill the process.
#$_POST["query"] or die('Restricted access');
2 Use preg_match to sanatize specific fields.
if (!preg_match("/^[a-zA-Z0-9]+$/", $_POST[query])){
die('Restricted access');
}
3 Use more fields, even if they are semi-meaningless and hidden, to add more reasons to kill the process through their absence, or lack of a certain text pattern (optional).
4 You shouldn't send a complete query through the POST at all. Just the elements that are necessary as input from the user. This will let you build the query in PHP and have more control of what actually makes it to the final query. Also the user doesn't need to know your table names
5 Use mysql_real_escape_string on the posted data to turn command characters into literal characters before entering data into a db. This way someone would have a last name of DROP TABLE whatever, instead of actually dropping table whatever.
$firstname = mysql_real_escape_string($_POST[fname]);
$lastname = mysql_real_escape_string($_POST[lname]);
$email = mysql_real_escape_string($_POST[email]);
$sql="INSERT INTO someTable (firstname, lastname, email)
VALUES('$firstname','$lastname','$email')";
6 Last, but not least, be creative, and find more reasons to kill your application, while at the same time giving the same die message on every die statement (once debugging is done). This way if someone is hacking you, you don't give them any feedback that they are getting through some of your obstacles.
There's always room for more security, but this should help a little.
You shouldn't trust your users so much! Always take into account, when working with Javascript, that an user could edit your calls to send what (s)he wants.
Here you are taking the query from the GET parameters and executing it without any kind of protection. How can you trust what $_GET['query'] contains? A way to do this would be to call a php page with some parameters through ajax, validate them using PHP and then execute a query built on the parameters you get, always thinking about what the values of such parameters could be.

Categories