[freeside-commits] branch master updated. c16ef0145a0049c3f20377e2c5076087e999cde0

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


The branch, master has been updated
       via  c16ef0145a0049c3f20377e2c5076087e999cde0 (commit)
      from  d2d137731f88b8a0d35294284ec3571f46bd18b5 (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 c16ef0145a0049c3f20377e2c5076087e999cde0
Author: Mark Wells <mark at freeside.biz>
Date:   Wed Jun 11 13:53:25 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 6f2bb80..782556b 100755
--- a/httemplate/view/cust_main.cgi
+++ b/httemplate/view/cust_main.cgi
@@ -185,79 +185,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' ) {
@@ -339,6 +274,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
old mode 100755
new mode 100644
similarity index 97%
rename from httemplate/view/cust_main/attachments.html
rename to httemplate/view/cust_main/notes/attachments.html
index d51d826..0c16835
--- 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
old mode 100755
new mode 100644
similarity index 97%
copy from httemplate/view/cust_main/notes.html
copy to httemplate/view/cust_main/notes/notes.html
index 2de68ff..6a7a06a
--- 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%)
 mode change 100755 => 100644
 copy httemplate/view/cust_main/{ => notes}/notes.html (97%)
 mode change 100755 => 100644
 create mode 100644 httemplate/view/cust_msg_part.html




More information about the freeside-commits mailing list