28 #include <boost/scoped_array.hpp>
34 #include "vfs/raw/rawdata.h"
35 #include "vfs/fife_boost_filesystem.h"
36 #include "util/base/exception.h"
37 #include "util/log/logger.h"
39 #include "zipsource.h"
40 #include "zipfilesource.h"
45 static const uint32_t LF_HEADER = 0x04034b50;
46 static const uint32_t DE_HEADER = 0x08064b50;
47 static const uint32_t CF_HEADER = 0x02014b50;
49 static Logger _log(LM_LOADERS);
51 ZipSource::ZipSource(VFS* vfs,
const std::string& zip_file) : VFSSource(vfs), m_zipfile(vfs->open(zip_file)) {
55 ZipSource::~ZipSource() {
61 return (m_zipTree.getNode(path.string()) != 0);
65 bfs::path filePath(path);
66 ZipNode* node = m_zipTree.getNode(filePath.string());
71 const ZipEntryData& entryData = node->getZipEntryData();
73 m_zipfile->
setIndex(entryData.offset);
74 uint8_t* data =
new uint8_t[entryData.size_real];
75 if (entryData.comp == 8) {
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);
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;
89 if (inflateInit2(&zstream, -15) != Z_OK) {
90 FL_ERR(_log,
LMsg(
"inflateInit2 failed"));
95 int32_t err = inflate(&zstream, Z_FINISH);
96 if (err != Z_STREAM_END) {
98 FL_ERR(_log,
LMsg(
"inflate failed: ") << zstream.msg);
100 FL_ERR(_log,
LMsg(
"inflate failed without msg, err: ") << err);
103 inflateEnd(&zstream);
108 inflateEnd(&zstream);
109 }
else if (entryData.comp == 0) {
110 m_zipfile->
readInto(data, entryData.size_real);
112 FL_ERR(_log,
LMsg(
"unsupported compression"));
116 return new RawData(
new ZipFileSource(data, entryData.size_real));
122 void ZipSource::readIndex() {
125 while (!readFileToIndex()) {}
128 bool ZipSource::readFileToIndex() {
130 if (header == DE_HEADER || header == CF_HEADER) {
145 if (header != LF_HEADER) {
146 FL_ERR(_log, LMsg(
"invalid local file header: ") << header);
151 FL_ERR(_log, LMsg(
"only zip version 2 is supported, required: ") << vneeded);
155 bfs::path filePath = bfs::path(m_zipfile->
readString(fnamelen));
159 FL_DBG(_log, LMsg(
"found file: ") << filePath.string() <<
" (" << compsize <<
"/" << realsize <<
") on offset " << offset);
162 if (gflags & (0x01 << 3)) {
168 if (lmodtime || lmoddate) {}
172 data.size_real = realsize;
173 data.size_comp = compsize;
174 data.offset = offset;
177 std::string filename = filePath.string();
178 ZipNode* node = m_zipTree.addNode(filename);
182 node->setZipEntryData(data);
190 std::set<std::string> result;
192 bfs::path fixedPath(path);
194 ZipNode* node = m_zipTree.getNode(fixedPath.string());
197 ZipNodeContainer files = node->getChildren(ZipContentType::File);
198 ZipNodeContainer::iterator iter;
199 for (iter = files.begin(); iter != files.end(); ++iter) {
200 result.insert((*iter)->getFullName());
209 std::set<std::string> result;
211 bfs::path fixedPath(path);
213 ZipNode* node = m_zipTree.getNode(fixedPath.string());
216 ZipNodeContainer files = node->getChildren(ZipContentType::Directory);
217 ZipNodeContainer::iterator iter;
218 for (iter = files.begin(); iter != files.end(); ++iter) {
219 result.insert((*iter)->getFullName());