Merge branch 'master' of https://github.com/jgoodman/Freeside
[freeside.git] / rt / share / html / Ticket / Elements / ShowMessageStanza
1 %# BEGIN BPS TAGGED BLOCK {{{
2 %#
3 %# COPYRIGHT:
4 %#
5 %# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
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 <%INIT>
49 my $plain_text_pre
50     = RT->Config->Get( 'PlainTextPre', $session{'CurrentUser'} );
51 my $plain_text_mono
52     = RT->Config->Get( 'PlainTextMono', $session{'CurrentUser'} );
53 my $Depth = 0;
54
55 my $ticket = $Transaction ? $Transaction->TicketObj : undef;
56
57 my $print_content = sub {
58     my $ref = shift;
59     return unless defined $$ref && length $$ref;
60
61     $m->callback( content => $ref, %ARGS );
62     if ( $ContentType eq 'text/plain' ) {
63         $m->comp( '/Elements/MakeClicky',
64                   content => $ref,
65                   ticket  => $ticket,
66                   %ARGS
67                 );
68
69         if ( defined $$ref && !$plain_text_pre && !$plain_text_mono ) {
70             $$ref =~ s{(\r?\n)}{<br />}g;
71         }
72     } else {
73         if ( defined $$ref ) {
74             $$ref =~ s/^[\r\n]+//g;
75         }
76     }
77     $m->out($$ref);
78 };
79
80 $m->out('<pre>')
81     if (    $ContentType eq 'text/plain'
82          && $plain_text_pre
83          && !$Depth
84          && !$plain_text_mono );
85 $m->out(   '<div class="message-stanza'
86          . ( ($ContentType eq 'text/plain' &&  $plain_text_mono) ? ' plain-text-white-space' : '' ) . '"'
87          . '>' );
88
89 if ( ref $Message ) {
90     my @stack;
91     my $para = '';
92     my $i    = 0;
93
94 AGAIN: foreach ( ; $i < @$Message; $i++ ) {
95         my $stanza = $Message->[$i];
96         if ( ref $stanza eq "HASH" ) {
97             # Fix message stanza nesting for Outlook's quoting styles
98             if (     $stanza->{raw}
99                  and not $stanza->{_outlooked}
100                  and $stanza->{raw} =~ /^               # start of an internal line
101                                         \s*             # optional whitespace
102                                         (?:
103                                             -{3,}       # at least three hyphens
104                                             \s*         # whitespace varies between Outlook versions
105                                                         # don't trigger on PGP signed message or signature blocks
106                                             (?!(?:BEGIN|END)\s+PGP)
107                                             \w          # at least one word character
108                                             [\w\s]{3,}? # the rest of the word(s), totalling at least 5 characters,
109                                                         #    loose to get different languages
110                                             \w          # at least one ending word character
111                                             \s*         # whitespace varies between Outlook versions
112                                             -{3,}       # at least three hyphens again
113                                           |
114                                             _{6,}       # OR: six or more underscores
115                                         )
116                                         \s*$            # optional whitespace until the end of the line
117                                        /xm )
118             {
119                 # There's content before the quoted message, but in the
120                 # same stanza.  Break it out!
121                 if ( my $start = $-[0] ) {
122                     my %preceding = %$stanza;
123
124                     # We don't process $stanza->{text} because we don't use it
125                     # and it isn't given to us by HTML::Quoted.  If we ever
126                     # need to, we can process it the same way as 'raw'.
127                     $preceding{raw} = substr($stanza->{raw}, 0, $start, '');
128
129                     # Replace the current stanza with the two we just created
130                     splice @$Message, $i, 1, \%preceding, $stanza;
131
132                     # Try it again from the top now that we've rejiggered our
133                     # stanzas.  We'll process the Outlook stanza again, and hit
134                     # the else below this time.
135                     redo;
136                 } else {
137                     # Nest the current stanza and everything that follows
138                     $stanza->{_outlooked}++;
139                     $stanza = $Message->[ $i ] = [ splice @$Message, $i ];
140                 }
141             }
142             else {
143                 $para .= ( defined $stanza->{raw} ? $stanza->{raw} : '' )."\n";
144             }
145         }
146         next unless ref $stanza eq "ARRAY";
147
148         $print_content->( \$para );
149         $para = '';
150
151         $Depth++;
152         push @stack, [ $Message, $i + 1 ];
153         ( $Message, $i ) = ( $stanza, -1 );
154
155         if ( $Depth == 1 ) {
156             $m->comp('FoldStanzaJS');
157         }
158         my @classes = ('message-stanza');
159         push @classes, $Depth == 1 ? 'closed' : 'open';
160         $m->out(   '<div class="' . join(" ", @classes) . '">' );
161     }
162     if ( length $para ) {
163         $print_content->( \$para );
164         $para = '';
165     }
166
167     if (@stack) {
168         ( $Message, $i ) = @{ pop @stack };
169         $Depth--;
170         $m->out('</div>');
171         goto AGAIN;
172     }
173 } else {
174     $print_content->( \$Message );
175 }
176
177 $m->out('</div>');
178 $m->out('</pre>')
179     if (    $ContentType eq 'text/plain'
180          && $plain_text_pre
181          && !$Depth
182          && !$plain_text_mono );
183 </%INIT>
184 <%ARGS>
185 $Message => undef
186 $Transaction => undef
187 $ContentType => 'text/plain'
188 </%ARGS>