Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions program/lib/Roundcube/rcube_mime.php
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,11 @@ public static function decode_mime_string($input, $fallback = null)
{
$default_charset = $fallback ?: self::get_charset();

// RFC 6532: detect raw UTF-8 in headers to avoid wrong charset conversion
if ($fallback !== false && mb_check_encoding($input, 'UTF-8') && preg_match('/[\x80-\xFF]/', $input)) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should not assume RCUBE_CHARSET is always UTF-8.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then should we change to

$default_charset = 'UTF-8';

instead?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have rebased and applied that part.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for that I had to force push, sorry if it made you inconvenient

$default_charset = 'UTF-8';
}

// rfc: all line breaks or other characters not found
// in the Base64 Alphabet must be ignored by decoding software
// delete all blanks between MIME-lines, differently we can
Expand Down
17 changes: 17 additions & 0 deletions tests/Framework/MimeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,23 @@ public function test_header_decode_qp()
}
}

/**
* Test decoding of raw UTF-8 headers (RFC 6532)
* Uses rcube_mime::decode_mime_string()
*/
public function test_header_decode_raw_utf8()
{
// Raw UTF-8 Korean with wrong fallback charset - should be preserved
$korean = "\xEC\x95\x88\xEB\x85\x95\xED\x95\x98\xEC\x84\xB8\xEC\x9A\x94"; // 안녕하세요
$res = \rcube_mime::decode_mime_string($korean, 'ISO-8859-1');
$this->assertSame($korean, $res, 'Raw UTF-8 header with Latin-1 fallback');

// Latin-1 high bytes (not valid UTF-8) - should still be converted
$latin1 = "caf\xE9"; // café in ISO-8859-1
$res = \rcube_mime::decode_mime_string($latin1, 'ISO-8859-1');
$this->assertSame('café', $res, 'Latin-1 header should be converted');
}

/**
* Test headers parsing
*/
Expand Down