NailBombJoe has asked for the wisdom of the Perl Monks concerning the following question:

I am using Mailscanner which is a virus/spam filter for email written in perl. I get this error when running Mailscanner. ack! no binary decoder!
at /usr/lib/perl5/site_perl/5.8.3/MIME/Entity.pm line 1851
Any ideas?
Joseph Wagner Network Manager

Replies are listed 'Best First'.
Re: no binary decoder!
by tachyon (Chancellor) on Oct 25, 2004 at 23:57 UTC

    Any ideas?

    Yes, use the source Luke. The error is a croak() so it identifies the caller:

    Entity.pm =1849= ### Get the encoding, defaulting to "binary" if unsupported: =1850= my $encoding = ($self->head->mime_encoding || 'binary'); =1851= my $decoder = best MIME::Decoder $encoding; =1852= $decoder->head($self->head); ### associate with head, i +f any

    OK so the issue is with the call (better written as) MIME::Decoder->best($encoding)

    Decoder.pm sub best { my ($class, $enc, @args) = @_; my $self = $class->new($enc, @args); if (!$self) { usage "unsupported encoding '$enc': using 'binary'"; $self = $class->new('binary') || croak "ack! no binary decoder!"; } $self; }

    So you see that we try to create an object with the passed encoding, and if the call to new returns undef we warn about the unsupported usage and default to binary. Regardless of the initial $enc (could be binary or an unknown) we know we must be calling new() with an enc type of binary and that call is returning false. That's how we get to croak.

    sub new { my ($class, @args) = @_; my ($encoding) = @args; my ($concrete_name, $concrete_path); ### Coerce the type to be legit: $encoding = lc($encoding || ''); ### Get the class: ($concrete_name = $DecoderFor{$encoding}) or return undef; ($concrete_path = $concrete_name.'.pm') =~ s{::}{/}g; ### Create the new object (if we can): my $self = { MD_Encoding => lc($encoding) }; require $concrete_path; bless $self, $concrete_name; $self->init(@args); } ### The stream decoders: %DecoderFor = ( ### Standard... '7bit' => 'MIME::Decoder::NBit', '8bit' => 'MIME::Decoder::NBit', 'base64' => 'MIME::Decoder::Base64', 'binary' => 'MIME::Decoder::Binary', 'none' => 'MIME::Decoder::Binary', 'quoted-printable' => 'MIME::Decoder::QuotedPrint', # snip ); sub init { $_[0]; }

    Now I simply don't see how you can possibly get that error!!! Even if you delete the Binary.pm module! The only way that the new function can return undef is if 'binary' is not in %DecodeFor, or if $self->init(@args) returns undef (it should not for the obvious reason that it returns $self). All I can suggest is putting some debugging warns into the new function to localise the bug and checking the content of %DecodeFor with Data::Dumper just prior to its use. It is a global so perhaps something is stomping on it. That is the only really logical explanation. I can't replicate it on my system, nor would I expect to be able to.

    cheers

    tachyon

      So, if you can't reproduce the error on your system, does that mean there is something wrong with some of my modules or my perl installation?
      Joseph Wagner Network Manager

        It means that you need to debug it, bacause it works for me. As noted the only logical explanation would seem to be stomping on that global hash. It is a very easy path trace that sould be trivial to debug. It won't debug itself. I suggest that there is a problem with the MailScanner application that is using MIME::Tools as both Perl and this Package are pretty damn stable. As suggested put in some debugging code and see what the problem is.

        At the top of the module put: my $DEBUG = 1; $DEBUG && require Data::Dumper; # them place statements like these $DEBUG && warn Data::Dumper::Dumper(\%hash); $DEBUG && warn "Sub foo() got @_\n";

        Once you have found and fixed the problem set $DEBUG = 0; and that code will become inactive.

        cheers

        tachyon