~ubuntu-branches/ubuntu/maverick/freecad/maverick

« back to all changes in this revision

Viewing changes to src/Base/zipios/zipfile.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Adam C. Powell, IV
  • Date: 2010-01-11 08:48:33 UTC
  • mfrom: (3.1.3 sid)
  • Revision ID: james.westby@ubuntu.com-20100111084833-4g9vgdqbkw8u34zb
Tags: 0.9.2646.5-1
* New upstream version (closes: #561696).
* Added swig to Build-Depends (closes: #563523, #563772).
* Removed python-opencv from Build-Depends and Recommends (closes: #560768).

Show diffs side-by-side

added added

removed removed

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