Created
April 26, 2020 04:32
-
-
Save mwgamera/2adedee9a75f253dc7a2fb1c57385c3b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env perl | |
# Fix some JPG data in SWF file so that swfrender doesn't trip on it. | |
# klg, Apr 2020 | |
use strict; | |
use warnings; | |
use IO::Compress::Deflate; | |
use IO::Uncompress::Inflate; | |
my $src = \*STDIN; | |
my $dst = \*STDOUT; | |
open $src, '<', shift or die $! if @ARGV; | |
# read the uncompressed part of the header | |
read $src, $_, 8 or die $!; | |
my ($magic, $version, $size) = unpack 'A3CV'; | |
die 'Not an SWF file.' unless $magic =~ /^[FCZ]WS$/; | |
die 'LZMA not supported' if $magic eq 'ZWS'; | |
if ($magic eq 'CWS') { | |
$src = IO::Uncompress::Inflate->new($src) | |
or die "inflate: $!"; | |
} | |
print $dst pack 'A3CV', 'CWS', $version, $size or die $!; | |
$dst = IO::Compress::Deflate->new($dst) or die "deflate: $!"; | |
# read the rest of a header and copy it out | |
read $src, $_, 1 or die $!; | |
print $dst $_ or die $!; | |
read $src, $_, (((ord >> 3) * 4 + 5 - 1) >> 3) + 4 or die $!; | |
print $dst $_ or die $!; | |
# read and copy all tags, modifying some | |
until (eof $src) { | |
read $src, $_, 2 or die $!; | |
print $dst $_ or die $!; | |
my $tag = unpack 'v'; | |
my $len = $tag & 0x3f; | |
if ($len == 0x3f) { | |
read $src, $_, 4, or die $!; | |
print $dst $_ or die $!; | |
$len = unpack 'V'; | |
} | |
$tag >>= 6; | |
if ($len) { | |
read $src, $_, $len or die $!; | |
$_ = fixjpgtags($tag, $_); | |
print $dst $_ or die $!; | |
} | |
} | |
sub fixjpgtags { | |
my ($tag, $data) = @_; | |
if ($tag == 6) { # DefineBits | |
substr($data, 2) = fixjpgdata(substr $data, 2); | |
} elsif ($tag == 8) { # JPEGTables | |
$data = fixjpgdata($data); | |
} elsif ($tag == 21) { # DefineBitsJPEG2 | |
substr($data, 2) = fixjpgdata(substr $data, 2); | |
} elsif ($tag == 35) { # DefineBitsJPEG3 | |
my $len = unpack 'x2V', $data; | |
substr($data, 6, $len) = fixjpgdata(substr $data, 6, $len); | |
} | |
return $data; | |
} | |
=for comment | |
SWF File Format Specification says: | |
"The data in this tag begins with the JPEG SOI marker 0xFF, 0xD8 and ends with | |
the EOI marker 0xFF, 0xD9. Before version 8 of the SWF file format, SWF files | |
could contain an erroneous header of 0xFF, 0xD9, 0xFF, 0xD8 before the JPEG SOI | |
marker. In addition to specifying JPEG data, DefineBitsJPEG2 can also contain | |
PNG image data and non-animated GIF89a." | |
=for comment | |
The offending files contained valid JFIF prefixed by EOI, i.e. data that | |
started with FF D9 FF D8 FF E0... Swftools would remove FF D9 FF D8 and | |
then complain that the rest starts with FF E0 so it does not look like JPEG. | |
Normalize things to start with single SOI, and pad with zeros to keep sizes | |
and alignment unchanged. | |
=cut | |
sub fixjpgdata { | |
local ($_) = @_; | |
return $_ if /\A\x89PNG|\AGIF/; | |
m/\A((\xff[\xd8\xd9])+)/ or die 'unexpected data in tag'; | |
my $L = length $1; | |
return "\xff\xd8" . substr($_, $L) . "\0" x ($L-2); | |
} | |
1; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment