00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "pent_include.h"
00020
00021 #include "ZipFile.h"
00022 #include "IDataSource.h"
00023 #include "FileSystem.h"
00024
00025
00026 #include "unzip.h"
00027
00028 DEFINE_RUNTIME_CLASSTYPE_CODE(NamedArchiveFile,ArchiveFile)
00029
00030 DEFINE_RUNTIME_CLASSTYPE_CODE(ZipFile,NamedArchiveFile);
00031
00032
00033
00034
00035
00036 static voidpf ids_open(voidpf opaque, const char* filename, int mode);
00037 static uLong ids_read(voidpf opaque, voidpf stream, void* buf, uLong size);
00038 static uLong ids_write(voidpf opaque, voidpf stream,
00039 const void* buf, uLong size);
00040 static long ids_tell(voidpf opaque, voidpf stream);
00041 static long ids_seek(voidpf opaque, voidpf stream, uLong offset, int origin);
00042 static int ids_close(voidpf opaque, voidpf stream);
00043 static int ids_error(voidpf opaque, voidpf stream);
00044
00045 PentZip::zlib_filefunc_def IDS_filefunc_templ = {
00046 ids_open, ids_read, ids_write, ids_tell, ids_seek, ids_close, ids_error, 0
00047 };
00048
00049
00050 ZipFile::ZipFile(IDataSource* ds_)
00051 {
00052 ds = ds_;
00053 PentZip::zlib_filefunc_def filefuncs = IDS_filefunc_templ;
00054 filefuncs.opaque = static_cast<void*>(ds);
00055
00056
00057 PentZip::unzFile unzfile = PentZip::unzOpen2("", &filefuncs);
00058
00059 valid = (unzfile != 0);
00060
00061 unzipfile = static_cast<void*>(unzfile);
00062
00063 if (valid) {
00064 valid = readMetadata();
00065 if (!valid) PentZip::unzClose(unzfile);
00066 }
00067 }
00068
00069
00070 ZipFile::~ZipFile()
00071 {
00072 if (valid) {
00073 PentZip::unzFile unzfile = static_cast<PentZip::unzFile>(unzipfile);
00074 PentZip::unzClose(unzfile);
00075 }
00076 delete ds;
00077 }
00078
00079
00080 bool ZipFile::isZipFile(IDataSource* ids)
00081 {
00082 PentZip::zlib_filefunc_def filefuncs = IDS_filefunc_templ;
00083 filefuncs.opaque = static_cast<void*>(ids);
00084
00085
00086 PentZip::unzFile unzfile = PentZip::unzOpen2("", &filefuncs);
00087
00088 if (unzfile != 0) {
00089 PentZip::unzClose(unzfile);
00090 return true;
00091 }
00092
00093 return false;
00094 }
00095
00096 bool ZipFile::readMetadata()
00097 {
00098 PentZip::unzFile unzfile = static_cast<PentZip::unzFile>(unzipfile);
00099
00100 PentZip::unz_global_info ginfo;
00101 if (PentZip::unzGetGlobalInfo(unzfile, &ginfo) != UNZ_OK) return false;
00102
00103 count = ginfo.number_entry;
00104
00105 globalComment = "";
00106 if (ginfo.size_comment > 0) {
00107 char* commentbuf = new char[ginfo.size_comment+1];
00108 int c = PentZip::unzGetGlobalComment(unzfile,
00109 commentbuf, ginfo.size_comment+1);
00110 if (c > 0) globalComment = commentbuf;
00111 delete[] commentbuf;
00112 }
00113
00114 PentZip::unz_file_info info;
00115 char name[256];
00116
00117 bool done = (PentZip::unzGoToFirstFile(unzfile) != UNZ_OK);
00118
00119 while (!done) {
00120 int ret = PentZip::unzGetCurrentFileInfo(unzfile, &info, name, 256,
00121 0, 0, 0, 0);
00122 if (ret != UNZ_OK) continue;
00123
00124 std::string filename = name;
00125 storeIndexedName(filename);
00126 sizes[filename] = info.uncompressed_size;
00127
00128 done = (PentZip::unzGoToNextFile(unzfile) != UNZ_OK);
00129 }
00130
00131 return true;
00132 }
00133
00134 bool ZipFile::exists(const std::string& name)
00135 {
00136 std::map<std::string, uint32>::iterator iter;
00137 iter = sizes.find(name);
00138 return (iter != sizes.end());
00139 }
00140
00141 uint32 ZipFile::getSize(const std::string& name)
00142 {
00143 std::map<std::string, uint32>::iterator iter;
00144 iter = sizes.find(name);
00145 if (iter == sizes.end()) return 0;
00146 return (iter->second);
00147 }
00148
00149 uint8* ZipFile::getObject(const std::string& name, uint32* sizep)
00150 {
00151 PentZip::unzFile unzfile = static_cast<PentZip::unzFile>(unzipfile);
00152 if (sizep) *sizep = 0;
00153
00154 if (PentZip::unzLocateFile(unzfile, name.c_str(), 1) != UNZ_OK) return 0;
00155
00156 PentZip::unz_file_info info;
00157 uint8* buf = 0;
00158
00159 if (PentZip::unzGetCurrentFileInfo(unzfile, &info, 0, 0, 0, 0, 0, 0)
00160 != UNZ_OK)
00161 return 0;
00162
00163 if (PentZip::unzOpenCurrentFile(unzfile) != UNZ_OK) return 0;
00164 uint32 size = info.uncompressed_size;
00165
00166 buf = new uint8[size];
00167
00168 if (PentZip::unzReadCurrentFile(unzfile, buf, size) < size) {
00169 delete[] buf;
00170 return 0;
00171 }
00172
00173 if (PentZip::unzCloseCurrentFile(unzfile) != UNZ_OK) {
00174 delete[] buf;
00175 return 0;
00176 }
00177
00178 if (sizep) *sizep = size;
00179
00180 return buf;
00181 }
00182
00183
00184
00185
00186
00187 static voidpf ids_open(voidpf opaque, const char* filename, int mode)
00188 {
00189
00190 if (mode != (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_EXISTING))
00191 return 0;
00192
00193
00194 return opaque;
00195 }
00196
00197 static uLong ids_read(voidpf opaque, voidpf stream, void* buf, uLong size)
00198 {
00199 IDataSource* ids = static_cast<IDataSource*>(stream);
00200 return ids->read(buf, size);
00201 }
00202
00203 static uLong ids_write(voidpf opaque, voidpf stream,
00204 const void* buf, uLong size)
00205 {
00206 return 0;
00207 }
00208
00209 static long ids_tell(voidpf opaque, voidpf stream)
00210 {
00211 IDataSource* ids = static_cast<IDataSource*>(stream);
00212 return ids->getPos();
00213 }
00214
00215 static long ids_seek(voidpf opaque, voidpf stream, uLong offset, int origin)
00216 {
00217 IDataSource* ids = static_cast<IDataSource*>(stream);
00218 switch (origin) {
00219 case ZLIB_FILEFUNC_SEEK_CUR:
00220 ids->skip(offset);
00221 break;
00222 case ZLIB_FILEFUNC_SEEK_END:
00223 ids->seek(ids->getSize()+offset);
00224 break;
00225 case ZLIB_FILEFUNC_SEEK_SET:
00226 ids->seek(offset);
00227 break;
00228 default:
00229 return -1;
00230 }
00231 return 0;
00232 }
00233
00234 static int ids_close(voidpf opaque, voidpf stream)
00235 {
00236 return 0;
00237 }
00238
00239 static int ids_error(voidpf opaque, voidpf stream)
00240 {
00241 return 0;
00242 }
00243