static unsigned char *read_zip_file(FILE *file, int offset, int *sizep) { int sig, method, csize, usize; int namelength, extralength; char *cdata, *udata; fseek(file, offset, 0); sig = getlong(file); if (sig != ZIP_LOCAL_FILE_SIG) { warn("zip: wrong signature for local file"); return NULL; } (void) getshort(file); /* version */ (void) getshort(file); /* general */ method = getshort(file); (void) getshort(file); /* file time */ (void) getshort(file); /* file date */ (void) getlong(file); /* crc-32 */ csize = getlong(file); /* csize */ usize = getlong(file); /* usize */ namelength = getshort(file); extralength = getshort(file); fseek(file, namelength + extralength, 1); if (method == 0 && csize == usize) { cdata = malloc(csize); fread(cdata, 1, csize, file); *sizep = csize; return (unsigned char*) cdata; } if (method == 8) { cdata = malloc(csize); fread(cdata, 1, csize, file); udata = malloc(usize); usize = stbi_zlib_decode_noheader_buffer(udata, usize, cdata, csize); free(cdata); if (usize < 0) { warn("zip: %s", stbi_failure_reason()); return NULL; } *sizep = usize; return (unsigned char*) udata; } warn("zip: unknown compression method"); return NULL; }
OOBase::SharedPtr<const char> Indigo::detail::ZipFile::load(const OOBase::String& prefix, const char* name) { OOBase::SharedPtr<const char> ret; OOBase::String filename(prefix); if (!filename.append(name)) LOG_ERROR_RETURN(("Failed to append string: %s",OOBase::system_error_text()),ret); OOBase::Table<OOBase::String,Info>::iterator i=m_mapFiles.find(filename); if (!i) return ret; // Read the local file header if (m_file.seek(i->second.m_offset,OOBase::File::seek_begin) == OOBase::uint64_t(-1)) LOG_ERROR_RETURN(("Failed to get seek in file: %s",OOBase::system_error_text()),ret); OOBase::uint8_t header[30]; if (m_file.read(header,30) != 30) LOG_ERROR_RETURN(("Failed to read local file header header in zip"),ret); static const OOBase::uint8_t LFR_HEADER[4] = { 0x50, 0x4b, 0x03, 0x04 }; if (memcmp(header,LFR_HEADER,4) != 0) LOG_ERROR_RETURN(("Invalid local file header header in zip"),ret); OOBase::uint16_t compression = read_uint16(header,8); OOBase::uint32_t compressed_size = read_uint32(header,18); size_t offset = 30 + read_uint16(header,26) + read_uint16(header,28); OOBase::SharedPtr<const char> mapping = m_file.auto_map<const char>(false,i->second.m_offset + offset,compressed_size); if (!mapping) LOG_ERROR_RETURN(("Failed to map file content: %s",OOBase::system_error_text()),ret); if (compression == 0) { ret = mapping; } else if (compression == 8) { void* p = OOBase::CrtAllocator::allocate(i->second.m_length,1); if (!p) LOG_ERROR_RETURN(("Failed to allocate: %s",OOBase::system_error_text()),ret); if (stbi_zlib_decode_noheader_buffer(static_cast<char*>(p),(int)i->second.m_length,mapping.get(),(int)compressed_size) == -1) { LOG_ERROR(("Failed to inflate file: %s",stbi_failure_reason())); OOBase::CrtAllocator::free(p); } else { ret = OOBase::const_pointer_cast<const char>(OOBase::make_shared<char>(static_cast<char*>(p))); if (!ret) { LOG_ERROR(("Failed to allocate: %s",OOBase::system_error_text())); OOBase::CrtAllocator::free(p); } } } else LOG_ERROR(("Unsupported zip compression method: %u",compression)); return ret; }