static bool findzipdirectory(FILE *f, zipdirectoryheader &hdr) { if(fseek(f, 0, SEEK_END) < 0) return false; uchar buf[1024], *src = NULL; int len = 0, offset = ftell(f), end = max(offset - 0xFFFF - ZIP_DIRECTORY_SIZE, 0); const uint signature = lilswap<uint>(ZIP_DIRECTORY_SIGNATURE); while(offset > end) { int carry = min(len, ZIP_DIRECTORY_SIZE-1), next = min((int)sizeof(buf) - carry, offset - end); offset -= next; memmove(&buf[next], buf, carry); if(next + carry < ZIP_DIRECTORY_SIZE || fseek(f, offset, SEEK_SET) < 0 || (int)fread(buf, 1, next, f) != next) return false; len = next + carry; uchar *search = &buf[next-1]; for(; search >= buf; search--) if(*(uint *)search == signature) break; if(search >= buf) { src = search; break; } } if(&buf[len] - src < ZIP_DIRECTORY_SIZE) return false; hdr.signature = lilswap(*(uint *)src); src += 4; hdr.disknumber = lilswap(*(ushort *)src); src += 2; hdr.directorydisk = lilswap(*(ushort *)src); src += 2; hdr.diskentries = lilswap(*(ushort *)src); src += 2; hdr.entries = lilswap(*(ushort *)src); src += 2; hdr.size = lilswap(*(uint *)src); src += 4; hdr.offset = lilswap(*(uint *)src); src += 4; hdr.commentlength = lilswap(*(ushort *)src); src += 2; if(hdr.signature != ZIP_DIRECTORY_SIGNATURE || hdr.disknumber != hdr.directorydisk || hdr.diskentries != hdr.entries) return false; return true; }
char *getfiledesc(const char *dir, const char *name, const char *ext) { if(!browsefiledesc || !dir || !name || !ext) return NULL; defformatstring(fn)("%s/%s.%s", dir, name, ext); path(fn); string text; if(!strcmp(ext, "dmo")) { stream *f = opengzfile(fn, "rb"); if(!f) return NULL; demoheader hdr; if(f->read(&hdr, sizeof(demoheader))!=sizeof(demoheader) || memcmp(hdr.magic, DEMO_MAGIC, sizeof(hdr.magic))) { delete f; return NULL; } delete f; lilswap(&hdr.version, 1); lilswap(&hdr.protocol, 1); const char *tag = "(incompatible file) "; if(hdr.version == DEMO_VERSION) { if(hdr.protocol == PROTOCOL_VERSION) tag = ""; else if(hdr.protocol == -PROTOCOL_VERSION) tag = "(recorded on modded server) "; } formatstring(text)("%s%s", tag, hdr.desc); text[DHDR_DESCCHARS - 1] = '\0'; return newstring(text); } else if(!strcmp(ext, "cgz")) { stream *f = opengzfile(fn, "rb"); if(!f) return NULL; header hdr; if(f->read(&hdr, sizeof(header))!=sizeof(header) || (strncmp(hdr.head, "CUBE", 4) && strncmp(hdr.head, "ACMP",4) && strncmp(hdr.head, "ACRM",4))) { delete f; return NULL; } delete f; lilswap(&hdr.version, 1); // hdr.maprevision, hdr.maptitle ... hdr.version, hdr.headersize, formatstring(text)("%s%s", (hdr.version>MAPVERSION) ? "(incompatible file) " : "", hdr.maptitle); text[DHDR_DESCCHARS - 1] = '\0'; return newstring(text); } return NULL; }
static bool readlocalfileheader(FILE *f, ziplocalfileheader &h, uint offset) { uchar buf[ZIP_LOCAL_FILE_SIZE]; if(fseek(f, offset, SEEK_SET) < 0 || fread(buf, 1, ZIP_LOCAL_FILE_SIZE, f) != ZIP_LOCAL_FILE_SIZE) return false; uchar *src = buf; h.signature = lilswap(*(uint *)src); src += 4; h.version = lilswap(*(ushort *)src); src += 2; h.flags = lilswap(*(ushort *)src); src += 2; h.compression = lilswap(*(ushort *)src); src += 2; h.modtime = lilswap(*(ushort *)src); src += 2; h.moddate = lilswap(*(ushort *)src); src += 2; h.crc32 = lilswap(*(uint *)src); src += 4; h.compressedsize = lilswap(*(uint *)src); src += 4; h.uncompressedsize = lilswap(*(uint *)src); src += 4; h.namelength = lilswap(*(ushort *)src); src += 2; h.extralength = lilswap(*(ushort *)src); src += 2; if(h.signature != ZIP_LOCAL_FILE_SIGNATURE) return false; // h.uncompressedsize or h.compressedsize may be zero - so don't validate return true; }
static bool readzipdirectory(const char *archname, FILE *f, int entries, int offset, uint size, vector<zipfile> &files) { uchar *buf = new uchar[size], *src = buf; if(fseek(f, offset, SEEK_SET) < 0 || fread(buf, 1, size, f) != size) { delete[] buf; return false; } loopi(entries) { if(src + ZIP_FILE_SIZE > &buf[size]) break; zipfileheader hdr; hdr.signature = lilswap(*(uint *)src); src += 4; hdr.version = lilswap(*(ushort *)src); src += 2; hdr.needversion = lilswap(*(ushort *)src); src += 2; hdr.flags = lilswap(*(ushort *)src); src += 2; hdr.compression = lilswap(*(ushort *)src); src += 2; hdr.modtime = lilswap(*(ushort *)src); src += 2; hdr.moddate = lilswap(*(ushort *)src); src += 2; hdr.crc32 = lilswap(*(uint *)src); src += 4; hdr.compressedsize = lilswap(*(uint *)src); src += 4; hdr.uncompressedsize = lilswap(*(uint *)src); src += 4; hdr.namelength = lilswap(*(ushort *)src); src += 2; hdr.extralength = lilswap(*(ushort *)src); src += 2; hdr.commentlength = lilswap(*(ushort *)src); src += 2; hdr.disknumber = lilswap(*(ushort *)src); src += 2; hdr.internalattribs = lilswap(*(ushort *)src); src += 2; hdr.externalattribs = lilswap(*(uint *)src); src += 4; hdr.offset = lilswap(*(uint *)src); src += 4; if(hdr.signature != ZIP_FILE_SIGNATURE) break; if(!hdr.namelength || !hdr.uncompressedsize || (hdr.compression && (hdr.compression != Z_DEFLATED || !hdr.compressedsize))) { src += hdr.namelength + hdr.extralength + hdr.commentlength; continue; } if(src + hdr.namelength > &buf[size]) break; string pname; int namelen = min((int)hdr.namelength, (int)sizeof(pname)-1); memcpy(pname, src, namelen); pname[namelen] = '\0'; path(pname); char *name = newstring(pname); zipfile &f = files.add(); f.name = name; f.header = hdr.offset; f.size = hdr.uncompressedsize; f.compressedsize = hdr.compression ? hdr.compressedsize : 0; #ifndef STANDALONE if(dbgzip) conoutf(CON_DEBUG, "%s: file %s, size %d, compress %d, flags %x", archname, name, hdr.uncompressedsize, hdr.compression, hdr.flags); #endif src += hdr.namelength + hdr.extralength + hdr.commentlength; } delete[] buf; return files.length() > 0; }