[freeside-commits] branch FREESIDE_3_BRANCH updated. 9fae251fc1e3069694ebaf4fae62bde844f45cff

Mark Wells mark at 420.am
Wed Jun 11 13:53:35 PDT 2014


The branch, FREESIDE_3_BRANCH has been updated
       via  9fae251fc1e3069694ebaf4fae62bde844f45cff (commit)
      from  c2f4d21edfe3434c02c9dbd666e684c2deb3258e (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 9fae251fc1e3069694ebaf4fae62bde844f45cff
Author: Mark Wells <mark at freeside.biz>
Date:   Wed Jun 11 13:51:22 2014 -0700

    display sent mail on customer notes page, and improve sent mail log UI, #29250

diff --git a/FS/FS/cust_msg.pm b/FS/FS/cust_msg.pm
index 8d57a54..72f64b9 100644
--- a/FS/FS/cust_msg.pm
+++ b/FS/FS/cust_msg.pm
@@ -3,6 +3,7 @@ package FS::cust_msg;
 use strict;
 use base qw( FS::cust_main_Mixin FS::Record );
 use FS::Record qw( qsearch qsearchs );
+use MIME::Parser;
 use vars qw( @statuses );
 
 =head1 NAME
@@ -149,6 +150,36 @@ sub check {
   $self->SUPER::check;
 }
 
+=item entity
+
+Returns the complete message as a L<MIME::Entity>.
+
+=item parts
+
+Returns a list of the MIME parts contained in the message, as L<MIME::Entity>
+objects.
+
+=cut
+
+sub entity {
+  my $self = shift;
+  if ( !exists($self->{entity}) ) {
+    my $parser = MIME::Parser->new;
+    my $output_dir = "$FS::UID::cache_dir/cache.$FS::UID::datasrc/mimeparts";
+    mkdir($output_dir) unless -d $output_dir;
+    $parser->output_under($output_dir);
+    $self->{entity} =
+      $parser->parse_data( $self->header . "\n" . $self->body );
+  }
+  $self->{entity};
+}
+
+sub parts {
+  my $self = shift;
+  # return only the parts with bodies, not the multipart containers
+  grep { $_->bodyhandle } $self->entity->parts_DFS;
+}
+
 =back
 
 =head1 SEE ALSO
diff --git a/httemplate/search/cust_msg.html b/httemplate/search/cust_msg.html
index 716addf..2b6f08e 100644
--- a/httemplate/search/cust_msg.html
+++ b/httemplate/search/cust_msg.html
@@ -1,6 +1,6 @@
 <& 'elements/search.html',
        'title' => $title,
-       'name'  => 'messages',
+       'name_singular'  => 'message',
        'query' => $query,
        'count_query' => $count_query,
        'header' => [ 
@@ -24,6 +24,12 @@
                      'status',
                      sub { encode_entities($_[0]->error) },
                   ],
+       'sort_fields' => [ '_date',
+                          'msgtype',
+                          'env_to',
+                          'status',
+                          'error',
+                        ],
        'align' => 'rllcl',
        'links' => [ ],
        'link_onclicks' => [ 
@@ -41,6 +47,7 @@
                   ],
        'html_init' => $html_init,
        'really_disable_download' => 1,
+       @_
 &>
 <%init>
 #hmm...
@@ -58,6 +65,9 @@ if ( $cgi->param('status') =~ /^(\w+)$/ ) {
 if ( $cgi->param('msgtype') =~ /^(\w+)$/ ) {
   push @where, "msgtype = '$1'";
 }
+if ( $cgi->param('custnum') =~ /^(\d+)$/ ) {
+  push @where, "custnum = $1";
+}
 my ($beginning, $ending) = FS::UI::Web::parse_beginning_ending($cgi, '');
 push @where, "(_date >= $beginning AND _date <= $ending)";
 
diff --git a/httemplate/view/cust_main.cgi b/httemplate/view/cust_main.cgi
index cdea49d..c6266ce 100755
--- a/httemplate/view/cust_main.cgi
+++ b/httemplate/view/cust_main.cgi
@@ -191,79 +191,14 @@ function areyousure(href, message) {
 
 % if ( $view eq 'notes' || $view eq 'jumbo' ) {
 
-%if ( $cust_main->comments =~ /[^\s\n\r]/ ) {
-<BR><% mt('Comments') |h %> 
-<% ntable("#cccccc") %><TR><TD><% ntable("#cccccc",2) %>
-<TR>
-  <TD BGCOLOR="#ffffff">
-    <PRE><% encode_entities($cust_main->comments) %></PRE>
-  </TD>
-</TR>
-</TABLE></TABLE>
-<BR><BR>
-% }
-<A NAME="notes">
-% my $notecount = scalar($cust_main->notes(0));
-% if ( ! $conf->exists('cust_main-disable_notes') || $notecount) {
-
-%   unless ( $view eq 'notes' && $cust_main->comments !~ /[^\s\n\r]/ ) {
-      <BR>
-      <A NAME="cust_main_note"><FONT SIZE="+2"><% mt('Notes') |h %></FONT></A><BR>
-%   }
-
-%   if ( $curuser->access_right('Add customer note') &&
-%        ! $conf->exists('cust_main-disable_notes')
-%      ) {
-
-  <& /elements/popup_link-cust_main.html,
-                'label'       => emt('Add customer note'),
-                'action'      => $p. 'edit/cust_main_note.cgi',
-                'actionlabel' => emt('Enter customer note'),
-                'cust_main'   => $cust_main,
-                'width'       => 616,
-                'height'      => 538, #575
-  &>
-
-%   }
-
-<BR>
-
-<& cust_main/notes.html, 'custnum' => $cust_main->custnum &>
-
-% }
-<BR>
-
-% if(! $conf->config('disable_cust_attachment') 
-%  and $curuser->access_right('Add attachment')) {
-<& /elements/popup_link-cust_main.html,
-              'label'       => emt('Attach file'),
-              'action'      => $p.'edit/cust_main_attach.cgi',
-              'actionlabel' => emt('Upload file'),
-              'cust_main'   => $cust_main,
-              'width'       => 480,
-              'height'      => 296,
-&>
-% }
-% if( $curuser->access_right('View attachments') ) {
-<& cust_main/attachments.html, 'custnum' => $cust_main->custnum &>
-%   if ($cgi->param('show_deleted')) {
-<A HREF="<% $p.'view/cust_main.cgi?custnum=' . $cust_main->custnum .
-           ($view ? ";show=$view" : '') . '#notes' 
-           %>"><I>(<% mt('Show active attachments') |h %>)</I></A>
-%   }
-% elsif($curuser->access_right('View deleted attachments')) {
-<A HREF="<% $p.'view/cust_main.cgi?custnum=' . $cust_main->custnum .
-           ($view ? ";show=$view" : '') . ';show_deleted=1#notes'
-           %>"><I>(<% mt('Show deleted attachments') |h %>)</I></A>
-%   }
-% }
-<BR>
+<& cust_main/notes.html, 'cust_main' => $cust_main &>
 
 % }
 
 % if ( $view eq 'jumbo' ) {
     <BR>
 % }
+
 <BR>
 
 % if ( $view eq 'tickets' || $view eq 'jumbo' ) {
@@ -345,6 +280,7 @@ if ( $cgi->param('custnum') =~ /^(\d+)$/ ) {
   my($query) = $cgi->keywords; # needs parens with my, ->keywords returns array
   $query =~ /^(\d+)$/;
   $custnum = $1;
+  $cgi->param('custnum', $1);
 }
 
 my $cust_main = qsearchs( {
diff --git a/httemplate/view/cust_main/notes.html b/httemplate/view/cust_main/notes.html
index 2de68ff..1cd6e09 100755
--- a/httemplate/view/cust_main/notes.html
+++ b/httemplate/view/cust_main/notes.html
@@ -1,143 +1,91 @@
-% if ( scalar(@notes) ) {
-
-<SCRIPT TYPE="text/javascript">
-
-    function display_notes_classnum(classnum){
-	document.getElementById('notes_'+classnum).style.display = 'block';
-	document.getElementById('notes_tablink_'+classnum).style.fontWeight = 'bold';
-
-	var divs = document.getElementsByTagName("div");
-	var i;
-	for(i=0; i < divs.length; i++){
-	    var d = divs[i];
-	    if(d.id.length > 6 && d.id.substring(0,6) == 'notes_') {
-		if(divs[i].id != 'notes_'+classnum) {
-		    divs[i].style.display = 'none';
-		}
-	    }
-	}
-	
-	var as = document.getElementsByTagName("a");
-	for(i=0; i < as.length; i++){
-	    var a = as[i];
-	    if(a.id.length > 14 && a.id.substring(0,14) == 'notes_tablink_') {
-		if(as[i].id != 'notes_tablink_'+classnum) {
-		    as[i].style.fontWeight = 'normal';
-		}
-	    }
-	}
-    }
-
-</SCRIPT>
-
-  <& /elements/init_overlib.html &>
-
-% my $bgcolor1 = '#eeeeee';
-% my $bgcolor2 = '#ffffff';
-% my $bgcolor = '';
-% my $last_classnum = -1;
-% my $skipheader = 0;
-% my %classes = ();
-%
-% foreach my $note (@notes) {
-%
-%   if ( $bgcolor eq $bgcolor1 ) {
-%     $bgcolor = $bgcolor2;
-%   } else {
-%     $bgcolor = $bgcolor1;
-%   }
-%
-%   my $pop = popurl(3);
-%   my $notenum = $note->notenum;
-%   my $onclick = include( '/elements/popup_link_onclick.html',
-%                            'action'      => popurl(2).
-%                                             'edit/cust_main_note.cgi'.
-%                                             "?custnum=$custnum".
-%                                             ";notenum=$notenum",
-%                            'actionlabel' => emt('Edit customer note'),
-%                            'width'       => 616,
-%                            'height'      => 538, #575
-%                            'frame'       => 'top',
-%                        );
-%   my $clickjs = qq!onclick="$onclick"!;
-%
-%   my $edit = '';
-%   if ($curuser->access_right('Edit customer note') ) {
-%     my $delete_url = $fsurl.'misc/delete-note.html?'.$notenum;
-%     $edit = qq! <A HREF="javascript:void(0);" $clickjs>(!.emt('edit').')</A>'.
-%             qq! <A HREF="$delete_url" !.
-%             qq! onclick="return confirm('Delete this note?')">!.
-%             '('.emt('delete').')</A>';
-%   }
-%
-% if ( $last_classnum != $note->classnum && !$skipheader ) {
-% my $tmp_classnum = $note->classnum ? $note->classnum : 0;
-% $classes{$tmp_classnum} = $note->classname ne '' ? $note->classname 
-%						     : emt('Other');
-% if ( $last_classnum != -1 ) {
-    </TABLE>
-  </DIV>
+% # Customer comments
+% if ( $cust_main->comments =~ /[^\s\n\r]/ ) {
+<BR><% mt('Comments') |h %>
+<% ntable("#cccccc") %><TR><TD><% ntable("#cccccc",2) %>
+<TR>
+  <TD BGCOLOR="#ffffff">
+    <PRE><% encode_entities($cust_main->comments) %></PRE>
+  </TD>
+</TR>
+</TABLE></TABLE>
+<BR><BR>
 % }
-% my $display = ($tmp_classnum == 0 || !$conf->exists('note-classes') 
-%				    || $conf->config('note-classes') < 2) 
-%							    ? 'block' : 'none';
-	<DIV 	id="notes_<% $tmp_classnum %>"
-		style="display:<% $display %>"
-	>
-	<& /elements/table-grid.html &>
-	<TR>
-	    <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Date') |h %></TH>
-%   if ( $conf->exists('cust_main_note-display_times') ) {
-	    <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Time') |h %></TH>
-%   }
-	    <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Person') |h %></TH>
-%   if ($conf->exists('note-classes') && $conf->config('note-classes') == 1) {
-	    <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Class') |h %></TH>
+
+% # Notes, if any
+<A NAME="notes">
+% my $notecount = scalar($cust_main->notes(0));
+% if ( ! $conf->exists('cust_main-disable_notes') || $notecount) {
+
+%   unless ( $view eq 'notes' && $cust_main->comments !~ /[^\s\n\r]/ ) {
+<P>
+  <A NAME="cust_main_note"><FONT SIZE="+2"><% mt('Notes') |h %></FONT></A>
+</P>
+
 %   }
-	    <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Note') |h %></TH>
-%   if ($curuser->access_right('Edit customer note') ) {
-	    <TH CLASS="grid" BGCOLOR="#cccccc"> </TH>
+
+%   if ( $curuser->access_right('Add customer note') &&
+%        ! $conf->exists('cust_main-disable_notes')
+%      ) {
+
+  <& /elements/popup_link-cust_main.html,
+                'label'       => emt('Add customer note'),
+                'action'      => $p. 'edit/cust_main_note.cgi',
+                'actionlabel' => emt('Enter customer note'),
+                'cust_main'   => $cust_main,
+                'width'       => 616,
+                'height'      => 538, #575
+  &>
+
 %   }
-	</TR>
-% $skipheader = (!$conf->exists('note-classes') || $conf->config('note-classes') < 2);
-% $last_classnum = $note->classnum;
+<BR>
+
+% # actually display notes
+<& notes/notes.html, 'cust_main' => $cust_main &>
+<BR>
+% } # end of notes
+
+% # Attachments
+% # XXX at some point move all of this into notes/attachments.html
+% if( $curuser->access_right('View attachments') ) {
+% # List attachments
+<& notes/attachments.html, 'cust_main' => $cust_main &>
+% # "Attach file" link
+% if(! $conf->config('disable_cust_attachment')
+%  and $curuser->access_right('Add attachment')) {
+<& /elements/popup_link-cust_main.html,
+              'label'       => emt('Attach file'),
+              'action'      => $p.'edit/cust_main_attach.cgi',
+              'actionlabel' => emt('Upload file'),
+              'cust_main'   => $cust_main,
+              'width'       => 480,
+              'height'      => 296,
+&>
 % }
 
-    <TR>
-      <% note_datestr($note,$conf,$bgcolor) %>
-      <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
-         <% $note->usernum ? $note->access_user->name : $note->otaker %>
-      </TD>
-% if ($conf->exists('note-classes') && $conf->config('note-classes') == 1) {
-      <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
-	<% $note->classname %>   
-      </TD>
-% }
-      <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
-        <% $note->comments | defang %>
-      </TD>
-% if($edit) {
-      <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"><% $edit %></TD>
-% }
-    </TR>
-
-% } #end display notes
-
-</TABLE>
-</DIV>
-
-% if ( $conf->exists('note-classes') && $conf->config('note-classes') == 2 ) {
-% 	my($classnum,$classname);
-<% mt('Show notes of class:') |h %>   
-% 	foreach my $classnum ( sort { $b <=> $a } (keys %classes) ) {
-	    <A	id="notes_tablink_<% $classnum %>"
-		HREF="javascript:display_notes_classnum(<% $classnum %>)"
-		style="font-weight: <% $classnum == 0 ? 'bold' : 'normal' %>"
-	    ><% $classes{$classnum} %></A>
-% 	}
-    <BR>
+%   if ($cgi->param('show_deleted')) {
+<A HREF="<% $p.'view/cust_main.cgi?custnum=' . $cust_main->custnum .
+           ($view ? ";show=$view" : '') . '#notes' 
+           %>"><I>(<% mt('Show active attachments') |h %>)</I></A>
+%   } elsif($curuser->access_right('View deleted attachments')) {
+<A HREF="<% $p.'view/cust_main.cgi?custnum=' . $cust_main->custnum .
+           ($view ? ";show=$view" : '') . ';show_deleted=1#notes'
+           %>"><I>(<% mt('Show deleted attachments') |h %>)</I></A>
+%   }
 % }
 
+<BR>
+% if ( $curuser->access_right('View email logs')
+%      and FS::cust_msg->count("custnum = $custnum")) {
+<BR>
+%   if (!$cgi->param('order_by')) {
+%     my $order_by = '_date';
+%     $order_by .= ' DESC' if $curuser->option('history_order') eq 'newest';
+%     $cgi->param('order_by', $order_by);
+%   }
+<& /search/cust_msg.html,
+  nohtmlheader  => 1,
+  html_init     => mt('Mail sent to this customer: '),
+&>
 % }
 <%init>
 
@@ -148,23 +96,9 @@ my $curuser = $FS::CurrentUser::CurrentUser;
 
 my(%opt) = @_;
 
-my $custnum = $opt{'custnum'};
-
-my $cust_main = qsearchs('cust_main', {'custnum' => $custnum} );
-die "Customer not found!" unless $cust_main;
-
-my (@notes) = $cust_main->notes($conf->exists('note-classes') && $conf->config('note-classes') == 2);
-
-#subroutines
+my $cust_main = $opt{'cust_main'};
+my $custnum = $cust_main->custnum;
 
-sub note_datestr {
-  my($note, $conf, $bgcolor) = @_ or return '';
-  my $td = qq{<TD CLASS="grid" BGCOLOR="$bgcolor" ALIGN="right">};
-  my $format = "$td%b %o, %Y</TD>";
-  $format .= "$td%l:%M%P</TD>"
-    if $conf->exists('cust_main_note-display_times');
-  ( my $strip = time2str($format, $note->_date) ) =~ s/ (\d)/$1/g;
-  $strip;
-}
+my $view =  $cgi->param('show') || $curuser->default_customer_view;
 
 </%init>
diff --git a/httemplate/view/cust_main/attachments.html b/httemplate/view/cust_main/notes/attachments.html
similarity index 97%
rename from httemplate/view/cust_main/attachments.html
rename to httemplate/view/cust_main/notes/attachments.html
index d51d826..0c16835 100755
--- a/httemplate/view/cust_main/attachments.html
+++ b/httemplate/view/cust_main/notes/attachments.html
@@ -113,10 +113,8 @@ my $curuser = $FS::CurrentUser::CurrentUser;
 die "access denied" if !$curuser->access_right('View attachments');
 my(%opt) = @_;
 
-my $custnum = $opt{'custnum'};
-
-my $cust_main = qsearchs('cust_main', {'custnum' => $custnum} );
-die "Customer not found!" unless $cust_main;
+my $cust_main = $opt{'cust_main'};
+my $custnum = $cust_main->custnum;
 
 my (@attachments) = qsearch('cust_attachment', {'custnum' => $custnum});
 
diff --git a/httemplate/view/cust_main/notes.html b/httemplate/view/cust_main/notes/notes.html
similarity index 97%
copy from httemplate/view/cust_main/notes.html
copy to httemplate/view/cust_main/notes/notes.html
index 2de68ff..6a7a06a 100755
--- a/httemplate/view/cust_main/notes.html
+++ b/httemplate/view/cust_main/notes/notes.html
@@ -148,10 +148,8 @@ my $curuser = $FS::CurrentUser::CurrentUser;
 
 my(%opt) = @_;
 
-my $custnum = $opt{'custnum'};
-
-my $cust_main = qsearchs('cust_main', {'custnum' => $custnum} );
-die "Customer not found!" unless $cust_main;
+my $cust_main = $opt{'cust_main'};
+my $custnum = $cust_main->custnum;
 
 my (@notes) = $cust_main->notes($conf->exists('note-classes') && $conf->config('note-classes') == 2);
 
diff --git a/httemplate/view/cust_msg.html b/httemplate/view/cust_msg.html
index 67ceef7..91a08eb 100755
--- a/httemplate/view/cust_msg.html
+++ b/httemplate/view/cust_msg.html
@@ -1,4 +1,16 @@
 <& /elements/header-popup.html &>
+<STYLE>
+P.pre {
+  font-family: monospace;
+  height: auto;
+  width: auto;
+  display: block;
+  white-space: pre-wrap;
+  text-align: left;
+  border: 1px solid #7e0079
+}
+</STYLE>
+  
 <TABLE>
 <TR><TD>From:</TD><TD><% $cust_msg->env_from %></TD></TR>
 <TR><TD>To:</TD><TD><% $env_to %></TD></TR>
@@ -8,31 +20,35 @@
 % if ( $cust_msg->error ) {
 <TR><TD>Error:</TD><TD><% encode_entities($cust_msg->error) %></TD></TR>
 % }
-<TR><TD colspan=2>
-<FORM name="myform">
-<SCRIPT type="text/javascript">
-function toggle_display(obj) {
-  document.getElementById('content-header').style.display = 
-    (obj.value == 'header' ? 'block' : 'none');
-  document.getElementById('content-body').style.display = 
-    (obj.value == 'body' ? 'block' : 'none');
-}
-</SCRIPT>
-<INPUT type="radio" name="what_to_show" onchange="toggle_display(this)" value="header" checked> Header
-<INPUT type="radio" name="what_to_show" onchange="toggle_display(this)" value="body"> Body
-</FORM>
-</TR>
-<TR><TD colspan=2 style="text-align:left">
-<TEXTAREA id="content-header" style="font-family:monospace" 
-readonly=1 cols=80 rows=20>
-<% encode_entities($cust_msg->header) %>
-</TEXTAREA>
-<TEXTAREA id="content-body" style="font-family:monospace;display:none" 
-readonly=1 cols=80 rows=20>
-<% encode_entities($cust_msg->body) %>
-</TEXTAREA>
-</TD></TR>
+<& /elements/menubar.html,
+  { 'newstyle' => 1,
+    'url_base' => $cgi->self_url . ';part=',
+    'selected' => $selected_index,
+  },
+  map { $partnames[$_] => $_ } (0 .. scalar(@parts) - 1),
+&>
 </TABLE>
+<DIV STYLE="text-align:center">
+% if ( $selected_part->isa('MIME::Entity') ) {
+%   my $type = $selected_part->mime_type;
+%   if ( $type =~ /^text/ ) {
+%#<TEXTAREA style="font-family:monospace" readonly=1 cols=80 rows=20>
+  <P CLASS="pre"><% encode_entities( $selected_part->bodyhandle->as_string ) %></P>
+%   } else { # show a download link
+%     my $url = $fsurl . "view/cust_msg_part.html?$custmsgnum+$selected_index";
+  <A HREF="<% $url %>">
+    <DIV STYLE="display: inline-block; padding: 4px; border: 2px solid #00c">
+%     if ( $type =~ /^image\/\w+$/ ) {
+      <IMG SRC="<% $url %>">
+%     } else {
+      <FONT SIZE="+1">Download <% $partnames[$selected_index] %></FONT>
+%     }
+  </A>
+%   }
+% } elsif ($selected_part->isa('MIME::Head')) {
+  <P CLASS="pre"><% encode_entities( $cust_msg->header ) %></P>
+% }
+</DIV>
 
 <& /elements/footer.html &>
 <%init>
@@ -52,4 +68,26 @@ my %label = (
   'failed' => 'Attempted: ',
   'prepared' => 'Not sent',
 );
+
+my $partname = sub {
+  my %friendly_name = ( 'text/plain' => 'Text', 'text/html' => 'HTML' );
+  my $part = shift;
+  $part->head->recommended_filename
+  || $friendly_name{$part->mime_type}
+  || $part->mime_type;
+};
+
+my @parts = $cust_msg->parts;
+my @partnames = map { &{$partname}($_) } @parts;
+push @parts, $cust_msg->entity->head;
+push @partnames, mt('Header');
+
+my $selected_part;
+my $selected_index = 0;
+if ( $cgi->param('part') =~ /^(\d+)$/ ) {
+  $selected_index = $1 if $1 < scalar(@parts);
+}
+$selected_part = $parts[$selected_index];
+$cgi->delete('part'); # for self_url
+
 </%init>
diff --git a/httemplate/view/cust_msg_part.html b/httemplate/view/cust_msg_part.html
new file mode 100644
index 0000000..0be5705
--- /dev/null
+++ b/httemplate/view/cust_msg_part.html
@@ -0,0 +1,23 @@
+<%init>
+die "access denied" unless $FS::CurrentUser::CurrentUser->access_right('View email logs');
+# invoke this as "view/cust_msg_part.html?$custmsgnum+$partnum"
+my ($custmsgnum, $partnum) = $cgi->keywords;
+$custmsgnum =~ /^\d+$/ or die "bad custmsgnum";
+$partnum =~ /^\d+$/ or die "bad partnum";
+my $cust_msg = FS::cust_msg->by_key($custmsgnum)
+  or die "message not found";
+my $part = ($cust_msg->parts)[$partnum]
+  or die "message part $partnum does not exist";
+
+my $filename = $part->head->recommended_filename;
+if (!$filename) {
+  # for lack of a better idea
+  $part->bodyhandle->{MB_Path} =~ /.*\/(.*)/;
+  $filename = $1;
+}
+
+$m->clear_buffer;
+$r->content_type($part->mime_type || 'application/octet-stream');
+$r->headers_out->add('Content-Disposition' => 'attachment;filename=' . $filename);
+$m->print($part->bodyhandle->as_string);
+</%init>

-----------------------------------------------------------------------

Summary of changes:
 FS/FS/cust_msg.pm                                  |   31 +++
 httemplate/search/cust_msg.html                    |   12 +-
 httemplate/view/cust_main.cgi                      |   70 +-----
 httemplate/view/cust_main/notes.html               |  234 +++++++-------------
 .../view/cust_main/{ => notes}/attachments.html    |    6 +-
 httemplate/view/cust_main/{ => notes}/notes.html   |    6 +-
 httemplate/view/cust_msg.html                      |   86 +++++--
 httemplate/view/cust_msg_part.html                 |   23 ++
 8 files changed, 218 insertions(+), 250 deletions(-)
 rename httemplate/view/cust_main/{ => notes}/attachments.html (97%)
 copy httemplate/view/cust_main/{ => notes}/notes.html (97%)
 create mode 100644 httemplate/view/cust_msg_part.html




More information about the freeside-commits mailing list