Debian lenny version packages
[pkg-perl] / deb-src / libarchive-zip-perl / libarchive-zip-perl-1.18 / examples / zipinfo.pl
1 #! /usr/bin/perl -w
2 # Print out information about a ZIP file.
3 # Note that this buffers the entire file into memory!
4 # usage:
5 # perl examples/zipinfo.pl zipfile.zip
6
7 use strict;
8
9 use Data::Dumper ();
10 use FileHandle;
11 use Archive::Zip qw(:ERROR_CODES :CONSTANTS :PKZIP_CONSTANTS);
12 use Archive::Zip::BufferedFileHandle;
13
14 $| = 1;
15
16 ### Workaround for a bug in version of Data::Dumper bundled
17 ### with some versions of Perl, which causes warnings when
18 ### calling ->Seen below.
19 if ( defined &Data::Dumper::init_refaddr_format ) {
20         Data::Dumper::init_refaddr_format();
21 }
22
23 # use constant END_OF_CENTRAL_DIRECTORY_SIGNATURE_STRING;
24 use constant CENTRAL_DIRECTORY_FILE_HEADER_SIGNATURE_STRING => pack( SIGNATURE_FORMAT,
25         CENTRAL_DIRECTORY_FILE_HEADER_SIGNATURE );
26 use constant LOCAL_FILE_HEADER_SIGNATURE_STRING => pack( SIGNATURE_FORMAT,
27         LOCAL_FILE_HEADER_SIGNATURE );
28
29 $Data::Dumper::Useqq = 1;       # enable double-quotes for string values
30 $Data::Dumper::Indent = 1;
31
32 my $zip = Archive::Zip->new();
33 my $zipFileName = shift(@ARGV);
34
35 my $fh = Archive::Zip::BufferedFileHandle->new();
36 $fh->readFromFile($zipFileName) or exit($!);
37
38 my $status = $zip->_findEndOfCentralDirectory($fh);
39 die("can't find EOCD\n") if $status != AZ_OK;
40
41 my $eocdPosition = $fh->tell( );
42
43 $status = $zip->_readEndOfCentralDirectory($fh);
44 die("can't read EOCD\n") if $status != AZ_OK;
45
46 my $zipDumper = Data::Dumper->new([$zip], ['ZIP']);
47 $zipDumper->Seen({ ref($fh), $fh });
48 print $zipDumper->Dump(), "\n";
49
50 my $expectedEOCDPosition = $zip->centralDirectoryOffsetWRTStartingDiskNumber()
51         + $zip->centralDirectorySize();
52
53 my $eocdOffset = $zip->{eocdOffset} = $eocdPosition - $expectedEOCDPosition;
54
55 if ($eocdOffset)
56 {
57         printf "Expected EOCD at %d (0x%x) but found it at %d (0x%x)\n",
58                 ($expectedEOCDPosition) x 2, ($eocdPosition) x 2;
59 }
60 else
61 {
62         printf("Found EOCD at %d (0x%x)\n\n", ($eocdPosition) x 2);
63 }
64
65 my $contents = $fh->contents();
66 my $offset = $eocdPosition + $eocdOffset - 1;
67 my $cdPos;
68 my @members;
69 my $numberOfMembers = $zip->numberOfCentralDirectoriesOnThisDisk(); 
70 foreach my $n (0 .. $numberOfMembers - 1)
71 {
72         my $index = $numberOfMembers - $n;
73         $cdPos = rindex($contents,
74                 CENTRAL_DIRECTORY_FILE_HEADER_SIGNATURE_STRING, $offset);
75         if ($cdPos < 0)
76         {
77                 print "No central directory found for member #$index\n";
78                 last;
79         }
80         else
81         {
82                 print "Found central directory for member #$index at $cdPos\n";
83                 $fh->seek($cdPos + SIGNATURE_LENGTH, 0);        # SEEK_SET
84                 my $newMember = $zip->ZIPMEMBERCLASS->_newFromZipFile(
85                         $fh, "($zipFileName)" );
86                 $status = $newMember->_readCentralDirectoryFileHeader();
87                 if ($status != AZ_OK and $status != AZ_STREAM_END)
88                 {
89                         printf "read CD header status=%d\n", $status;
90                         last;
91                 }
92                 unshift(@members, $newMember);
93
94                 my $memberDumper = Data::Dumper->new([$newMember], ['CDMEMBER' . $index ]);
95                 $memberDumper->Seen({ ref($fh), $fh });
96                 print $memberDumper->Dump(), "\n";
97         }
98         $offset = $cdPos - 1;
99 }
100
101 if ($cdPos >= 0 and 
102         $cdPos != $zip->centralDirectoryOffsetWRTStartingDiskNumber())
103 {
104         printf "Expected to find central directory at %d (0x%x), but found it at %d (0x%x)\n",
105                 ($zip->centralDirectoryOffsetWRTStartingDiskNumber()) x 2,
106                 ($cdPos) x 2;
107 }
108
109 print "\n";
110
111 # Now read the local headers
112
113 foreach my $n (0 .. $#members)
114 {
115         my $member = $members[$n];
116         $fh->seek($member->localHeaderRelativeOffset() + $eocdOffset + SIGNATURE_LENGTH, 0);
117         $status = $member->_readLocalFileHeader();
118         if ($status != AZ_OK and $status != AZ_STREAM_END)
119         {
120                 printf "member %d read header status=%d\n", $n+1, $status;
121                 last;
122         }
123
124         my $memberDumper = Data::Dumper->new([$member], ['LHMEMBER' . ($n + 1)]);
125         $memberDumper->Seen({ ref($fh), $fh });
126         print $memberDumper->Dump(), "\n";
127
128         my $endOfMember = $member->localHeaderRelativeOffset()
129                 + $member->_localHeaderSize()
130                 + $member->compressedSize();
131
132         if ($endOfMember > $cdPos
133                 or ($n < $#members and 
134                         $endOfMember > $members[$n+1]->localHeaderRelativeOffset()))
135         {
136                 print "Error: ";
137         }
138         printf("End of member: %d, CD at %d", $endOfMember, $cdPos);
139         if ( $n < $#members )
140         {
141                 printf(", next member starts at %d",
142                         $members[$n+1]->localHeaderRelativeOffset());
143         }
144         print("\n\n");
145 }
146
147 # vim: ts=4 sw=4