28 #include <boost/scoped_array.hpp>
34 #include "util/base/exception.h"
35 #include "vfs/raw/rawdata.h"
36 #include "util/log/logger.h"
38 #include "zipsource.h"
39 #include "zipfilesource.h"
43 static const uint32_t LF_HEADER = 0x04034b50;
44 static const uint32_t DE_HEADER = 0x08064b50;
45 static const uint32_t CF_HEADER = 0x02014b50;
47 static Logger _log(LM_LOADERS);
49 ZipSource::ZipSource(VFS* vfs,
const std::string& zip_file) : VFSSource(vfs), m_zipfile(vfs->open(zip_file)) {
53 ZipSource::~ZipSource() {
58 return m_files.find(file) != m_files.end();
62 type_files::const_iterator i = m_files.find(path);
63 assert(i != m_files.end());
64 const s_data& info = i->second;
67 uint8_t* data =
new uint8_t[info.size_real];
69 FL_DBG(_log,
LMsg(
"trying to uncompress file ") << path <<
" (compressed with method " << info.comp <<
")");
70 boost::scoped_array<uint8_t> compdata(
new uint8_t[info.size_comp]);
71 m_zipfile->
readInto(compdata.get(), info.size_comp);
74 zstream.next_in = compdata.get();
75 zstream.avail_in = info.size_comp;
76 zstream.zalloc = Z_NULL;
77 zstream.zfree = Z_NULL;
78 zstream.opaque = Z_NULL;
79 zstream.next_out = data;
80 zstream.avail_out = info.size_real;
82 if (inflateInit2(&zstream, -15) != Z_OK) {
83 FL_ERR(_log,
LMsg(
"inflateInit2 failed"));
88 int err = inflate(&zstream, Z_FINISH);
89 if (err != Z_STREAM_END) {
91 FL_ERR(_log,
LMsg(
"inflate failed: ") << zstream.msg);
93 FL_ERR(_log,
LMsg(
"inflate failed without msg, err: ") << err);
101 inflateEnd(&zstream);
102 }
else if (info.comp == 0) {
103 m_zipfile->
readInto(data, info.size_real);
105 FL_ERR(_log,
LMsg(
"unsupported compression"));
109 return new RawData(
new ZipFileSource(data, info.size_real));
112 void ZipSource::readIndex() {
116 while (!readFileToIndex()) {}
119 bool ZipSource::readFileToIndex() {
121 if (header == DE_HEADER || header == CF_HEADER) {
136 if (header != LF_HEADER) {
137 FL_ERR(_log, LMsg(
"invalid local file header: ") << header);
142 FL_ERR(_log, LMsg(
"only zip version 2 is supported, required: ") << vneeded);
146 std::string filename = m_zipfile->
readString(fnamelen);
149 FL_DBG(_log, LMsg(
"found file: ") << filename <<
" (" << compsize <<
"/" << realsize <<
") on offset " << offset);
152 if (gflags & (0x01 << 3)) {
158 if (lmodtime || lmoddate) {}
162 data.size_real = realsize;
163 data.size_comp = compsize;
164 data.offset = offset;
165 data.path = filename;
168 m_files[filename] = data;
175 std::set<std::string> result;
177 std::string fixedPath = fixPath(path);
178 int path_len = path.length();
179 if (fixedPath[path_len - 1] !=
'/') {
184 type_files::const_iterator end = m_files.end();
185 for (type_files::const_iterator i = m_files.begin(); i != end; ++i) {
186 std::string name = i->first;
187 int len = name.length();
188 if (len && name.find(fixedPath) == 0 && name[len - 1] !=
'/') {
189 name = name.substr(path_len);
190 size_t pos = name.find(
"/");
191 if (pos != std::string::npos)
203 std::set<std::string> result;
205 std::string fixedPath = fixPath(path);
206 int path_len = path.length();
207 if (fixedPath[path_len - 1] !=
'/') {
212 type_files::const_iterator end = m_files.end();
213 for (type_files::const_iterator i = m_files.begin(); i != end; ++i) {
214 std::string name = i->first;
215 int len = name.length();
216 if (len && name.find(fixedPath) == 0 && name[len - 1] ==
'/' && len > path_len) {
217 name = name.substr(path_len);
218 size_t pos = name.find(
"/");
219 if (pos != std::string::npos) {
220 name = name.substr(0, pos);