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
virtual FileCollection * clone() const
Create a heap allocated clone of the object this method is called for.
Definition: zipfile.cpp:41
Header file that defines ZipFile.
Header file that defines FileCollection.
A BackBuffer instance is useful for reading the last part of a file in an efficient manner...
Definition: backbuffer.h:32
Header file that defines some simple data types.
SimpleSmartPointer is a simple reference counting smart pointer template.
The header file for BackBuffer.
int readChunk(int &read_pointer)
Reads another chunk and returns the size of the chunk that has been read.
Definition: backbuffer.h:75
Specialization of ZipLocalEntry, that add fields for storing the extra information, that is only present in the entries in the zip central directory and not in the local entry headers.
Definition: ziphead.h:102
An IOException is used to signal an I/O error.
virtual ConstEntryPointer getEntry(const string &name, MatchPath matchpath=MATCH) const
Definition: fcoll.cpp:34
ConstEntryPointer getNextEntry()
An FCollException is used to signal a problem with a FileCollection.
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
A concrete implementation of the abstract FileEntry base class for ZipFile entries, specifically for representing the information present in the local headers of file entries in a zip file.
Definition: ziphead.h:22
Header file that defines ZipInputStream.
static ZipFile openEmbeddedZipFile(const string &name)
Definition: zipfile.cpp:19
virtual ~ZipFile()
Destructor.
Definition: zipfile.cpp:46