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"
9 #include "zipios++/zipios_defs.h"
10 
11 #include "backbuffer.h"
12 
13 namespace zipios {
14 
15 //
16 // Public
17 //
18 
19 ZipFile ZipFile::openEmbeddedZipFile( const string &name ) {
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 
30 ZipFile::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 
55 istream *ZipFile::getInputStream( const ConstEntryPointer &entry ) {
56  if ( ! _valid )
57  throw InvalidStateException( "Attempt to use an invalid FileCollection" ) ;
58  return getInputStream( entry->getName() ) ;
59 }
60 
61 istream *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 
84 bool 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 
98 bool 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 
141 bool 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 
161 bool 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 
178 void 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 */
ZipFile()
Default constructor.
Definition: zipfile.h:37
Header file that defines ZipFile.
Header file that defines FileCollection.
Header file that defines some simple data types.
SimpleSmartPointer is a simple reference counting smart pointer template.
The header file for BackBuffer.
virtual FileCollection * clone() const
Create a heap allocated clone of the object this method is called for.
Definition: zipfile.cpp:41
ConstEntryPointer getNextEntry()
An object member function may throw this exception, if the operation it normally performs is inapprop...
virtual istream * getInputStream(const ConstEntryPointer &entry)
Definition: zipfile.cpp:55
virtual void close()
Closes the FileCollection.
Definition: zipfile.cpp:50
Header file that defines ZipInputStream.
static ZipFile openEmbeddedZipFile(const string &name)
Definition: zipfile.cpp:19
virtual ~ZipFile()
Destructor.
Definition: zipfile.cpp:46
virtual ConstEntryPointer getEntry(const string &name, MatchPath matchpath=MATCH) const
Definition: fcoll.cpp:34