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 zis->getNextEntry();
75 return zis;
76 }
77}
78
79
80//
81// Private
82//
83
84bool ZipFile::init( istream &_zipfile ) {
85
86 // Check stream error state
87 if ( ! _zipfile ) {
88 setError ( "Error reading from file" ) ;
89 return false ;
90 }
91
92 _valid = readCentralDirectory( _zipfile ) ;
93
94 return _valid ;
95}
96
97
98bool ZipFile::readCentralDirectory ( istream &_zipfile ) {
99 // Find and read eocd.
100 if ( ! readEndOfCentralDirectory( _zipfile ) )
101 throw FCollException( "Unable to find zip structure: End-of-central-directory" ) ;
102
103 // Position read pointer to start of first entry in central dir.
104 _vs.vseekg( _zipfile, _eocd.offset(), ios::beg ) ;
105
106 int entry_num = 0 ;
107 // Giving the default argument in the next line to keep Visual C++ quiet
108 _entries.resize ( _eocd.totalCount(), 0 ) ;
109 while ( ( entry_num < _eocd.totalCount() ) ) {
110 ZipCDirEntry *ent = new ZipCDirEntry ;
111 _entries[ entry_num ] = ent ;
112 _zipfile >> *ent ;
113 if ( ! _zipfile ) {
114 if ( _zipfile.bad() )
115 throw IOException( "Error reading zip file while reading zip file central directory" ) ;
116 else if ( _zipfile.fail() )
117 throw FCollException( "Zip file consistency problem. Failure while reading zip file central directory" ) ;
118 else if ( _zipfile.eof() )
119 throw IOException( "Premature end of file while reading zip file central directory" ) ;
120 }
121 ++entry_num ;
122 }
123
124 // Consistency check. eocd should start here
125
126 int pos = _vs.vtellg( _zipfile ) ;
127 _vs.vseekg( _zipfile, 0, ios::end ) ;
128 int remaining = static_cast< int >( _vs.vtellg( _zipfile ) ) - pos ;
129 if ( remaining != _eocd.eocdOffSetFromEnd() )
130 throw FCollException( "Zip file consistency problem. Zip file data fields are inconsistent with zip file layout" ) ;
131
132 // Consistency check 2, are local headers consistent with
133 // cd headers
134 if ( ! confirmLocalHeaders( _zipfile ) )
135 throw FCollException( "Zip file consistency problem. Zip file data fields are inconsistent with zip file layout" ) ;
136
137 return true ;
138}
139
140
141bool ZipFile::readEndOfCentralDirectory ( istream &_zipfile ) {
142 BackBuffer bb( _zipfile, _vs ) ;
143 int read_p = -1 ;
144 bool found = false ;
145 while ( ! found ) {
146 if ( read_p < 0 )
147 if ( ! bb.readChunk ( read_p ) ) {
148 found = false ;
149 break ;
150 }
151 if ( _eocd.read( bb, read_p ) ) {
152 found = true ;
153 break ;
154 }
155 --read_p ;
156 }
157
158 return found ;
159}
160
161bool ZipFile::confirmLocalHeaders( istream &_zipfile ) {
162 Entries::const_iterator it ;
163 ZipCDirEntry *ent ;
164 int inconsistencies = 0 ;
165 ZipLocalEntry zlh ;
166 for ( it = _entries.begin() ; it != _entries.end() ; it++ ) {
167 ent = static_cast< ZipCDirEntry * >( (*it).get() ) ;
168 _vs.vseekg( _zipfile, ent->getLocalHeaderOffset(), ios::beg ) ;
169 _zipfile >> zlh ;
170 if ( ! _zipfile || zlh != *ent ) {
171 inconsistencies++ ;
172 _zipfile.clear() ;
173 }
174 }
175 return ! inconsistencies ;
176}
177
178void ZipFile::setError ( string error_str ) {
179 _valid = false ;
180#ifdef _USE_EXCEPTIONS
181 throw error_str ; // define exception class instead.
182#else
183 cerr << error_str << endl ; // define operator<< for exception class if such a class replaces string
184#endif
185}
186
187
188}
189
194/*
195 Zipios++ - a small C++ library that provides easy access to .zip files.
196 Copyright (C) 2000 Thomas Søndergaard
197
198 This library is free software; you can redistribute it and/or
199 modify it under the terms of the GNU Lesser General Public
200 License as published by the Free Software Foundation; either
201 version 2 of the License, or (at your option) any later version.
202
203 This library is distributed in the hope that it will be useful,
204 but WITHOUT ANY WARRANTY; without even the implied warranty of
205 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
206 Lesser General Public License for more details.
207
208 You should have received a copy of the GNU Lesser General Public
209 License along with this library; if not, write to the Free Software
210 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
211*/
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.
ConstEntryPointer getNextEntry()
Opens the next entry in the zip archive and returns a const pointer to a FileEntry object for the ent...
Header file that defines FileCollection.
Header file that defines ZipFile.
Header file that defines ZipInputStream.
Header file that defines some simple data types.