package App::winmaildat2tar;
use v5.14;
use warnings;
our $VERSION = "0.9901";
use Getopt::EX::Long qw(:DEFAULT Configure ExConfigure);
ExConfigure BASECLASS => [ __PACKAGE__, "Getopt::EX" ];
Configure "bundling";
my $default_format = $0 =~ /2(\w+)$/ ? $1 : 'tar';
use Getopt::EX::Hashed; {
has format => 'f =s', is => 'ro', default => $default_format;
}
no Getopt::EX::Hashed;
sub run {
(my $app, local @ARGV) = splice @_;
$app->getopt or usage();
my $archive;
@ARGV or usage();
for my $file (@ARGV) {
use Convert::TNEF;
my $tnef = Convert::TNEF->read_in($file, { output_to_core => 'ALL' })
or die $Convert::TNEF::errstr;
my @attachments = $tnef->attachments or do {
warn "$file: no attachment data\n";
next;
};
for my $ent (@attachments) {
my $name = $ent->longname // $ent->name // unknown();
($archive //= App::winmaildat2tar::Archive->new($app->format))
->add($name, $ent->data);
}
}
print $archive->write if $archive;
exit;
}
sub usage {
die sprintf "Usage: %s winmail.dat\n", $0 =~ s|.*/||r;
}
sub unknown {
my $seq = (state $_seq)++;
sprintf "unknown%s.dat", $seq ? "_$seq" : "";
}
1;
######################################################################
package App::winmaildat2tar::Archive {
use v5.14;
use warnings;
use Data::Dumper;
use Moo; {
has format => ( is => 'ro', required => 1 );
has archive => ( is => 'rw' );
around BUILDARGS => sub {
my ($orig, $class, $format) = @_;
$format =~ s/^([a-z\d])([a-z\d]*)$/\u$1\L$2/i
or die "$format: invalid format.\n";
$class->$orig(format => $format);
};
sub BUILD {
my($obj, $args) = @_;
my $class = ref $obj;
my $format = $obj->format;
my $subclass = "$class\::$format";
bless $obj, $subclass;
$obj->can('newarchive') or die "$format: unknown format.\n";
$obj->newarchive or die;
}
} no Moo;
sub newarchive {
my $obj = shift;
$obj->archive($obj->module->new);
}
sub module {
sprintf "Archive::%s", shift->format;
}
sub write {
shift->archive->write;
}
}
package App::winmaildat2tar::Archive::Tar {
use v5.14;
use warnings;
use Archive::Tar;
our @ISA = qw(App::winmaildat2tar::Archive);
sub add {
my $obj = shift;
my($name, $data) = @_;
my $option = { uname => 'nobody', gname => 'nogroup' };
$obj->archive->add_data($name, $data, $option);
}
}
package App::winmaildat2tar::Archive::Ar {
use v5.14;
use warnings;
use Archive::Ar;
our @ISA = qw(App::winmaildat2tar::Archive);
sub add {
my $obj = shift;
my($name, $data) = @_;
$obj->archive->add_data($name, $data);
}
}
package App::winmaildat2tar::Archive::Zip {
use v5.14;
use warnings;
use Archive::Zip;
our @ISA = qw(App::winmaildat2tar::Archive);
sub add {
my $obj = shift;
my($name, $data) = @_;
$obj->archive->addString($data, $name);
}
sub write {
my $obj = shift;
open my $fh, ">", \my $data or die "open: $!";
$obj->archive->writeToFileHandle($fh);
close $fh;
$data;
}
}
1;
__END__
=encoding utf-8
=head1 NAME
winmaildat2tar - Convert winmail.dat (TNEF data) to tentative archive
=head1 SYNOPSIS
winmaildat2tar file
=head1 DESCRIPTION
Document is inlcuded in executable script.
=head1 AUTHOR
Kazumasa Utashiro
=head1 LICENSE
Copyright 2020- Kazumasa Utashiro.
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.
=cut