Zipios++
zipfile.cpp
Go to the documentation of this file.
1
2#include "zipios++/zipios-config.h"
3
4#include "zipios++/meta-iostreams.h"
5
6#include "zipios++/fcoll.h"
7#include "zipios++/zipfile.h"
10
11#include "backbuffer.h"
12
13namespace zipios {
14
15//
16// Public
17//
18
20 // open zipfile, read 4 last bytes close file
21 // create ZipFile object.
22 ifstream ifs( name.c_str(), ios::in | ios::binary ) ;
23 ifs.seekg( -4, ios::end ) ;
24 uint32 start_offset = readUint32( ifs ) ;
25 ifs.close() ;
26 return ZipFile( name, start_offset, 4 ) ;
27}
28
29
30ZipFile::ZipFile( const string &name , int s_off, int e_off
31 /* , ios::open_mode mode */ )
32 : _vs( s_off, e_off ) {
33
34 _filename = name ;
35
36 ifstream _zipfile( name.c_str(), ios::in | ios::binary ) ;
37 init( _zipfile ) ;
38}
39
40
42 return new ZipFile( *this ) ;
43}
44
45
47 close() ;
48}
49
51 _valid = false ;
52
53}
54
56 if ( ! _valid )
57 throw InvalidStateException( "Attempt to use an invalid FileCollection" ) ;
58 return getInputStream( entry->getName() ) ;
59}
60
61istream *ZipFile::getInputStream( const string &entry_name,
62 MatchPath matchpath ) {
63 if ( ! _valid )
64 throw InvalidStateException( "Attempt to use an invalid ZipFile" ) ;
65
66 ConstEntryPointer ent = getEntry( entry_name, matchpath ) ;
67
68 if ( ent == 0 )
69 return 0 ;
70 else {
71 ZipInputStream *zis( new ZipInputStream( _filename,
72 static_cast< const ZipCDirEntry * >( ent.get() )->
73 getLocalHeaderOffset() + _vs.startOffset() ) ) ;
74 return zis;
75 }
76}
77
78
79//
80// Private
81//
82
83bool ZipFile::init( istream &_zipfile ) {
84
85 // Check stream error state
86 if ( ! _zipfile ) {
87 setError ( "Error reading from file" ) ;
88 return false ;
89 }
90
91 _valid = readCentralDirectory( _zipfile ) ;
92
93 return _valid ;
94}
95
96
97bool ZipFile::readCentralDirectory ( istream &_zipfile ) {
98 // Find and read eocd.
99 if ( ! readEndOfCentralDirectory( _zipfile ) )
100 throw FCollException( "Unable to find zip structure: End-of-central-directory" ) ;
101
102 // Position read pointer to start of first entry in central dir.
103 _vs.vseekg( _zipfile, _eocd.offset(), ios::beg ) ;
104
105 int entry_num = 0 ;
106 // Giving the default argument in the next line to keep Visual C++ quiet
107 _entries.resize ( _eocd.totalCount(), 0 ) ;
108 while ( ( entry_num < _eocd.totalCount() ) ) {
109 ZipCDirEntry *ent = new ZipCDirEntry ;
110 _entries[ entry_num ] = ent ;
111 _zipfile >> *ent ;
112 if ( ! _zipfile ) {
113 if ( _zipfile.bad() )
114 throw IOException( "Error reading zip file while reading zip file central directory" ) ;
115 else if ( _zipfile.fail() )
116 throw FCollException( "Zip file consistency problem. Failure while reading zip file central directory" ) ;
117 else if ( _zipfile.eof() )
118 throw IOException( "Premature end of file while reading zip file central directory" ) ;
119 }
120 ++entry_num ;
121 }
122
123 // Consistency check. eocd should start here
124
125 int pos = _vs.vtellg( _zipfile ) ;
126 _vs.vseekg( _zipfile, 0, ios::end ) ;
127 int remaining = static_cast< int >( _vs.vtellg( _zipfile ) ) - pos ;
128 if ( remaining != _eocd.eocdOffSetFromEnd() )
129 throw FCollException( "Zip file consistency problem. Zip file data fields are inconsistent with zip file layout" ) ;
130
131 // Consistency check 2, are local headers consistent with
132 // cd headers
133 if ( ! confirmLocalHeaders( _zipfile ) )
134 throw FCollException( "Zip file consistency problem. Zip file data fields are inconsistent with zip file layout" ) ;
135
136 return true ;
137}
138
139
140bool ZipFile::readEndOfCentralDirectory ( istream &_zipfile ) {
141 BackBuffer bb( _zipfile, _vs ) ;
142 int read_p = -1 ;
143 bool found = false ;
144 while ( ! found ) {
145 if ( read_p < 0 )
146 if ( ! bb.readChunk ( read_p ) ) {
147 found = false ;
148 break ;
149 }
150 if ( _eocd.read( bb, read_p ) ) {
151 found = true ;
152 break ;
153 }
154 --read_p ;
155 }
156
157 return found ;
158}
159
160bool ZipFile::confirmLocalHeaders( istream &_zipfile ) {
161 Entries::const_iterator it ;
162 ZipCDirEntry *ent ;
163 int inconsistencies = 0 ;
164 ZipLocalEntry zlh ;
165 for ( it = _entries.begin() ; it != _entries.end() ; it++ ) {
166 ent = static_cast< ZipCDirEntry * >( (*it).get() ) ;
167 _vs.vseekg( _zipfile, ent->getLocalHeaderOffset(), ios::beg ) ;
168 _zipfile >> zlh ;
169 if ( ! _zipfile || zlh != *ent ) {
170 inconsistencies++ ;
171 _zipfile.clear() ;
172 }
173 }
174 return ! inconsistencies ;
175}
176
177void ZipFile::setError ( string error_str ) {
178 _valid = false ;
179#ifdef _USE_EXCEPTIONS
180 throw error_str ; // define exception class instead.
181#else
182 cerr << error_str << endl ; // define operator<< for exception class if such a class replaces string
183#endif
184}
185
186
187}
188
193/*
194 Zipios++ - a small C++ library that provides easy access to .zip files.
195 Copyright (C) 2000 Thomas Søndergaard
196
197 This library is free software; you can redistribute it and/or
198 modify it under the terms of the GNU Lesser General Public
199 License as published by the Free Software Foundation; either
200 version 2 of the License, or (at your option) any later version.
201
202 This library is distributed in the hope that it will be useful,
203 but WITHOUT ANY WARRANTY; without even the implied warranty of
204 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
205 Lesser General Public License for more details.
206
207 You should have received a copy of the GNU Lesser General Public
208 License along with this library; if not, write to the Free Software
209 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
210*/
The header file for BackBuffer.
FileCollection is an abstract baseclass that represents a collection of files.
Definition fcoll.h:21
virtual ConstEntryPointer getEntry(const string &name, MatchPath matchpath=MATCH) const
Returns a ConstEntryPointer to a FileEntry object for the entry with the specified name.
Definition fcoll.cpp:34
An object member function may throw this exception, if the operation it normally performs is inapprop...
SimpleSmartPointer is a simple reference counting smart pointer template.
Specialization of ZipLocalEntry, that add fields for storing the extra information,...
Definition ziphead.h:102
ZipFile is a FileCollection, where the files are stored in a .zip file.
Definition zipfile.h:20
virtual ~ZipFile()
Destructor.
Definition zipfile.cpp:46
virtual void close()
Closes the FileCollection.
Definition zipfile.cpp:50
ZipFile()
Default constructor.
Definition zipfile.h:37
static ZipFile openEmbeddedZipFile(const string &name)
Opens a Zip archive embedded in another file, by writing the zip archive to the end of the file follo...
Definition zipfile.cpp:19
virtual FileCollection * clone() const
Create a heap allocated clone of the object this method is called for.
Definition zipfile.cpp:41
virtual istream * getInputStream(const ConstEntryPointer &entry)
Returns a pointer to an opened istream for the specified FileEntry.
Definition zipfile.cpp:55
ZipInputStream is an istream that gets it's input from a zip file.
Header file that defines FileCollection.
Header file that defines ZipFile.
Header file that defines ZipInputStream.
Header file that defines some simple data types.