line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package SWF::Header;
|
2
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
21421
|
use strict;
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
36
|
|
4
|
1
|
|
|
1
|
|
4
|
use vars qw($VERSION);
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
51
|
|
5
|
|
|
|
|
|
|
$VERSION = '0.04';
|
6
|
|
|
|
|
|
|
|
7
|
1
|
|
|
1
|
|
897
|
use SWF::BinStream;
|
|
1
|
|
|
|
|
31793
|
|
|
1
|
|
|
|
|
24
|
|
8
|
1
|
|
|
1
|
|
9
|
use Carp;
|
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
705
|
|
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
=head1 NAME
|
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
SWF::Header - extract header information from SWF files.
|
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
=head1 SYNOPSIS
|
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
use SWF::Header;
|
17
|
|
|
|
|
|
|
my $header_data = SWF::Header->read_file('/path/to/file.swf');
|
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
or
|
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
my $header_data = SWF::Header->read_data($binary_data);
|
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
or
|
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
my $h = SWF::Header->new();
|
26
|
|
|
|
|
|
|
my %headers = map { $_ => $h->read_file($_) } @files;
|
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
=head1 DESCRIPTION
|
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
I pulls the descriptive information out of the header of a shockwave (.swf) file. It returns a hashref of height, width, duration, framerate, shockwave version and file size.
|
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
=head2 METHODS
|
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
=over 4
|
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
=item new()
|
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
Creates a reader object. You don't normally need to call the constructor directly unless you want to read several files. Either read_file or read_data will construct an object to do the work if called as a class method.
|
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
=cut
|
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
sub new {
|
44
|
2
|
|
|
2
|
1
|
15
|
my $class = shift;
|
45
|
2
|
|
|
|
|
8
|
my $self = {
|
46
|
|
|
|
|
|
|
_version => 5,
|
47
|
|
|
|
|
|
|
_stream => undef,
|
48
|
|
|
|
|
|
|
};
|
49
|
2
|
|
|
|
|
7
|
return bless $self, $class;
|
50
|
|
|
|
|
|
|
}
|
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
=item stream( $stream )
|
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
A set or get method that can be used to provide an SWF::BinStream::Read object you want to work with. If none is supplied or exists already, calls new_stream to create a new one.
|
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
=cut
|
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
sub stream {
|
59
|
15
|
|
|
15
|
1
|
23
|
my ($self, $s) = @_;
|
60
|
15
|
50
|
|
|
|
29
|
return $self->{_stream} = $s if $s;
|
61
|
15
|
50
|
|
|
|
92
|
return $self->{_stream} if $self->{_stream};
|
62
|
0
|
|
|
|
|
0
|
return $self->new_stream;
|
63
|
|
|
|
|
|
|
}
|
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
=item new_stream()
|
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
Resets the reader's stream to a new SWF::BinStream::Read object, ready to start from scratch. Both read_file and read_data call this method before handing over to parse_header.
|
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
=cut
|
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
sub new_stream {
|
72
|
1
|
|
|
1
|
1
|
2
|
my ($self, $data) = @_;
|
73
|
1
|
|
|
0
|
|
14
|
return $self->{_stream} = SWF::BinStream::Read->new($data, sub{ Carp::croak("The stream ran short by $_[0] bytes.") });
|
|
0
|
|
|
|
|
0
|
|
74
|
|
|
|
|
|
|
}
|
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
=item read_file( $file )
|
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
Opens and reads the first few bytes of the file supplied (as either a filehandle or a path), uses them to start a new stream then calls parse_header.
|
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
=cut
|
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
sub read_file {
|
83
|
1
|
|
|
1
|
1
|
425
|
my ($self, $path) = @_;
|
84
|
1
|
50
|
|
|
|
4
|
return unless $path;
|
85
|
1
|
|
|
|
|
2
|
my $file;
|
86
|
1
|
50
|
|
|
|
5
|
if (ref($path)) {
|
87
|
0
|
|
|
|
|
0
|
$file = $path;
|
88
|
|
|
|
|
|
|
} else {
|
89
|
1
|
50
|
|
|
|
75
|
open( $file, $path ) or Carp::croak(1, "opening $path failed: $!");
|
90
|
|
|
|
|
|
|
}
|
91
|
1
|
|
|
|
|
3
|
binmode($file);
|
92
|
1
|
|
|
|
|
46
|
read($file, my $data, 4096);
|
93
|
|
|
|
|
|
|
|
94
|
1
|
50
|
|
|
|
9
|
$self = $self->new() unless ref $self;
|
95
|
1
|
|
|
|
|
6
|
$self->new_stream($data);
|
96
|
1
|
|
|
|
|
136
|
return $self->parse_header;
|
97
|
|
|
|
|
|
|
}
|
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
=item read_data( $string )
|
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
Just for consistency. All this does is start a new stream with the data supplied and call parse_header.
|
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
=cut
|
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
sub read_data {
|
106
|
0
|
|
|
0
|
1
|
0
|
my ($self, $data) = @_;
|
107
|
0
|
0
|
|
|
|
0
|
return unless $data;
|
108
|
|
|
|
|
|
|
|
109
|
0
|
0
|
|
|
|
0
|
$self = $self->new() unless ref $self;
|
110
|
0
|
|
|
|
|
0
|
$self->new_stream($data);
|
111
|
0
|
|
|
|
|
0
|
return $self->parse_header;
|
112
|
|
|
|
|
|
|
}
|
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
=item parse_header( $string )
|
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
Checks that this is a properly-formatted SWF file, then pulls the relevant bytes out of the header block of the file and returns a hashref containing the stage dimensions, coordinates, duration, frame rate, version and file size. In detail:
|
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
{
|
119
|
|
|
|
|
|
|
signature => 'FWS' or 'CWS',
|
120
|
|
|
|
|
|
|
version => Shockwave language version,
|
121
|
|
|
|
|
|
|
filelen => Length of entire file in bytes,
|
122
|
|
|
|
|
|
|
xmin => Stage left edge, in twips,
|
123
|
|
|
|
|
|
|
xmax => Stage right edge, in twips from left,
|
124
|
|
|
|
|
|
|
ymin => Stage top edge,
|
125
|
|
|
|
|
|
|
ymax => Stage bottom edge, in twips from top,
|
126
|
|
|
|
|
|
|
rate => Frame rate in fps,
|
127
|
|
|
|
|
|
|
count => total number of frames in movie,
|
128
|
|
|
|
|
|
|
width => calculated width of stage (in pixels),
|
129
|
|
|
|
|
|
|
height => calculated height of stage (in pixels),
|
130
|
|
|
|
|
|
|
duration => calculated duration of movie (in seconds),
|
131
|
|
|
|
|
|
|
background => calculated background color of movie (in html format),
|
132
|
|
|
|
|
|
|
}
|
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
=cut
|
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
sub parse_header {
|
137
|
1
|
|
|
1
|
1
|
2
|
my ($self, $data) = @_;
|
138
|
1
|
50
|
|
|
|
5
|
$self->stream->add_stream($data) if $data;
|
139
|
|
|
|
|
|
|
|
140
|
1
|
|
|
|
|
2
|
my $header = {};
|
141
|
1
|
|
|
|
|
4
|
$header->{signature} = $self->stream->get_string(3);
|
142
|
1
|
50
|
33
|
|
|
51
|
if ($header->{signature} ne 'CWS' && $header->{signature} ne 'FWS') {
|
143
|
0
|
|
|
|
|
0
|
Carp::carp "This is not an SWF stream ";
|
144
|
0
|
|
|
|
|
0
|
return;
|
145
|
|
|
|
|
|
|
}
|
146
|
1
|
|
|
|
|
5
|
$header->{version} = $self->{_version} = $self->stream->get_UI8;
|
147
|
1
|
|
|
|
|
33
|
$header->{filelen} = $self->stream->get_UI32;
|
148
|
1
|
50
|
|
|
|
35
|
$self->stream->add_codec('Zlib') if $header->{signature} eq 'CWS';
|
149
|
|
|
|
|
|
|
|
150
|
1
|
|
|
|
|
75797
|
my $nbits = $self->stream->get_bits(5);
|
151
|
1
|
|
|
|
|
49
|
$header->{xmin} = $self->stream->get_sbits($nbits);
|
152
|
1
|
|
|
|
|
39
|
$header->{xmax} = $self->stream->get_sbits($nbits);
|
153
|
1
|
|
|
|
|
40
|
$header->{ymin} = $self->stream->get_sbits($nbits);
|
154
|
1
|
|
|
|
|
38
|
$header->{ymax} = $self->stream->get_sbits($nbits);
|
155
|
1
|
|
|
|
|
32
|
$header->{rate} = $self->stream->get_UI16 / 256;
|
156
|
1
|
|
|
|
|
32
|
$header->{count} = $self->stream->get_UI16;
|
157
|
1
|
|
|
|
|
31
|
$header->{width} = int(($header->{xmax} - $header->{xmin}) / 20);
|
158
|
1
|
|
|
|
|
6
|
$header->{height} = int(($header->{ymax} - $header->{ymin}) / 20);
|
159
|
1
|
|
|
|
|
3
|
$header->{duration} = $header->{count} / $header->{rate};
|
160
|
|
|
|
|
|
|
|
161
|
1
|
|
|
|
|
3
|
my $temp = $self->stream->get_sbits($nbits);
|
162
|
1
|
|
|
|
|
38
|
my $background_r = $self->stream->get_UI8();
|
163
|
1
|
|
|
|
|
25
|
my $background_g = $self->stream->get_UI8();
|
164
|
1
|
|
|
|
|
22
|
my $background_b = $self->stream->get_UI8();
|
165
|
1
|
|
|
|
|
25
|
$header->{background} = sprintf ("#%02X%02X%02X", $background_r, $background_g, $background_b);
|
166
|
|
|
|
|
|
|
|
167
|
1
|
|
|
|
|
43
|
return $header;
|
168
|
|
|
|
|
|
|
}
|
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
=head1 COPYRIGHT
|
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
Copyright 2004 William Ross (wross@cpan.org)
|
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
But obviously based entirely on previous work by Yasuhiro Sasama.
|
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
This library is free software; you can redistribute it
|
177
|
|
|
|
|
|
|
and/or modify it under the same terms as Perl itself.
|
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
=head1 SEE ALSO
|
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
L, L, L, L
|
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
The SWF file format specification from Macromedia can be found at
|
184
|
|
|
|
|
|
|
http://www.openswf.org/spec/SWFfileformat.html
|
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
=cut
|
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
1;
|