diff --unified --recursive --new-file MIME-tools-5.411/lib/MIME/Field/ParamVal.pm MIME-tools-5.411.patched/lib/MIME/Field/ParamVal.pm --- MIME-tools-5.411/lib/MIME/Field/ParamVal.pm 2000-11-04 14:54:49.000000000 -0500 +++ MIME-tools-5.411.patched/lib/MIME/Field/ParamVal.pm 2004-01-08 14:41:22.000000000 -0500 @@ -100,6 +100,9 @@ # token = 1* # my $TSPECIAL = '()<>@,;:\ $b } keys %{$rfc2231params{$param}}) { + $params{$param} .= $rfc2231params{$param}{$part}; + } debug " field param <$param> = <$params{$param}>"; } diff --unified --recursive --new-file MIME-tools-5.411/lib/MIME/Parser.pm MIME-tools-5.411.patched/lib/MIME/Parser.pm --- MIME-tools-5.411/lib/MIME/Parser.pm 2000-11-12 00:55:11.000000000 -0500 +++ MIME-tools-5.411.patched/lib/MIME/Parser.pm 2004-01-08 14:52:17.000000000 -0500 @@ -250,6 +250,7 @@ $self->{MP5_IgnoreErrors} = 1; $self->{MP5_UseInnerFiles} = 0; $self->{MP5_UUDecode} = 0; + $self->{MP5_MaxParts} = -1; $self->interface(ENTITY_CLASS => 'MIME::Entity'); $self->interface(HEAD_CLASS => 'MIME::Head'); @@ -277,6 +278,7 @@ $self->{MP5_Filer}->results($self->{MP5_Results}); $self->{MP5_Filer}->init_parse(); $self->{MP5_Filer}->purgeable([]); ### just to be safe + $self->{MP5_NumParts} = 0; 1; } @@ -378,7 +380,8 @@ =item extract_nested_messages OPTION I -Some MIME messages will contain a part of type C: +Some MIME messages will contain a part of type C +or C: literally, the text of an embedded mail/news/whatever message. This option controls whether (and how) we parse that embedded message. @@ -386,8 +389,8 @@ C document, without attempting to decode its contents. If the OPTION is true (the default), the body of the C -part is parsed by this parser, creating an entity object. -What happens then is determined by the actual OPTION: +or C part is parsed by this parser, creating an +entity object. What happens then is determined by the actual OPTION: =over 4 @@ -705,6 +708,9 @@ ### Parse the next part, and add it to the entity... my $part = $self->process_part($in, $part_rdr, Retype=>$retype); + return undef unless defined($part); + + $ent->add_part($part); ### ...and look at how we finished up: @@ -944,6 +950,7 @@ ### Parse the message: my $msg = $self->process_part($in, $rdr); + return undef unless defined($msg); ### How to handle nested messages? if ($self->extract_nested_messages eq 'REPLACE') { @@ -969,11 +976,19 @@ # Retype => retype this part to the given content-type # # Return the entity. -# Fatal exception on failure. +# Fatal exception on failure. Returns undef if message to complex +# # sub process_part { my ($self, $in, $rdr, %p) = @_; + if ($self->{MP5_MaxParts} > 0) { + $self->{MP5_NumParts}++; + if ($self->{MP5_NumParts} > $self->{MP5_MaxParts}) { + # Return UNDEF if msg too complex + return undef; + } + } $rdr ||= MIME::Parser::Reader->new; #debug "process_part"; $self->results->level(+1); @@ -995,12 +1010,13 @@ ### Handle, according to the MIME type: if ($type eq 'multipart') { - $self->process_multipart($in, $rdr, $ent); + return undef unless defined($self->process_multipart($in, $rdr, $ent)); } - elsif (("$type/$subtype" eq "message/rfc822") && - $self->extract_nested_messages) { + elsif (("$type/$subtype" eq "message/rfc822" || + ("$type/$subtype" eq "message/partial" && $head->mime_attr("content-type.number") == 1)) && + $self->extract_nested_messages) { $self->debug("attempting to process a nested message"); - $self->process_message($in, $rdr, $ent); + return undef unless defined($self->process_message($in, $rdr, $ent)); } else { $self->process_singlepart($in, $rdr, $ent); @@ -1047,7 +1063,6 @@ =back Returns the parsed MIME::Entity on success. -Throws exception on failure. =cut @@ -1086,7 +1101,8 @@ (which minimally implements getline() and read()). Returns the parsed MIME::Entity on success. -Throws exception on failure. +Throws exception on failure. If the message contained too many +parts (as set by I), returns undef. =cut @@ -1098,7 +1114,7 @@ my $bm = benchmark { $self->init_parse; - ($entity) = $self->process_part($in, undef); ### parse! + $entity = $self->process_part($in, undef); ### parse! }; $self->debug("t parse: $bm"); @@ -1346,6 +1362,33 @@ #------------------------------ +=item max_parts NUM + +I +Limits the number of MIME parts we will parse. + +Normally, instances of this class parse a message to the bitter end. +Messages with many MIME parts can cause excessive memory consumption. +If you invoke this method, parsing will abort with a die() if a message +contains more than NUM parts. + +If NUM is set to -1 (the default), then no maximum limit is enforced. + +With no argument, returns the current setting as an integer + +=cut + +sub max_parts { + my($self, $num) = @_; + if (@_ > 1) { + $self->{MP5_MaxParts} = $num; + } + return $self->{MP5_MaxParts}; +} + +#------------------------------ + + =item output_to_core YESNO I diff --unified --recursive --new-file MIME-tools-5.411/lib/MIME/Words.pm MIME-tools-5.411.patched/lib/MIME/Words.pm --- MIME-tools-5.411/lib/MIME/Words.pm 2000-11-10 11:45:12.000000000 -0500 +++ MIME-tools-5.411.patched/lib/MIME/Words.pm 2004-01-08 14:53:12.000000000 -0500 @@ -186,7 +186,7 @@ $@ = ''; ### error-return ### Collapse boundaries between adjacent encoded words: - $encstr =~ s{(\?\=)\r?\n[ \t](\=\?)}{$1$2}gs; + $encstr =~ s{(\?\=)\s*(\=\?)}{$1$2}gs; pos($encstr) = 0; ### print STDOUT "ENC = [", $encstr, "]\n";