I am working on a project that uses OSCommerce with MySQL and I'm confused as to when I should use tep_db_input() or tep_db_prepare_input(). I'd assume I should use tep_db_input() around any strings that are being inserted/updated, but then when should the other function be used?
For example, if I were to SELECT some data from the database, and use the result to then INSERT a row into another table, do I need to prepare the input at some point? Or just use tep_db_input again?
$width = '3"'; // 3 inches
$new_height = '3\' 5"'; // 3 feet 5 inches
$result = tep_db_query(
"SELECT height
FROM measurements
WHERE width = '".tep_db_input($width)."'"
);
while ($row = tep_db_fetch_array($result)) {
tep_db_query(
"INSERT INTO measurement_history (
field,
old_value,
new_value
) VALUES (
'height',
'".tep_db_input($row['height'])."',
'".tep_db_input($new_height)."'
)"
);
}
Is this correct?
Edit:: In case anyone isn't familiar with those functions, here are their definitions:
function tep_sanitize_string($string) {
$patterns = array ('/ +/','/[<>]/');
$replace = array (' ', '_');
return preg_replace($patterns, $replace, trim($string));
}
function tep_db_input($string, $link = 'db_link') {
global $$link;
if (function_exists('mysql_real_escape_string')) {
return mysql_real_escape_string($string, $$link);
} elseif (function_exists('mysql_escape_string')) {
return mysql_escape_string($string);
}
return addslashes($string);
}
function tep_db_prepare_input($string) {
if (is_string($string)) {
return trim(tep_sanitize_string(stripslashes($string)));
} elseif (is_array($string)) {
reset($string);
while (list($key, $value) = each($string)) {
$string[$key] = tep_db_prepare_input($value);
}
return $string;
} else {
return $string;
}
}
tep_db_input uses mysql_real_escape_string or mysql_escape_string and that's a recommended way to prepare your database input.
(And I guess this function will use mysqli_real_escape_string() or similiar in a later release since mysql_real_escape_string will be deprecated starting with PHP 5.5.0. )
Where tep_db_input with mysql_real_escape_string just does escaping:
mysql_real_escape_string() calls MySQL's library function mysql_real_escape_string,
which prepends backslashes to the following characters: \x00, \n, \r, \, ', " and \x1a.
tep_db_prepare_input does different things like trimming whitespaces and replacing brackets and unquoting(!) by calling stripslashes.
So my advice would be: always use tep_db_input. And if you use tep_db_prepare_input to get rid of whitespace etc. use tep_db_input afterwards, too.
This is a bit weird, but you use both. Doing it this way will prevent attacks from malicious users, as well as unintended problems from unusual inputs.
Use tep_db_prepare input on any input data from the HTML form. This clears up issues with HTML, magic quotes, and script injections. Do not use this on text retrieved from the database.
Then you use tep_db_input before writing it to the database. This will escape the MySQL characters to prevent SQL injection attacks and other such problems.
Here's a code sample that shows it:
$clean = tep_db_prepare_input($_POST['name']);
$query_text = tep_db_query("select * from " . TABLE_NAME . " where name='" . tep_db_input($clean) . "'");
Related
I am trying to handle text which may contains single quotes and other special char. If it is enclised with single quote, it does not proceed. So I am trying to enclose single quoted string into double quoted string.
I already checked previous threads.
Here is the code:
Check result : http://ideone.com/gWFdUb
<?php
function clean($string) {
eval('$string = "'.$string.'";');
$string = str_replace(' ', ' ', $string); // Replaces all spaces with hyphens.
return preg_replace('/[^A-Za-z0-9 #\-]/', '', $string); // Removes special chars.
}
$d = clean('this was readlly n'ice 'test for#me to') ;
echo $d;
What wrong with eval line?
I am processing user tweets, post for two purpose.
To store into mysql table. (mysqli_real_escape) did not help
To process the each string into text for matching and POS(part of speech) tagging.
I get stuck due to such characters in text. So trying to remove it before I start processing.
UPDATE:
Check this, here I am already using mysqli_real_escape_String even the script stops when it reach this
...
mention-179
May Thanks #ShaleMarkets #01Finser #52York #AB_CutRock #AFSPG #AJSmith222 #AlbertaEnergy #andymartin #annemullettamg #APGQ_officiel-440929408564477952-Tue Mar 04 19:18:57 +0000 2014-19:03:572014:03:04201403Adnan Aftab Nizamani0131
mention-180
Thank you for #ShaleMarkets, to promoting, thank you very much for an award. Glad to have been able to help you :)-440897048963850240-Tue Mar 04 17:10:22 +0000 2014-17:03:222014:03:04201403♘-₭ℜi℘-0582
mention-181
#ShaleMarkets https://t.co/aM8liykQqR-440890009273393152-Tue Mar 04 16:42:24 +0000 2014-16:03:242014:03:04201403Bre Burey018
What's wrong in mention-181 so that it got stuck? Here is the code
foreach ($tweets1 as $item)
{
$count = $count + 1;
$text = $item->text;
//echo $userid.$text;
$text_id = $item->id;
$constant = 'mention';
$time = $item->created_at;
//echo $time;
//$dt = new DateTime('#' . strtotime($time));
$dt = \DateTime::createFromFormat('D M d H:i:s e Y', $time);
//var_dump($dt);
$tweet_time = $dt->format('H:m:s');
$tweet_dtm = $dt->format('Y:m:d');
$year = $dt->format('Y');
$month = $dt->format('m');
$user_name = $item->user->name;
// echo $year.$month.$user_name;
$inreplyto = $item->in_reply_to_screen_name;
$rt_count = $item->retweet_count;
$follower_count = $item->user->followers_count;
echo $constant."-".$count."<br>".$text."-".$text_id."-".$time."-".$tweet_time.$tweet_dtm.$year.$month.$user_name.$rt_count.$follower_count."<br>";
echo "<br>";
$con = mysqli_connect('127.0.0.1', 'root', 'root', 'root');
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
return;
}
$text = mysqli_real_escape_string($con,$text);
$insertQuery1 = "INSERT INTO twitter_mention(`username`,`userid`,`tweet_text`,`text_id`,`time`,`month`,`year`,`date`,`user_follower_count`,`rt_count`,`constant`,`in_reply_to`) VALUES ('".$twitteruser."','".$userid."','".$text."','".$text_id."','".$tweet_time."','".$month."','".$year."','".$tweet_dtm."','".$follower_count."','".$rt_count."','".$constant."','".$inreplyto."')";
if (!mysqli_query($con,$insertQuery1))
{
// die('Error: ' . mysqli_error($con));
// echo "error";
}
Always use contextual escaping
You can't generically "clean" data without any context of what it's for. Do not try to build a single function to handle all the possible cases. Just don't. It's pointless. In your function, you're trying to "clean" the string by removing certain characters. You can't clean a string by removing a set of characters. That idea is flawed because you're always going to have to allow the use of some characters that are special in some syntax or the other.
Instead, treat the string according to the context where it's going to be used. For example:
If you are going to use this string in an SQL query, you have to use prepared statements (or mysqli_real_escape_string()) to properly escape the data.
If you're going to output this value in HTML markup, you need to use htmlspecialchars() to escape the data.
If you're going to use it as command-line argument, you need to use escapeshellcmd() or escapeshellarg().
Further reading:
Security.SE — What's the best way to sanitize user input in PHP?
What's the best method for sanitizing user input with PHP?
Does eliminating dangerous characters avoid SQL-injection?
In this answer, I'll try to address your original question:
What wrong with eval line?
Nothing. The second-to-last line is the only line that contains a syntax error. You aren't escaping the single-quotes correctly. Try the following:
$d = clean('this was readlly n\'ice \'test for#me to');
It should now produce this output:
this was readlly nice test for#me to
I'm not sure if this is the expected result. If you update the question to include what exactly you're trying to achieve and why do you care which type of quotes the string was wrapped in, maybe I can help you find a solution.
Try this one-
<?php
function clean($string) {
eval("\$string = \"$string\";");
$string = str_replace(' ', ' ', $string); // Replaces all spaces with hyphens.
return preg_replace('/[^a-zA-Z0-9_ %\[\]\.\(\)%&-]/s', '', $string); // Removes special chars.
}
$d = clean("this was readlly n'ice 'test for#me to") ;
echo $d;
?>
The output is- this was readlly nice test forme to
I have a dilemma how should I mysql_real_escape_string() my variables without inserting them into the database \n, \r, \x00 when someone uses " ' or <br> on my comment field, I tried with preg_replace instead of mysql_real_escape_string, but seems I don't know exactly how to allow all the chars and signs I want.
mysql_real_escape_string only escapes values so that your queries don't break, it also protects against SQL injection if used correctly.
If you don't want certain characters you will need to use additional functions to strip them before you apply mysql_real_escape_string.
[insert obligatory "use prepared statements" comment]
Ex:
$string = "My name is
John";
$filtered_string = str_replace("\n", " ", $string); // filter
$escaped = mysql_real_escape_string($filtered_string); // sql escape
mysql_query("INSERT INTO `messages` SET `message` = '" . $escaped . "'");
You should be able to use str_replace to help with this:
mysql_real_escape_string(str_replace(array("\n", "\r\n", "\x00", '"', '\''), '', $input));
Having said that, it is a good idea to switch to mysqli or PDO for database read / write. Both of these allow prepared statements, which reduce the risk of SQL injections.
Here's an example of PDO:
$stmt = $PDOConnection->prepare('INSERT INTO example_table (input_field) VALUES (:input_field)');
$stmt->bindParam(':input_field', $input);
$stmt->execute();
How to make a php script that takes a argument and escapes a quote mark in every string it finds, no matter how many levels of nested array are there.
I tried something like this
$FileName = preg_replace("/'/", '', $UserInput);
but i donot want to replace the string
function recAddslashes($var){
return is_array($var) ? array_map(__FUNCTION__, $var) : addcslashes($var, "'");
}
(see addcslashes)
Not tested, but should do the trick:
function escape_single_quotes( $arg ){
if( is_array( $arg ) ){
foreach( $arg as &$k ){
$k = escape_single_quotes( $k );
}
}else{
$arg = str_replace("'","\'", $arg);
}
return $arg;
}
you need to create a recursive function that loop thought each array and is the its not an array it will replace the ' and then echo it then again loop to the next array
function traverseArray($array)
{
// Loops through each element. If element again is array, function is recalled. If not, result is echoed.
foreach($array as $key=>$value)
{
if(is_array($value))
{
traverseArray($value);
}else{
$FileName = preg_replace("/'/", '', $value);
echo $FileName;
}
}
}
If you're wanting to make the file name safe, you could employ a whitelist approach and only allow certain characters:
$Filename = preg_replace('/[^A-Za-z0-9_\-]/', '_', $userInput);
The above regex will replace any character that is not a letter, a number, a dash or an underscore. Any character that is not allowed will be replaced by an underscore. Whitelisting (allowing a small list of "safe" characters) is a much safer than blacklisting (disallowing a long list of "unsafe" characters). My first assumption is that you're allowing the user to specify the name of a file on your server. However, if you are using this approach to guard against SQL injections, then you're most definitely heading down the wrong road. Prepared Statements are the only recommended way to protect your database against SQL injections.
I have text that consist of some sentences. I have to parse the sentences that separated by dot and count words in every sentence. The sentences that contain more than 5 words will be inserted into database. here's my code :
<?php
require_once 'conf/conf.php';// connect to database
function saveContent ($text) {
//I have to get every sentence without lose the dot
$text1 = str_replace('.', ".dot", $text);
$text2 = explode ('dot',$text1);
//Text that contain ' cannot be inserted to database, so i need to remove it
$text3 = str_replace("'", "", $text2);
//Selecting the sentence that only consist of more than words
for ($i=0;$i<count($text3);$i++){
if(count(explode(" ", $text3[$i]))>5){
$save = $text3[$i];
$q0 = mysql_query("INSERT INTO tbdocument VALUES('','$files','".$save."','','','') ");
}
}
}
$text= "I have some text files in my folder. I get them from extraction process of pdf journals files into txt files. here's my code";
$a = saveContent($text);
?>
The result is only 1 sentence (the first sentence) that can be inserted in database.
I need your help, thank you so much : )
There are many ways to improve this (and to make it work correctly).
Rather than replace . with .dot, you can simply explode on the . and remember to replace it later. However, what if your sentence is something like Mr. Smith went to Washington.? You can't differentiate those periods with much reliability.
The variable $files in your INSERT is not defined in scope of this function. We don't know where it comes from or what you expect it to contain, but here, it will be NULL.
function saveContent ($text) {
// Just explode on the . and replace it later...
$sentences = explode(".", $text);
// Don't remove single quotes. They'll be properly escaped later...
// Rather than an incremental loop, use a proper foreach loop:
foreach ($sentences as $sentence) {
// Using preg_split() instead of explode() in case there are multiple spaces in sequence
if (count(preg_split('/\s+/', $sentence)) > 5) {
// Escape and insert
// And add the . back onto it
$save = mysql_real_escape_string($sentence) . ".";
// $files is not defined in scope of this function!
$q = mysql_query("INSERT INTO tbdocument VALUES('', '$files', '$sentence', '', '', '')");
// Don't forget to check for errors.
if (!$q) {
echo mysql_error();
}
}
}
}
In the long run, consider moving away from the mysql_*() functions and begin learning an API which supports prepared statements such as PDO or MySQLi. The old mysql_*() functions are soon to be deprecated and lack the security offered by prepared statements.
After a lot of operations I've got some like:
$exr = "2+3/1.5";
How I can get result of this expression? Like this:
$result = (floatval)$exr; // show: 4
Of course it doesn't work. I've got only 2, first symbol.
Any easy way to solve this?
You can use the PHP eval function like this:
$exr = '2+3/1.5';
eval('$result = ' . $exr . ';');
var_dump($result);
// float(4)
Read this note carefully:
Caution: The eval() language construct is very dangerous because it allows
execution of arbitrary PHP code. Its use thus is discouraged. If you
have carefully verified that there is no other option than to use this
construct, pay special attention not to pass any user provided data
into it without properly validating it beforehand.
Eval is EVIL
I dont know why every answer here is telling you to do this? But avoid using this.
Here is very good function that can do the same without the eval() Source
function calculate_string( $mathString ) {
$mathString = trim($mathString); // trim white spaces
$mathString = ereg_replace ('[^0-9\+-\*\/\(\) ]', '', $mathString); // remove any non-numbers chars; exception for math operators
$compute = create_function("", "return (" . $mathString . ");" );
return 0 + $compute();
}
Use it as
$exr = '2+3/1.5';
echo calculate_string($exr);
You could use the eval function:
$result = eval($exr); // show: 4
Try:
$exr = "2+3/1.5";
echo eval("return $exr;"); //shows 4
You could use eval.
$result = eval($exr);
The easiest way would be to just run it through eval(), but that is very insecure. For security I'd recommend to filter certain characters, like a-z and special chars like ";:'.