Allow only one br in nl2br - php

I let my members of my website to post some information about them in textarea. I use function nl2br to be it more prettier, smth like that:
$text_of_area = nl2br($_POST['text_area_name']); //yeah, of course i use functions against xss, sql injection attacks
mysql_query("..."); //here I insert a text
But here is problem. I don't want to allow people to use more then one enter (br) allowed in text, so what can I do?

Why not just replace more than one new line away prior to calling nl2br?
If you want to let them use only one new line at all in their post:
$firstPos = strpos($text, "\n");
if ($firstPos !== false) {
$text = substr_replace(array("\r","\n"),'', $text, $firstPos + 1);
}
$text = nl2br($text);
If you want to let them use only one consecutive new line (allowing foo\nbar\nbaz):
$text = preg_replace('#[\r\n]+#', "\n", $text);
$text = nl2br($text);

You could do:
$text_of_area = nl2br(str_replace("\r\n", "\n", $_POST['text_area_name']));

Related

How to add new line in php echo

The text of story content in my database is:
I want to add\r\nnew line
(no quote)
When I use:
echo nl2br($story->getStoryContent());
to replace the \r\n with br, it doesn't work. The browser still display \r\n. When I view source, the \r\n is still there and br is nowhere to be found also. This is weird because when I test the function nl2br with simple code like:
echo nl2br("Welcome\r\nThis is my HTML document");
it does work. Would you please tell me why it didn't work? Thank you so much.
The following snippet uses a technique that you may like better, as follows:
<?php
$example = "\n\rSome Kind\r of \nText\n\n";
$replace = array("\r\n", "\n\r", "\r", "\n");
$subs = array("","","","");
$text = str_replace($replace, $subs, $example );
var_dump($text); // "Some Kind of Text"
Live demo here
I doubt that you need "\n\r" but I left it in just in case you feel it is really necessary.
This works by having an array of line termination strings to be replaced with an empty string in each case.
I found the answer is pretty simple. I simply use
$text = $this->storyContent;
$text = str_replace("\\r\\n","<br>",$text);
$text = str_replace("\\n\\r","<br>",$text);
$text = str_replace("\\r","<br>",$text);
$text = str_replace("\\n","<br>",$text);

echo characters only in one line with explode function php

here is what i want to do
i am working with php explode function trying to limit characters it prints after defined condition
{
$result=http://php.net
new line characters i don't want to print
$links =explode("://",$result);
$nows=$links[1];
echo $nows;
}
as you can see the above code will print
php.net
new line characters i don't want to print
but instead i want to stop printing after
php.net
You can replace newline characters with nothing:
$nows = str_replace("\n", "", $links[1]);
$nows = str_replace("\r", "", $nows);
echo $nows;
If you want only what is printed on the first line, try this:
$result = "php.net
and some other text";
$nows = reset(explode("\n", str_replace("\r\n", "\n", $result)));
If the part you're looking after will always be in the first line:
$result="http://php.net
new line characters i don't want to print";
$links = explode("\n",$result);
/*
$links[0] ->http://php.net
$links[1] ->new line characters i don't want to print
*/
$links =explode("://",$links[0]);
$nows=$links[1];
echo $nows;
/*
php.net
*/
Anyway , Consider giving more details about your case in order to offer a better way.
For instance , maybe regex?
Try
$nows = trim( $links[1] );
TRIM() will remove newlines among other things
Manual page
EDIT:
Well now we have the actual situation which you say is :-
$result=http://php.net</br>nameserver:ns1</br>nameserver:ns2.
Try
$t = explode( '</br>', $result );
$t1 = explode ( '://', $t[0] );
echo $t1[1];
Just as a note, if it is you that is creating this string somewhere else </br> is not a valid html tag, it should be <br> or if you are using XHTML it should be <br />.

For very basic markdown, will these regular expressions work?

just a quick question about Regular expressions: Will this code work for any grooming I will need to do? (i.e. Can this be inputted into a database and be safe?)
function markdown2html($text) {
$text = htmlspecialchars($text, ENT_QUOTES, 'UTF-8');
// Strong Emphasis
$text = preg_replace('/__(.+?)__/s', '<strong>$1</strong>', $text);
$text = preg_replace('/\*\*(.+?)\*\*/s', '<strong>$1</strong>', $text);
// Underline
$text = preg_replace('/_([^_]+)_/', '<p style="text-decoration: underline;">$1</p>', $text);
//Italic
$text = preg_replace('/\*([^\*]+)\*/', '<em>$1</em>', $text);
// Windows to Unix
$text = str_replace('\r\n', '\n', $text);
// Macintosh to Unix
$text = str_replace('\r', '\n', $text);
//Paragraphs
$text = '<p>' . str_replace("\n\n", '</p><p>', $text) . '</p>';
$text = str_replace("\n", '<br />', $text);
// [Linked Text](Url)
$text = preg_replace('/\[([^\]]+)]\(([a-z0-9._~:\/?##!$&\'()*+,;=%]+)\)/i', '$1', $text);
return $text;
}
No, absolutely not.
Your code has nothing to do with SQL -- it does not modify ' or \ characters at all. Commingling the formatting functionality of this function with SQL escaping is silly.
Your code may also introduce HTML injection in some situations -- I'm particularly suspicious of the URL linking regex. Without a proper parser involved, I would not trust it an inch.
No, the data can not assured to be safe after passing through that function.
You need to either escape sql-sensitive characters or use PDO/Mysqli. Preapared statements are much more handy anyway.
Don't use the old way of hacking together a query, ie:
$query = 'select * from table where col = '.$value;
You're just asking for trouble there.
A couple of things jumped out at me:
I believe that the first two regexs ('/__(.+?)__/s' and the corresponding one for *) handle ___word___ and ***word*** incorrectly –– they will treat the third character as part of the word, so you will get *word* (where the first * is bold and the trailing one is not) instead of word.
On the third one ('/_([^_]+)_/'), is it really appropriate for
do _not_ do that
to turn into
do <p style="text-decoration: underline;">not</p> do that
?
Of course I’m not saying that it’s OK to use if you fix these issues.

nl2br() creates an extra new line

I am trying to insert a description text field into the database.
I was previously just doing something like this:
$group_description = mysql_real_escape_string($_POST['group_description']);
But it was creating problems because when I was taking things out of the database, they were being displayed with \n\r strings instead of new lines.
Here is an example of a page with that problem:
http://www.comehike.com/hikes/hiking_group.php?hiking_group_id=48
So I tried to fix it by adding nl2br like this:
$group_description = mysql_real_escape_string(nl2br($_POST['group_description']));
But that just inserted an extra line :( Here is the example of the current problem:
http://www.comehike.com/hikes/hiking_group.php?hiking_group_id=50
Here is an example of an insert statement I use:
$insert_group_sql = 'INSERT INTO hiking_groups( title , group_description ) VALUES ( "'.$group_name.'" , "'.$group_description.'" ) ';
What is the proper way to do this?
Here is the code I use to display the $group_description
//Convert all urls to links
$group_description = preg_replace('#([\s|^])(www)#i', '$1http://$2', $group_description);
$pattern = '#((http|https|ftp|telnet|news|gopher|file|wais):\/\/[^\s]+)#i';
$replacement = '$1';
$group_description = preg_replace($pattern, $replacement, $group_description);
$group_description = str_replace("\'" , "'", $group_description );
$group_description = nl2br($group_description);
/* Convert all E-mail matches to appropriate HTML links */
$pattern = '#([0-9a-z]([-_.]?[0-9a-z])*#[0-9a-z]([-.]?[0-9a-z])*\\.';
$pattern .= '[a-wyz][a-z](fo|g|l|m|mes|o|op|pa|ro|seum|t|u|v|z)?)#i';
$replacement = '\\1';
$group_description = preg_replace($pattern, $replacement, $group_description);
First, I suggest that you do as Spudley suggests, keep it in the original form in the database and format it once you display it.
nl2br() should work, so I suggest that you check the input data to see exactly what is being input (which is easier to do if you don't format it before you store it in the DB). What it do is it takes \n, \n\r, \r\n and \r and inserts a <br/> instead. You should check that for instance there is no space in between \n and \r.
Also, make sure that you only use nl2br() in one place, since it doesn't replace the new lines, it just inserts the <br/> (that is, if you do nl2br(nl2br($group_description)) you will get two <br/>)
Update:
I see in the additional code that when you display the description, you already have a nl2br(). You need to remove one of them, so that you only add the <br/>s once.
Also, instead of this:
$group_description = str_replace("\'" , "'", $group_description );
$group_description = nl2br($group_description);
Try this:
$group_description = stripslashes($group_description);
$group_description = nl2br($group_description);
That should remove all the sanitizing that mysql_real_escape_string() did, which should solve the problem of the \n\r showing in the text.
Try trim before passing to nl2br:
nl2br( trim($_POST['group_description']) )

Formatting text received via api

I get text via api and sometimes the text can be like so:
hello
world!
How are you?
But I do need the text to be like this:
hello world! How are you?
How to do that?
you can replace the newlines in the text by doing:
$newmsg = str_replace("\n",' ',$yourmsg);
Here is the link to the php function documentation:
http://php.net/manual/en/function.str-replace.php
EDIT: I added a space in the code so it does "hello world..." instead of "helloworld"
Use
$str=" test
hello
world" ;
str_replace ( "\n"," " , $str
) ;
If you want number of replaced count pass the fourth argument
str_replace ( "\n"," " , $str , $count ) ;
$str=<<<EOF
hello
world!
How are you?
EOF;
$s = explode("\n",$str);
print_r(implode(" ",$s));
Here is a really ridiculous solution that I would probably use (bear in mind, ocdcoder's answer works just fine), to make sure I accounted for all possible line endings:
$line_ends = array("\r\n", "\r", "\n"); //notice the order is important.
$new_msg = str_replace($line_ends, " ", $orig_msg);
This way, if there are double line ends, it gets rid of them, but if not, it goes back and checks for single line endings.
But if you want to get more complicated, you could replace your possible carriage-returns with line-ends:
$msg_newline_fix = str_replace("\r", "\n", $orig_message);
$msg_double_newline_fix = str_replace("\n\n", "\n", $msg_newline_fix);
$newmsg = str_replace("\n", " ", $msg_double_newline_fix);
But again, I'm a bit wacky like that. Another crazy solution might be:
$msg_newline_fix = str_replace("\r", "\n", $orig_message);
$msg_array_lines = explode("\n", $msg_newline_fix);
foreach($msg_array_lines as $msg_line){
$clean_line = rtrim($msg_line);
if($clean_line !== '') {
$msg_clean_array[] = $clean_line;
}
}
$new_msg = implode(" ", $msg_clean_array);
But if you know your line endings will be new lines (\n) and not carriage returns (\r) then you are probably safe with a simple one line str_replace.
Finally, you might actually want to preserve line endings when it indicates a new paragraph, something like:
Hello
World!
This is a
new paragraph.
In which case, I would suggest normalizing the line-endings first (making it consistently the same thing so we aren't guessing) and then replacing those empty lines with some kind of safe token you can go back and replace with your new line. Something like:
$msg_carriage_fix = str_replace("\r", "\n\n", $orig_message);
$msg_double_carriage_fix = str_replace("\n\n\n", "\n\n", $msg_newline_fix);
Now we are at the point where we know each line, including empty lines, have only one \n at the end. By replacing the potential \r with two \n, and then replacing only three \n in a row with two \n we avoid the risk of removing any line endings if there were no carriage-return \rs in the first place. Then we can finally do:
$msg_hold_true_linebreaks = str_replace("\n\n", "%line-break%", $msg_double_carriage_fix);
$msg_strip_new_lines = str_replace("\n"," ",$msg_hold_true_linebreaks);
and last but not least:
$new_msg = str_replace("%line-break%","\n",$msg_strip_new_lines);
But,that is only if you really want to keep those true line-breaks and if you want to be extra sure you are ready for carriage-returns, line-ends, and the dreaded \r\n.
I would show yet another version that may shorter and involves using implode and explode, but I'm sure that's enough for now.
edit
Here is a slightly simpler version of that last suggestion, which tries to account for both line endings and intentional line breaks:
$msg_rn_fix = str_replace("\r\n", "\n", $orig_msg);
$msg_r_fix = str_replace("\r", "\n", $msg_rn_fix);
We now know each line ends with a single \n, including empty lines...
$msg_array = explode("\n", $msg_r_fix);
Normal lines each get an array value, but we also know that if the array value is nothing, that it was an intentional hard return...
foreach($msg_array as $msg_line) {
$clean_msg_lines[] = ($msg_line == '') ? "\n" : $msg_line;
}
then we put it all back together:
$new_msg = implode(" ", $clean_msg_lines);
The only flaw is that there will be an extra space before and after each line end. This is easily fixed:
$new_msg = str_replace(" \n ", "\n", $new_msg);
I like this last solution so much, I'm going to copy it below without commentary.
My favorite version
$msg_rn_fix = str_replace("\r\n", "\n", $orig_msg);
$msg_r_fix = str_replace("\r", "\n", $msg_rn_fix);
$msg_array = explode("\n", $msg_r_fix);
foreach($msg_array as $msg_line) {
$clean_msg_lines[] = ($msg_line == '') ? "\n" : $msg_line;
}
$new_msg = implode(" ", $clean_msg_lines);
$new_msg = str_replace(" \n ", "\n", $new_msg);

Categories