Sending curly braces via PHP to mySQL - php

First of all, I know it's not how it's supposed to be. But the system has been setup like this so I have to try and work with it.
I have a column of entries in a mySQL table that look like this {12}-{32} and so forth. 12 is the id of the brand of a car, 32 the model.
Now I have to create a query in PHP where a part of it is like this:
(PD1.fieldValue = '{". $_SESSION['carId'] ."}-{". $_SESSION['carModelId'] ."}'
Guess what, that doesnt work with curly braces ofcourse. The SESSION part is completely empty (yes, they have a value outside the query).
Is there anyway to fix this so I still can send the variables inside the braces to mySQL?

Whenever you find yourself having trouble getting some characters into your database, that is a strong hint that your database code is insecure and vulnerable to SQL injection. You have to take a step back and look a little more broadly, thinking "What are all of the possible characters that aren't being escaped properly?" Luckily, you don't have to actually know. You just need to use the built-in escape functions.
The ideal solution is to use placeholders. The syntax depends on what database API you're using (mysqli, or PDO; deprecated mysql doesn't support them). There exist many excellent resources on how to use placeholders; this is the first result I pulled from Google and it looks right to me.
The somewhat less ideal solution is to use the real_escape_string function for your database API. Example for either mysqli or mysql:
// Using heredoc syntax, you can clean up your queries like so.
$sql_template = <<<SQL
SELECT
PC.id AS cId,
P.id AS pId
FROM PAGE_CATALOG P
LEFT JOIN PAGE_CATALOG_CONFIG PC ON (PC.id = P.cId)
WHERE PD1.fieldValue = '%s'
AND P.productCode REGEXP '%s'
AND PC.id = '1'
AND P.enabled = '1'
GROUP BY P.id
ORDER BY P.productVolgorde ASC
LIMIT 0, 10
SQL;
// For mysqli:
// $mysqli = new mysqli(...)
$sql = sprintf(
$sql_template,
$mysqli->real_escape_string('{' . $_SESSION['carId'] . '}-{' . $_SESSION['carModelId'] . '}'),
$mysqli->real_escape_string($MAL_TYPE)
);
$result = $mysqli->query($sql);
// For mysql:
$sql = sprintf(
$sql_template,
mysql_real_escape_string('{' . $_SESSION['carId'] . '}-{' . $_SESSION['carModelId'] . '}'),
mysql_real_escape_string($MAL_TYPE)
);
$result = mysql_query($sql);

Related

sql returning no results

The following code is returning no results where I use the variable in the code of $dep if I manually put the value in of 1 it returns the expected result. I have tried it with no quotes single quotes and double quotes. I have looked though loads of examples and I cannot see what I am doing wrong
$dep = 1;
if (!$names) {
$sql = "SELECT topic_id, topic_pid, ispublic, isactive, topic, dept_id FROM '.TOPIC_TABLE
. ' WHERE dept_id='$dep' ORDER BY `sort`";
$res = db_query($sql);
I'm pretty sure your error is related to wrong quotes used.
In your code, you write
$sql = "SELECT topic_id, topic_pid, ispublic, isactive, topic, dept_id FROM '.TOPIC_TABLE
. ' WHERE dept_id='$dep' ORDER BY `sort`";
After FROM, you are using single-quotes('), but your whole query has been enclosed into double-quotes("), so that creates the issue.
It should be:
$sql = "SELECT topic_id, topic_pid, ispublic, isactive, topic, dept_id FROM ".TOPIC_TABLE
. " WHERE dept_id='$dep' ORDER BY `sort`";
EDIT: Forgot to point out you should seriously use PDO or any other SQL Injection prevention methods. If, under any circumstance, your $dep variable could be sent via a public form, you could end up by having your DB dumped in the best case.
There's a syntax error in the second line of the query - if you want single-quotes in the query, then you need to enclose it all in double-quotes:
$sql = "SELECT topic_id, topic_pid, ispublic, isactive, topic, dept_id FROM ' .TOPIC_TABLE
. " WHERE dept_id='$dep' ORDER BY `sort`";
By the way, building a query like this, using string concatenation, is a REALLY BAD IDEA and leaves you open to SQL injection attacks - you should use prepared statements and parameters instead.
First as Fred -ii says make sure the if statement is executing properly. Then if dept_id is an integer value then you should not need the single quotes as scaisEdge says. Otherrwise the SQL looks fine. Make sure that there are in deed records in the database for the dept_id that is being passed in.

query multiple columns php/mysql

new to php and am enrolled on a course, so can ask tutor tomorrow if this is more complicated than i think it might be!
I have an sql query, and it works fine. But I am trying to add and 'and' in the select statement.
This is what I have at the minute
$query = "SELECT * from table1 where table1.age <= " . $_POST['min_age'] ;
I have a 'region' input on my linked html page and want results to be returned only if the min_age and region values match those inputted by the user.
I have tried adding an 'and where' but it doesn't work and I am not sure if it is because of the multiple "'s or if what I am trying to do needs a different method?
Thanks
If you need multiple conditions, just separate them with AND:
... WHERE table1.age <= ? AND table1.region = ?
No need to use WHERE again. Just like you wouldn't need to use if() more than once if you were writing a complex condition in PHP.
PS: This isn't directly related to your question, but you should get into the habit of not putting $_POST or $_GET variables directly into your SQL queries. It's a good way to get hacked! Ask your tutor about "SQL injection," or read my presentation SQL Injection Myths and Fallacies.
I know you're just starting out, but if you were training to be an electrician, you would place a high priority on learning how to avoid being electrocuted or how to avoid causing a fire.
Here's how I would write your query using mysqli. One advantage of using query parameters is you never need to worry about where you start and end your quotes.
$query = "SELECT * from table1 where table1.age <= ? AND table1.region = ?";
$stmt = $mysqli->prepare($query) or trigger_error($mysqli->error, E_USER_ERROR);
$stmt->bind_param("is", $_POST["min_age"], $_POST["region"]);
$stmt->execute() or trigger_error($stmt->error, E_USER_ERROR);
The other good habit I'm showing here is to always report if prepare() or execute() return an error.
If you must interpolate variables into your SQL, first make sure you protect the variables either by coercing the value to an integer, or else by using a proper escaping function like mysqli_real_escape_string(). Don't put $_POST variables directly into the string. Also you don't have to stop and restart the quotes if you use PHP's syntax for embedding variables directly in double-quoted strings:
$age = (int) $_POST["min_age"];
$region = $mysqli->real_escape_string($_POST["region"]);
$query = "SELECT * from table1 where table1.age <= {$age}
AND table1.region = '{$region}'";

Do I sanitize/escape correctly?

I've made a simple search-script in PHP that searches a mySQL database and outputs the result. How this works is like this:
User searches for "jack's" through a search-form.
My PHP-script GETs this search, and sanitizes it.
Then the script, with the use of SELECT and LIKE, gets the results.
The script then outputs the result to the user.
Lastly, the script tells the user that "jack's returned x results." with the help of escaping.
What I would like to ask is, am I doing it right?
This is how I sanitize before SELECTING from the database:
if(isset($_GET['q'])){
if(strlen(trim($_GET['q'])) >= 2){
$q = trim(mysql_real_escape_string(addcslashes($_GET['q'], '%_')));
$sql = "SELECT name, age, address FROM book WHERE name LIKE '%".$q."%'";
}
}
And this is how I escape before outputting "jack's returned x results.":
echo htmlspecialchars(stripslashes($q)) . " returned x results.";
Is this the correct way to do it?
By the way, I know that PDO and mySQLi is preferred as they sanitize themselves through the use of prepared statements, but I have no real experience with them whatsoever. But I would gladly take a look, if you guys could link me some newbie tutorials/explanations.
Furthermore, I heard that magic_quotes and charset could in some way or another lead to injections -- is this correct?
For some reason we need also escape a backslash too.
So, the proper code would be, I believe
if(isset($_GET['q'])){
$_GET['q'] = trim($_GET['q']);
if(strlen($_GET['q']) >= 2){
$q = $_GET['q'];
$q = '%'.addCslashes($q, '\%_').'%';
// now we have the value ready either for escaping or binding
$q = mysql_real_escape_string($q);
$sql = "SELECT name, age, address FROM book WHERE name LIKE '$q'";
//or
$sql = "SELECT name, age, address FROM book WHERE name LIKE ?";
$stm = $pdo->prepare($sql);
$stm->execute(array($q));
$data = $stm->fetchAll();
}
}
For the output, use
echo htmlspecialchars($_GET['q']);
stripslashes not needed here.
Furthermore, I heard that magic_quotes and charset could in some way or another lead to injections -- is this correct?
magic quotes won't harm your security if you won't use them.
charset is dangerous in case of some extremely rare encodings but only if improperly set. if mysql(i)_set_charset or DSN (in case of PDO) were used for the purpose - you are safe again.
As for PDO, a tag wiki should be enough for starter, I believe

Why will the following SQL command not work with mysql_query in PHP?

SELECT *
FROM `enzymes`
INNER JOIN `compounds`
ON compounds.compound_id = enzymes.compound_id
WHERE `ec` LIKE '1.11%'
it works in phpmyadmin and mysql workbench.
It won't work regardless whether I backtick everything use mysql_real_escape_string and add the database name where appropriate. the phpmyadmin php code won't work either.
ERRORS: Warning: mysql_fetch_assoc() expects parameter 1 to be resource, boolean given in....
same error for all other query-resource dependent functions
Upd:
case 'ec':
$dbl = mysql_connect(DB_ADDRESS, DB_USER, DB_PASSWORD);
mysql_select_db("kegg", $dbl);
//a)connection is fine
//b)tried with explicitly providing the db name vs with pre-selection
$sql = "SELECT * FROM enzymes INNER JOIN `compounds` ON compounds.compound_id=enzymes.compound_id";
print_r($sql);
$result = mysql_query( $sql, $dbl);
print mysql_error ($dbl);
while ($row = mysql_fetch_assoc($result)) {
print_r($row)
$items[ $row['name'] ] = $row['compound_id'];
}
,,,
Solution: Thanks everyone,- Brad gave the crucial answer first.
$sql = "SELECT enzymes.*, compounds.*\n"
. "FROM enzymes\n"
. " INNER JOIN compounds\n"
. " ON compounds.compound_id = enzymes.compound_id\n"
. "WHERE enzymes.ec LIKE '1.11%' LIMIT 0, 30 ";
A similar topic came up recently where it was suggested that it only works when selecting specific fields. The crucial solution when all data is desired is to resolve ambiguities to:
enzymes.*, compounds.*
Given that error, mysql_query is returning a boolean FALSE, indicating an error. Try this:
$result = mysql_query(...your query here...) or die(mysql_error());
to see exactly what the error is.
My gut is telling me the database is confused by your column references. When you start doing joins, and especially when you have columns names that may match, it's good practice to be explicit on what you're selecting, comparing, etc. e.g.
SELECT enzymes.*
FROM enzymes
INNER JOIN compounds
ON compounds.compound_id = enzymes.compound_id
WHERE counpounds.ec LIKE '1.11%'
But, without knowing the exact error that's occurring, this can only be a guess.
UPDATE
Now that I see the error, make sure you're testing for a proper query response. When you call mysql_query (or whatever you use), check the resource for failure before trying to fetch the result. Most connection libraries have a *_error or *_last_error method you can call to see what caused the failure.
There are a number of reasons that a query will work in environments like phpMyAdmin but not through PHP's mysql functions. For starters, make sure you've selected the proper database with a USE command via PHP's mysql_select_db function (docs). When using phpMyAdmin, that is being performed in the background automatically, not so with a PHP script.
If you specify the names of the database in your query, the previous step won't be required, BUT, your code will be that much harder to maintain if there is ever a change in the database name.
To specify the table, do this: SELECT field1, field2 FROM database_name.table_name WHERE...
Second, if you are using double or single quotes incorrectly, the variables might not be parsed or other such issues: this will cause your query to be invalid. A code sample would help determine if this is the case.
This indicated that you should pass an mySQL resource in whith the mysql_query.
look at:
resource mysql_query ( string $query [, resource $link_identifier ] )
You will get the $link_identifier when opening a connection:
$link = mysql_connect('localhost', 'mysql_user', 'mysql_password');
if (!$link) {
die('Could not connect: ' . mysql_error());
}
Avoid column ambiguous error in MySQL INNER JOIN.
Please try:
SELECT compounds.compound_id as cid, enzymes.compound_id as eid
FROM `enzymes`
INNER JOIN `compounds`
ON compounds.compound_id = enzymes.compound_id
WHERE `enzymes`.`ec` LIKE '1.11%'
And if you'll get similar pairs of ids, the problem is here.

query problem with a text with a single quote

I need to do this query:
SELECT * FROM brands WHERE brand =`l'artigiano italiano`
Should be quite simple but it's not working.
Like all my queries I try to execute it with the following code
$myDB = Database::getConnection($target='....',$key='....');
$sqlLogo = 'SELECT * FROM brands WHERE brand =`' . $brand->merk . '`';
$resultLogo = $myDB->query($sqlLogo);
When I open the page I get the following error
PDOException: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'l'artigiano italiano' in 'where clause': SELECT * FROM brands WHERE brand =`l'artigiano italiano`; Array ( ) in merken_admin_settings() (line 23 of /home/mediaspe/domains/mediaspex.be/public_html/juniorsteps/sites/all/modules/merken/merken.admin.inc)
I tried to use
WHERE brand = "..."
and
WHERE brand = `...`
but both did not work.
Any suggestions about the possible cause? I'm staring blind at the code at the moment.
You should escape anything you embed in a SQL query. As you are using PDO, you should do it with $myDB->quote():
$sqlLogo = "SELECT * FROM brands WHERE brand = '" . $myDB->quote($brand->merk) . "'";
You can use both double quotes (") and single quotes (') for enclosing your values, but not back quotes (`).
It is even better to use prepared statements:
$stmt = $myDB->prepare("SELECT * FROM brands WHERE brand = :brand");
$resultLogo = $stmt->execute(array('brand' => $brand->merk));
This way you don't have to take care of escaping.
Have you tried escaping the single quote?
"l\'artigiano italiano"
MySQL String Syntax
While all of the other answers are valid for regular mysql_* functions, if you are using PDO, you should be taking advantage of prepared statements. They were made for just this purpose.
Just escaping the single quote can do the trick but try PDO prepared statements, they help you with security too (as already discussed here)
You can do it like this:
$brand = "l'artigiano italiano";
$stmt = $db->prepare('SELECT * FROM brands WHERE brand = :brand');
$stmt->execute( array(':brand' => $brand) );
It looks like you're using Drupal. If that's so (I assume so from the way you get the database connection and obviously the tag), you should execute your query like this:
$result = db_query('SELECT * FROM {brands} WHERE brand = :brand', array(':brand' => $brand));
That's all. Note:
Use of db_query(), which will call Database::getConnection() internally. You only need to call Database::getConnection() yourself if you want to connect to another than the default connection.
Use uf curly braces ({}) for tables managed by Drupal (which means, tables installed through hook_schema() of your module). If this is an external table not related to the Drupal installation, you won't need those. The curly braces ensure that the proper table name prefix is inserted in case the drupal installation was configured with one (which is for example the case when running tests!)
You can use :placeholder syntax for the dynamic values and directly specify the value in the second argument of db_query() (or $myMD->query(), that's the same interface).

Categories