[Rt-commit] rt branch, 4.2/rt-forward-encoding, created. rt-4.2.9-6-g7c95ce1
Wallace Reis
wreis at bestpractical.com
Thu Nov 13 17:13:18 EST 2014
The branch, 4.2/rt-forward-encoding has been created
at 7c95ce15e07a4614638916e5d33828f3c6bef830 (commit)
- Log -----------------------------------------------------------------
commit 7c95ce15e07a4614638916e5d33828f3c6bef830
Author: Wallace Reis <wreis at bestpractical.com>
Date: Tue Nov 4 19:32:23 2014 -0200
Forwarded messages break attachments with non-ASCII filenames
On RT 4.2.3, forwarded messages lost header info cause RT takes every
header from DB and apply MIME transfer encoding to each as a full line,
thus losing information about the internal structure of the header, if
it has any.
This aim to fix by applying the correct encoding according to rfc2231
before assembling the MIME object. It worths mentioning that we are not
using MIME::Field::ParamVal to assemble the parts, because at the moment
it doesn't know how to do so correctly.
Fixes: #29753.
diff --git a/lib/RT/Attachment.pm b/lib/RT/Attachment.pm
index 4f1763c..b3428f7 100644
--- a/lib/RT/Attachment.pm
+++ b/lib/RT/Attachment.pm
@@ -80,6 +80,7 @@ use MIME::Base64;
use MIME::QuotedPrint;
use MIME::Body;
use RT::Util 'mime_recommended_filename';
+use URI;
sub _OverlayAccessible {
{
@@ -469,6 +470,44 @@ recursively added to the entity.
=cut
+sub _EncodeHeaderToMIME {
+ my ( $self, $header_name, $header_val ) = @_;
+ if ($header_name =~ /^Content-/i) {
+ my $params = MIME::Field::ParamVal->parse_params($header_val);
+ $header_val = delete $params->{'_'};
+ foreach my $key ( sort keys %$params ) {
+ my $value = $params->{$key};
+ if ( $value =~ /[^\x00-\x7f]/ ) { # check for non-ASCII
+ $value = q{UTF-8''} . URI->new(
+ Encode::encode('UTF-8', $value)
+ );
+ $value =~ s/(["\\])/\\$1/g;
+ $header_val .= qq{; ${key}*="$value"};
+ }
+ else {
+ $header_val .= qq{; $key="$value"};
+ }
+ }
+ }
+ elsif ( $header_name =~ /^(?:Resent-)?(?:To|From|B?Cc|Sender|Reply-To)$/i ) {
+ my @addresses = RT::EmailParser->ParseEmailAddress( $header_val );
+ foreach my $address ( @addresses ) {
+ foreach my $field (qw(phrase comment)) {
+ my $v = $address->$field() or next;
+ $v = RT::Interface::Email::EncodeToMIME( String => $v );
+ $address->$field($v);
+ }
+ }
+ $header_val = join ', ', map $_->format, @addresses;
+ }
+ else {
+ $header_val = RT::Interface::Email::EncodeToMIME(
+ String => $header_val
+ );
+ }
+ return $header_val;
+}
+
sub ContentAsMIME {
my $self = shift;
my %opts = (
@@ -479,7 +518,9 @@ sub ContentAsMIME {
my $entity = MIME::Entity->new();
foreach my $header ($self->SplitHeaders) {
my ($h_key, $h_val) = split /:/, $header, 2;
- $entity->head->add( $h_key, RT::Interface::Email::EncodeToMIME( String => $h_val ) );
+ $entity->head->add(
+ $h_key, $self->_EncodeHeaderToMIME($h_key, $h_val)
+ );
}
# since we want to return original content, let's use original encoding
diff --git a/t/web/ticket_forward.t b/t/web/ticket_forward.t
index a298b3c..8339e1a 100644
--- a/t/web/ticket_forward.t
+++ b/t/web/ticket_forward.t
@@ -36,18 +36,18 @@ diag "Forward Ticket" if $ENV{TEST_VERBOSE};
$m->submit_form(
form_name => 'ForwardMessage',
fields => {
- To => 'rt-to at example.com, rt-too at example.com',
+ To => '"Foo" <rt-foo at example.com>, rt-too at example.com',
Cc => 'rt-cc at example.com',
Bcc => 'root',
},
button => 'ForwardAndReturn'
);
$m->content_contains(
- 'Forwarded Ticket to <rt-to at example.com>, <rt-too at example.com>, <rt-cc at example.com>, root (Enoch Root)',
+ 'Forwarded Ticket to Foo <rt-foo at example.com>, <rt-too at example.com>, <rt-cc at example.com>, root (Enoch Root)',
'txn msg' );
my ($mail) = RT::Test->fetch_caught_mails;
like( $mail, qr!Subject: test forward!, 'Subject field' );
- like( $mail, qr!To: .*?rt-to\@example.com!i, 'To field' );
+ like( $mail, qr!To: .*?rt-foo\@example.com!i, 'To field' );
like( $mail, qr!To: .*?rt-too\@example.com!i, 'To field' );
like( $mail, qr!Cc: rt-cc\@example.com!i, 'Cc field' );
like( $mail, qr!Bcc: root\@localhost!i, 'Bcc field' );
@@ -108,7 +108,7 @@ diag "Forward Transaction with attachments but empty content" if $ENV{TEST_VERBO
$m->form_name('TicketCreate');
my $attach = $m->current_form->find_input('Attach');
- $attach->filename("awesome.patch");
+ $attach->filename('awesome.pátch');
$attach->headers('Content-Type' => 'text/x-diff');
$m->set_fields(
Subject => 'test forward, empty content but attachments',
@@ -123,8 +123,8 @@ diag "Forward Transaction with attachments but empty content" if $ENV{TEST_VERBO
Attach => RT::Test::get_relocatable_file('bpslogo.png', '..', 'data'), # an image!
);
$m->submit;
- $m->content_like( qr/Ticket \d+ created/i, 'created the ticket' );
- $m->content_like( qr/awesome\.patch/, 'uploaded patch file' );
+ $m->content_like( qr/Ticket \d+ created/i, 'created the ticket' );
+ $m->content_like( qr/awesome.p\%C3\%A1tch/, 'uploaded patch file' );
$m->content_like( qr/text\/x-diff/, 'uploaded patch file content type' );
$m->content_like( qr/bpslogo\.png/, 'uploaded image file' );
$m->content_like( qr/image\/png/, 'uploaded image file content type' );
@@ -143,7 +143,7 @@ diag "Forward Transaction with attachments but empty content" if $ENV{TEST_VERBO
like( $mail, qr/Subject: test forward, empty content but attachments/, 'Subject field' );
like( $mail, qr/To: rt-test\@example.com/, 'To field' );
like( $mail, qr/This is a forward of transaction/, 'content' );
- like( $mail, qr/awesome\.patch/, 'att file name' );
+ like( $mail, qr/filename\*\=\"UTF\-8\'\'awesome.p\%C3\%A1tch\"/, 'att file name' );
like( $mail, qr/this is an attachment/, 'att content' );
like( $mail, qr/text\/x-diff/, 'att content type' );
like( $mail, qr/bpslogo\.png/, 'att image file name' );
@@ -153,7 +153,7 @@ diag "Forward Transaction with attachments but empty content" if $ENV{TEST_VERBO
diag "Forward Transaction with attachments but no 'content' part" if $ENV{TEST_VERBOSE};
{
my $mime = MIME::Entity->build(
- From => 'test at example.com',
+ From => '"Tést" <test at example.com>',
Subject => 'attachments for everyone',
Type => 'multipart/mixed',
);
@@ -214,6 +214,7 @@ diag "Forward Transaction with attachments but no 'content' part" if $ENV{TEST_V
like( $forward_txn, qr/This is a forward of transaction/, 'forward description' );
like( $forward_ticket, qr/Subject: $tag test forward, attachments but no "content"/, 'Subject field is from ticket' );
like( $forward_ticket, qr/This is a forward of ticket/, 'forward description' );
+ like( $forward_ticket, qr/From: \=\?UTF-8\?.* \<test\@example\.com\>/i );
for my $mail ($forward_txn, $forward_ticket) {
like( $mail, qr/To: rt-test\@example.com/, 'To field' );
-----------------------------------------------------------------------
More information about the rt-commit
mailing list