FIFE  6e1afdbeda11afe9ac53e6023a4be96ef88f1dc6
zipsource.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2005-2017 by the FIFE team *
3  * http://www.fifengine.net *
4  * This file is part of FIFE. *
5  * *
6  * FIFE is free software; you can redistribute it and/or *
7  * modify it under the terms of the GNU Lesser General Public *
8  * License as published by the Free Software Foundation; either *
9  * version 2.1 of the License, or (at your option) any later version. *
10  * *
11  * This library is distributed in the hope that it will be useful, *
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
14  * Lesser General Public License for more details. *
15  * *
16  * You should have received a copy of the GNU Lesser General Public *
17  * License along with this library; if not, write to the *
18  * Free Software Foundation, Inc., *
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
20  ***************************************************************************/
21 
22 // Standard C++ library includes
23 #include <algorithm>
24 #include <list>
25 
26 // 3rd party library includes
27 #include "zlib.h"
28 #include <boost/scoped_array.hpp>
29 
30 // FIFE includes
31 // These includes are split up in two parts, separated by one empty line
32 // First block: files included from the FIFE root src directory
33 // Second block: files included from the same folder
34 #include "vfs/raw/rawdata.h"
36 #include "util/base/exception.h"
37 #include "util/log/logger.h"
38 
39 #include "zipsource.h"
40 #include "zipfilesource.h"
41 #include "zipnode.h"
42 
43 namespace FIFE {
44 
45  static const uint32_t LF_HEADER = 0x04034b50;
46  static const uint32_t DE_HEADER = 0x08064b50;
47  static const uint32_t CF_HEADER = 0x02014b50;
48 
49  static Logger _log(LM_LOADERS);
50 
51  ZipSource::ZipSource(VFS* vfs, const std::string& zip_file) : VFSSource(vfs), m_zipfile(vfs->open(zip_file)) {
52  readIndex();
53  }
54 
56  delete m_zipfile;
57  }
58 
59  bool ZipSource::fileExists(const std::string& file) const {
60  bfs::path path(file);
61  return (m_zipTree.getNode(path.string()) != 0);
62  }
63 
64  RawData* ZipSource::open(const std::string& path) const {
65  bfs::path filePath(path);
66  ZipNode* node = m_zipTree.getNode(filePath.string());
67 
68  assert(node != 0);
69 
70  if (node) {
71  const ZipEntryData& entryData = node->getZipEntryData();
72 
73  m_zipfile->setIndex(entryData.offset);
74  uint8_t* data = new uint8_t[entryData.size_real]; // beware of me - one day i WILL cause memory leaks
75  if (entryData.comp == 8) { // compressed using deflate
76  FL_DBG(_log, LMsg("trying to uncompress file ") << path << " (compressed with method " << entryData.comp << ")");
77  boost::scoped_array<uint8_t> compdata(new uint8_t[entryData.size_comp]);
78  m_zipfile->readInto(compdata.get(), entryData.size_comp);
79 
80  z_stream zstream;
81  zstream.next_in = compdata.get();
82  zstream.avail_in = entryData.size_comp;
83  zstream.zalloc = Z_NULL;
84  zstream.zfree = Z_NULL;
85  zstream.opaque = Z_NULL;
86  zstream.next_out = data;
87  zstream.avail_out = entryData.size_real;
88 
89  if (inflateInit2(&zstream, -15) != Z_OK) {
90  FL_ERR(_log, LMsg("inflateInit2 failed"));
91  delete[] data;
92  return 0;
93  }
94 
95  int32_t err = inflate(&zstream, Z_FINISH);
96  if (err != Z_STREAM_END) {
97  if (zstream.msg) {
98  FL_ERR(_log, LMsg("inflate failed: ") << zstream.msg);
99  } else {
100  FL_ERR(_log, LMsg("inflate failed without msg, err: ") << err);
101  }
102 
103  inflateEnd(&zstream);
104  delete[] data;
105  return 0;
106  }
107 
108  inflateEnd(&zstream);
109  } else if (entryData.comp == 0) { // uncompressed
110  m_zipfile->readInto(data, entryData.size_real);
111  } else {
112  FL_ERR(_log, LMsg("unsupported compression"));
113  delete[] data;
114  return 0;
115  }
116 
117  return new RawData(new ZipFileSource(data, entryData.size_real));
118  }
119 
120  return 0;
121  }
122 
124  m_zipfile->setIndex(0);
125 
126  while (!readFileToIndex()) {}
127  }
128 
130  uint32_t header = m_zipfile->read32Little();
131  if (header == DE_HEADER || header == CF_HEADER) { // decryption header or central directory header - we are finished
132  return true;
133  }
134 
135  uint16_t vneeded = m_zipfile->read16Little();
136  uint16_t gflags = m_zipfile->read16Little();
137  uint16_t comp = m_zipfile->read16Little();
138  uint16_t lmodtime = m_zipfile->read16Little();
139  uint16_t lmoddate = m_zipfile->read16Little();
141  uint32_t compsize = m_zipfile->read32Little();
142  uint32_t realsize = m_zipfile->read32Little();
143  uint16_t fnamelen = m_zipfile->read16Little();
144  uint16_t extralen = m_zipfile->read16Little();
145 
146  if (header != LF_HEADER) {
147  FL_ERR(_log, LMsg("invalid local file header: ") << header);
148  return true;
149  }
150 
151  if (vneeded > 20) {
152  FL_ERR(_log, LMsg("only zip version 2 is supported, required: ") << vneeded);
153  return true;
154  }
155 
156  bfs::path filePath = bfs::path(m_zipfile->readString(fnamelen));
157 
158  m_zipfile->moveIndex(extralen);
159  uint32_t offset = m_zipfile->getCurrentIndex();
160  FL_DBG(_log, LMsg("found file: ") << filePath.string() << " (" << compsize << "/" << realsize << ") on offset " << offset);
161 
162  m_zipfile->moveIndex(compsize);
163  if (gflags & (0x01 << 3)) {
164  crc = m_zipfile->read32Little();
165  compsize = m_zipfile->read32Little();
166  realsize = m_zipfile->read32Little();
167  }
168 
169  if (lmodtime || lmoddate) {} // shut up the compiler (warnings of unused variables)
170 
171  ZipEntryData data;
172  data.comp = comp;
173  data.size_real = realsize;
174  data.size_comp = compsize;
175  data.offset = offset;
176  data.crc32 = crc;
177 
178  std::string filename = filePath.string();
179  ZipNode* node = m_zipTree.addNode(filename);
180 
181  if (node) {
182  // store the zip entry information in the node
183  node->setZipEntryData(data);
184  }
185 
186  return false;
187  }
188 
189 
190  std::set<std::string> ZipSource::listFiles(const std::string& path) const {
191  std::set<std::string> result;
192 
193  bfs::path fixedPath(path);
194 
195  ZipNode* node = m_zipTree.getNode(fixedPath.string());
196 
197  if (node) {
199  ZipNodeContainer::iterator iter;
200  for (iter = files.begin(); iter != files.end(); ++iter) {
201  result.insert((*iter)->getFullName());
202  }
203  }
204 
205  return result;
206  }
207 
208  // FIXME: quick&very dirty..
209  std::set<std::string> ZipSource::listDirectories(const std::string& path) const {
210  std::set<std::string> result;
211 
212  bfs::path fixedPath(path);
213 
214  ZipNode* node = m_zipTree.getNode(fixedPath.string());
215 
216  if (node) {
218  ZipNodeContainer::iterator iter;
219  for (iter = files.begin(); iter != files.end(); ++iter) {
220  result.insert((*iter)->getFullName());
221  }
222  }
223 
224  return result;
225  }
226 }
static const uint32_t CF_HEADER
Definition: zipsource.cpp:47
uint32_t size_real
Definition: zipnode.h:56
std::vector< ZipNode * > ZipNodeContainer
Definition: zipnode.h:61
void moveIndex(int32_t offset)
move the current index
Definition: rawdata.cpp:90
uint32_t crc32
Definition: zipnode.h:54
std::set< std::string > listFiles(const std::string &path) const
list all files in a directory of this source
Definition: zipsource.cpp:190
Helper class to create log strings out from separate parts Usage: LMsg("some text") << variable << "...
Definition: logger.h:82
bool fileExists(const std::string &file) const
WARNING: fileExists, listFiles and listDirectories are not.
Definition: zipsource.cpp:59
VFSSource abstract baseclass.
Definition: vfssource.h:46
std::vector< ZipNode * > getChildren(ZipContentType::Enum contentType=ZipContentType::All) const
gives access to retrieve the children of this node
Definition: zipnode.cpp:122
bool readFileToIndex()
Definition: zipsource.cpp:129
ZipNode * addNode(const std::string &nodePath)
adds a node to the proper place in the tree based on the node path name
Definition: ziptree.cpp:48
ZipSource(VFS *vfs, const std::string &zip_file)
Definition: zipsource.cpp:51
uint32_t size_comp
Definition: zipnode.h:55
static Logger _log(LM_AUDIO)
RawData * m_zipfile
Definition: zipsource.h:66
ZipTree m_zipTree
Definition: zipsource.h:65
ZipNode * getNode(const std::string &name) const
accessor for getting a node by name
Definition: ziptree.cpp:91
Definition: zipnode.h:48
#define FL_ERR(logger, msg)
Definition: logger.h:73
uint32_t getCurrentIndex() const
get the current index
Definition: rawdata.cpp:79
unsigned char uint8_t
Definition: core.h:38
uint16_t comp
Definition: zipnode.h:53
uint32_t offset
Definition: zipnode.h:57
unsigned short uint16_t
Definition: core.h:39
virtual RawData * open(const std::string &path) const
open a file inside this source
Definition: zipsource.cpp:64
std::string readString(size_t len)
read a string with len bytes, not assuming a terminating 0 Appends a null terminator character to the...
Definition: rawdata.cpp:128
uint32_t read32Little()
reads a uint16_t littleEndian and converts them to the host-byteorder
Definition: rawdata.cpp:113
void readInto(uint8_t *buffer, size_t len)
read len bytes into buffer
Definition: rawdata.cpp:94
the main VFS (virtual file system) class
Definition: vfs.h:58
void setZipEntryData(const ZipEntryData &entryData)
sets the zip file entry information for this node in the zip archive
Definition: zipnode.cpp:240
uint16_t read16Little()
reads a uint16_t littleEndian and converts them to the host-byteorder
Definition: rawdata.cpp:108
void setIndex(uint32_t index)
set the current index
Definition: rawdata.cpp:83
static const uint32_t DE_HEADER
Definition: zipsource.cpp:46
Create a Logger instance to communicate with LogManager Logger stores information about the current m...
Definition: logger.h:211
unsigned int uint32_t
Definition: core.h:40
std::set< std::string > listDirectories(const std::string &path) const
list all directories in a directory of this source
Definition: zipsource.cpp:209
const ZipEntryData & getZipEntryData() const
accessor for the entry data associated with this node in the zip archive
Definition: zipnode.cpp:245
#define FL_DBG(logger, msg)
Definition: logger.h:70
static const uint32_t LF_HEADER
Definition: zipsource.cpp:45
Used to access diffrent kinds of data.
Definition: rawdata.h:48