diff options
Diffstat (limited to 'qpdf/fix-qdf')
-rwxr-xr-x | qpdf/fix-qdf | 397 |
1 files changed, 0 insertions, 397 deletions
diff --git a/qpdf/fix-qdf b/qpdf/fix-qdf deleted file mode 100755 index 2892a462..00000000 --- a/qpdf/fix-qdf +++ /dev/null @@ -1,397 +0,0 @@ -#!/usr/bin/env perl - -require 5.008_001; -use warnings; -use strict; -use File::Basename; - -my $whoami = basename($0); -my $dirname = dirname($0); - -if ((@ARGV == 1) && ($ARGV[0] eq '--version')) -{ - exec "$dirname/qpdf", '--version'; - exit 2; -} - -my $offset = 0; -my $last_offset = 0; - -my $file = shift(@ARGV); -if (defined $file) -{ - open(F, "<$file") or die "$whoami: can't open $file: $!\n"; -} -else -{ - $file = 'stdin'; - open(F, "<&STDIN") or die "$whoami: can't dup stdin: $!\n"; -} -binmode F; -binmode STDOUT; - -my $line = get_line(); -if (! ((defined $line) && ($line =~ m/^%PDF-1\.\d+\b/))) -{ - die "$whoami: $file: not a pdf file\n"; -} -print $line; -$line = get_line(); -die "$whoami: $file: premature EOF\n" unless defined $line; -print $line; -$line = get_line(); -if (! ((defined $line) && ($line =~ m/^%QDF-1.\d+\b/))) -{ - die "$whoami: $file: not a qdf file\n"; -} -print $line; - -my $last_obj = 0; -my @xref = (); - -my $stream_start = 0; -my $stream_length = 0; -my $xref_offset = 0; -my $xref_f1_nbytes = 0; -my $xref_f2_nbytes = 0; -my $xref_size = 0; - -my $cur_state = 0; -my $st_top = ++$cur_state; -my $st_in_obj = ++$cur_state; -my $st_in_stream = ++$cur_state; -my $st_after_stream = ++$cur_state; -my $st_in_ostream_dict = ++$cur_state; -my $st_in_ostream_offsets = ++$cur_state; -my $st_in_ostream_outer = ++$cur_state; -my $st_in_ostream_obj = ++$cur_state; -my $st_in_xref_stream_dict = ++$cur_state; -my $st_in_length = ++$cur_state; -my $st_at_xref = ++$cur_state; -my $st_before_trailer = ++$cur_state; -my $st_in_trailer = ++$cur_state; -my $st_done = ++$cur_state; - -my @ostream = (); -my @ostream_offsets = (); -my @ostream_discarded = (); -my $ostream_idx = 0; -my $ostream_id = 0; -my $ostream_extends = ""; - -my $state = $st_top; -while (defined($line = get_line())) -{ - if ($state == $st_top) - { - if ($line =~ m/^(\d+) 0 obj$/) - { - check_obj_id($1); - $state = $st_in_obj; - } - elsif ($line =~ m/^xref$/) - { - $xref_offset = $last_offset; - $state = $st_at_xref; - } - print $line; - } - elsif ($state == $st_in_obj) - { - print $line; - if ($line =~ m/^stream$/) - { - $state = $st_in_stream; - $stream_start = $offset; - } - elsif ($line =~ m/^endobj$/) - { - $state = $st_top; - } - elsif ($line =~ m,/Type /ObjStm,) - { - $state = $st_in_ostream_dict; - $ostream_id = $last_obj; - } - elsif ($line =~ m,/Type /XRef,) - { - $xref_offset = $xref[-1][1]; - $xref_f1_nbytes = 0; - my $t = $xref_offset; - while ($t) - { - $t >>= 8; - ++$xref_f1_nbytes; - } - # Figure out how many bytes we need for ostream index. - # Make sure we get at least 1 byte even if there are no - # object streams. - my $max_objects = 1; - foreach my $e (@xref) - { - my ($type, $f1, $f2) = @$e; - if ((defined $f2) && ($f2 > $max_objects)) - { - $max_objects = $f2; - } - } - while ($max_objects) - { - $max_objects >>=8; - ++$xref_f2_nbytes; - } - my $esize = 1 + $xref_f1_nbytes + $xref_f2_nbytes; - $xref_size = 1 + @xref; - my $length = $xref_size * $esize; - print " /Length $length\n"; - print " /W [ 1 $xref_f1_nbytes $xref_f2_nbytes ]\n"; - $state = $st_in_xref_stream_dict; - } - } - elsif ($state == $st_in_ostream_dict) - { - if ($line =~ m/^stream/) - { - $state = $st_in_ostream_offsets; - } - else - { - push(@ostream_discarded, $line); - if ($line =~ m,/Extends (\d+ 0 R),) - { - $ostream_extends = $1; - } - } - # discard line - } - elsif ($state == $st_in_ostream_offsets) - { - if ($line =~ m/^\%\% Object stream: object (\d+)/) - { - check_obj_id($1); - $stream_start = $last_offset; - $state = $st_in_ostream_outer; - push(@ostream, $line); - } - else - { - push(@ostream_discarded, $line); - } - # discard line - } - elsif ($state == $st_in_ostream_outer) - { - adjust_ostream_xref(); - push(@ostream_offsets, $last_offset - $stream_start); - $state = $st_in_ostream_obj; - push(@ostream, $line); - } - elsif ($state == $st_in_ostream_obj) - { - push(@ostream, $line); - if ($line =~ m/^\%\% Object stream: object (\d+)/) - { - check_obj_id($1); - $state = $st_in_ostream_outer; - } - elsif ($line =~ m/^endstream/) - { - $stream_length = $last_offset - $stream_start; - write_ostream(); - $state = $st_in_obj; - } - } - elsif ($state == $st_in_xref_stream_dict) - { - if ($line =~ m,/(Length|W) ,) - { - # already printed - } - elsif ($line =~ m,/Size ,) - { - my $size = 1 + @xref; - print " /Size $xref_size\n"; - } - else - { - print $line; - } - if ($line =~ m/^stream\n/) - { - my $pack = "(C C$xref_f1_nbytes C$xref_f2_nbytes)"; - print pack($pack, 0, 0, 0); - foreach my $x (@xref) - { - my ($type, $f1, $f2) = @$x; - $f2 = 0 unless defined $f2; - my @f1 = (); - my @f2 = (); - foreach my $d ([\@f1, $f1, $xref_f1_nbytes], - [\@f2, $f2, $xref_f2_nbytes]) - { - my ($fa, $f, $nbytes) = @$d; - for (my $i = 0; $i < $nbytes; ++$i) - { - unshift(@$fa, $f & 0xff); - $f >>= 8; - } - } - print pack($pack, $type, @f1, @f2); - } - print "\nendstream\nendobj\n\n"; - print "startxref\n$xref_offset\n\%\%EOF\n"; - $state = $st_done; - } - } - elsif ($state == $st_in_stream) - { - if ($line =~ m/^endstream$/) - { - $stream_length = $last_offset - $stream_start; - $state = $st_after_stream; - } - print $line; - } - elsif ($state == $st_after_stream) - { - if ($line =~ m/^\%QDF: ignore_newline$/) - { - --$stream_length; - } - elsif ($line =~ m/^(\d+) 0 obj$/) - { - check_obj_id($1); - $state = $st_in_length; - } - print $line; - } - elsif ($state == $st_in_length) - { - if ($line !~ m/^\d+$/) - { - die "$file:$.: expected integer\n"; - } - my $new = "$stream_length\n"; - $offset -= length($line); - $offset += length($new); - print $new; - $state = $st_top; - } - elsif ($state == $st_at_xref) - { - my $n = scalar(@xref); - print "0 ", $n+1, "\n0000000000 65535 f \n"; - for (@xref) - { - my ($type, $f1, $f2) = @$_; - printf("%010d 00000 n \n", $f1); - } - $state = $st_before_trailer; - } - elsif ($state == $st_before_trailer) - { - if ($line =~ m/^trailer <</) - { - print $line; - $state = $st_in_trailer; - } - # no output - } - elsif ($state == $st_in_trailer) - { - if ($line =~ m/^ \/Size \d+$/) - { - print " /Size ", scalar(@xref) + 1, "\n"; - } - else - { - print $line; - } - if ($line =~ m/^>>$/) - { - print "startxref\n$xref_offset\n\%\%EOF\n"; - $state = $st_done; - } - } - elsif ($state == $st_done) - { - # ignore - } -} - -die "$whoami: $file: premature EOF\n" unless $state == $st_done; - -sub get_line -{ - my $line = scalar(<F>); - if (defined $line) - { - $last_offset = $offset; - $offset += length($line); - } - $line; -} - -sub check_obj_id -{ - my $cur_obj = shift; - if ($cur_obj != $last_obj + 1) - { - die "$file:$.: expected object ", $last_obj + 1, "\n"; - } - $last_obj = $cur_obj; - push(@xref, [1, $last_offset]); -} - -sub adjust_ostream_xref -{ - pop(@xref); - push(@xref, [2, $ostream_id, $ostream_idx++]); -} - -sub write_ostream -{ - my $first = $ostream_offsets[0]; - my $onum = $ostream_id; - my $offsets = ""; - my $n = scalar(@ostream_offsets); - for (@ostream_offsets) - { - $_ -= $first; - ++$onum; - $offsets .= "$onum $_\n"; - } - my $offset_adjust = length($offsets); - $first += length($offsets); - $stream_length += length($offsets); - my $dict_data = ""; - $dict_data .= " /Length $stream_length\n"; - $dict_data .= " /N $n\n"; - $dict_data .= " /First $first\n"; - if ($ostream_extends) - { - $dict_data .= " /Extends $ostream_extends\n"; - } - $dict_data .= ">>\n"; - $offset_adjust += length($dict_data); - print $dict_data; - print "stream\n"; - print $offsets; - foreach (@ostream) - { - print $_; - } - - for (@ostream_discarded) - { - $offset -= length($_); - } - $offset += $offset_adjust; - - $ostream_idx = 0; - $ostream_id = 0; - @ostream = (); - @ostream_offsets = (); - @ostream_discarded = (); - $ostream_extends = ""; -} |