179 lines
5.0 KiB
PHP
179 lines
5.0 KiB
PHP
<?php
|
|
/**
|
|
* @class mailConvert
|
|
*
|
|
* This class converts mail body to xHTML in a descent fashion.
|
|
* It can also rewrap mail body.
|
|
*
|
|
* @package Clearbricks
|
|
* @subpackage Mail
|
|
*
|
|
* @copyright Olivier Meunier & Association Dotclear
|
|
* @copyright GPL-2.0-only
|
|
*/
|
|
|
|
class mailConvert
|
|
{
|
|
public $url_pattern = '%(?<![\[\|])(http|https|ftp|news):(//)?(.*?)(["\s\)]|>|<|\Z)%msu'; ///< URL pattern
|
|
|
|
public static function toHTML($str)
|
|
{
|
|
$o = new self;
|
|
return $o->html(rtrim($str), true);
|
|
}
|
|
|
|
public static function rewrap($str, $l = 72)
|
|
{
|
|
$o = new self;
|
|
return $o->wrap($str, $l);
|
|
}
|
|
|
|
public static function getSubject($str)
|
|
{
|
|
while (preg_match('/^re: /msiu', $str)) {
|
|
$str = preg_replace('/^re: /msiu', '', $str);
|
|
}
|
|
return $str;
|
|
}
|
|
|
|
public function html($str, $with_signature = false)
|
|
{
|
|
$res = '';
|
|
$signature = '';
|
|
|
|
if ($with_signature && preg_match('/^(-- \r?\n.+?)\Z/msu', $str, $m)) {
|
|
$m[1] = preg_replace('/^-- \r?\n/msu', '', $m[1]);
|
|
$signature = '<pre class="signature">' . $this->htmlParseBlock($m[1]) . '</pre>';
|
|
$str = preg_replace('/^-- \r?\n(.+?)\Z/msu', '', $str);
|
|
$str = rtrim($str);
|
|
}
|
|
|
|
foreach ($this->getTockens($str) as $t) {
|
|
switch ($t['type']) {
|
|
case 'block':
|
|
$t['content'] = $this->htmlParseBlock($t['content']);
|
|
$res .= '<pre>' . $t['content'] . "</pre>\n";
|
|
break;
|
|
case 'quote':
|
|
$res .= "<blockquote>\n" . $this->html($t['content']) . "</blockquote>\n\n";
|
|
break;
|
|
}
|
|
}
|
|
|
|
return $res . $signature;
|
|
}
|
|
|
|
public function wrap($str, $l = 72)
|
|
{
|
|
$str = $this->prepareString($str);
|
|
|
|
$res = '';
|
|
|
|
foreach (explode("\n", $str) as $line) {
|
|
$sep = "\n";
|
|
if (preg_match('/^([>\|]+\s*)/su', $line, $m)) {
|
|
$sep .= $m[1];
|
|
}
|
|
|
|
$line = wordwrap($line, $l, $sep, false) . "\n";
|
|
|
|
$res .= $line;
|
|
}
|
|
|
|
return $res;
|
|
}
|
|
|
|
protected function prepareString($str)
|
|
{
|
|
return preg_replace('/\r?\n/msu', "\n", $str);
|
|
}
|
|
|
|
protected function getTockens($str)
|
|
{
|
|
$str = $this->prepareString($str);
|
|
|
|
$tockens = [];
|
|
$type = null;
|
|
$id = -1;
|
|
|
|
foreach (explode("\n", $str) as $line) {
|
|
if (preg_match('/^(?:\s*)(?:>|\|)(?:\s?)(.*?)$/su', $line, $m)) {
|
|
if ($type != 'quote' && !trim($m[1])) {
|
|
continue;
|
|
}
|
|
|
|
if ($type == 'quote') {
|
|
$tockens[$id]['content'] .= $m[1] . "\n";
|
|
} else {
|
|
$id++;
|
|
$type = 'quote';
|
|
$tockens[$id]['type'] = $type;
|
|
$tockens[$id]['content'] = $m[1] . "\n";
|
|
}
|
|
}
|
|
# Empty line
|
|
elseif (preg_match('/^\s*$/su', $line)) {
|
|
if ($type == 'block') {
|
|
$tockens[$id]['content'] .= "\n";
|
|
}
|
|
}
|
|
# Defaults to block
|
|
else {
|
|
if ($type == 'block') {
|
|
$tockens[$id]['content'] .= $line . "\n";
|
|
} else {
|
|
$id++;
|
|
$type = 'block';
|
|
$tockens[$id]['type'] = $type;
|
|
$tockens[$id]['content'] = $line . "\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach ($tockens as $i => $t) {
|
|
$tockens[$i]['content'] = preg_replace('/\n$/su', '', $t['content']);
|
|
}
|
|
|
|
return $tockens;
|
|
}
|
|
|
|
protected function htmlParseBlock($str)
|
|
{
|
|
$str = html::escapeHTML($str);
|
|
|
|
# Transform links
|
|
$str = preg_replace_callback($this->url_pattern, [$this, 'htmlUrlHandler'], $str);
|
|
|
|
# Transform * / _ strings (does not work, may transform links href)
|
|
#$str = preg_replace_callback('%([\*_/])([\w\s]+?)([\*_/])%msu',[$this,'htmlFormatHandler'],$str);
|
|
|
|
return $str;
|
|
}
|
|
|
|
protected function htmlUrlHandler($m)
|
|
{
|
|
$url = $m[1] . ':' . html::decodeEntities($m[2] . $m[3]);
|
|
$content = $url;
|
|
$title = '';
|
|
|
|
if (strlen($url) > 42) {
|
|
$content = substr($url, 0, 42) . '...';
|
|
$title = ' title="' . html::escapeHTML($url) . '"';
|
|
}
|
|
|
|
return '<a href="' . html::escapeHTML($url) . '"' . $title . '>' . html::escapeHTML($content) . '</a>' . $m[4];
|
|
}
|
|
|
|
protected function htmlFormatHandler($m)
|
|
{
|
|
switch ($m[1]) {
|
|
case '*':
|
|
return '<strong>' . $m[2] . '</strong>';
|
|
case '/':
|
|
return '<em>' . $m[2] . '</em>';
|
|
case '_':
|
|
return '<ins>' . $m[2] . '</ins>';
|
|
}
|
|
}
|
|
}
|