File Coverage

blib/lib/IO/SWF.pm
Criterion Covered Total %
statement 9 9 100.0
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 12 12 100.0


line stmt bran cond sub pod time code
1             package IO::SWF;
2              
3 1     1   7 use strict;
  1         2  
  1         34  
4 1     1   5 use warnings;
  1         2  
  1         35  
5              
6 1     1   6 use base 'Class::Accessor::Fast';
  1         2  
  1         6662  
7             use IO::SWF::Bit;
8             use IO::SWF::Type::RECT;
9             use IO::SWF::Tag;
10             use Compress::Zlib;
11              
12             __PACKAGE__->mk_accessors( qw(
13             _headers
14             _header_size
15             _tags
16             _swfdata
17             shape_adjust_mode
18             ));
19              
20             sub new {
21             my ($class, $args) = @_;
22             my $self;
23             if(ref $args eq 'HASH') {
24             return $class->SUPER::new($args);
25             }else{
26             return $class->SUPER::new;
27             }
28             }
29              
30             sub _set_headers {
31             my ($self, %args) = @_;
32             my $header = $self->_headers ? $self->_headers : {};
33             foreach my $key (keys %args) {
34             $header->{$key} = $args{$key};
35             }
36             $self->_headers($header);
37             }
38              
39             sub _set_tag {
40             my ($self, $tag) = @_;
41             my @tags = $self->_tags ? @{$self->_tags} : ();
42             push @tags, $tag;
43             $self->_tags(\@tags);
44             }
45              
46             sub parse {
47             my ($self, $swfdata) = @_;
48             my $reader = IO::SWF::Bit->new();
49             $reader->input($swfdata);
50             $self->_swfdata($swfdata);
51             ## SWF Header ##
52             $self->_set_headers(
53             'Signature' => $reader->getData(3),
54             'Version' => $reader->getUI8(),
55             'FileLength' => $reader->getUI32LE(),
56             );
57              
58             if (substr($self->_headers->{'Signature'}, 0, 1) eq 'C') {
59             # swf binary compressed by zlib
60             my $uncompressed_data = Compress::Zlib::memGunzip(substr($swfdata, 8));
61             if (!defined $uncompressed_data) {
62             return 0;
63             }
64             my ($byte_offset, $dummy) = $reader->getOffset();
65             $reader->setOffset(0, 0);
66             $swfdata = $reader->getData($byte_offset) . $uncompressed_data;
67             $reader = IO::SWF::Bit->new();
68             $reader->input($swfdata);
69             $self->_swfdata($swfdata);
70             $reader->setOffset($byte_offset, 0);
71             }
72             ## SWF Movie Header ##
73             my $ret = IO::SWF::Type::RECT::parse($reader);
74             $self->_set_headers('FrameSize' => $ret);
75             $reader->byteAlign();
76             $self->_set_headers(
77             'FrameRate' => $reader->getUI16LE(),
78             'FrameCount' => $reader->getUI16LE(),
79             );
80              
81             my ($header_size, $dummy) = $reader->getOffset();
82             $self->_header_size($header_size);
83              
84             ## SWF Tags ##
85             while (1) {
86             my %swfInfo = ('Version' => $self->_headers->{'Version'});
87             my $tag = IO::SWF::Tag->new(\%swfInfo);
88             $tag->parse($reader);
89             $self->_set_tag($tag);
90             if ($tag->code == 0) { # END Tag
91             last;
92             }
93             }
94             return 1;
95             }
96              
97             sub build {
98             my $self = shift;
99             my $writer_head = IO::SWF::Bit->new();
100             my $writer = IO::SWF::Bit->new();
101              
102             ## SWF Header ##
103             $writer_head->putData($self->_headers->{'Signature'});
104             $writer_head->putUI8($self->_headers->{'Version'});
105             $writer_head->putUI32LE($self->_headers->{'FileLength'});
106              
107             ## SWF Movie Header ##
108             IO::SWF::Type::RECT::build($writer, $self->_headers->{'FrameSize'});
109             $writer->byteAlign();
110             $writer->putUI16LE($self->_headers->{'FrameRate'});
111             $writer->putUI16LE($self->_headers->{'FrameCount'});
112              
113             ## SWF Tags ##
114             my $idx = 0;
115             foreach my $tag (@{$self->_tags}) {
116             my $tagData = $tag->build();
117             if ($tagData) {
118             $writer->putData($tagData);
119             }
120             else {
121             die "tag build failed (tag idx=$idx)";
122             }
123             $idx++;
124             }
125             my ($fileLength, $bit_offset_dummy) = $writer->getOffset();
126             $fileLength += 8; # swf header
127             $self->_set_headers('FileLength' => $fileLength);
128             $writer_head->setUI32LE($fileLength, 4);
129             if (substr($self->_headers->{'Signature'}, 0, 1) eq 'C') {
130             return $writer_head->output() . Compress::Zlib::memGzip($writer->output());
131             }
132             return $writer_head->output().$writer->output();
133             }
134              
135             sub dump {
136             my ($self, $opts_href) = @_;
137             my %opts = ref($opts_href) ? %{$opts_href} : ();
138             my $bitio;
139             if (defined $opts{'hexdump'}) {
140             $bitio = IO::SWF::Bit->new();
141             $bitio->input($self->_swfdata);
142             }
143             ## SWF Header ##
144             print 'Signature: '.$self->_headers->{'Signature'}."\n";
145             print 'Version: '.$self->_headers->{'Version'}."\n";
146             print 'FileLength: '.$self->_headers->{'FileLength'}."\n";
147             print 'FrameSize: '. IO::SWF::Type::RECT::string($self->_headers->{'FrameSize'})."\n";
148             print 'FrameRate: '.($self->_headers->{'FrameRate'} / 0x100)."\n";
149             print 'FrameCount: '.$self->_headers->{'FrameCount'}."\n";
150              
151             if ($opts{'hexdump'}) {
152             $bitio->hexdump(0, $self->_header_size);
153             $opts{'bitio'} = $bitio; # for tag
154             }
155              
156             ## SWF Tags ##
157            
158             print 'Tags:'."\n";
159             foreach my $tag (@{$self->_tags}) {
160             $tag->dump(\%opts);
161             }
162             }
163              
164             1;