Master to 4.2.8
[usit-rt.git] / share / html / Elements / ShowTransactionAttachments
CommitLineData
af59614d
MKG
1%# BEGIN BPS TAGGED BLOCK {{{
2%#
3%# COPYRIGHT:
4%#
320f0092 5%# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
af59614d
MKG
6%# <sales@bestpractical.com>
7%#
8%# (Except where explicitly superseded by other copyright notices)
9%#
10%#
11%# LICENSE:
12%#
13%# This work is made available to you under the terms of Version 2 of
14%# the GNU General Public License. A copy of that license should have
15%# been provided with this software, but in any event can be snarfed
16%# from www.gnu.org.
17%#
18%# This work is distributed in the hope that it will be useful, but
19%# WITHOUT ANY WARRANTY; without even the implied warranty of
20%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21%# General Public License for more details.
22%#
23%# You should have received a copy of the GNU General Public License
24%# along with this program; if not, write to the Free Software
25%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26%# 02110-1301 or visit their web page on the internet at
27%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
28%#
29%#
30%# CONTRIBUTION SUBMISSION POLICY:
31%#
32%# (The following paragraph is not intended to limit the rights granted
33%# to you to modify and distribute this software under the terms of
34%# the GNU General Public License and is only of importance to you if
35%# you choose to contribute your changes and enhancements to the
36%# community by submitting them to Best Practical Solutions, LLC.)
37%#
38%# By intentionally submitting any modifications, corrections or
39%# derivatives to this work, or any other work intended for use with
40%# Request Tracker, to Best Practical Solutions, LLC, you confirm that
41%# you are the copyright holder for those contributions and you grant
42%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
43%# royalty-free, perpetual, license to use, copy, create derivative
44%# works based on those contributions, and sublicense and distribute
45%# those contributions and any derivatives thereof.
46%#
47%# END BPS TAGGED BLOCK }}}
48<%PERL>
49# Find all the attachments which have parent $Parent
50# For each of these attachments
51foreach my $message ( @{ $Attachments->{ $Parent || 0 } || [] } ) {
52 $m->comp( 'ShowMessageHeaders',
53 WarnUnsigned => $WarnUnsigned,
54 Message => $message,
55 DisplayHeaders => \@DisplayHeaders,
56 );
57
58 my $name = defined $message->Filename && length $message->Filename ? $message->Filename : '';
c33a4027 59 if ( $message->ContentLength or $name ) {
af59614d
MKG
60</%PERL>
61<div class="downloadattachment">
62<a href="<% $AttachmentPath %>/<% $Transaction->Id %>/<% $message->Id %>/<% $name | u%>"><&|/l&>Download</&> <% length $name ? $name : loc('(untitled)') %></a>\
63% if ( $DownloadableHeaders && ! length $name && $message->ContentType =~ /text/ ) {
64 / <a href="<% $AttachmentPath %>/WithHeaders/<% $message->Id %>"><% loc('with headers') %></a>
65% }
66% $m->callback(CallbackName => 'AfterDownloadLinks', ARGSRef => \%ARGS, Object => $Object, Transaction => $Transaction, Attachment => $message);
67<br />
68<span class="downloadcontenttype"><% $message->ContentType %> <% $message->FriendlyContentLength %></span>
69</div>
70% }
71%# If there is sub-messages, open a dedicated div
72% if ( $Attachments->{ $message->id } ) {
73<div class="messageattachments">
74% } else {
75<div class="messagebody">
76% }
77<%PERL>
78
79$render_attachment->( $message );
80
81$m->comp(
82 $m->current_comp,
83 %ARGS,
84 Parent => $message->id,
85 ParentObj => $message,
86
87 displayed_inline => $displayed_inline,
88);
89
90</%PERL>
91</div>
92% }
93<%ARGS>
94$Transaction
95$Object => $Transaction->Object
96$ShowHeaders => 0
97$DownloadableHeaders => 1
98$AttachmentPath => undef
99$Attachments => {}
100$AttachmentContent => {}
101$Parent => 0
102$ParentObj => undef
103$WarnUnsigned => 0
104
105# Keep track of CID images we display inline
106$displayed_inline => {}
107</%ARGS>
108<%INIT>
109my @DisplayHeaders=qw(_all);
110if ( $Transaction->Type =~ /EmailRecord$/ ) {
111 @DisplayHeaders = qw(To Cc Bcc);
112}
113
114# If the transaction has anything attached to it at all
115elsif (!$ShowHeaders) {
116 @DisplayHeaders = qw(To From RT-Send-Cc Cc Bcc Date Subject);
117 push @DisplayHeaders, 'RT-Send-Bcc' if RT->Config->Get('ShowBccHeader');
118}
119
c33a4027 120$m->callback(CallbackName => 'MassageDisplayHeaders', DisplayHeaders => \@DisplayHeaders, Transaction => $Transaction, ShowHeaders => $ShowHeaders);
af59614d
MKG
121
122my $render_attachment = sub {
123 my $message = shift;
124 my $name = defined $message->Filename && length $message->Filename ? $message->Filename : '';
125
126 my $content_type = lc $message->ContentType;
127
128 # if it has a content-disposition: attachment, don't show inline
129 my $disposition = $message->GetHeader('Content-Disposition');
130
131 if ( $disposition && $disposition =~ /^\s*attachment/i ) {
132 $disposition = 'attachment';
133 } else {
134 $disposition = 'inline';
135 }
136
137 # If it's text
138 if ( $content_type =~ m{^(text|message)/} ) {
139 my $max_size = RT->Config->Get( 'MaxInlineBody', $session{'CurrentUser'} );
140 if ( $disposition ne 'inline' ) {
141 $m->out('<p>'. loc( 'Message body is not shown because sender requested not to inline it.' ) .'</p>');
142 return;
143 }
144 elsif ( length $name && RT->Config->Get('SuppressInlineTextFiles', $session{'CurrentUser'} ) ) {
145 $m->out('<p>'. loc( 'Text file is not shown because it is disabled in preferences.' ) .'</p>');
146 return;
147 }
148 elsif ( $max_size && $message->ContentLength > $max_size ) {
149 $m->out('<p>'. loc( 'Message body is not shown because it is too large.' ) .'</p>');
150 return;
151 }
152
153 if (
154
155 # it's a toplevel object
156 !$ParentObj
157
158 # or its parent isn't a multipart alternative
159 || ( $ParentObj->ContentType !~ m{^multipart/(?:alternative|related)$}i )
160
161 # or it's of our prefered alterative type
162 || (
163 (
164 RT->Config->Get('PreferRichText', $session{CurrentUser})
165 && ( $content_type =~ m{^text/(?:html|enriched)$} )
166 )
167 || ( !RT->Config->Get('PreferRichText', $session{CurrentUser})
168 && ( $content_type !~ m{^text/(?:html|enriched)$} )
169 )
170 )
171 ) {
172
173 my $content;
174 # If we've cached the content, use it from there
175 if (my $x = $AttachmentContent->{ $Transaction->id }->{$message->id}) {
176 $content = $x->Content;
177 }
178 else {
179 $content = $message->Content;
180 }
181
182 $RT::Logger->debug(
183 "Rendering attachment #". $message->id
184 ." of '$content_type' type"
185 );
186
187 # if it's a text/html clean the body and show it
188 if ( $content_type eq 'text/html' ) {
189 $content = $m->comp( '/Elements/ScrubHTML', Content => $content );
190
191 if (RT->Config->Get('ShowTransactionImages')) {
192 my @rewritten = RT::Interface::Web::RewriteInlineImages(
193 Content => \$content,
194 Attachment => $message,
195 # Not technically correct to search all parts of the
196 # MIME structure, but it saves having to go to the
197 # database again and is unlikely to break display.
198 Related => [ map { @$_ } values %$Attachments ],
199 AttachmentPath => $AttachmentPath,
200 );
201 $displayed_inline->{$_}++ for @rewritten;
202 }
203
204 $m->comp(
205 '/Elements/MakeClicky',
206 content => \$content,
207 html => 1,
208 object => $Object,
209 );
210
211 if ( !length $name && RT->Config->Get( 'QuoteFolding', $session{CurrentUser} ) ) {
212 eval {
213 require HTML::Quoted;
214 $content = HTML::Quoted->extract($content)
215 };
216 if ($@) {
217 RT->Logger->error(
218 "HTML::Quoted couldn't process attachment #@{[$message->id]}: $@."
219 . " This is a bug, please report it to rt-bugs\@bestpractical.com.");
220 }
221 }
222
223 $m->comp(
224 'ShowMessageStanza',
225 Message => $content,
226 Transaction => $Transaction,
227 ContentType => 'text/html',
228 );
229 }
230
231 elsif ( $content_type eq 'text/enriched' ) {
232 $content = $m->comp( '/Elements/ScrubHTML', Content => $content );
233 $m->out( $content );
234 }
235
236 # It's a text type we don't have special handling for
237 else {
238 if ( !length $name && RT->Config->Get( 'QuoteFolding', $session{CurrentUser} ) ) {
239 eval {
240 require Text::Quoted;
241 Text::Quoted::set_quote_characters(undef);
242 $content = Text::Quoted::extract($content);
243 };
244 if ($@) {
245 RT->Logger->error(
246 "Text::Quoted couldn't process attachment #@{[$message->id]}: $@."
247 . " This is a bug, please report it to rt-bugs\@bestpractical.com.");
248 }
249 }
250
251 $m->comp(
252 'ShowMessageStanza',
253 Message => $content,
254 Transaction => $Transaction,
255 ContentType => 'text/plain',
256 );
257 }
258 }
259 }
260
261 # if it's an image, show it as an image
262 elsif ( $content_type =~ m{^image/} ) {
263 if (not RT->Config->Get('ShowTransactionImages')) {
264 $m->out('<p><i>'. loc( 'Image not shown because display is disabled in system configuration.' ) .'</i></p>');
265 return;
266 }
267 elsif ( $displayed_inline->{$message->Id} ) {
268 $m->out('<p><i>'. loc( 'Image displayed inline above' ) .'</i></p>');
269 return;
270 }
271 elsif ( $disposition ne 'inline' ) {
272 $m->out('<p>'. loc( 'Image not shown because sender requested not to inline it.' ) .'</p>');
273 return;
274 }
275
276 my $filename = length $name ? $name : loc('(untitled)');
277 my $efilename = $m->interp->apply_escapes( $filename, 'h' );
278 $m->out(
279 qq{<img alt="$efilename" title="$efilename"}
280 . ' src="'. $AttachmentPath .'/'. $Transaction->Id .'/'. $message->Id .'/'
281 . $m->interp->apply_escapes( $filename, 'u', 'h' )
282 . '" />'
283 );
284 }
285 elsif ( $message->ContentLength && $message->ContentLength > 0 ) {
286 $m->out( '<p>' .
287 loc( 'Message body not shown because it is not plain text.' ) .
288 '</p>'
289 );
290 }
291};
292
293</%INIT>