Showing posts with label perl. Show all posts
Showing posts with label perl. Show all posts

15 June 2008

MIME-decoding email attachments

Occasionally a friend will forward a message to my gmail account, and the forwarded message ends up as a plain-text attachment in the message I receive. If the original message had an attachment, that attachment appears as a MIME-encoded section of the attachment.

If this happens to you, you could try the following. Save the attachment as a text file, and open that file in a text editor. Delete all the lines except the lines which represent the encoded attachment (don't keep the attachment headers, just the lines of text which are 76 characters wide [the last line may be shorter--keep that one, too]). Don't forget to get rid of the lines after the attachment. Save the file as encoded.txt.

Save the following to an executable file called mime_decode somewhere in your $PATH:

#!/usr/bin/perl -w

use strict;
use diagnostics;

use Carp;
use MIME::Base64;

my $usage = "$0 infile outfile";
if ( @ARGV != 2 ) {
die "usage: $usage\n";
}
my ( $infile, $outfile ) = @ARGV;

open my $fh, '<', $infile or croak "cannot read $infile";
my $encoded = join '', <$fh>;
close $fh;

my $decoded = decode_base64($encoded);
open $fh, '>', $outfile or croak "cannot write $outfile";
print {$fh} $decoded;
close $fh;


Then run the following command:

mime_decode encoded.txt decoded


decoded should be the original attachment.

If you know of a standard utility which does this (especially if it doesn't require the user to prune the email message), please leave a comment.

09 March 2008

Class::Accessor constructors

I'm a pretty big fan of Class::Accessor. It's great for those occasions when you need to write a Perl module which has lots of attributes. You tell your module to inherit from Class::Accessor, provide a list of attributes, and your module automatically has accessors and mutators for all of those attributes. Class::Accessor even takes care of creating your module's constructor.

That last point was actually giving me some trouble the other day. I was writing a Perl module, and it turned out to have several attributes (counters that needed to be incremented while parsing a file), so I decided to have my module inherit from Class::Accessor. But one of the attributes was going to be an instance of another class (I wanted to use composition, rather than multiple inheritance), and I wanted to instantiate this object when my object is instantiated. But since Class::Accessor creates my constructor automatically, it wasn't clear to me how I'd do this.

With a little fiddling, I was able to override the Class::Accessor constructor in such a way that it still created my accessors and mutators, but also allowed me to do other object initialization tasks:

package Gakkk;

use strict;
use diagnostics;
use warnings;

use base qw/ Class::Accessor /;
Gakkk->mk_accessors(
qw/
flamningle
line_number
num_parse_errors
num_zortbiptons
/
);

use Some::Other::Class;

sub new {
my $class = shift @_;

my $self = $class->SUPER::new(@_);
$self->flamningle( Some::Other::Class->new() );
$self->line_number(0);
$self->num_parse_errors(0);
$self->num_zortbiptons(0);

return $self;
}

# other methods, ...

1;


The call to $class->SUPER::new(@_) gives what's left of the argument list (@_) to the constructor of the parent class (Class::Accessor) and returns an instance of my class. I'm then able to initialize my object attributes without requiring that the calling code do it explicitly. Without overriding the constructor, the caller would have to do something like this:

my $gakkk = Gakkk->new(
{
flamningle => Some::Other::Class->new(),
line_number => 0,
num_parse_errors => 0,
num_zortbiptons => 0,
}
);


Having overridden the constructor, the caller can instantiate the class like this:

my $gakkk = Gakkk->new();

02 February 2008

Python 3.0 To Be Backwards Incompatible

According to a Slashdot post, just about all python code will require at least some changes when python 3.0 comes out in early 2008. I've never learned python, and news like this makes me glad that I've never bothered. (Besides, a syntax predicated on whitespace just seems weird to me.)

I wonder how Red Hat feels about this, considering that a lot of the RHEL system scripts are in python. They'll probably have a lot of rewriting to do for RHEL6.

I suppose that similar criticism could be leveled at Perl6 v. Perl5 (although there is talk of some sort of compatibility mode as well as a Perl5-to-Perl6 translater). But it's probably a moot point: as far as I can tell, Perl6 will never, ever be released.

09 November 2007

perl breakage

I run a bunch of CentOS 4 boxes at work, and recent yum updates to perl caused me a lot of problems. If I tried doing just about anything in cpan, I'd get errors like this:

Use of uninitialized value in concatenation (.) or string at
/path/to/Scalar/Util.pm line 30.

and this

Undefined subroutine &Compress::Zlib::gzopen ...


After several Web searches, I found a Google Groups posting which recommended manually installing Scalar::List::Utils.

I have no idea what Scalar::List::Utils has to do with anything, but it seemed
to work. Thank you, Peter Scott.

If you try this, and the Compress::Zlib::gzopen errors persist, you could try the following (admittedly drastic) measure. It was successful for me in one case where just installing Scalar::List::Utils wasn't enough (for whatever reason). Try running the following search against your perl libraries (might be in a different directory on a non-RedHat-like distribution):

find /usr/lib/perl5/ -type f -path '*Compress/Zlib.pm'

Delete or rename the Zlib.pm files found, and then try 'install Compress::Zlib' in cpan (you may need to 'force install Compress::Zlib').