Converting to MYSQLI from MYSQL... Broken escape function - php

I've spent five hours on this same problem, getting too frustrated to think it through properly, some help would be appreciated.
File include structure is kind of like:
page.php includes-> head.php includes->(*glo_functions.php* then *sql_functions.php*)
The line in page.php causing triggering the error:
$logdata = $db->escape($_POST['logdata']);
Connection made, in file like: globals.php:
$db->connect();
The escape() function, in file like: sql_functions.php
function escape($text) {
return mysqli_real_escape_string($this->connection_id, '$text');
}
The problem (anywhere that calls the function):
function log_add($text)
{
global $db, $row;
$IP = $_SERVER['REMOTE_ADDR'];
$text= $db->escape($text);
$db->query("INSERT INTO log VALUES(NULL, {$row['userid']}, unix_timestamp(), '$text', '$IP')");
}
Many errors have happened. If connection_id and $text are in reverse it says it expects parameter 1 and kills the script.
Ideally there will be a way for the escape function to sanitize the information somehow. After this has been execute, as of now, my log table is being populated with $text and not the actual text.
I understand preparing queries would be a better option but would take a lot more than 5 hours to do that with every query. I'm converting from SQL, therefore data is universally escaped when needed by calling the function, therefore everywhere where data needs escaped, it is calling to this function already.
Edited:
$db=new database;
$db->configure($_CONFIG['hostname'],
$_CONFIG['username'],
$_CONFIG['password'],
$_CONFIG['database'],
$_CONFIG['persistent']);
$db->connect();

return mysqli_real_escape_string($this->connection_id, '$text');
You put the variable inside single-quotes, so it will use the literal string "$text", not the value of a variable $text.
You could use double-quotes to ensure the variable is expanded:
return mysqli_real_escape_string($this->connection_id, "$text");
Or else just don't put it in quotes at all for this case. Passing a variable to a PHP function is not SQL injection.
return mysqli_real_escape_string($this->connection_id, $text);
Of course when you use a variable inside a string literal in an SQL query, you do need to delimit it with single-quotes.
I agree with other commenters that using query parameters is superior, if only because you never have to worry about quotes again. But I understand that you have to forego that code update for now.

function escape($text) {
global $link; // link to db
return mysqli_real_escape_string($link, $text);
}
Or
function escape($text) {
global $db; // db object
return $db->real_escape_string($text);
}
or only if escape is a method of the same class where you create your $db object:
function escape($text) {
return $this->mysqli_real_escape_string($text);
}

Related

Mixing variable in string after a function call in PHP

I want to mix a variable after call a function, but not when I set the variable.
My example code:
<?php
$greeting = "hi! {$gbye}";
function greetings() {
global $greeting;
$gbye = "goodbye!";
return $greeting;
}
echo greetings();
?>
Fiddle: http://phpfiddle.org/main/code/kd5w-p7q4
I tried escaping the $ symbol: \$, but this only gives me the complete text. And replacing the escaped symbol make the same.
The $gbye variable is inside a language file, by this reason, I have to save the word ($gbye) until I call the function (to replace it as if the full string ($greeting = "hi! {$gbye}";) was inside the function). It's just an example.
So what can I do?
For language file usage, you may want to use your own meta keyword, instead of php variable syntax. This is ensure what you want to do is seperated from what PHP wants to do. This will save you from future bugs and maintenance effort. For example,
<?php
$greeting = "hi! #gbye#";
function greetings() {
global $greeting;
return str_replace("#gbye#", "goodbye!", $greeting);
}
echo greetings();
?>

Atomic string replacement in PHP

In our web application, we have a class which emulates prepared statements for correct escaping of SQL parameters.
Now, I now it would be much better to just use PDO, but the app is very old and the refactoring could be quite long, so for the time being I just wanted to fix a bug I found.
Consider this piece of code which uses our classes:
$s = Q()->statement("SELECT * FROM DUAL WHERE 1 = :a AND 2 = :b AND 3 = :c");
$s->bindValue('c', ':b');
$s->bindValue('b', ':a');
$s->bindValue('a', ':c');
var_dump($s->prepared);
the first line creates the statement, then some values are bound, then I dump the prepared statement.
The result of this is the following:
SELECT * FROM DUAL WHERE 1 = ':c' AND 2 = '':c'' AND 3 = ''':c'''
and this happens because the parameters are substituted one at a time from the last to the first.
I also tried doing the replacement in a single function call, using str_replace() with array parameters, but to no avail.
So I would like to know if there is a way to make this operation somehow "atomic" so that if a placeholder value is another valid placeholder it does not get replaced.
EDIT:
Here is the method of my class which does the replacement:
protected function prepare() {
if (!$this->db) {
trigger_error (__METHOD__ . ': no Connection available to properly quote the value', E_USER_WARNING);
return false;
}
$this->prepared = str_replace(
array_map(array($this, 'getPlaceholderName'), array_keys($this->params)),
array_map(array($this->db, 'quote'), array_values($this->params)),
$this->original
);
return true;
}
You probably want a single call to good old strtr() whith the array signature:
string strtr ( string $str , array $replace_pairs )
Of course, plain string replacement is just a hack and can never replace a proper SQL parser, but I guess you already know that.
This is the code you want to use:
$queryString = strtr($queryString, array(":a" => "b",":b"=>"c", ":c" => "a"));

Replacement variable inside of the replacing variable

I have a function, that check user language and write it down in a variable. After a time, i come of idea to merge they, so that i need a call the function anytime before the first use of a variable, so i put a call of function inside of var, with a idea, that i would be replace it self. But it does not working, becouse it trying to give me a "Closure Object" back, i think it is a function in clear and not the result :( Here is the important part of code:
$GLOBALS['user_language'] = function()
{
return get_user_language();
}
function get_user_language()
{
$user_language = 'en';
$GLOBALS['user_language'] = $user_language;
return $user_language;
}
//somewhere in the script
print_r($GLOBALS['user_language']);
I wish to get 'en' out, nothing more.
function get_user_language()
{
$user_language = 'en';
$GLOBALS['user_language'] = $user_language;
return $user_language;
}
$GLOBALS['user_language'] = get_user_language();
//somewhere in the script
print_r($GLOBALS['user_language']);
But this is strange because you set it already in get_user_language() then you pull it again. It would almost create a loop. The proper way would probably be to remove the $GLOBALS['user_language'] = $user_language; from the function.
Hope this answers your question.
Just use print_r(get_user_language()) instead of print_r($GLOBALS['user_language']);.
If getting the user's language multiple times would be particularly slow (e.g. a database query would be executed over and over again), you can do something like this:
function get_user_language()
{
static $user_language = null;
if ($user_language === null) {
$user_language = 'en'; // this would be where you make the DB query
}
return $user_language;
}
In practice, in a large PHP application, this code would generally be located in a class and would store the value as an object property, so that, for example, the application can cache DB query results for multiple users rather than for only the current one.

Always get an empty array in foreach loop

There are two columns in the database table "system". I have the systemId and want to get the mobileSystemId. But the variable $mobileSystemIds which I already defined as global is always empty.
EDIT: Now array_map doesn´t work. I always get my Exception output "Arrayfehler ArrayMap"
I have the following code :
$mobileSystemIds=array();
function getMobileSystemId($systemId)
{
global $mysqli;
global $mobileSystemIds;
$query="SELECT mobileSystemId FROM system WHERE systemId ='" .$systemId ."'";
if(!$result=$mysqli->query($query))
{
echo "Datenbankfehler DB-QUery";
exit(0);
}
if (!$mobileSystemId=$result->fetch_assoc())
{
echo "Datenbankfehler DB-Fetch";
exit(0);
}
$mobileSystemId=$mobileSystemId["mobileSystemId"];
echo "mobile System ID: " .$mobileSystemId ."<br />";
return $mobileSystemId;
}
if(!$mobileSystemIds=array_map("getMobileSystemId",$systemList))
{
echo "Arrayfehler ArrayMap";
}
In this case, using a return in your function would be much cleaner.
Nothing to do with your problem, but is your $systemId var trusted ? (To prevent SQL injection).
Update:
if(!$mobileSystemIds=array_map("getMobileSystemId",$systemList))
{
echo "Arrayfehler ArrayMap";
}
ought to read (just checked; it works for me):
$mobileSystemIds = array_map('getMobileSystemId', $systemsList);
if (empty($mobileSystemIds))
{
if (empty($systemsList) || !(is_array($systemsList)))
echo "OK: no mobile IDs, but no systems either";
else
echo "THIS now is strange :-(";
}
else
{
echo "Alles OK";
var_dump($mobileSystemIds);
}
I tried this by returning a dummy value based on input; if it does not work for you, there must be something strange in the database.
(Update: the text below refers to your original code, which did not use array mapping)
Your code ought to be working as it is. You put several $mobileSystemId 's into a single $mobileSystemId.
It works: I tested with a simpler code, removing the DB calls but leaving your code, and spelling, untouched.
So, the error must be elsewhere. I would guess that this code is included into something else, and:
the $mobileSystemIds = array(); declaration gets executed more than once, thereby losing all its data;
the $mobileSystemIds = array(); declaration is itself included in a more local scope and you read it from outside, reading an empty value or a totally different value.
Try replacing the first part of your code with:
GLOBAL $mobileSystemsIds;
if (defined($mobileSystemsIds))
trigger_error("mobileSystemsId defined more than once", E_USER_ERROR);
else
$mobileSystemsIds = array();
and also, in the function body:
if (!defined($mobileSystemsId))
trigger_error("mobileSystemsId should have been defined", E_USER_ERROR);

PHP repeating piece of code wtih access to variables

How to repeat the same PHP snippet in different PHP files?
For example I define the variable $user, then I insert PHP code, which have an access to this variable.
Update:
I'm going to use this with if statement
Example(without if statement):
function sanitizeString($var)
{
$var = htmlentities($var, ENT_QUOTES, "UTF-8");
return mysql_real_escape_string($var);
}
$user = sanitizeString($_POST['user']);
$pass = sanitizeString($_POST['pass']);
//code i want to repeat in different files
$user=$user;
$pass=$pass;
#salt generation
$salt=uniqid(mt_rand(), true);
#Add data to tables
queryMysql("INSERT INTO accounts VALUES('$user', '".hash('sha512',$pass+$salt)."', '$salt', '$cookie_value')");
mysql_query("INSERT INTO passwordreset VALUES('$user', NULL, NULL)");
//end of code to repeat
Use functions with parameters, that's what they're for. Snippets of code that can be reused in a different context with different variables.
Make classes and methods
class User
{
public $user;
public function User($name)
{
$user = $name;
}
}
$User = new User('name1');
echo $User->user;
$User = new User('name2');
echo $User->user;
$User = new User('name3');
echo $User->user;
$User = new User('name4');
echo $User->user;
Output: name1name2name3name4
U Can add the code or variable in one php file and then include that file where ever u want
U can see the example here
(Removed global keyword as it is not necessary in this case)
One method is to use the $GLOBALS variable, which is accessible anywhere much like $_SERVER, $_POST etc. See Superglobals. As Deceze mentioned, global variables are typically not the best solution, as they are prone to causing accidental errors. For more information about this, give this a read.
$GLOBALS['user'] = "RadGH";
include "my_file.php";
my_file.php:
echo $GLOBALS['user'];
From Bondeye in a comment, using a constant is preferred when dealing with data that does not need to be changed. One of the problems with globals is that somewhere down the line data may be changed or referenced accidentally. Since constants cannot be changed, that is not the case.
define('USER', 'RadGH');
include "my_file.php";
my_file.php:
echo USER;

Categories