FreeCAD

Форк
0
/
zipfile.cpp 
215 строк · 6.0 Кб
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
#if defined(_WIN32) && defined(ZIPIOS_UTF8)
13
#include <Base/FileInfo.h>
14
#endif
15

16
namespace zipios {
17

18
//
19
// Public
20
//
21

22
ZipFile ZipFile::openEmbeddedZipFile( const string &name ) {
23
  // open zipfile, read 4 last bytes close file
24
  // create ZipFile object.
25
  ifstream ifs( name.c_str(), ios::in | ios::binary ) ;
26
  ifs.seekg( -4, ios::end ) ;
27
  uint32 start_offset = readUint32( ifs ) ;
28
  ifs.close() ;
29
  return ZipFile( name, start_offset, 4 ) ; 
30
}
31

32

33
ZipFile::ZipFile( const string &name , int s_off, int e_off
34
		  /* , ios::open_mode mode */ ) 
35
  : _vs( s_off, e_off ) {
36

37
  _filename = name ;
38
  
39
#if defined(_WIN32) && defined(ZIPIOS_UTF8)
40
  std::wstring wsname = Base::FileInfo(name).toStdWString();
41
  ifstream _zipfile( wsname.c_str(), ios::in | ios::binary ) ;
42
#else
43
  ifstream _zipfile( name.c_str(), ios::in | ios::binary ) ;
44
#endif
45
  init( _zipfile ) ;
46
}
47

48

49
FileCollection *ZipFile::clone() const {
50
  return new ZipFile( *this ) ;
51
}
52

53

54
ZipFile::~ZipFile() {
55
  close() ;
56
}
57

58
void ZipFile::close() {
59
  _valid = false ;
60

61
}
62

63
istream *ZipFile::getInputStream( const ConstEntryPointer &entry ) {
64
  if ( ! _valid )
65
    throw InvalidStateException( "Attempt to use an invalid FileCollection" ) ;
66
  return getInputStream( entry->getName() ) ;
67
}
68

69
istream *ZipFile::getInputStream( const string &entry_name, 
70
				  MatchPath matchpath ) {
71
  if ( ! _valid )
72
    throw InvalidStateException( "Attempt to use an invalid ZipFile" ) ;
73

74
  ConstEntryPointer ent = getEntry( entry_name, matchpath ) ;
75
  
76
  if ( !ent )
77
    return nullptr ;
78
  else
79
    return new ZipInputStream( _filename,	
80
			   static_cast< const ZipCDirEntry * >( ent.get() )->
81
			   getLocalHeaderOffset() + _vs.startOffset() ) ;
82
}
83

84

85
//
86
// Private
87
//
88

89
bool ZipFile::init( istream &_zipfile ) {
90

91
  // Check stream error state
92
  if ( ! _zipfile ) {
93
    setError ( "Error reading from file" ) ;
94
    return false ;
95
  }
96
  
97
  _valid = readCentralDirectory( _zipfile ) ;
98

99
  return _valid ;
100
}
101

102

103
bool ZipFile::readCentralDirectory ( istream &_zipfile ) {
104
  // Find and read eocd. 
105
  if ( ! readEndOfCentralDirectory( _zipfile ) )
106
    throw FCollException( "Unable to find zip structure: End-of-central-directory" ) ;
107

108
  // Position read pointer to start of first entry in central dir.
109
  _vs.vseekg( _zipfile,  _eocd.offset(), ios::beg ) ;
110

111
  int entry_num = 0 ;
112
  // Giving the default argument in the next line to keep Visual C++ quiet
113
  _entries.resize ( _eocd.totalCount(), nullptr ) ;
114
  while ( ( entry_num < _eocd.totalCount() ) ) {
115
    ZipCDirEntry *ent = new ZipCDirEntry ; 
116
    _entries[ entry_num ] = ent ;
117
    _zipfile >>  *ent ;
118
    if ( ! _zipfile ) {
119
      if ( _zipfile.bad()  ) 
120
	throw IOException( "Error reading zip file while reading zip file central directory" ) ;
121
      else if ( _zipfile.fail() )
122
	throw FCollException( "Zip file consistency problem. Failure while reading zip file central directory" ) ;
123
      else if ( _zipfile.eof()  )
124
	throw IOException( "Premature end of file while reading zip file central directory" ) ;
125
    }
126
    ++entry_num ;
127
  }
128

129
  // Consistency check. eocd should start here
130
  
131
  int pos = _vs.vtellg( _zipfile ) ;
132
  _vs.vseekg( _zipfile, 0, ios::end ) ;
133
  int remaining = static_cast< int >( _vs.vtellg( _zipfile ) ) - pos ;
134
  if ( remaining != _eocd.eocdOffSetFromEnd() )
135
    throw FCollException( "Zip file consistency problem. Zip file data fields are inconsistent with zip file layout" ) ;
136

137
  // Consistency check 2, are local headers consistent with
138
  // cd headers
139
  if ( ! confirmLocalHeaders( _zipfile ) )
140
    throw FCollException( "Zip file consistency problem. Zip file data fields are inconsistent with zip file layout" ) ;
141
  
142
  return true ;
143
}
144

145

146
bool ZipFile::readEndOfCentralDirectory ( istream &_zipfile ) {
147
  BackBuffer bb( _zipfile, _vs ) ;
148
  int read_p = -1 ;
149
  bool found = false ;
150
  while ( ! found ) {
151
    if ( read_p < 0 )
152
      if ( ! bb.readChunk ( read_p ) ) {
153
	found = false ;
154
	break ;
155
      }
156
    if ( _eocd.read( bb, read_p ) ) {
157
      found = true ;
158
      break ;
159
    }
160
    --read_p ;
161
  }
162

163
  return found ;
164
}
165

166
bool ZipFile::confirmLocalHeaders( istream &_zipfile ) {
167
  Entries::const_iterator it ;
168
  ZipCDirEntry *ent ;
169
  int inconsistencies = 0 ;
170
  ZipLocalEntry zlh ;
171
  for ( it = _entries.begin() ; it != _entries.end() ; it++ ) {
172
    ent = static_cast< ZipCDirEntry * >( (*it).get()  ) ;
173
    _vs.vseekg( _zipfile, ent->getLocalHeaderOffset(), ios::beg ) ;
174
    _zipfile >> zlh ;
175
    if ( ! _zipfile || zlh != *ent ) {
176
      inconsistencies++ ;
177
      _zipfile.clear() ;
178
    }
179
  }
180
  return ! inconsistencies ;
181
}
182

183
void ZipFile::setError ( string error_str ) {
184
  _valid = false ;
185
#ifdef _USE_EXCEPTIONS
186
    throw  error_str ; // define exception class instead.
187
#else
188
    cerr << error_str << endl ; // define operator<< for exception class if such a class replaces string
189
#endif
190
}
191

192

193
}
194

195
/** \file
196
    The implementation of ZipFile.
197
*/
198

199
/*
200
  Zipios++ - a small C++ library that provides easy access to .zip files.
201
  Copyright (C) 2000  Thomas Søndergaard
202
  
203
  This library is free software; you can redistribute it and/or
204
  modify it under the terms of the GNU Lesser General Public
205
  License as published by the Free Software Foundation; either
206
  version 2 of the License, or (at your option) any later version.
207
  
208
  This library is distributed in the hope that it will be useful,
209
  but WITHOUT ANY WARRANTY; without even the implied warranty of
210
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
211
  Lesser General Public License for more details.
212
  
213
  You should have received a copy of the GNU Lesser General Public
214
  License along with this library; if not, write to the Free Software
215
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
216
*/
217

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.