79 $fieldDateInTimeStamp = makeTimestamp($timeString);
81 $formattedDate = FormatDate($titleDateFormat, $fieldDateInTimeStamp, (time() + CTimeZone::getOffset()));
85 $fromList = static::convertContactListToString(
$from);
86 $toList = static::convertContactListToString(
$to);
87 $ccList = static::convertContactListToString($cc);
90 $body = Helper\Message::sanitizeHtml($body);
96 '#DATE#' => $formattedDate,
99 '#FROM_LIST#' => $fromList,
100 '#TO_LIST#' => $toList,
101 '[blockquote]' =>
'<blockquote style="margin: 0 0 0 5px; padding: 5px 5px 5px 8px; border-left: 4px solid #e2e3e5; ">',
102 '[/blockquote]' =>
'</blockquote>'
108 '#DATE#' => $formattedDate,
111 '#FROM_LIST#' => $fromList,
112 '#TO_LIST#' => $toList,
113 '#CC_LIST#' => $ccList,
114 '[blockquote]' =>
'<blockquote style="margin: 0 0 0 5px; padding: 5px 5px 5px 8px; border-left: 4px solid #e2e3e5; ">',
115 '[/blockquote]' =>
'</blockquote>'
161 if (isset($this->html))
165 $html = str_replace(array(
"\r",
"\n"),
'',
$html);
166 $html = preg_replace(
'/<br\s*\/?>/is',
"\n",
$html);
168 $html = str_ireplace(
'</div>',
"</div>\n",
$html);
169 $html = str_ireplace(
'</p>',
"</p>\n",
$html);
170 $html = preg_replace(
'/<\/h([1-6])>/i',
"</h\\1>\n",
$html);
171 $html = str_ireplace(
'</table>',
"</table>\n",
$html);
172 $html = str_ireplace(
'</tr>',
"</tr>\n",
$html);
173 $html = str_ireplace(
'</pre>',
"</pre>\n",
$html);
175 $html = preg_replace(
'/(\n\s*)?<div/i',
"\n<div",
$html);
176 $html = preg_replace(
'/(\n\s*)?<p(?=\s|>)/i',
"\n<p",
$html);
177 $html = preg_replace(
'/(\n\s*)?<h([1-6])/i',
"\n<h\\2",
$html);
178 $html = preg_replace(
'/(\n\s*)?<table/i',
"\n<table",
$html);
179 $html = preg_replace(
'/(\n\s*)?<tr/i',
"\n<tr",
$html);
180 $html = preg_replace(
'/(\n\s*)?<pre/i',
"\n<pre",
$html);
182 $html = preg_replace(
'/(\n\s*)?<hr[^>]*>(\s*\n)?/i',
"\n<hr>\n",
$html);
186 list($before, $quote, $after) = $parts;
187 $html = sprintf(
'%s%s%s', $before, static::QUOTE_PLACEHOLDER, $after);
192 foreach ($this->attachments as $item)
194 $html = preg_replace(
195 sprintf(
'/<img[^>]+src\s*=\s*(\'|\")?\s*(cid:%s)\s*\1[^>]*>/is', preg_quote($item[
'contentId'],
'/')),
196 sprintf(
'[ATTACHMENT=%s]', $item[
'uniqueId']),
203 $html = preg_replace(
'/<style[^>]*>.*?<\/style>/is',
'',
$html);
204 $html = preg_replace(
'/<script[^>]*>.*?<\/script>/is',
'',
$html);
205 $html = preg_replace(
'/<title[^>]*>.*?<\/title>/is',
'',
$html);
206 $html = preg_replace(
'/<caption[^>]*>.*?<\/caption>/is',
'',
$html);
209 $html = preg_replace(
'/<a\s[^>]*href\s*=\s*([^\'\"\s>]+)\s*[^>]*>/is',
'<a href="\1">',
$html);
212 $html = preg_replace(
'/<strong[^>]*>(.*?)<\/strong>/is',
'<b>\1</b>',
$html);
213 $html = preg_replace(
'/<em[^>]*>(.*?)<\/em>/is',
'<i>\1</i>',
$html);
214 $html = preg_replace(
'/<blockquote[^>]*>(.*?)<\/blockquote>/is',
'<quote>\1</quote>',
$html);
215 $html = preg_replace(
'/<hr[^>]*>/is',
'________________________________________',
$html);
216 $html = preg_replace(
'/<del[^>]*>(.*?)<\/del>/is',
'<s>\1</s>',
$html);
217 $html = preg_replace(
'/<ins[^>]*>(.*?)<\/ins>/is',
'<u>\1</u>',
$html);
218 $html = preg_replace(
'/<h([1-6])[^>]*>(.*?)<\/h\1>/is',
'<b>\2</b>',
$html);
219 $html = preg_replace(
'/<dl[^>]*>(.*?)<\/dl>/is',
'<ul>\1</ul>',
$html);
220 $html = preg_replace(
'/<dt[^>]*>/is',
'<li>',
$html);
221 $html = preg_replace(
'/<dd[^>]*>/is',
' - ',
$html);
222 $html = preg_replace(
'/<(sub|sup)[^>]*>(.*?)<\/\1>/is',
'(\2)',
$html);
225 $html = preg_replace(
'/<th[^>]*>(.*?)<\/th>/is',
'<td>\1</td>',
$html);
227 $sanitizer = new \CBXSanitizer();
229 $sanitizer->addTags(array(
230 'a' => array(
'href'),
235 'img' => array(
'src'),
236 'font' => array(
'color',
'size',
'face'),
249 $sanitizer->applyDoubleEncode(
false);
252 $parser = new \CTextParser();
255 $text = html_entity_decode(
$text, ENT_QUOTES | ENT_HTML401, LANG_CHARSET);
258 $text = preg_replace(
'/<\/?([abuis]|img|font|ul|ol|li|table|tr|td|th|quote|br)(?=\s|>)[^>]*>/i',
'',
$text);
260 $text = preg_replace(
'/[\t\x20]+/',
"\x20",
$text);
269 if ($this->type ==
'reply' and $parts = $this->
splitText($text))
271 list($before, $quote, $after) = $parts;
272 $text = sprintf(
'%s%s%s', $before, static::QUOTE_PLACEHOLDER, $after);
277 foreach ($this->attachments as $item)
280 sprintf(
'[cid:%s]', $item[
'contentId']),
281 sprintf(
'[ATTACHMENT=%s]', $item[
'uniqueId']),
288 if ($this->type ==
'reply' && mb_strpos(
$text, static::QUOTE_PLACEHOLDER))
291 $text = preg_replace(sprintf(
'/\s*%s\s*/', preg_quote(static::QUOTE_PLACEHOLDER,
'/')),
"\n\n",
$text);
294 if ($this->type ==
'forward')
298 $text = preg_replace(
'/\[tr\]\s*\[\/tr\]/is',
'',
$text);
299 $text = preg_replace(
'/\[table\]\s*\[\/table\]/is',
'',
$text);
302 $text = preg_replace(
'/(\s*\n){2,}/',
"\n\n",
$text);
305 $text = sprintf(
'[ATTACHMENT=%s]', $item[
'uniqueId']);
307 if (!empty($this->secret))
308 $text = str_replace($this->secret,
'xxxxxxxx',
$text);
354 $parts = preg_split(
'/(<blockquote.+?<\/blockquote>)/is',
$html,
null, PREG_SPLIT_DELIM_CAPTURE);
356 if (count($parts) > 3)
358 $parts = array_merge(
359 array(join(array_slice($parts, 0, -2))),
360 array_slice($parts, -2)
365 if (count($parts) == 3)
366 $parts = preg_split(
'/(<blockquote.+<\/blockquote>)/is',
$html,
null, PREG_SPLIT_DELIM_CAPTURE);
369 if (count($parts) < 3)
370 $parts = preg_split(static::QUOTE_HTML_REGEX,
$html,
null, PREG_SPLIT_DELIM_CAPTURE);
372 if (count($parts) == 3)
386 $parts = preg_split(
'/((?:^>.*$\n?){2,})/m',
$text,
null, PREG_SPLIT_DELIM_CAPTURE);
388 if (count($parts) < 3)
389 $parts = preg_split(
'/((?:^\|.*$\n?){2,})/m',
$text,
null, PREG_SPLIT_DELIM_CAPTURE);
391 if (count($parts) < 3)
394 (?:^_{20,}\n(?:[\t\x20]*\n)?)?
395 (?:^(?:from|to|subject|sent|date):\x20[^\n]+$\n?){2,8}.*
397 $parts = preg_split($outlookRegex,
$text,
null, PREG_SPLIT_DELIM_CAPTURE);
400 if (count($parts) == 3)
416 if (preg_match_all(
'/^([^\:\n]{1,20}):[\t\x20]+(.+)$/m'.BX_UTF_PCRE_MODIFIER, $head, $matches, PREG_SET_ORDER))
419 'value' => $this->subject,
420 'strlen' => mb_strlen($this->subject),
421 'sgnlen' => mb_strlen(trim($this->subject))
424 $isHeader =
function($key, $value) use (&
$subject)
426 if (mb_strlen(trim($value)) >= 10 &&
$subject[
'sgnlen'] >= 10)
428 $dist =
$subject[
'strlen'] - mb_strlen($value);
432 if ($dist >= 0 && mb_strpos(
$subject[
'value'], $value) !==
false)
437 if (max(
$subject[
'strlen'], mb_strlen($value)) < 256 && levenshtein(
$subject[
'value'], $value) < 10)
444 $date = preg_replace(
'/(?<=[\s\d])UT$/i',
'+0000', trim($value));
445 if (preg_match(
'/\d{1,2}:\d{2}(:\d{2})?\x20?(am|pm)?/i', $date) && strtotime($date) !==
false)
450 if (preg_match(
'/([a-z\d_](\.?[a-z\d_-]+)*)?[a-z\d_]@(([a-z\d][a-z\d-]*)?[a-z\d]\.?)+/i', $value))
458 foreach ($matches as $item)
460 $score += (int) $isHeader($item[1], $item[2]);
510 list($before, $after) = explode(static::QUOTE_PLACEHOLDER,
$text, 2);
515 $data = static::reduceTags($before);
526 $fullHeadRegex =
'/(?:^|\n\n)
527 (?<hr>_{20,}\n(?:[\t\x20]*\n)?)?
528 (?<head>(?:[^\:\n]{1,20}:[\t\x20]+.+(?:\n|$)){2,6})\s*$
529 /x'.BX_UTF_PCRE_MODIFIER;
530 if (preg_match($fullHeadRegex, $data, $matches))
532 $score = (int) !empty($matches[
'hr']);
537 $pattern = preg_replace(array(
'/.+/',
'/\n/'), array(
'.+',
'\n'), $matches[0]);
538 $before = preg_replace_callback(
539 sprintf(
'/%s$/', $pattern),
547 return sprintf(
'%s%s%s', $before, static::QUOTE_PLACEHOLDER, $after);
556 $shortHeadRegex =
'/(?:^|\n)
557 (?<date>.{5,50}\d),?\x20
558 [^\d\n]{0,20}(?<time>\d{1,2}\:\d{2}(?:\:\d{2})?\x20?(?:am|pm)?),?\x20
560 /ix'.BX_UTF_PCRE_MODIFIER;
561 if (preg_match($shortHeadRegex, $data, $matches))
568 $pattern = preg_replace(array(
'/.+/',
'/\n/'), array(
'.+',
'\n'), $matches[0]);
569 $before = preg_replace_callback(
570 sprintf(
'/%s$/', $pattern),
578 return sprintf(
'%s%s%s', $before, static::QUOTE_PLACEHOLDER, $after);
596 $data = static::reduceTags(
$text);
598 $shortHeadRegex =
'/(?:^|\n)\s*
599 -{3,}.{4,40}?-{3,}[\t\x20]*\n
600 (?<head>(?:[\t\x20]*\n)?
601 (?<date>.{5,50}\d),?\x20
602 [^\d\n]{0,20}(?<time>\d{1,2}\:\d{2}(?:\:\d{2})?\x20?(?:am|pm)?),?\x20
603 (?<from>.+):(?:\s*\n)?)
604 /ix'.BX_UTF_PCRE_MODIFIER;
606 $hasMarker = preg_match($shortHeadRegex, $data);
607 $fullHeadRegex =
'/(?:^|\n\n)\s*
608 (?<marker>-{3,}.{4,40}?-{3,}[\t\x20]*\n)'.($hasMarker ?
'' :
'?').
'
609 (?<head>(?:[\t\x20]*\n)?
610 (?<lines>(?:[^\:\n]{1,20}:[\t\x20]+.+(?:\n|$)){2,6}))
612 /x'.BX_UTF_PCRE_MODIFIER;
614 if (preg_match($fullHeadRegex, $data, $matches, PREG_OFFSET_CAPTURE))
616 $score = (int) !empty($matches[
'marker'][0]);
622 $pattern = preg_replace(
623 array(
'/.+/',
'/\n/'), array(
'.+',
'\n'),
624 array(substr($data, 0, $matches[
'head'][1]), $matches[
'head'][0])
627 return preg_replace_callback(
628 sprintf(
'/^(%s)(%s)/', $pattern[0], $pattern[1]),
638 if (preg_match($shortHeadRegex, $data, $matches, PREG_OFFSET_CAPTURE))
646 $pattern = preg_replace(
647 array(
'/.+/',
'/\n/'), array(
'.+',
'\n'),
648 array(substr($data, 0, $matches[
'head'][1]), $matches[
'head'][0])
651 return preg_replace_callback(
652 sprintf(
'/^(%s)(%s)/', $pattern[0], $pattern[1]),