Is there any possibility in PHP to save new lines in an textarea into a sql database?
I mean without typing in html commands like br ?
If not, how its done here? And how i can install it into my programm?
Thanks for help!
$descriptionraw = mysqli_real_escape_string($conn, $_POST['setdescription']);
$description = nl2br($descriptionraw);
The premise of this question is flawed, as the newlines are stored in the database already.
At least as long as you haven't done anything to remove them prior to saving the input, that is.
The question should be how to display the newlines in HTML pages, and for this you have a couple of methods.
Either use a <pre> tag around the output. This will cause the text to be showns preformatted, and thus include the newlines as actual content. The bad side about this is that the text won't break normally, and as such can (and will) break out of the natural flow of your page.
Or use nl2br() or a custom nl2p() function, when echoing the content to the browser. This translates the newlines into <br> (or <p>) tags, and will follow the normal flow of your site's layout. Which makes this the recommended method.
PS: This line is wrong:
$description = nl2br($descriptionraw);
This is function to format output to a HTML-compatible viewer, a database is not. Using nl2br() and similar functions before you save stuff to the database will only cause you headaches, especially if you ever want to view the data in something that is not equipped to handle HTML code. (Such as the native MySQL client.)
Quick and dirty examples, using PDO:
First for saving the data:
$input = filter_var ($_POST['input'], FILTER);
$stmt = $db->prepare ("INSERT INTO `table`(`input`) VALUES (:data)");
$stmt->exec (array (':data' => $input));
Then for displaying it:
$output = '';
$res = $db->exec ("SELECT `input` FROM `table`");
foreach ($res->fetchArray () as $row) {
$output .= nl2br ($row['input']);
}
echo $output;
User php function nl2br
echo nl2br("This\r\nis\n\ra\nstring\r");
Related
I have a simple comments section with which I would like to be able to style each comment, saving the text and html tags in the database.
For the most part, I feel confident about the way I am inserting my comment data into my database. Of course, if you feel otherwise, I am not opposed to hearing your opinion.
if(isset($_POST["comment"])) {
$userid = $_SESSION['user_id'];
$comment = $conn->real_escape_string(trim($_POST['comment']));
$sql = "INSERT INTO comments (`user_id`, `comment`, `parent_id`, `type`)
VALUES ('.$userid.', '$comment', '$parent_id', '$type')";
if ($conn->query($sql) === TRUE) {
echo "Thanks for the comment!";
} else {
die("Error commenting" . $conn->error);
}
}
However, if I go directly through MySQL and update a row to a simple javascript alert, it renders and I receive the alert on page load. Accordingly, I have a hole in my reading of the data.
while($row = mysqli_fetch_array($result)) {
$parent_id = $row['parent_id'];
$type = $row['type'];
echo '<h1>'.$row['user_name'].'</h1>';
echo '<p>'.$row['comment'].'</p>';
}
I know that I can make this safer through something like strip_tags($row['comment']). However, if I do this, there cannot be any styling on the comments as <p> tags (and other tags for that matter) will be stripped. Accordingly, my question is this: how can I read the data in a way that prevents glaring XSS holes while allowing simple html styling (much like you see on these comments).
Thanks so much!
first of all you can use a harmless bbcode in your commenting system for that matter, but i think you didn't understand strip_tags() well. strip_tags() has two arguments. first one is your string but second one is allowed tags (tags that can pass through strip_tags()) so it goes like this for example:
<?php
$text = '<p>Test texts.</p><!-- Comment --> and other text';
echo strip_tags($text);
# Allow <p> and <a>
echo strip_tags($text, '<p><a>');
?>
and it outputs this:
<p>Test texts.</p> and other text
you can use strip_tags() documentation here
strip_tags() has a second argument, which is a string of allowable tags.
In this case, all tags would be removed:
$comment = "<script>alert('Hello world');</script>This is <i>a comment</i>.";
$strippedComment = strip_tags($comment);
echo $comment;
This would result in: alert('Hello world');This is a comment.
However, with the second argument you can allow basic formatting tags, like so:
$comment = "<script>alert('Hello world');</script>This is <i>a comment</i>.";
$strippedComment = strip_tags($comment, "<i><u><b>");
echo $comment;
This would now result in: alert('Hello world');This is <i>a comment</i>.
http://php.net/strip_tags
Unfortunately, the other answers are wrong: Using strip_tags is not secure.
The reason?
A user could simply enter code like this to bypass your sanitization:
<p onmouseover="alert('This could be evil XSS')">Test texts.</p> and other text
Passing this through strip_tags allowing <p> tags does not remove the code:
echo strip_tags("<p onmouseover=\"alert('This could be evil XSS')\">Test texts.</p> and other text", "<p>");
as p's attribute is still output:
<p onmouseover="alert('This could be evil XSS')">Test texts.</p> and other text
which will run:
You should implement a Content Security Policy on any pages where you output the user controlled text in addition to making the text safe for HTML output by using a sanitizer such as HTML Purifier. This should be effective in preventing injected script commands from running.
The CSP allows you to effectively stop inline script from being executed by the browser. It is currently supported by modern browsers such as Chrome and Firefox (although IE only currently has partial support).
This is done by a HTTP response header from your page.
e.g.
Content-Security-Policy: script-src 'self' https://apis.google.com
will stop inline JavaScript from being executed if a user managed to inject it into your page (it will be ignored with a warning), but will allow script tags referencing either your own server or https://apis.google.com. This can be customised to your needs as required. The HTML sanitizer is still needed for browsers that do not support CSP so you should still run all user supplied input through that first.
I'm storing HTML and text data in my database table in its raw form - however I am having a slight problem in getting it to output correctly. Here is some sample data stored in the table AS IS:
<p>Professional Freelance PHP & MySQL developer based in Manchester.
<br />Providing an unbeatable service at a competitive price.</p>
To output this data I do:
echo $row['details'];
And this outputs the data correctly, however when I do a W3C validator check it says:
character "&" is the first character of a delimiter but occurred as data
So I tried using htmlemtities and htmlspecialchars but this just causes the HMTL tags to output on the page.
What is the correct way of doing this?
Use & instead of &.
What you want to do is use the php function htmlentities()...
It will convert your input into html entities, and then when it is outputted it will be interpreted as HTML and outputted as the result of that HTML...For example:
$mything = "<b>BOLD & BOLD</b>";
//normally would throw an error if not converted...
//lets convert!!
$mynewthing = htmlentities($mything);
Now, just insert $mynewthing to your database!!
htmlentities is basically as superset of htmlspecialchars, and htmlspecialchars replaces also < and >.
Actually, what you are trying to do is to fix invalid HTML code, and I think this needs an ad-hoc solution:
$row['details'] = preg_replace("/&(?![#0-9a-z]+;)/i", "&", $row['details']);
This is not a perfect solution, since it will fail for strings like: someone&son; (with a trailing ;), but at least it won't break existing HTML entities.
However, if you have decision power over how the data is stored, please enforce that the HTML code stored in the database is correct.
In my Projects I use XSLT Parser, so i had to change to (e.g.). But this is the safety way i found...
here is my code
$html = trim(addslashes(htmlspecialchars(
html_entity_decode($_POST['html'], ENT_QUOTES, 'UTF-8'),
ENT_QUOTES, 'UTF-8'
)));
And when you read from DB, don't forget to use stripslashes();
$html = stripslashes($mysq_row['html']);
I am in the middle of creating a comment box where people can ask their questions.
I get a lot of people asking how do they do something which involves inputting code into the form.
The form goes through htmlpurifier to make sure its safe to use.
But when ever someone inputs echo codes etc it does not allow it.
Or if someone inputs a div then it does not allow that either, even when wrapping in the < code >.
For instance this:
<code><div class="classname"></div></code>
will just add a div.
and
<code><?php echo $word; ?></code>
Will not show the code at all.
The way I have set this up the htmlpurifier is:
$content = $_POST['comment'];
$rawf = str_replace('<code>', '<pre><code>', $content);
$rawfp = str_replace('</code>', '</code></pre>', $rawf);
require_once '../Libs/htmlPurifier/library/HTMLPurifier.auto.php';
$purifierconfig = HTMLPurifier_Config::createDefault();
$purifierconfig->set('HTML.Allowed', 'b,a[href],i,em,br,code,pre');
$purifier = new HTMLPurifier($purifierconfig);
$clean_html = $purifier->purify($rawfp);
$ticketpost = str_replace('<a ', '<a rel="nofollow" ', $clean_html);
Then the $ticketpost is inserted into the database using PDO prepared statements.
Is there something I am not doing, or doing wrong?
If so please could you help.
Thanks
Your problem is, if the input is truly HTML, then any code fragments need to be escaped in order to show up in the result. We have special <![CDATA[ put code here ]]> syntax for just that, but sometimes, you don't want to bother users with extra syntax like that. In that case, you could do a preg_replace_callback on code tags, where the callback escapes the code between two code tags. But notice, now, there is no way to express a code fragment that contains code tags! So it is all tradeoffs.
I have a form that, among other things, accepts an image for upload and sticks it in the database. Previously I had a function filtering the POSTed data that was basically:
function processInput($stuff) {
$formdata = $stuff;
$formdata = htmlentities($formdata, ENT_QUOTES);
return "'" . mysql_real_escape_string(stripslashes($formdata)) . "'";
}
When, in an effort to fix some weird entities that weren't getting converted properly I changed the function to (all that has changed is I added that 'UTF-8' bit in htmlentities):
function processInput($stuff) {
$formdata = $stuff;
$formdata = htmlentities($formdata, ENT_QUOTES, 'UTF-8'); //added UTF-8
return "'" . mysql_real_escape_string(stripslashes($formdata)) . "'";
}
And now images will not upload.
What would be causing this? Simply removing the 'UTF-8' bit allows images to upload properly but then some of the MS Word entities that users put into the system show up as gibberish. What is going on?
**EDIT: Since I cannot do much to change the code on this beast I was able to slap a bandaid on by using htmlspecialchars() rather than htmlentities() and that seems to at least leave the image data untouched while converting things like quotes, angle brackets, etc.
bobince's advice is excellent but in this case I cannot now spend the time needed to fix the messy legacy code in this project. Most stuff I deal with is object oriented and framework based but now I see first hand what people mean when they talk about "spaghetti code" in PHP.
function processInput($stuff) {
$formdata = $stuff;
$formdata = htmlentities($formdata, ENT_QUOTES);
return "'" . mysql_real_escape_string(stripslashes($formdata)) . "'";
}
This function represents a basic misunderstanding of string processing, one common to PHP programmers.
SQL-escaping, HTML-escaping and input validation are three separate functions, to be used at different stages of your script. It makes no sense to try to do them all in one go; it will only result in characters that are ‘special’ to any one of the processes getting mangled when used in the other parts of the script. You can try to tinker with this function to try to fix mangling in one part of the app, but you'll break something else.
Why are images being mangled? Well, it's not immediately clear via what path image data is going from a $_FILES temporary upload file to the database. If this function is involved at any point though, it's going to completely ruin the binary content of an image file. Backslashes removed and HTML-escaped... no image could survive that.
mysql_real_escape_string is for escaping some text for inclusion in a MySQL string literal. It should be used always-and-only when making an SQL string literal with inserted text, and not globally applied to input. Because some things that come in in the input aren't going immediately or solely to the database. For example, if you echo one of the input values to the HTML page, you'll find you get a bunch of unwanted backslashes in it when it contains characters like '. This is how you end up with pages full of runaway backslashes.
(Even then, parameterised queries are generally preferable to manual string hacking and mysql_real_escape_string. They hide the details of string escaping from you so you don't get confused by them.)
htmlentities is for escaping text for inclusion in an HTML page. It should be used always-and-only in the output templating bit of your PHP. It is inappropriate to run it globally over all your input because not everything is going to end up in an HTML page or solely in an HTML page, and most probably it's going to go to the database first where you absolutely don't want a load of < and & rubbish making your text fail to search or substring reliably.
(Even then, htmlspecialchars is generally preferable to htmlentities as it only encodes the characters that really need it. htmlentities will add needless escaping, and unless you tell it the right encoding it'll also totally mess up all your non-ASCII characters. htmlentities should almost never be used.)
As for stripslashes... well, you sometimes need to apply that to input, but only when the idiotic magic_quotes_gpc option is turned on. You certainly shouldn't apply it all the time, only when you detect magic_quotes_gpc is on. It is long deprecated and thankfully dying out, so it's probably just as good to bomb out with an error message if you detect it being turned on. Then you could chuck the whole processInput thing away.
To summarise:
At start time, do no global input processing. You can do application-specific validation here if you want, like checking a phone number is just numbers, or removing control characters from text or something, but there should be no escaping happening here.
When making an SQL query with a string literal in it, use SQL-escaping on the value as it goes into the string: $query= "SELECT * FROM t WHERE name='".mysql_real_escape_string($name)."'";. You can define a function with a shorter name to do the escaping to save some typing. Or, more readably, parameterisation.
When making HTML output with strings from the input or the database or elsewhere, use HTML-escaping, eg.: <p>Hello, <?php echo htmlspecialchars($name); ?>!</p>. Again, you can define a function with a short name to do echo htmlspecialchars to save on typing.
I want to display on screen data send by the user,
remembering it can contain dangerous code, it is the best to clean this data with html entities.
Is there a better way to do html entities, besides this:
$name = clean($name, 40);
$email = clean($email, 40);
$comment = clean($comment, 40);
and this:
$data = array("name", "email," "comment")
function confHtmlEnt($data)
{
return htmlentities($data, ENT_QUOTES, 'UTF-8');
}
$cleanPost = array_map('confHtmlEnt', $_POST);
if so, how, and how does my wannabe structure
for html entities look?
Thank you for not flaming the newb :-).
"Clean POST", the only problem is you might not know in what context will your data appear. I have a Chat server now that works via browser client and a desktop client and both need data in a different way. So make sure you save the data as "raw" as possible into the DB and then worry about filtering it on output.
Do not encode everything in $_POST/$_GET. HTML-escaping is an output-encoding issue, not an input-checking one.
Call htmlentities (or, usually better, htmlspecialchars) only at the point where you're taking some plain text and concatenating or echoing it into an HTML page. That applies whether the text you are using comes from a submitted parameter, or from the database, or somewhere else completely. Call mysql_real_escape_string only at the point you insert plain text into an SQL string literal.
It's tempting to shove all that escaping stuff in its own box at the top of the script and then forget about it. But text preparation really doesn't work like that, and if you pretend it does you'll find your database irreparably full of double-encoded crud, backslashes on your HTML page and security holes you didn't spot because you were taking data from a source other than the (encoded) parameters.
You can make the burden of remembering to mysql_real_escape_string go away by using mysqli's parameterised queries or another higher-level data access layer. You can make the burden of typing htmlspecialchars every time less bothersome by defining a shorter-named function for it, eg.:
<?php
function h($s) {
echo(htmlspecialchars($s, ENT_QUOTES));
}
?>
<h1> Blah blah </h1>
<p>
Blah blah <?php h($title); ?> blah.
</p>
or using a different templating engine that encodes HTML by default.
If you wish to convert the five special HTML characters to their equivalent entities, use the following method:
function filter_HTML($mixed)
{
return is_array($mixed)
? array_map('filter_HTML',$mixed)
: htmlspecialchars($mixed,ENT_QUOTES);
}
That would work for both UTF-8 or single-byte encoded string.
But if the string is UTF-8 encoded, make sure to filter out any invalid characters sequence, prior to using the filter_HTML() function:
function make_valid_UTF8($str)
{
return iconv('UTF-8','UTF-8//IGNORE',$str)
}
Also see: http://www.phpwact.org/php/i18n/charsets#character_sets_character_encoding_issues
You need to clean every element bevor displaying it. I do it usually with a function and an array like your secound example.
If you use a framework with a template engine, there is quite likely a possibility to auto-encode strings. Apart from that, what's simpler than calling a function and getting the entity-"encoded" string back?
Check out the filter libraries in php, in particular filter_input_array.
filter_input_array(INPUT_POST, FILTER_SANITIZE_SPECIAL_CHARS);