You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spamassassin.apache.org by fe...@apache.org on 2006/09/06 04:24:58 UTC

svn commit: r440575 - in /spamassassin/trunk/lib/Mail/SpamAssassin: Message.pm Message/Node.pm

Author: felicity
Date: Tue Sep  5 19:24:57 2006
New Revision: 440575

URL: http://svn.apache.org/viewvc?view=rev&rev=440575
Log:
use temp files for mime parts that we're unlikely to use during processing, and fall-back to memory-only if it's not going to work out.  also, use a scalar to hold the decoded information.

Modified:
    spamassassin/trunk/lib/Mail/SpamAssassin/Message.pm
    spamassassin/trunk/lib/Mail/SpamAssassin/Message/Node.pm

Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Message.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Message.pm?view=diff&rev=440575&r1=440574&r2=440575
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Message.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Message.pm Tue Sep  5 19:24:57 2006
@@ -807,8 +807,31 @@
     $msg->{'name'} = $ct[3];
   }
 
-  $msg->{'raw'} = $body;
   $msg->{'boundary'} = $boundary;
+
+  # If the part type is not one that we're likely to want to use, go
+  # ahead and write the part data out to a temp file -- why keep sucking
+  # up RAM with something we're not going to use?
+  #
+  if ($msg->{'type'} !~ m@^(?:text/(?:plain|html)$|message\b)@) {
+    my $filepath;
+    ($filepath, $msg->{'raw'}) = Mail::SpamAssassin::Util::secure_tmpfile();
+
+    if ($filepath) {
+      # The temp file was created, let's try to delete it now
+      if (!unlink $filepath) {
+        # We couldn't delete the file, so abort trying to make the temp file.
+        close($msg->{'raw'});
+	unlink $filepath; # try again with the file closed
+      }
+      $msg->{'raw'}->print(@{$body});
+    }
+  }
+
+  # if the part didn't get a temp file, go ahead and store the data in memory
+  if (!exists $msg->{'raw'}) {
+    $msg->{'raw'} = $body;
+  }
 }
 
 # ---------------------------------------------------------------------------

Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Message/Node.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Message/Node.pm?view=diff&rev=440575&r1=440574&r2=440575
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Message/Node.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Message/Node.pm Tue Sep  5 19:24:57 2006
@@ -255,7 +255,22 @@
 =cut
 
 sub raw {
-  return $_[0]->{'raw'};
+  my $self = shift;
+
+  # Ok, if we're called we are expected to return an array.
+  # so if it's a file reference, read in the message into an array...
+  #
+  # NOTE: that "ref undef" works, so don't bother checking for a defined var
+  # first.
+  if (ref $self->{'raw'} eq 'GLOB') {
+    my @array;
+    my $fd = $self->{'raw'};
+    seek $fd, 0, 0;
+    @array = <$fd>;
+    return \@array;
+  }
+
+  return $self->{'raw'};
 }
 
 =item decode()
@@ -277,13 +292,26 @@
       return undef;
     }
 
+    my $raw;
+
+    # if the part is held in a temp file, read it into the scalar
+    if (ref $self->{'raw'} eq 'GLOB') {
+      my $fd = $self->{'raw'};
+      seek $fd, 0, 0;
+      local $/ = undef;
+      $raw = <$fd>;
+    }
+    else {
+      # create a new scalar from the raw array in memory
+      $raw = join('', @{$self->{'raw'}});
+    }
+
     my $encoding = lc $self->header('content-transfer-encoding') || '';
 
     if ( $encoding eq 'quoted-printable' ) {
       dbg("message: decoding quoted-printable");
-      $self->{'decoded'} = [
-        map { s/\r\n/\n/; $_; } split ( /^/m, Mail::SpamAssassin::Util::qp_decode( join ( "", @{$self->{'raw'}} ) ) )
-	];
+      $self->{'decoded'} = Mail::SpamAssassin::Util::qp_decode($raw);
+      $self->{'decoded'} =~ s/\r\n/\n/g;
     }
     elsif ( $encoding eq 'base64' ) {
       dbg("message: decoding base64");
@@ -291,16 +319,16 @@
       # if it's not defined or is 0, do the whole thing, otherwise only decode
       # a portion
       if ($bytes) {
-        return Mail::SpamAssassin::Util::base64_decode(join("", @{$self->{'raw'}}), $bytes);
+        return Mail::SpamAssassin::Util::base64_decode($raw, $bytes);
       }
       else {
         # Generate the decoded output
-        $self->{'decoded'} = [ Mail::SpamAssassin::Util::base64_decode(join("", @{$self->{'raw'}})) ];
+        $self->{'decoded'} = Mail::SpamAssassin::Util::base64_decode($raw);
       }
 
       # If it's a type text or message, split it into an array of lines
       if ( $self->{'type'} =~ m@^(?:text|message)\b/@i ) {
-        $self->{'decoded'} = [ map { s/\r\n/\n/; $_; } split(/^/m, $self->{'decoded'}->[0]) ];
+        $self->{'decoded'} =~ s/\r\n/\n/g;
       }
     }
     else {
@@ -311,17 +339,17 @@
       else {
         dbg("message: no encoding detected");
       }
-      $self->{'decoded'} = $self->{'raw'};
+      $self->{'decoded'} = $raw;
     }
   }
 
   if ( !defined $bytes || $bytes ) {
-    my $tmp = join("", @{$self->{'decoded'}});
     if ( !defined $bytes ) {
-      return $tmp;
+      # force a copy
+      return '' . $self->{'decoded'};
     }
     else {
-      return substr($tmp, 0, $bytes);
+      return substr($self->{'decoded'}, 0, $bytes);
     }
   }
 }