X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=rt%2Flib%2FRT%2FDashboard%2FMailer.pm;h=0125dda6172141a904fe1b86e7611a70efd6b51d;hb=de9d037528895f7151a9aead6724ce2df95f9586;hp=eb620e65de7a8d68e22a7099808e0fa46cc8b2e7;hpb=e9e0cf0989259b94d9758eceff448666a2e5a5cc;p=freeside.git diff --git a/rt/lib/RT/Dashboard/Mailer.pm b/rt/lib/RT/Dashboard/Mailer.pm index eb620e65d..0125dda61 100644 --- a/rt/lib/RT/Dashboard/Mailer.pm +++ b/rt/lib/RT/Dashboard/Mailer.pm @@ -2,7 +2,7 @@ # # COPYRIGHT: # -# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC +# This software is Copyright (c) 1996-2017 Best Practical Solutions, LLC # # # (Except where explicitly superseded by other copyright notices) @@ -60,6 +60,7 @@ use RT::Interface::Web::Handler; use RT::Interface::Web; use File::Temp 'tempdir'; use HTML::Scrubber; +use URI::QueryParam; sub MailDashboards { my $self = shift; @@ -349,6 +350,7 @@ sub EmailDashboard { $RT::Logger->debug('Mailing dashboard "'.$dashboard->Name.'" to user '.$currentuser->Name." <$email>"); my $ok = RT::Interface::Email::SendEmail( + %{ RT->Config->Get('Crypt')->{'Dashboards'} || {} }, Entity => $entity, ); @@ -379,12 +381,19 @@ sub BuildEmail { # already attached this object return "cid:$cid_of{$uri}" if $cid_of{$uri}; - $cid_of{$uri} = time() . $$ . int(rand(1e6)); my ($data, $filename, $mimetype, $encoding) = GetResource($uri); + return $uri unless defined $data; + + $cid_of{$uri} = time() . $$ . int(rand(1e6)); - # downgrade non-text strings, because all strings are utf8 by - # default, which is wrong for non-text strings. - if ( $mimetype !~ m{text/} ) { + # Encode textual data in UTF-8, and downgrade (treat + # codepoints as codepoints, and ensure the UTF-8 flag is + # off) everything else. + my @extra; + if ( $mimetype =~ m{text/} ) { + $data = Encode::encode( "UTF-8", $data ); + @extra = ( Charset => "UTF-8" ); + } else { utf8::downgrade( $data, 1 ) or $RT::Logger->warning("downgrade $data failed"); } @@ -396,6 +405,7 @@ sub BuildEmail { Disposition => 'inline', Name => RT::Interface::Email::EncodeToMIME( String => $filename ), 'Content-Id' => $cid_of{$uri}, + @extra, ); return "cid:$cid_of{$uri}"; @@ -403,22 +413,22 @@ sub BuildEmail { inline_css => sub { my $uri = shift; my ($content) = GetResource($uri); - return $content; + return defined $content ? $content : ""; }, inline_imports => 1, ); my $entity = MIME::Entity->build( - From => Encode::encode_utf8($args{From}), - To => Encode::encode_utf8($args{To}), + From => Encode::encode("UTF-8", $args{From}), + To => Encode::encode("UTF-8", $args{To}), Subject => RT::Interface::Email::EncodeToMIME( String => $args{Subject} ), Type => "multipart/mixed", ); $entity->attach( - Data => Encode::encode_utf8($content), Type => 'text/html', Charset => 'UTF-8', + Data => Encode::encode("UTF-8", $content), Disposition => 'inline', Encoding => "base64", ); @@ -451,7 +461,7 @@ sub BuildEmail { autohandler_name => '', # disable forced login and more data_dir => $data_dir, ); - $mason->set_escape( h => \&RT::Interface::Web::EscapeUTF8 ); + $mason->set_escape( h => \&RT::Interface::Web::EscapeHTML ); $mason->set_escape( u => \&RT::Interface::Web::EscapeURI ); $mason->set_escape( j => \&RT::Interface::Web::EscapeJS ); } @@ -524,7 +534,13 @@ sub BuildEmail { sub GetResource { my $uri = URI->new(shift); - my ($content, $filename, $mimetype, $encoding); + my ($content, $content_type, $filename, $mimetype, $encoding); + + # Avoid trying to inline any remote URIs. We absolutified all URIs + # using WebURL in SendDashboard() above, so choose the simpler match on + # that rather than testing a bunch of URI accessors. + my $WebURL = RT->Config->Get("WebURL"); + return unless $uri =~ /^\Q$WebURL/; $RT::Logger->debug("Getting resource $uri"); @@ -537,40 +553,35 @@ sub GetResource { $path = "/$path" unless $path =~ m{^/}; - $HTML::Mason::Commands::r->path_info($path); - - # grab the query arguments - my %args; - for (split /&/, ($uri->query||'')) { - my ($k, $v) = /^(.*?)=(.*)$/ - or die "Unable to parse query parameter '$_'"; - - for ($k, $v) { s/%(..)/chr hex $1/ge } - - # no value yet, simple key=value - if (!exists $args{$k}) { - $args{$k} = $v; - } - # already have key=value, need to upgrade it to key=[value1, value2] - elsif (!ref($args{$k})) { - $args{$k} = [$args{$k}, $v]; - } - # already key=[value1, value2], just add the new value - else { - push @{ $args{$k} }, $v; - } + # Try the static handler first for non-Mason CSS, JS, etc. + my $res = RT::Interface::Web::Handler->GetStatic($path); + if ($res->is_success) { + RT->Logger->debug("Fetched '$path' from the static handler"); + $content = $res->decoded_content; + $content_type = $res->headers->content_type; + } else { + # Try it through Mason instead... + $HTML::Mason::Commands::r->path_info($path); + + # grab the query arguments + my %args = map { $_ => [ map {Encode::decode("UTF-8",$_)} + $uri->query_param($_) ] } $uri->query_param; + # Convert empty and single element arrayrefs to a non-ref scalar + @$_ < 2 and $_ = $_->[0] + for values %args; + + $RT::Logger->debug("Running component '$path'"); + $content = RunComponent($path, %args); + + $content_type = $HTML::Mason::Commands::r->content_type; } - $RT::Logger->debug("Running component '$path'"); - $content = RunComponent($path, %args); - # guess at the filename from the component name $filename = $1 if $path =~ m{^.*/(.*?)$}; # the rest of this was taken from Email::MIME::CreateHTML::Resolver::LWP ($mimetype, $encoding) = MIME::Types::by_suffix($filename); - my $content_type = $HTML::Mason::Commands::r->content_type; if ($content_type) { $mimetype = $content_type;