bool ZipArchive::copyFileToNewZip(CentralDir *cdir, Stream *newZipStream) { // [tom, 1/24/2007] Using the stored compressor allows us to copy the raw // data regardless of compression method without having to re-compress it. Compressor *comp = Compressor::findCompressor(Stored); if(comp == NULL) return false; if(! mStream->setPosition(cdir->mLocalHeadOffset)) return false; // Copy file header // FIXME [tom, 1/24/2007] This will currently not copy the extra fields FileHeader fh; if(! fh.read(mStream)) return false; cdir->mLocalHeadOffset = newZipStream->getPosition(); if(! fh.write(newZipStream)) return false; // Copy file data Stream *readS = comp->createReadStream(cdir, mStream); if(readS == NULL) return false; bool ret = newZipStream->copyFrom(readS); // [tom, 1/24/2007] closeFile() just frees the relevant filters and // thus it is safe to call from here. closeFile(readS); return ret; }
Stream *ZipArchive::openFileForRead(const CentralDir *fileCD) { if(mMode != Read && mMode != ReadWrite) return NULL; if((fileCD->mInternalFlags & (CDFileDeleted | CDFileOpen)) != 0) return NULL; Stream *stream = mStream; if(fileCD->mInternalFlags & CDFileDirty) { // File is dirty, we need to read from the temporary file for(S32 i = 0;i < mTempFiles.size();++i) { if(mTempFiles[i]->getCentralDir() == fileCD) { // Found the temporary file if(! mTempFiles[i]->rewind()) { if(isVerbose()) Con::errorf("ZipArchive::openFile - %s: %s is dirty, but could not rewind temporary file?", mFilename ? mFilename : "<no filename>", fileCD->mFilename.c_str()); return NULL; } stream = mTempFiles[i]; break; } } if(stream == mStream) { if(isVerbose()) Con::errorf("ZipArchive::openFile - %s: %s is dirty, but no temporary file found?", mFilename ? mFilename : "<no filename>", fileCD->mFilename.c_str()); return NULL; } } else { // Read from the zip file directly if(! mStream->setPosition(fileCD->mLocalHeadOffset)) { if(isVerbose()) Con::errorf("ZipArchive::openFile - %s: Could not locate local header for file %s", mFilename ? mFilename : "<no filename>", fileCD->mFilename.c_str()); return NULL; } FileHeader fh; if(! fh.read(mStream)) { if(isVerbose()) Con::errorf("ZipArchive::openFile - %s: Could not read local header for file %s", mFilename ? mFilename : "<no filename>", fileCD->mFilename.c_str()); return NULL; } } Stream *attachTo = stream; U16 compMethod = fileCD->mCompressMethod; if(fileCD->mFlags & Encrypted) { if(fileCD->mCompressMethod == AESEncrypted) { // [tom, 1/19/2007] Whilst AES support does exist, I'm not including it in TGB // to avoid having to deal with crypto export legal issues. Con::errorf("ZipArchive::openFile - %s: File %s is AES encrypted, but AES is not supported in this version.", mFilename ? mFilename : "<no filename>", fileCD->mFilename.c_str()); } else { ZipCryptRStream *cryptStream = new ZipCryptRStream; cryptStream->setPassword(DEFAULT_ZIP_PASSWORD); cryptStream->setFileEndPos(stream->getPosition() + fileCD->mCompressedSize); if(! cryptStream->attachStream(stream)) { delete cryptStream; return NULL; } attachTo = cryptStream; } } Compressor *comp = Compressor::findCompressor(compMethod); if(comp == NULL) { if(isVerbose()) Con::errorf("ZipArchive::openFile - %s: Unsupported compression method (%d) for file %s", mFilename ? mFilename : "<no filename>", fileCD->mCompressMethod, fileCD->mFilename.c_str()); return NULL; } return comp->createReadStream(fileCD, attachTo); }