HTML safe wrapping of long lines - php

I'm having problems sending HTML emails with long lines of text. The WYSIWYG editor (FCKEditor 2.5) used on the site keeps removing all the \n characters on certain browsers, including IE and Chrome. The result is an email with a single huge line of text. This wouldn't be a problem if it wasn't for email clients that wrap lines of over 998 characters by inserting ! \n in it. Of course, these almost always end up in the most unfortunate places, breaking HTML tags and looking nasty in the content itself.
My initial solution was to add a line feed after every HTML tag or every 900 to 990 characters. This is the regex I ended up with:
return preg_replace("/(<\/[^\>]+>|<[^\>]+\/>|>[^<]{900,990}\s)(\n)*/","$1\n",$str);
However, when there are lines that don't contain any tags at all, the whitespace matching part is never triggered. But if I remove the > from it's beginning, it starts breaking tags.
Is there a better way than regex to do this, or can this regex be healed?
EDIT: The 1000 character line length limit is defined in RFC 821.

Following my comment, I'm posting this as I have been able to run a test.
tidy::repairString shoud do the job just fine, better than any regex solution.
$content = "<html>......</html>";
$oTidy = new tidy();
$content = $oTidy->repairString($content,
array("show-errors" => 0, "show-warnings" => false),
"utf8"
);
Adapt the Charset parameter (3rd) to your needs.
The clean option is unneeded for this, I was wrong in my comment.

If I understand everything correctly, you don't need to concern yourself with lines that don't contain HTML at all - these can be left to be handled by email clients.

Related

PHP preg_match match consecutive newline chars

I am trying to prevent certain kinds of posts on my site, which are mostly meant to make it look like they contain some content but are just spam. Specifically, the posts are a few random words, some newline characters, and a random character.
So, I know some legit users might have use for using two newline chars (to create a blank line between paragraphs), but I figure 3+ can be marked as spam.
I tested this regex on regex101 and it works fine, but is never triggered when I test on my site, any ideas as to why? When I uncomment the echo line, it will show me the number 4 for my test data, so I know it sees the newlines.. is my regex formed incorrectly?!
Test data:
This is a potential
spam post
Code:
//echo substr_count($lowercaseBody, "\n");
if (preg_match('/\n{3,}./', $lowercaseBody)){
error("Stop Spamming my chan you .");
}
The data likely contains CRLF's, not just LF's.
The substr_count test does not care about the interleaving CR's, but your regex patterns does.
Use (\r?\n) instead of the \n to allow both CRLF's and LF's (different browsers/OS's, may use different new-lines):
if (preg_match('/(\r?\n){3,}./', $lowercaseBody)){
error("Stop Spamming my chan you .");
}

Line break gets replaced with rn in php

So, I have a taxtarea where the user makes a blog post but when the user submits it their line breaks get replaced with a 'rn' and I don't know why. I thought it was the php script but when I rewrote it and after taking away the str_replaces' it still replaced a new line with a rn.
What is happening?
In textarea just like any Text Editor, New Line are carriage (\r) or newline feed (\n) characters or combination of the two (depending on the OS). To convert these characters to linebreak of HTML, use the nl2br() of PHP.
Check PHP Manual for reference.
Try removing any stripslahes(). Stripslashes removes any backslashes and forward slashes. For example, line breaks are being sent as \n or \r and the stripslashes() takes away the backslashes in those, so that's why it says 'rn'.
I had this very problem, and this solution helped me. Good luck!

Can't understand why Zend_Mail::addHeader() strips newlines

(Since this is my first SO question, let me just say I hope it's not too Zend-specific. As far as I can tell this shouldn't be a problem. Although I could have posted it in a Zend-specific forum, I feel like I'm at least as likely to get a good answer here, especially since the answer might involve MIME-related issues that transcend Zend Framework. I'm basically trying to understand whether the issue I'm facing should be considered a ZF bug, or if I'm misunderstanding something or misusing it.)
I've been using Zend_Mail to build up a MIME message that gets sent through SendGrid, an email distribution service. Their platform allows you to send emails through their SMTP server, but gives added features when you use a special header (X-SMTPAPI) whose value is a JSON-encoded string of proprietary parameters, which can get quite long.
Eventually, the header I was passing got too long (I think >1000 chars), and I got errors. I was confused because I knew that it was getting passed through PHP's native wordwrap() function before I passed the value to Zend_Mail::addHeader(), so I thought line length should never be a problem.
It turns out that addHeader() strips newlines very deliberately, and with no particular explanation by way of comments.
// In Zend_Mail::addHeader()
$value = $this->_filterOther($value);
// In Zend_Mail::_filterOther()
$rule = array("\r" => '',
"\n" => '',
"\t" => '',
);
return strtr($data, $rule);
Ok, this seemed reasonable at first -- maybe ZF wants full control of formatting and line-wrapping. The next method called in Zend_Mail::addHeader() is
$value = $this->_encodeHeader($value);
This method encodes the value (either quoted-printable or base64 as appropriate) and chunks it into lines of appropriate length, but only if it contains "non-printable characters", as determined by Zend_Mime::isPrintable($value).
Looking into that method, newlines (\n) are indeed considered non-printable characters! So if only they hadn't been stripped out of the string in the previous method call, the long header would get encoded as QP and chunked into 72-char lines, and everything would work fine. In fact, I did a test where I commented out the call to _filterOther(), and the long header gets encoded and goes through with no problem. But now I've just made a careless hack to ZF without really understanding the purpose behind the line I removed, so this can't be a long-term solution.
My medium-term solution has been to extend Zend_Mail and create a new method, addHeaderForceEncode(), which will always encode the value of the header, and thus always chunk it into short lines. But I'm still not satisfied because I don't understand why that _filterOther() call was necessary in the first place -- maybe I shouldn't be working around it at all.
Can anyone explain to me why this behaviour exists of stripping newlines? It seems to inevitably lead to situations where a header can get too long if it doesn't contain any "non-printable characters" other than newlines.
I've done a bunch of different searches on this subject and looked through some ZF bug reports, but haven't seen anyone talking about this. Surprisingly it seems to be a really obscure issue. FYI I'm working with ZF 1.11.11.
Update: In case anyone wants to follow the ZF issue I opened about this, here it is: Zend_Mail::addHeader() UNfolds long headers, then throws exception
You're probably running into a few things. Per RFC 2821, text lines in SMTP can't exceed 1000 characters:
text line
The maximum total length of a text line including the is
1000 characters (not counting the leading dot duplicated for
transparency). This number may be increased by the use of SMTP
Service Extensions.
A header can't contain newlines, so that's probably why Zend is stripping them. For long headers, it's common to insert a line break (CRLF in SMTP) and a tab to "wrap" them.
Excerpt from RFC 822:
Each header field can be viewed as a single, logical line of
ASCII characters, comprising a field-name and a field-body.
For convenience, the field-body portion of this conceptual
entity can be split into a multiple-line representation; this
is called "folding". The general rule is that wherever there
may be linear-white-space (NOT simply LWSP-chars), a CRLF
immediately followed by AT LEAST one LWSP-char may instead be
inserted.
I would say that the _encodeHeader() function should possibly look at line length, and if the header is longer than some magic value, do the "wrap and tab" to have it span multiple lines.

Removing Break Lines

I've asked this question before but I didn't seem to get the right answer. I've got a problem with new lines in text. Javascript and jQuery don't like things like this:
alert('text
text);
When I pull information from a database table that has a break line in it, JS and jQuery can't parse it correctly. I've been told to use n2lbr(), but that doesn't work when someone uses 'shift+enter' or 'enter' when typing text into a message (which is where I get this problem). I still end up with separate lines when using it. It seems to correctly apply the BR tag after the line break, but it still leaves the break there.
Can anyone provide some help here? I get the message data with jQuery and send it off to PHP file to storage, so I'd like to fix the problem there.
This wouldn't be a problem normally, but I want to pull all of a users messages when they first load up their inbox and then display it to them via jQuery when they select a certain message.
You could use a regexp to replace newlines with spaces:
alert('<?php preg_replace("/[\n\r\f]+/m","<br />", $text); ?>');
The m modifier will match across newlines, which in this case I think is important.
edit: sorry, didn't realise you actually wanted <br /> elements, not spaces. updated answer accordingly.
edit2: like #LainIwakura, I made a mistake in my regexp, partly due to the previous edit. my new regexp only replaces CR/NL/LF characters, not any whitespace character (\s). note there are a bunch of unicode linebreak characters that i haven't acknowledged... if you need to deal with these, you might want to read up on the regexp syntax for unicode
Edit: Okay after much tripping over myself I believe you want this:
$str = preg_replace('/\n+/', '<br />', $str);
And with that I'm going to bed...too late to be answering questions.
I usually use json_encode() to format string for use in JavaScript, as it does everything that's necessary for making JS-valid value.

PHP form removing line breaks

I use a php form processor script that works fine. Except when users submit text in a multi-line text field, any line breaks or new lines are stripped out of the resulting string variable that is passed on. This often makes it unreadable by whoever receives the form results.
I'm no php expert but am sure the answer lies in the code that is stripping characters. What I'm unsure of is if I stop it stripping characters will this result in a security risk?
The strip array reads:
array('*', '|', '>', '<', '/', '\\\', '\"', 'Bcc', 'BCC', 'bcc');
What can I change here to retain the line breaks?
Thanks in advance for any help.
If your problem is with the submitted string then this means that the submitted string did not contain any line breaks or newline chars.
In one occassion i looked up the wrap="(hard|physical)" attribute on the text area. Some values of this attribute force the textarea to maintain line-breaks in the user text.
Did you try using nl2br($text) on the submitted text;
I believe you have an issue at the rendering phase. Have you tried:
echo nl2br($text);
Where $text is the text you're talking about.
Nothing there is stripping line breaks.
It's more likely that you're not doing anything on the display side to make the line breaks display. You're outputting HTML, and to HTML a line break is just more whitespace. You'll probably benefit from applying nl2br().

Categories