Convert::yEnc::Decoder - decodes yEncoded files


Convert-yEnc documentation Contained in the Convert-yEnc distribution.

Index


Code Index:

NAME

Top

Convert::yEnc::Decoder - decodes yEncoded files

SYNOPSIS

Top

  use Convert::yEnc::Decoder;

  $decoder = new Convert::yEnc::Decoder;
  $decoder = new Convert::yEnc::Decoder $dir;

  $decoder->out_dir($dir);

  eval 
  { 
      $decoder->decode( $file);
      $decoder->decode(\*FILE);
      $decoder->decode;
  };
  print $@ if $@;

  $name   = $decoder->name;
  $file   = $decoder->file;
  $size   = $decoder->size;

  $ybegin = $decoder->ybegin;
  $ypart  = $decoder->ypart;
  $yend   = $decoder->yend;




ABSTRACT

Top

yEnc decoder

DESCRIPTION

Top

Convert::yEnc::Decoder decodes a yEncoded file and writes it to disk. Methods are provided for returning information about the decoded file.

Exports

Nothing.

Methods

$decoder = new Convert::yEnc::Decoder
$decoder = new Convert::yEnc::Decoder $dir

Creates and returns a new Convert::yEnc::Decoder object.

Decoded files will be written to $dir. If $dir is omitted, it defaults to the current working directory.

$decoder->out_dir($dir)

Sets the output directory to $dir.

$decoder->decode($file)
$decoder->decode(\*FILE)
$decoder->decode

Decodes a file. dies if there are any errors.

The first form reads from the file named $file. The second form reads from the file handle FILE. The third form reads from STDIN.

The data stream need not begin at the =yBegin line; decode will search until it finds it. decode stops reading when it finds the =yend line, so Decoder can decode multiple files from the same data stream.

decode may be called repeatedly on the same Decoder object to decode multiple files.

$name = $decoder->name

After a successful decode, returns the name of the file that was created.

$file = $decoder->file

After a successful decode, returns the complete path of the file that was created.

$size = $decoder->size

After a successful decode, returns the size of the decoded file.

$ybegin = $decoder->ybegin

After a successful decode, returns the =ybegin line.

$ypart = $decoder->ypart

After a successful decode, returns the =ypart line, or undef if there wasn't one.

$yend = $decoder->yend

After a successful decode, returns the =yend line.

NOTES

Top

1-liner

To decode a single file on the command line, write

    perl -MConvert::yEnc::Decoder -e 'Convert::yEnc::Decoder->new->decode' < myFile




TODO

Top

SEE ALSO

Top

AUTHOR

Top

Steven W McDougall, <swmcd@world.std.com>

COPYRIGHT AND LICENSE

Top


Convert-yEnc documentation Contained in the Convert-yEnc distribution.

package Convert::yEnc::Decoder;

use strict;
use IO::File;
use warnings;

use constant yEncBrainDamage => 1;


sub new
{
    my($class, $dir) = @_;

    my $decoder = { dir => $dir || '.' };

    bless $decoder, $class
}

sub out_dir
{
    my($decoder, $dir) = @_;

    $decoder->{dir} = $dir;
}


sub decode
{
    my($decoder, $in) = @_;

    delete $decoder->{temp};

    $decoder->_in($in);
    $decoder->_begin;
    $decoder->_out;
    $decoder->_part if $decoder->{temp}{begin}{part};
    $decoder->_body;
    $decoder->_end;
}

sub _in
{
    my($decoder, $in) = @_;

    my $IN = ref $in ? $in : 
                       defined $in ? (new IO::File $in) : \*STDIN;

    $IN or die ref $decoder, "::decode: Can't open $in: $!\n";
    $decoder->{temp}{IN} = $IN;
}

sub _begin
{
    my $decoder = shift;
    my $temp    = $decoder->{temp};
    my $IN      = $temp->{IN};

    my $begin;
    while ($begin = <$IN>) 
    { 
	$begin =~ /^=ybegin/ and last;
    }

    $begin or die ref $decoder, "::_begin: Can't find =ybegin line\n";
    
    my @begin = split ' ', $begin;

    for my $field (@begin)
    {
	my($key, $val) = split /=/, $field;
	$temp->{begin}{$key} = $val;
    }

    my($name) = $begin =~ /name=(.*)/;  # Horrid Martian.
    $name =~ s/^\s+|\s+$//g;
    $temp->{begin}{name} = $name;

    $temp->{line}{ybegin} = $begin;
}

sub _out
{
    my $decoder = shift;
    my $dir     = $decoder->{dir};
    my $temp    = $decoder->{temp};
    my $name 	= $temp->{begin}{name};
    my $file 	= "$dir/$name";
    my $mode    = O_CREAT | O_WRONLY;
    my $OUT  	= new IO::File $file, $mode or	
	die ref $decoder, "::_out: Can't open $file: $!\n";
    
    binmode $OUT or
	die ref $decoder, "::_out: Can't binmode $file: $!\n";

    $temp->{name} = $name;
    $temp->{file} = $file;
    $temp->{OUT } = $OUT;
}

sub _part
{
    my $decoder = shift;
    my $temp    = $decoder->{temp};
    my $IN      = $temp->{IN };
    my $OUT     = $temp->{OUT};
    my $part 	= <$IN>;
       $part 	=~ /^=ypart/ or die ref $decoder, "::_part: No =ypart line\n";
    my @part 	= split ' ', $part;

    for my $field (@part)
    {
	my($key, $val) = split /=/, $field;
	$temp->{part}{$key} = $val;
    }

    my $begin  = $temp->{part}{begin};
    my $end    = $temp->{part}{end  };
    my $offset = $begin - yEncBrainDamage;
    my $size   = $end   - $offset;

    seek $OUT, $offset, 0 or 
	die ref $decoder, "::_part: Can't seek to $begin: $!\n";

    $temp->{part}{size } = $size;
    $temp->{line}{ypart} = $part;
}

sub _body
{
    my $decoder = shift;
    my $temp    = $decoder->{temp};
    my $file    = $temp->{file};
    my $IN      = $temp->{IN};
    my $OUT     = $temp->{OUT};
    my $line;

    while ($line = <$IN>)
    {
	$line =~ /^=yend/ and last;
	chomp $line;

	$decoder->_line($line);

	print $OUT $line or
	    die "can't print to $file: $!\n";
    }

    close $OUT;
    $temp->{line}{yend} = $line;
}

sub _line
{
    $_[1] =~ s/=(.)/chr(ord($1)+256-64 & 255)/egosx;
    $_[1] =~ tr[\000-\377][\326-\377\000-\325];
    
}

sub _end
{
    my $decoder = shift;
    my $temp    = $decoder->{temp};
    my $end     = $temp->{line}{yend};
       $end     =~ /^=yend/ or die ref $decoder, "::end: No =yend line\n";

    my @end = split ' ', $end;

    for my $field (@end)
    {
	my($key, $val) = split /=/, $field;
	$temp->{end}{$key} = $val;
    }

    my $beginSize  =  $temp->{begin}{size};
    my $partSize   =  $temp->{part }{size};
    my $endSize    =  $temp->{end  }{size};
    my $decodeSize =  defined $partSize ? $partSize : $beginSize;

    $decodeSize == $endSize or 
	die ref $decoder, 
	"::_end: Begin/PartSize $decodeSize != EndSize $endSize\n";

    if (not defined $partSize)
    {
	my $file     = $temp->{file};
	my $fileSize = (stat $file)[7];
	$beginSize == $fileSize or 
	    die ref $decoder, 
	    "::_end: BeginSize $beginSize != FileSize $fileSize\n";
    }

    $temp->{size} = $decodeSize;
}

sub name   { shift->{temp}{name} }
sub file   { shift->{temp}{file} }
sub size   { shift->{temp}{size} }
sub ybegin { shift->{temp}{line}{ybegin} }
sub ypart  { shift->{temp}{line}{ypart } }
sub yend   { shift->{temp}{line}{yend  } }


1

__END__