mysqli::real_escape_string creates \r\n problems? - php

I have a form where the users use TinyMCE to fill out some information, and that form is then POSTed, and stored in a database.
The problem appears to be that mysqli::real_escape_string is turning carriage return line feeds into escaped versions of themselves, and storing them. Well... that is part of the design. But when I re-read the database, and run stripslashes() on the data as it is read from the DB, I get output like this:
Here si some good HTML code
rn
But you can see
rn
that there are annoying
rn
"rn" on blank lines between everything.
How can I store HTML in the DB, and retrieve it without having this \r\n problem?

The original answer is not categorically out of date.
The modern best solution is to use PDO.
$pdo = new PDO($dsn);
$sql = "INSERT INTO posts (`foo`) VALUES (?)";
$stmt = $pdo->prepare($sql);
$values = $_POST['text_area'];
$stmt->execute( [ $values ] );

The simplest solution would be to remove the CRLF from the data first
$str = str_replace("\r\n", "", $str);
Be sure to use double quotes so PHP knows to look for CRLF and not a literal \r\n

Well in documentation it is mentioned that
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.
so better replace these strings
and
stripslashes()
returns a string with backslashes stripped off. (\' becomes ' and so on.) Double backslashes (\) are made into a single backslash ().

Related

Cannot replace carriage return and new line in php

I get a string from the frontend which has a line break in it. It is saved in an array which looks like this:
[address] => Array (
[0] => Foo
Bar
)
I then use json_encode() on the array before writing it into the SQL DB:
$string = json_encode( $string, JSON_UNESCAPED_UNICODE );
This turns the array into:
{"address":["Foo\r\nBar"]}
Unfortunately the DB doesn't like \r or \n if not escaped, so it gets rid of the \r and \n.
So the first question is, is there a function that I can use to properly escape the string, so it can be written properly into the DB without losing the line break?
I didn't find any function for that, so I tried to use str_replace to just replace the \r\n with \\n. The function is:
$string = str_replace(["\r\n","\r","\n"], "\\n", $string);
This however does not work. I don't know why. The function itself works, as I tried to replace only "n" with "bla" and it worked. However the moment I try to replace the backslash it does not find anything to replace. I don't know if some "special" backslash character is used here or what else could be going on here.
This is driving me nuts, seriously. So I hope somebody can help me out. Thanks in advance.
Problem :
Your str_replace is not working because you are using double quotes.
Solution :
You should replace your double quotes with single quotes and then the magic will happen :D
$string = str_replace(['\r\n','\r','\n'], '\\n', $string);
EXTRA USEFUL INFORMATION : For more you should take a look at for details as it's useful to get to know the difference between double quotes and single quotes as:
What is the difference between single-quoted and double-quoted strings in PHP?
It depends on how you insert the string into the DB. However you do it, you need to escape it properly.
If you're using PDO, you can achieve this like this:
$conn = new PDO(.....);
$sql_str = $conn->quote($string);
$conn->exec("INSERT INTO table (str_value) {$sql_str}");
Or, better use a prepared statement:
$conn = new PDO(.....);
$stm = $conn->prepare("INSERT INTO table (str_value) :value");
$stm->execute(array(':value' => $string));
Hope that works.
Storing JSON directly in a database? Yeuch!
However if you really must do it, then why do you feel the need to change the representation of the data? When you run it back through a JSON decoder you wil get the original data back. The problem is only how to get it into a safe format for insertion into your database.
That you have created this from a PHP array implies you've got NO EXCUSE for not checking the content of the data before you save it (not that writing data supplied directly from Javascript is in any way valid or forgiveable).
is there a function that I can use to properly escape the string
Yes, there are several - but you've not told us which API you are using. This is not some magical trick to solve the problem you currently find yourself in - escaping any data you write to your database properly is essential to prevent SQL injection.
In addition to the PDO methods mentioned by Alex, you can do it in the (deprecated) mysql extension using mysql_escape_string/mysql_real_escape_string or in mysqli procedural code with mysql_escape_string / mysqli_real_escape_string or msqli_prepare + mysqli_bind_param. The mysqli functions also have object oriented representations.

Angularjs - multi lines in text area

I have a textarea in my html for user to input some text. I can get it to save into mysql table field with text attribute using php. Before insert into mysql, I will mysql_real_escape_string($data);(for security reason). But when I retrieve it back out from database, I will get
{"bittext":"i
love
mcD"}
With that I will get error:
Error: JSON Parse error: Unterminated string
parse#[native code]
I am not sure how I can reformat it back so that I can parse it to JSON.
Update:
I found out that I did not add json_encode($data) function. Now I can turn
{"bittext":"i
love
mcD"}
into
{"bittext":"i\nlove\nmcD"}
But I am having problem to convert \n to \\n using $data = str_replace(array('\r\n', '\r', '\n'),'\\n', $data);. For some reason \\n is not working. Is there other way to do this?
Update2:
After much of messing around with the code, I finally got it to work:
$je = json_encode($rs,JSON_PRETTY_PRINT);
$nl = array('\r\n', '\r', '\n');
$je = str_replace($nl,'\\n', $je);
My initial issue is when I log it with firephpcore, I can only see \n even after str_replace($nl,'\\n', $je). But as I do more test and found out it actually already work even though it did not display well in console.
From the documentation for mysql_real_escape_string();
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.
Your insert statement will inculde the string '{"bittext":"i \\nlove \\nmcD"}' - notice we are escaping the escape character here, which is what mysql_real_escape_string() does.
Which will insert into your table the string '{"bittext":"i \nlove \nmcD"}' - this is what you should see if you do a select from the mysql client.
Somewhere, either pre-insert, or post-select your code is processing the value and changing '\n', to an actual newline byte, instead of leaving it as the string '\n'.
You could patch this by running;
$data = str_replace(array("\r\n", "\r", "\n"), "\\n", $data);
However, I would recommend you track back through your code to see where in your pipeline escaped strings are getting converted to actuals.

How to store escaped characters in MySQL and display them in php?

For example I want to store the String "That's all". MySQL automatically escapes the ' character. How do I echo that String from the database using php but remove the \ in front of escaped characters like \' ? I would also like to preserve other formatting like new lines and blank spaces.
Have you tried stripslashes(), regarding the linebreaks just use the nl2br() function.
Example:
$yourString = "That\'s all\n folks";
$yourString = stripslashes(nl2br($yourString));
echo $yourString;
Note: \\ double slashes will turn to \ single slashes
You should probably setup your own function, something like:
$yourString = "That\'s all\n folks";
function escapeString($string) {
return stripslashes(nl2br($string));
}
echo escapeString($yourString);
There are also several good examples in the nl2br() docs
Edit 2
The reason your are seeing these is because mysql is escaping line breaks, etc. I am guessing you are using mysql_* functions. You should probably look into mysqli or PDO.
Here is an example:
$yourString = "That's all
folks";
echo mysql_escape_string($yourString);
Outputs:
That\'s all\r\n folks
If you use prepared statements, those characters will not be escaped on insert.
Use stripslashes() to remove slashes if you cannot avoid adding slashes on input.
At first, magic_quotes_gpc escapes the character like ' or ". You can also disable this in your php.ini. But then you should escape the things yourself that no query can get "infected".
Lookup mysql injection for more information.
When the escaped string is been written in your database. The string doesn't contain theses escape charakters and when you output them again. You should see the result as you want it.
Me for myself prefer the method by storing everything without escapes and escape or display things when I output them. You could also easily use an str_replace("\n", "", $text) to prevent newslines are displayed.
Greetings MRu

nl2br not working on ical summary line feeds "\n"

I'm collecting a summary of an ical event in PHP. The thing is, that the summary contains line breaks \nand I want to replace them with <br> when inserting the events.
In my PHPMyAdmin after escaping the ical summary I see the characters \n, but without escaping the ical summary I can't see the characters \n. However, without escaping I can see actual real line-breaks. I need to escape the ical summary to make my database safe. Using the nl2br function is not working in both cases? Why?
CODE:
//without escaping
$title = $vevent->getProperty('summary');//Object method which retrieves the summary of an event
$title = nl2br($title);
//with escaping
$title = mysql_real_escape_string($vevent->getProperty('summary'));
$title = nl2br($title);
Hrm, what about reading the handbook page, my friend? http://php.net/manual/en/function.mysql-real-escape-string.php says
mysql_real_escape_string() calls MySQL's library function mysql_real_escape_string, which prepends backslashes to the following characters: \x00, \n,
Your line breaks are already SQL escaped. so you need to nl2br before.
And the usual rant I give to everyone: why are you using the mysql extension in 2011? It went out of fashion half a decade ago. Use mysqli or PDO and prepared statements, then you dont need to worry about escaping.
You can do it the other way around:
//with escaping
$title = nl2br($title);
$title = mysql_real_escape_string($vevent->getProperty('summary'));
But you shouldn't need to call nl2br before inserting into the database. It's better to do nl2br when you output the data to the browser. That way you store the actual data in the database (which later can be used in other context) and format it with HTML before outputting.

keep textarea input format after using mysql_real_escape_string to store

I am using php5.3.6 and mysql 5.1.56 and CodeIgniter. Here is what I did.
Input some text in textarea, something like this:
what's this?
I'm bob.
$string = $_POST['name'];
$insertdata = mysql_real_escape_string($string);
Insert $insertdata into database.
It shows "what\'s this?\n\n\nI\'m bob."(without double quotes) in the table.
Query the data stored in database, use stripslashes on it and then put it back to the textarea.
It shows "what's this?nnnI'm bob."(without double quotes) in the textarea.
My questions are:
In step 4, shouldn't it be "what\'s this?\n\n\n I\'m bob." stored in the table?
I checked php manual. It says:
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.
How am I supposed to keep the textarea input format after using mysql_real_escape_string()?
Is there anyway to choose which slash to strip and which not to?
Notes:
magic quotes option is off
I did not use stripslashes() before
using mysql_real_escape_string()
If I use addslashes() instead of
mysql_real_escape_string(),
everything works fine.
I don' want to use addslashes() since
it is not as secure as
mysql_real_escape_string(), as far as
I know.
Thanks,
Milo
This really does feel a lot like magic_quotes_gpc = On. Are you disabling it in php.ini or at runtime? It needs to be the former, otherwise it'll remain on.
http://www.php.net/manual/en/security.magicquotes.disabling.php
The magic_quotes_gpc directive may only be disabled at the system level, and not at runtime. In otherwords, use of ini_set() is not an option.
Short answer:
// double quotes are *very* important, or chars are not interpreted
$text_from_db=str_replace("\\r","\r",str_replace("\\n","\n",$text_from_db));
Long answer
Pretty simple but tricky.
You write your textarea and hit the "return" key, there is placed a \r\n (on Windows systems) with slashes that escape the "r" and "n" letter rising their special meaning of carriage return and newline.
You actually can't see them because they are "not printable" chars.
The slash char itself (0x1B) is invisible, that is a single slash is a "not printable" char, to make it visible you have to "transform" it in a printable slash char (0x5C) and to achieve that you have to double it "\\".
Now back to the question: if you can read the slash, probably that's beacuse that slash is not the 0x1B but rather 0x5C, so the "n" and "r" lose their special meaning and you get them as mere strings.
The code I posted does this conversion, converting the "[0x5C]n" string in a "[0x1B]" char.
Notes
Hope this helps, it did for me. IMPORTANT : it is not normal that the text that comes from the db has this issue if it has been stored correctly. My suggestion is to triple check insertion and retrieving because (given from the issue) you could be applying the quoting twice somewhere.
The Best Solution..
$insertdata = mysql_real_escape_string($string); (You can insert it in your database if you want)
echo stripslashes(str_replace('\r\n',PHP_EOL,$insertdata)); (The output is exactly as your input was)
You must escape data before inserting it into the database, to ensure you do not produce broken queries and to avoid SQL injections.
However, when you retrieve that data via a SELECT, you'll receive the data unescaped, ready to be used.
MySQL escapes the string, but when displaying the result back to you it will give you the same result as if it was unescaped.

Categories