diff --git a/config.php.in b/config.php.in
index cae1079..1aa24fb 100644
--- a/config.php.in
+++ b/config.php.in
@@ -277,6 +277,7 @@
$config['DECIMAL_SEPARATOR'] = "."; // See https://www.php.net/manual/en/function.number-format
$config['THOUSANDS_SEPARATOR'] = ","; // for the format options
+$config['ENABLE_GB2312_FIX'] = 1;
$config['FROM_LENGTH_TO_SHOW'] = 28;
@@ -434,7 +435,7 @@
define('TABLE_DELETED', 'deleted');
define('VIEW_MESSAGES', 'v_messages');
-define('EOL', "\n");
+define('EOL', "\r\n");
define('DIR_SYSTEM', DIR_BASE . 'system/');
define('DIR_MODEL', DIR_BASE . 'model/');
diff --git a/webui/model/mail/mail.php b/webui/model/mail/mail.php
index c9bdb74..f589342 100644
--- a/webui/model/mail/mail.php
+++ b/webui/model/mail/mail.php
@@ -8,6 +8,9 @@
require_once 'Zend/Mail/Protocol/Smtp.php';
require_once 'Zend/Mail/Protocol/Smtp/Auth/Login.php';
+ // Workaround for the zend framework
+ $msg = str_replace("\r", "", $msg);
+
$ok = 0;
if($to == "" || strlen($msg) < 30){ return $ok; }
@@ -118,7 +121,7 @@
$s = strstr($hdr, "Subject:");
if($s) {
$l1 = strlen($s);
- $l2 = strlen(strstr($s, "\n"));
+ $l2 = strlen(strstr($s, EOL));
if($l1 > $l2 + 10) {
$subject = substr($s, 0, $l1 - $l2) . EOL;
}
diff --git a/webui/model/search/message.php b/webui/model/search/message.php
index 395fbfd..4d132ea 100644
--- a/webui/model/search/message.php
+++ b/webui/model/search/message.php
@@ -198,7 +198,7 @@
'cc' => $cc,
'subject' => $this->highlight_search_terms($subject, $terms),
'date' => $date,
- 'message' => $this->message['text/html'] ? $this->message['text/html'] : $this->message['text/plain'],
+ 'message' => $this->message['text/html'] ? $this->highlight_search_terms($this->message['text/html']) : $this->highlight_search_terms($this->message['text/plain']),
'has_journal' => $has_journal,
'verification' => $this->verification
);
@@ -220,6 +220,10 @@
}
}
+ if($html == 0) {
+ $s = preg_replace("/THE_BREAK_HTML_TAG/", "
", $s);
+ }
+
if(count($terms) <= 0) { return $s; }
if($html == 0) {
diff --git a/webui/system/helper/mime.php b/webui/system/helper/mime.php
index 9e5d585..cf00571 100644
--- a/webui/system/helper/mime.php
+++ b/webui/system/helper/mime.php
@@ -5,6 +5,12 @@
const HEADER_FIELDS = ['from', 'to', 'cc', 'subject', 'date'];
+ public static function normalize_message($message) {
+ $a = preg_split("/\r?\n/", $message);
+ return implode(EOL, $a);
+ }
+
+
public static function parseMessage($message, &$result) {
self::splitMessage($message, $headers, $body);
@@ -18,10 +24,10 @@
self::parseMessage($body, $result);
}
else {
- $result[] = array(
+ $result[] = [
'headers' => $headers,
'body' => $body
- );
+ ];
}
return;
@@ -39,7 +45,7 @@
}
else {
if(in_array($headers['content-type']['type'], ["text/plain", "text/html"])) {
- $result[] = array('headers' => $headers, 'body' => $body);
+ $result[] = ['headers' => $headers, 'body' => $body];
}
else if($headers['content-type']['type'] == "message/rfc822") {
self::parseMessage($body, $result);
@@ -51,23 +57,21 @@
public static function splitMime($body, $boundary) {
$start = 0;
- $res = array();
-
- $body = self::remove_LF($body);
+ $res = [];
// Extract the mime parts excluding the boundary itself
- $p = strpos($body, '--' . $boundary . "\n", $start);
+ $p = strpos($body, '--' . $boundary . EOL, $start);
if($p === false) {
// no parts found!
- return array();
+ return [];
}
// Position after first boundary line
$start = $p + 3 + strlen($boundary);
- while(($p = strpos($body, '--' . $boundary . "\n", $start)) !== false) {
+ while(($p = strpos($body, '--' . $boundary . EOL, $start)) !== false) {
$res[] = substr($body, $start, $p-$start);
$start = $p + 3 + strlen($boundary);
}
@@ -76,7 +80,7 @@
$p = strpos($body, '--' . $boundary . '--', $start);
if($p === false) {
- return array();
+ return [];
}
// The remaining part also needs to be parsed:
@@ -86,22 +90,22 @@
}
- public static function splitMessage($message, &$headers, &$body, $EOL = "\n") {
+ public static function splitMessage($message, &$headers, &$body) {
self::splitMessageRaw($message, $headers, $journal, $body);
$headers = self::splitHeaders($headers);
}
- public static function splitMessageRaw($message, &$headers, &$journal, &$body, $EOL = "\n") {
+ public static function splitMessageRaw($message, &$headers, &$journal, &$body) {
$headers = [];
$body = '';
- $message = self::remove_LF($message);
+ $message = self::normalize_message($message);
// Find an empty line between headers and body, otherwise we got a header-only message
- if(strpos($message, $EOL . $EOL)) {
- list($headers, $body) = explode($EOL . $EOL, $message, 2);
+ if(strpos($message, EOL . EOL)) {
+ list($headers, $body) = explode(EOL . EOL, $message, 2);
// Check if the header is actually a journal header
$headers_array = self::splitHeaders($headers);
@@ -113,7 +117,7 @@
if(count($parts) >= 2) {
self::splitMessageRaw($parts[0], $s, $j, $journal);
- $i = strpos($parts[1], $EOL . $EOL);
+ $i = strpos($parts[1], EOL . EOL);
$msg = substr($parts[1], $i);
$i = 0;
@@ -141,26 +145,16 @@
}
- public static function removeJournal(&$message, $EOL = "\n") {
+ public static function removeJournal(&$message) {
$has_journal = 0;
- $crlfs = substr_count($message, "\r\n");
-
self::splitMessageRaw($message, $headers, $journal, $body);
if($journal) {
$has_journal = 1;
}
- // If the message has >10 CRLF sequences, then we assume
- // that we need to restore the removed LF characters
- if($crlfs > 10) {
- $headers = str_replace("\n", "\r\n", $headers);
- $body = str_replace("\n", "\r\n", $body);
- $EOL = "\r\n";
- }
-
- $message = $headers . $EOL . $EOL . $body;
+ $message = $headers . EOL . EOL . $body;
return $has_journal;
}
@@ -188,7 +182,7 @@
continue;
}
- $headers[$lower] = array($headers[$lower], $header);
+ $headers[$lower] = [$headers[$lower], $header];
}
// Add some default values, if they are missing
@@ -204,9 +198,21 @@
for($i=0; $i $v) {
-
- if(strchr($v, "\n")) {
- $result[$k] = explode("\n", $v);
+ if(strchr($v, EOL)) {
+ $result[$k] = explode(EOL, $v);
}
}
@@ -277,7 +282,7 @@
public static function splitContentType($field = '') {
- $split = array();
+ $split = [];
$what = 'type';
$field = $what . '=' . $field;
@@ -285,7 +290,7 @@
return $split;
}
- $split = array();
+ $split = [];
foreach ($matches[1] as $key => $name) {
$name = strtolower($name);
if($matches[2][$key][0] == '"') {
@@ -299,13 +304,7 @@
}
- public static function remove_LF($message = '') {
- return str_replace("\r", "", $message);
- //return preg_replace("/\r/", "", $message);
- }
-
-
- public static function getBoundary($headers = array()) {
+ public static function getBoundary($headers = []) {
if(isset($headers['content-type']['boundary'])) {
return $headers['content-type']['boundary'];
}
@@ -314,7 +313,7 @@
}
- public static function fixMimeBodyPart($headers = array(), $body = '') {
+ public static function fixMimeBodyPart($headers = [], $body = '') {
if(isset($headers['content-transfer-encoding'])) {
if(strtolower($headers['content-transfer-encoding']) == 'quoted-printable') {
@@ -327,16 +326,17 @@
}
if(isset($headers['content-type']['charset'])) {
- if(strtolower($headers['content-type']['charset']) == 'gb2312') {
+ if(ENABLE_GB2312_FIX && strtolower($headers['content-type']['charset']) == 'gb2312') {
$headers['content-type']['charset'] = 'GBK';
}
+
$body = iconv($headers['content-type']['charset'], 'utf-8' . '//IGNORE', $body);
}
if(strtolower($headers['content-type']['type']) == 'text/plain') {
$body = self::escape_lt_gt_symbols($body);
- $body = preg_replace("/\n/", "
\n", $body);
- $body = "\n" . self::printNicely($body);
+ $body = preg_replace("/\n/", "THE_BREAK_HTML_TAG\n", $body);
+ $body = EOL . self::printNicely($body);
}
return $body;
@@ -361,9 +361,9 @@
$nice .= $x[$i] . " ";
$k += strlen($x[$i]);
- if(strstr($x[$i], "\n")){ $k = 0; }
+ if(strstr($x[$i], EOL)){ $k = 0; }
- if($k > 70){ $nice .= "\n"; $k = 0; }
+ if($k > 70){ $nice .= EOL; $k = 0; }
}
return $nice;
diff --git a/webui/tests/ParseMessageTest.php b/webui/tests/ParseMessageTest.php
index fbf67cd..80469b6 100644
--- a/webui/tests/ParseMessageTest.php
+++ b/webui/tests/ParseMessageTest.php
@@ -11,17 +11,17 @@
public function providerTestParseMessage() {
return [
- ["1.eml", 1, ["Liebe Gueste,\n\ndie Einarbeitung der Rechen- und Summenfunktionen ins RK-Formular"]],
- ["2.eml", 1, ["Hallo!\nDie seltsamen Zeilenumbr=C3=BCche treten tats=C3=A4chlich auf."]],
- ["3.eml", 1, ["\n\nCan we discuss? Send Reply For more information, THANKS."]],
+ ["1.eml", 1, ["Liebe Gueste,\r\n\r\ndie Einarbeitung der Rechen- und Summenfunktionen ins RK-Formular"]],
+ ["2.eml", 1, ["Hallo!\r\nDie seltsamen Zeilenumbr=C3=BCche treten tats=C3=A4chlich auf."]],
+ ["3.eml", 1, ["\r\n\r\nCan we discuss? Send Reply For more information, THANKS."]],
["4.eml", 2, ["=0D=0A=0D=0A=0D=0A=0D=0A", "=0D=0A"]],
- ["8.eml", 2, ["Hello,\n\nYou have received a newsletter from Chemol Travel.", ""]],
+ ["7.eml", 2, ["Mai ajánlat: \r\n \r\n Exkluzív!", ""]],
+ ["8.eml", 2, ["Hello,\r\n\r\nYou have received a newsletter from Chemol Travel.", ""]],
];
- }
+ }
/**
diff --git a/webui/tests/SplitMessageTest.php b/webui/tests/SplitMessageTest.php
index 8947de6..8cc9e88 100644
--- a/webui/tests/SplitMessageTest.php
+++ b/webui/tests/SplitMessageTest.php
@@ -1,70 +1,65 @@
'aaa', 'to' => 'bbb', 'cc' => '', 'date' => '', SUBJECT => 'test', CONTENT_TYPE => array('type' => TEXT_PLAIN)),
- THIS_IS_A_TEST],
+ ["From: aaa\r\nTo:bbb\r\nSubject: test\r\n\r\nThis is a test",
+ array('from' => 'aaa', 'to' => 'bbb', 'cc' => '', 'date' => '', 'subject' => 'test', 'content-type' => array('type' => 'text/plain')),
+ "This is a test"],
- ["From: aaa\r\nTo:bbb\r\nCC ccc\r\nSubject: test\r\n\r\n" . THIS_IS_A_TEST,
- array('from' => 'aaa', 'to' => 'bbb', 'cc' => '', 'date' => '', SUBJECT => 'test', CONTENT_TYPE => array('type' => TEXT_PLAIN)),
- THIS_IS_A_TEST],
+ ["From: aaa\r\nSender: alala@aaa\r\nTo:bbb\r\nCC ccc\r\nSubject: test\r\n\r\nThis is a test",
+ array('sender' => 'alala@aaa', 'from' => 'aaa', 'to' => 'bbb', 'cc' => '', 'date' => '', 'subject' => 'test', 'content-type' => array('type' => 'text/plain')),
+ "This is a test"],
- ["From: aaa\nTo:bbb\nSubject: test\n\n" . THIS_IS_A_TEST,
- array('from' => 'aaa', 'to' => 'bbb', 'cc' => '', 'date' => '', SUBJECT => 'test', CONTENT_TYPE => array('type' => TEXT_PLAIN)),
- THIS_IS_A_TEST],
+ ["From: aaa\nTo:bbb\nSubject: test\n\nThis is a test",
+ array('from' => 'aaa', 'to' => 'bbb', 'cc' => '', 'date' => '', 'subject' => 'test', 'content-type' => array('type' => 'text/plain')),
+ "This is a test"],
- ["From: aaa\r\nTo:bbb\r\nSubject: test\r\n\r\n\r\n\r\n" . THIS_IS_A_TEST . "\nAaa\n",
- array('from' => 'aaa', 'to' => 'bbb', 'cc' => '', 'date' => '', SUBJECT => 'test', CONTENT_TYPE => array('type' => TEXT_PLAIN)),
- "\n\n" . THIS_IS_A_TEST . "\nAaa\n"],
+ ["From: aaa\r\nTo:bbb\r\nSubject: test\r\n\r\n\r\n\r\nThis is a test\nAaa\n",
+ array('from' => 'aaa', 'to' => 'bbb', 'cc' => '', 'date' => '', 'subject' => 'test', 'content-type' => array('type' => 'text/plain')),
+ "\r\n\r\nThis is a test\r\nAaa\r\n"],
- ["From: aaa\r\nTo:bbb\r\nSubject: test\r\nContent-type: text/html\r\n\r\n\r\n" . THIS_IS_A_TEST . "\nAaa\n",
- array('from' => 'aaa', 'to' => 'bbb', 'cc' => '', 'date' => '', SUBJECT => 'test', CONTENT_TYPE => array('type' => 'text/html')),
- "\n" . THIS_IS_A_TEST . "\nAaa\n"],
+ ["From: aaa\r\nTo:bbb\r\nSubject: test\r\nContent-type: text/html\r\n\r\n\r\nThis is a test\nAaa\n",
+ array('from' => 'aaa', 'to' => 'bbb', 'cc' => '', 'date' => '', 'subject' => 'test', 'content-type' => array('type' => 'text/html')),
+ "\r\nThis is a test\r\nAaa\r\n"],
- ["From: aaa\nTo:bbb\nSubject: test\nContent-Type: text/plain\n\n" . THIS_IS_A_TEST,
- array('from' => 'aaa', 'to' => 'bbb', 'cc' => '', 'date' => '', SUBJECT => 'test', CONTENT_TYPE => array('type' => TEXT_PLAIN)),
- THIS_IS_A_TEST],
+ ["From: aaa\nTo:bbb\nSubject: test\nContent-Type: text/plain\n\nThis is a test",
+ array('from' => 'aaa', 'to' => 'bbb', 'cc' => '', 'date' => '', 'subject' => 'test', 'content-type' => array('type' => 'text/plain')),
+ "This is a test"],
- ["From: aaa\nTo:bbb\nSubject: test\nDate: Sun, 17 Apr 2016 22:40:03 +0800\nDKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=chemoltravel.hu; s=ml;\n\tt=1471888357; bh=A/l/HLQe3HM4Xc4jFxAmhaWVCMU=;\n\th=Date:To:From:Subject:Sender:From:To:Subject:Date;\n\tb=JlEqXiAKBOoT/YyXKTMsXnEphh2J6sXxgNmbKbGybjo3cU1rgQEL0m1h26gl5AaBP\nContent-Type: " . TEXT_PLAIN . "\n\n" . THIS_IS_A_TEST,
- array('from' => 'aaa', 'to' => 'bbb', 'cc' => '', SUBJECT => 'test', 'date' => 'Sun, 17 Apr 2016 22:40:03 +0800', 'dkim-signature' => 'v=1; a=rsa-sha1; c=relaxed/relaxed; d=chemoltravel.hu; s=ml; t=1471888357; bh=A/l/HLQe3HM4Xc4jFxAmhaWVCMU=; h=Date:To:From:Subject:Sender:From:To:Subject:Date; b=JlEqXiAKBOoT/YyXKTMsXnEphh2J6sXxgNmbKbGybjo3cU1rgQEL0m1h26gl5AaBP', CONTENT_TYPE => array('type' => TEXT_PLAIN)),
- THIS_IS_A_TEST],
+ ["From: aaa\nTo:bbb\nSubject: test\nDate: Sun, 17 Apr 2016 22:40:03 +0800\nDKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=chemoltravel.hu; s=ml;\n\tt=1471888357; bh=A/l/HLQe3HM4Xc4jFxAmhaWVCMU=;\n\th=Date:To:From:Subject:Sender:From:To:Subject:Date;\n\tb=JlEqXiAKBOoT/YyXKTMsXnEphh2J6sXxgNmbKbGybjo3cU1rgQEL0m1h26gl5AaBP\nContent-Type: text/plain\n\nThis is a test",
+ array('from' => 'aaa', 'to' => 'bbb', 'cc' => '', 'subject' => 'test', 'date' => 'Sun, 17 Apr 2016 22:40:03 +0800', 'dkim-signature' => 'v=1; a=rsa-sha1; c=relaxed/relaxed; d=chemoltravel.hu; s=ml; t=1471888357; bh=A/l/HLQe3HM4Xc4jFxAmhaWVCMU=; h=Date:To:From:Subject:Sender:From:To:Subject:Date; b=JlEqXiAKBOoT/YyXKTMsXnEphh2J6sXxgNmbKbGybjo3cU1rgQEL0m1h26gl5AaBP', 'content-type' => array('type' => 'text/plain')),
+ "This is a test"],
- ["From: aaa\nTo:bbb\nSubject: test\nContent-Type: text/PLAIN\n\n" . THIS_IS_A_TEST,
- array('from' => 'aaa', 'to' => 'bbb', 'cc' => '', 'date' => '', SUBJECT => 'test', CONTENT_TYPE => array('type' => TEXT_PLAIN)),
- THIS_IS_A_TEST],
+ ["From: aaa\nTo:bbb\nSubject: test\nContent-Type: text/PLAIN\n\nThis is a test",
+ array('from' => 'aaa', 'to' => 'bbb', 'cc' => '', 'date' => '', 'subject' => 'test', 'content-type' => array('type' => 'text/plain')),
+ "This is a test"],
- ["From: aaa\nTo:bbb\nSubject: test\nContent-Type: text/plain; charset=\"ISO-8859-1\"\n\n" . THIS_IS_A_TEST,
- array('from' => 'aaa', 'to' => 'bbb', 'cc' => '', 'date' => '', SUBJECT => 'test', CONTENT_TYPE => array('type' => TEXT_PLAIN, 'charset' => 'ISO-8859-1')),
- THIS_IS_A_TEST],
+ ["From: aaa\nTo:bbb\nSubject: test\nContent-Type: text/plain; charset=\"ISO-8859-1\"\n\nThis is a test",
+ array('from' => 'aaa', 'to' => 'bbb', 'cc' => '', 'date' => '', 'subject' => 'test', 'content-type' => array('type' => 'text/plain', 'charset' => 'ISO-8859-1')),
+ "This is a test"],
- ["From: aaa\nTo:bbb\nSubject: test\nMIME-Version: 1.0\nContent-Type: multipart/alternative; boundary=\"_=_SWIFT_v4_1460476188_145aa333fc0127705a7e904aab6d1957_=_\"\n\n" . THIS_IS_A_TEST,
- array('from' => 'aaa', 'to' => 'bbb', 'cc' => '', 'date' => '', SUBJECT => 'test', 'mime-version' => '1.0', CONTENT_TYPE => array('type' => 'multipart/alternative', 'boundary' => '_=_SWIFT_v4_1460476188_145aa333fc0127705a7e904aab6d1957_=_')),
- THIS_IS_A_TEST],
+ ["From: aaa\nTo:bbb\nSubject: test\nMIME-Version: 1.0\nContent-Type: multipart/alternative; boundary=\"_=_SWIFT_v4_1460476188_145aa333fc0127705a7e904aab6d1957_=_\"\n\nThis is a test",
+ array('from' => 'aaa', 'to' => 'bbb', 'cc' => '', 'date' => '', 'subject' => 'test', 'mime-version' => '1.0', 'content-type' => array('type' => 'multipart/alternative', 'boundary' => '_=_SWIFT_v4_1460476188_145aa333fc0127705a7e904aab6d1957_=_')),
+ "This is a test"],
- ["From: aaa\nTo:bbb\nSubject: test\nMIME-Version: 1.0\nContent-Type: multipart/alternative;\n boundary=\"_=_SWIFT_v4_1460476188_145aa333fc0127705a7e904aab6d1957_=_\"\n\n" . THIS_IS_A_TEST,
- array('from' => 'aaa', 'to' => 'bbb', 'cc' => '', 'date' => '', SUBJECT => 'test', 'mime-version' => '1.0', CONTENT_TYPE => array('type' => 'multipart/alternative', 'boundary' => '_=_SWIFT_v4_1460476188_145aa333fc0127705a7e904aab6d1957_=_')),
- THIS_IS_A_TEST],
+ ["From: aaa\nTo:bbb\nSubject: test\nMIME-Version: 1.0\nContent-Type: multipart/alternative;\n boundary=\"_=_SWIFT_v4_1460476188_145aa333fc0127705a7e904aab6d1957_=_\"\n\nThis is a test",
+ array('from' => 'aaa', 'to' => 'bbb', 'cc' => '', 'date' => '', 'subject' => 'test', 'mime-version' => '1.0', 'content-type' => array('type' => 'multipart/alternative', 'boundary' => '_=_SWIFT_v4_1460476188_145aa333fc0127705a7e904aab6d1957_=_')),
+ "This is a test"],
- ["From: aaa\nTo:bbb\nSubject: test\nMIME-Version: 1.0\nContent-Type: multipart/related;\n\ttype=\"multipart/alternative\";\n\tboundary=\"----=_NextPart_000_0006_01D195BC.69E26510\"\n\n" . THIS_IS_A_TEST,
- array('from' => 'aaa', 'to' => 'bbb', 'cc' => '', 'date' => '', SUBJECT => 'test', 'mime-version' => '1.0', CONTENT_TYPE => array('type' => 'multipart/alternative', 'boundary' => '----=_NextPart_000_0006_01D195BC.69E26510')),
- THIS_IS_A_TEST],
+ ["From: aaa\nTo:bbb\nSubject: test\nMIME-Version: 1.0\nContent-Type: multipart/related;\n\ttype=\"multipart/alternative\";\n\tboundary=\"----=_NextPart_000_0006_01D195BC.69E26510\"\n\nThis is a test",
+ array('from' => 'aaa', 'to' => 'bbb', 'cc' => '', 'date' => '', 'subject' => 'test', 'mime-version' => '1.0', 'content-type' => array('type' => 'multipart/alternative', 'boundary' => '----=_NextPart_000_0006_01D195BC.69E26510')),
+ "This is a test"],
- ];
- }
+ ];
+ }
/**