Is it possible to parametarize query that has a concatenation variable? - php

As learning php and sql injections, I would like to parametize my queries for safe and secure website app. however, mine does not work I try to parametize my update and select my query but I didn't achieved the goal to make the program working.
The current output is throwing an error the ? is not found
As of now here is my code, am I missing something that does not work?
<?php
//connection
$connection = mysqli_connect("hostserver","username","");
$db = mysqli_select_db($connection, 'dbname');
if (isset($_POST['qrname'])) {
$qrid = $_POST['qrid'];
//Query No. 1
$qrQuery = "SELECT * FROM scratch_cards WHERE code='$qrid' ";
$qrQuery_run = mysqli_query($connection,$qrQuery);
//Query No. 2
$qrQuery2 = "UPDATE scratch_cards SET status = 'U' WHERE code='$qrid' ";
$qrQuery_run2 = mysqli_query($connection,$qrQuery2);
$qrQuery2->bind_param("s", $qrid);
$qrQuery2->execute();
while ($qrRow = mysqli_fetch_array($qrQuery_run)) {
$txtQrvalue = $qrRow['amount'];
$txtQrstatus = $qrRow['status'];
// QUERY TO UPDATE THE VALUE
// BIND AND PARAMETIZE MY QUERY
$qrQuery3 = $db->parepare("UPDATE shopusers SET ewallet = ewallet + " . (0+?) . " WHERE id = '?' ");
$qrQuery3->bind_param("ii", $txtQrvalue, $id);
$qrQuery3->execute();
//END
}

If I'm reading your question and code right, you can reduce this down to two queries using a JOIN instead, that way you can get rid of the SELECT statement. Use prepared statements for both.
I also specified your connection's charset to UTF-8 (which you should set for your PHP and HTML headers, and your database-tables too).
<?php
$connection = mysqli_connect("hostserver","username","");
$db = mysqli_select_db($connection, 'dbname');
$connection->set_charset("utf8");
if (isset($_POST['qrname'])) {
$qrid = $_POST['qrid'];
$sql = "UPDATE scratch_cards SET status = 'U' WHERE code=?";
$stmt = $connection->prepare($sql);
$stmt->bind_param("s", $qrid);
$stmt->execute();
$stmt->close();
$sql = "UPDATE shopusers su
INNER JOIN scratch_cards sc
ON sc.qrid = su.code
SET su.ewallet = su.ewallet + sc.amount,
sc.status = 'U'
WHERE sc.code = ?";
$stmt = $connection->prepare($sql);
$stmt->bind_param("s", $qrid);
$stmt->execute();
$stmt->close();
}

we have the foll syntax in PDO bind param, where i have put your update query as an example and it works perfectly fine. Try searching for named parameter binding
<?php
$user = 'root';
$pass = 'xxxx';
$DB = 'test';
$host = 'localhost';
$mysqlConnection = new \PDO('mysql:host='.$host.';dbname='.$DB, $user, $pass);
$mysqlConnection->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
$sql = 'update info set fname = fname + :fn where id = 1';
$stmt = $mysqlConnection->prepare($sql);
$stmt->bindValue(':fn', '100');
$stmt->execute();
echo $stmt->rowCount();
?>

Is this the query you wanted to run using mysqli bind params???
<?php
ini_set('display_errors', 1);
$user = 'root';
$pass = 'xxxx';
$DB = 'test';
$host = 'localhost';
$sql = 'update info set fname = fname + ? where id = 1';
$conn = new mysqli($host, $user, $pass, $DB);
$stmt = $conn->prepare($sql);
$stmt->bind_param("i", $val);
$val = 100;
$stmt->execute();
printf("%d Row inserted.\n", $stmt->affected_rows);
exit;

Related

PHP: if statement testing if DB value equals a number - if true execute multiple sql query

Hello, I am trying to make php code that executes multiple sql queries as long as a certain database value equals 1. If that value does not equal one, then redirect the page to oops.php.
Here is my code so far:
<?php
session_start();
$servername = "localhost";
$username = "myUser";
$password = "myPass";
$dbname = "cashball_accounts";
$cash_amount = $_SESSION['cash_amount'];
// Create connection
$userid = $_SESSION['id'];
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
// Fetch the existing value of the cash_amount against that particular user here. You can use the SELECT cash_amount from users where userid = $userid
$_SESSION['cash_amount'] += $_POST['cashmade'];
$sql = "UPDATE users SET cashincheck = 0 WHERE id = ?";
$stmt = $conn->prepare($sql);
$stmt->bind_param('s', $userid);
$result = $stmt->execute();
if($result)
{
echo "cashin complete!";
}
else
{
echo mysqli_error($conn);
session_start();
session_unset();
session_destroy();
}
$conn->close();
?>
So I want everything from the //Fetch comment to the if($result) to execute if the variable "cashincheck" is equal to 1 in the database.
For example:
if(SELECT cashincheck FROM users WHERE id = ? = 1) {
$_SESSION['cash_amount'] += $_POST['cashmade'];
$sql = "UPDATE users SET cashincheck = 0 WHERE id = ?";
$stmt = $conn->prepare($sql);
$stmt->bind_param('s', $userid);
$result = $stmt->execute();
} else {
//redirect to oops.php
}
**/\ I know this wont work at all it's just an example /**
I also want to make several other if statements and update the database accordingly, meaning more sql queries and if statements will be needed,so how would I add more?
another example for a separate if statement:
if($_POST['cashmade'] < $_POST['type']) {
$sql = "UPDATE users SET moneymade = moneymade + $_POST['cashmade'] WHERE id = ?";
$stmt = $conn->prepare($sql);
$stmt->bind_param('s', $userid);
$result = $stmt->execute();
} else {
$sql = "UPDATE users SET moneylost = moneylost + $_POST['type'] - $_POST['cashmade'] WHERE id = ?";
$stmt = $conn->prepare($sql);
$stmt->bind_param('s', $userid);
$result = $stmt->execute();
}

PDO delete from MySQL

I have a problem with a PDO code.
I try the code below.
$id = null;
if ( !empty($_GET['t_id'])) {
$id = $_REQUEST['t_id'];
}
$action = isset($_POST['_DELETE_']) ? $_POST['_DELETE_'] : "";
if ($action == 'do_not_delete') {
header("Location: index.php?action=DEL_ERROR");
}
if($action=='delete') {
$host = "localhost";
$db_name = "_notice";
$username = "root";
$password = "111";
$con = new PDO("mysql:host={$host};dbname={$db_name}", $username, $password);
$id = $_REQUEST['t_id'];
$query = "DELETE FROM topics WHERE topic_id = ?";
$stmt = $con->prepare($query);
$stmt->bindParam(1, $id);
$exc = $stmt->execute();
if($exc){
$con = null;
header("Location: index.php?action=DEL_OK");
}else{
$con = null;
header("Location: index.php?action=DEL_ERROR");
}}
Anything happens (dose not delete element from the database).
I have no errors on page; even when i use a try catch block, or page parameter like index.php?action=DELETE
You need to call $stmt->execute() after preparing the query and binding parameters.
Update:
You are checking the content of $_GET['t_id'] but always setting $id to $_REQUEST['t_id'], and everything will execute only if $_POST['_DELETE_'] contains delete.
Also, try to check the resulting query and parameters with $stmt->debugDumpParams() before executing and maybe replace your bindParam with $stmt->bindParam(1, $id, PDO::PARAM_INT).

Safe PDO mySQL SELECT statement with for loop

I was told to use PDO to safely retrieve data from a database. Now I'm wondering if this would be safe or work at all:
$dbtype = "sqlite";
$dbhost = "localhost";
$dbname = "test";
$dbuser = "root";
$dbpass = "admin";
$conn = new PDO("mysql:host=$dbhost;dbname=$dbname",$dbuser,$dbpass);
$firstName = htmlspecialchars($_POST["firstName"]);
foreach($conn->query('SELECT * FROM employeeTable WHERE firstName = ' . $firstName) as $row) {
echo $row['lastName'].' '.$row['email'];
}
Because to me it looks like it would still be possible to "inject" something into the query.
So my question is: Is that really safe and if not how exactly would I make it safe?
I think you'd better use the following to prepare, the process of preparing is to void the injection
$sql = 'SELECT * FROM employeeTable WHERE firstName = :firstName';
$sth = $conn->prepare($sql);
$sth -> bindParam(':firstName', $firstName);
$sth -> execute();
$result = $sth->fetchAll(PDO::FETCH_OBJ);
foreach ($result as $key => $value) {
echo $value->lastName, $value->email;
}
Just remember to don't directly concatenate post variables to your query, just use prepared statements. And after the execution of prepared statements, you need to fetch the results:
$select = $conn->prepare('SELECT * FROM employeeTable WHERE firstName = :firstName');
$select->execute(array(':firstName' => $_POST["firstName"));
while($row = $select->fetch(PDO::FETCH_ASSOC))
echo $row['lastName'].' '.$row['email'];
}
Here is a good read:
http://wiki.hashphp.org/PDO_Tutorial_for_MySQL_Developers

PHP PDO MySQL get entries from Access and INSERT into MySQL

My goal here is to replicate a local MS Access database into my MySQL database (using php PDO)
The MS Access database is located on a network shared drive and updates itself with new entries every 6 hours.
In the code below I retrieved the max id number from MySQL table 'production_schedule', then I made an ODBC connection to retrieve all entries from MS ACCESS database that are greater than the max id number.
But now I cannot figure out how to insert these new entries into the MySQL table 'production_schedule'.
Can anyone please help?
<?php
/*USING XAMPP*/
$dsn = "mysql:host=localhost;dbname=qmsdb;charset=utf8";
$uname = "root";
$pword = "";
$db = null;
$limit = 10;
$counter = 0;
while (true) {
try {
$db = new PDO($dsn, $uname, $pword);
$db->exec( "SET CHARACTER SET utf8" );
$db->setAttribute( PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC );
$db->setAttribute( PDO::ATTR_PERSISTENT, true );
break;
}
catch (Exception $e) {
$db = null;
$counter++;
if ($counter == $limit)
throw $e;
}
}
$aid = $db->prepare("SELECT MAX(id) FROM production_schedule");
$aid->execute();
$big_id = $aid->fetchColumn();
$refid = intval($big_id);
$conn=odbc_connect('Prod_Schedule','','');
if (!$conn) {
exit("Connection Failed: " . $conn);
}
$sql="SELECT * FROM Schedule WHERE ID > $refid";
$rs=odbc_exec($conn,$sql);
if (!$rs) {
exit("Error in SQL");
}
***** INSERT CODE TO PUT THESE MS ACCESS ENTRIES INTO THE MYSQL TABLE ******
?>
something like this maybe:
while(odbc_fetch_row($rs)){
$sql = "INSERT INTO production_schedule (fieldName1, fieldName2, fieldName3) VALUES (?, ?, ?)";
$stmt = $dbh->prepare($sql);
for($i=1;$i<=odbc_num_fields($rs);$i++){
$stmt->bindValue($i, odbc_result($rs,$i));
}
$stmt->execute();
}
Note: depends on how many data you have to dump, you should use a solution like this: PDO Prepared Inserts multiple rows in single query to reduce risk of PHP timeout.
I just tested the following code and it seems to work okay for me:
$dsn = "mysql:host=localhost;port=3307;dbname=myDb;charset=utf8";
$uname = "root";
$pword = "whatever";
$mysqlDb = new PDO($dsn, $uname, $pword);
$mysqlDb->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$mysqlSql = "INSERT INTO clients (LastName, FirstName) VALUES (?, ?)";
$mysqlCmd = $mysqlDb->prepare($mysqlSql);
$LastName = '';
$FirstName = '';
$mysqlCmd->bindParam(1, $LastName, PDO::PARAM_STR, 255);
$mysqlCmd->bindParam(2, $FirstName, PDO::PARAM_STR, 255);
$connStr =
'Driver={Microsoft Access Driver (*.mdb, *.accdb)};' .
'Dbq=C:\\Users\\Public\\Database1.accdb;';
$accessDb = odbc_connect($connStr, "", "");
$accessSql = "SELECT LastName, FirstName FROM Clients";
$accessResult = odbc_exec($accessDb, $accessSql);
while ($accessData = odbc_fetch_array($accessResult)) {
$LastName = $accessData["LastName"];
$FirstName = $accessData["FirstName"];
$mysqlCmd->execute();
}
First create a function to insert the values into MySQL, then loop through the ODBC results;
function createProductionSchedule($company,$person,$order){
$mysqli_con=mysqli_connect(DBHOST,DBUSER,DBPASS,DBNAME);
if (mysqli_connect_errno($mysqli_con))
{
echo 'Failed to connect to MySQL';
}
//Obviously your own fields here
$company = mysqli_real_escape_string($mysqli_con, $company);
$person = mysqli_real_escape_string($mysqli_con, $person);
$order = mysqli_real_escape_string($mysqli_con, $order);
$sql = "INSERT INTO production_schedule VALUES ('$company','$person','$order')";
mysqli_query($mysqli_con, $sql);
return mysqli_insert_id($mysqli_con);
mysqli_close($mysqli_con);
}
Then in your code section
while (odbc_fetch_row($rs))
{
$company=odbc_result($rs,"Company");
$person=odbc_result($rs,"Person");
$order=odbc_result($rs,"Order");
//Call the function to insert the record
createProductionSchedule($company,$person,$order);
}
odbc_close($conn);

MySql PHP Update Error

I've been messing about with this code for a few hours now and can't work out why it's not working. It's a profile update php page that is passed through JQuery and all seems to be fine except for it actually updating into the table. Here is the code I'm using:
session_start();
include("db-connect.php");//Contains $con
$get_user_sql = "SELECT * FROM members WHERE username = '$user_username'";
$get_user_res = mysqli_query($con, $get_user_sql);
while($user = mysqli_fetch_array($get_user_res)){
$user_id = $user['id'];
}
$name = mysqli_real_escape_string($con, $_REQUEST["name"]);
$location = mysqli_real_escape_string($con, $_REQUEST["location"]);
$about = mysqli_real_escape_string($con, $_REQUEST["about"]);
$insert_member_sql = "UPDATE profile_members SET id = '$user_id', names = '$name', location = '$location', about = '$about' WHERE id = '$user_id'";
$insert_member_res = mysqli_query($con, $insert_member_sql) or die(mysqli_error($con));
if(mysqli_affected_rows($con)>0){
echo "1";
}else{
echo "0";
}
All I get as the return value is 0, can anybody spot any potential mistakes? Thanks
To begin with, use
require("db-connect.php");
instead of
include("db-connect.php");
And now, consider using prepared statements, your code is vulnerable to sql injections.
Consider using PDO instead of the mysql syntax, in the long run I find it much better to use and it avoids a lot of non-sense-making problems, you can do it like this (You can keep it in the db-connect file if you want, and even make the database conncetion become global):
// Usage: $db = connectToDatabase($dbHost, $dbName, $dbUsername, $dbPassword);
// Pre: $dbHost is the database hostname,
// $dbName is the name of the database itself,
// $dbUsername is the username to access the database,
// $dbPassword is the password for the user of the database.
// Post: $db is an PDO connection to the database, based on the input parameters.
function connectToDatabase($dbHost, $dbName, $dbUsername, $dbPassword)
{
try
{
return new PDO("mysql:host=$dbHost;dbname=$dbName;charset=UTF-8", $dbUsername, $dbPassword);
}
catch(PDOException $PDOexception)
{
exit("<p>An error ocurred: Can't connect to database. </p><p>More preciesly: ". $PDOexception->getMessage(). "</p>");
}
}
And then init the variables:
$host = 'localhost';
$user = 'root';
$databaseName = 'databaseName';
$pass = '';
Now you can access your database via
$db = connectToDatabase($host, $databaseName, $user, $pass);
Now, here's how you can solve your problem (Using prepared statements, avoiding sql injection):
function userId($db, $user_username)
{
$query = "SELECT * FROM members WHERE username = :username;";
$statement = $db->prepare($query); // Prepare the query.
$statement->execute(array(
':username' => $user_username
));
$result = $statement->fetch(PDO::FETCH_ASSOC);
if($result)
{
return $result['user_id'];
}
return false
}
function updateProfile($db, $userId, $name, $location, $about)
{
$query = "UPDATE profile_members SET name = :name, location = :location, about = :about WHERE id = :userId;";
$statement = $db->prepare($query); // Prepare the query.
$result = $statement->execute(array(
':userId' => $userId,
':name' => $name,
':location' => $location,
':about' => $about
));
if($result)
{
return true;
}
return false
}
$userId = userId($db, $user_username); // Consider if it is not false.
$name = $_REQUEST["name"];
$location = $_REQUEST["location"];
$about = $_REQUEST["about"];
$updated = updateProfile($db, $userId, $name, $location, $about);
You should check the queries though, I fixed them a little bit but not 100% sure if they work.
You can easily make another function which inserts into tha database, instead of updating it, or keeping it in the same function; if you find an existance of the entry, then you insert it, otherwise you update it.

Categories