starting to work...
[freeside.git] / rt / share / html / Ticket / Elements / ShowMessageStanza
index 6f88751..8a85443 100755 (executable)
@@ -2,7 +2,7 @@
 %#
 %# COPYRIGHT:
 %#
-%# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC
+%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC
 %#                                          <sales@bestpractical.com>
 %#
 %# (Except where explicitly superseded by other copyright notices)
 %# those contributions and any derivatives thereof.
 %#
 %# END BPS TAGGED BLOCK }}}
-<%perl>
-if ( ref $Message ) {
-    $m->out('<pre>') if $plain_text_pre && !$Depth && !$plain_text_mono;
-    $m->out( qq{<div class="message-stanza-depth-$Depth } .($plain_text_mono ? "plain-text-white-space" : "") .qq{">} );
+<%INIT>
+my $plain_text_pre
+    = RT->Config->Get( 'PlainTextPre', $session{'CurrentUser'} );
+my $plain_text_mono
+    = RT->Config->Get( 'PlainTextMono', $session{'CurrentUser'} );
+my $Depth = 0;
+
+my $ticket = $Transaction ? $Transaction->TicketObj : undef;
+
+my $print_content = sub {
+    my $ref = shift;
+    return unless defined $$ref && length $$ref;
 
+    $m->callback( content => $ref, %ARGS );
+    if ( $ContentType eq 'text/plain' ) {
+        $m->comp( '/Elements/MakeClicky',
+                  content => $ref,
+                  ticket  => $ticket,
+                  %ARGS
+                );
+
+        if ( defined $$ref && !$plain_text_pre && !$plain_text_mono ) {
+            $$ref =~ s{(\r?\n)}{<br />}g;
+        }
+    } else {
+        if ( defined $$ref ) {
+            $$ref =~ s/^[\r\n]+//g;
+        }
+    }
+    $m->out($$ref);
+};
+
+if ( ref $Message ) {
+    $m->out('<pre>')
+        if (    $ContentType eq 'text/plain'
+             && $plain_text_pre
+             && !$Depth
+             && !$plain_text_mono );
+    $m->out(   '<div class="message-stanza'
+             . ( ($ContentType eq 'text/plain' &&  $plain_text_mono) ? ' plain-text-white-space' : '' ) . '"'
+             . '>' );
 
     my @stack;
     my $para = '';
-    my $i = 0;
+    my $i    = 0;
 
-    AGAIN: foreach ( ; $i < @$Message; $i++ ) {
+AGAIN: foreach ( ; $i < @$Message; $i++ ) {
         my $stanza = $Message->[$i];
         if ( ref $stanza eq "HASH" ) {
-            $para .= ( defined $stanza->{raw} ? $stanza->{raw} : '') ."\n";
+            # Fix message stanza nesting for Outlook's quoting styles
+            if (     $stanza->{raw}
+                 and not $stanza->{_outlooked}
+                 and $stanza->{raw} =~ /^               # start of an internal line
+                                        \s*             # optional whitespace
+                                        (?:
+                                            -{3,}       # at least three hyphens
+                                            \s*         # whitespace varies between Outlook versions
+                                                        # don't trigger on PGP signed message or signature blocks
+                                            (?!(?:BEGIN|END)\s+PGP)
+                                            \w          # at least one word character
+                                            [\w\s]{3,}? # the rest of the word(s), totalling at least 5 characters,
+                                                        #    loose to get different languages
+                                            \w          # at least one ending word character
+                                            \s*         # whitespace varies between Outlook versions
+                                            -{3,}       # at least three hyphens again
+                                          |
+                                            _{6,}       # OR: six or more underscores
+                                        )
+                                        \s*$            # optional whitespace until the end of the line
+                                       /xm )
+            {
+                # There's content before the quoted message, but in the
+                # same stanza.  Break it out!
+                if ( my $start = $-[0] ) {
+                    my %preceding = %$stanza;
+
+                    # We don't process $stanza->{text} because we don't use it
+                    # and it isn't given to us by HTML::Quoted.  If we ever
+                    # need to, we can process it the same way as 'raw'.
+                    $preceding{raw} = substr($stanza->{raw}, 0, $start, '');
+
+                    # Replace the current stanza with the two we just created
+                    splice @$Message, $i, 1, \%preceding, $stanza;
+
+                    # Try it again from the top now that we've rejiggered our
+                    # stanzas.  We'll process the Outlook stanza again, and hit
+                    # the else below this time.
+                    redo;
+                } else {
+                    # Nest the current stanza and everything that follows
+                    $stanza->{_outlooked}++;
+                    $stanza = $Message->[ $i ] = [ splice @$Message, $i ];
+                }
+            }
+            else {
+                $para .= ( defined $stanza->{raw} ? $stanza->{raw} : '' )."\n";
+            }
         }
         next unless ref $stanza eq "ARRAY";
 
-        $print_content->( \$para ); $para = '';
+        $print_content->( \$para );
+        $para = '';
 
         $Depth++;
-        push @stack, [$Message, $i+1];
-        ($Message, $i) = ($stanza, -1);
-        $m->out( qq{<div class="message-stanza-depth-$Depth">} );
+        push @stack, [ $Message, $i + 1 ];
+        ( $Message, $i ) = ( $stanza, -1 );
+
+        if ( $Depth == 1 ) {
+            $m->comp('FoldStanzaJS');
+        }
+        my @classes = ('message-stanza');
+        push @classes, $Depth == 1 ? 'closed' : 'open';
+        $m->out(   '<div class="' . join(" ", @classes) . '">' );
     }
     if ( length $para ) {
-        $print_content->( \$para ); $para = '';
+        $print_content->( \$para );
+        $para = '';
     }
 
-    if ( @stack ) {
-        ($Message, $i) = @{ pop @stack };
+    if (@stack) {
+        ( $Message, $i ) = @{ pop @stack };
         $Depth--;
         $m->out('</div>');
         goto AGAIN;
     }
 
     $m->out('</div>');
-    $m->out('</pre>') if $plain_text_pre && !$Depth && !$plain_text_mono;
+    $m->out('</pre>')
+        if (    $ContentType eq 'text/plain'
+             && $plain_text_pre
+             && !$Depth
+             && !$plain_text_mono );
 } else {
-      $print_content->( \$Message );
+    $print_content->( \$Message );
 }
-</%perl>
-<%INIT>
-my $plain_text_pre = RT->Config->Get('PlainTextPre', $session{'CurrentUser'});
-my $plain_text_mono = RT->Config->Get('PlainTextMono', $session{'CurrentUser'});
-
-my $ticket = $Transaction ? $Transaction->TicketObj : undef;
-
-my $print_content = sub {
-    my $ref = shift;
-    return unless defined $$ref && length $$ref;
-
-    $m->callback( content => $ref, %ARGS );
-    $m->comp('/Elements/MakeClicky', content => $ref, ticket => $ticket, %ARGS);
-    unless ( $plain_text_pre || $plain_text_mono ) {
-        $$ref =~ s{(\r?\n)}{<br />}g if defined $$ref;
-    }
-    $m->out( $$ref );
-};
 </%INIT>
 <%ARGS>
 $Message => undef
-$Depth => 0
 $Transaction => undef
+$ContentType => 'text/plain'
 </%ARGS>