/* void onDataAvailable (in nsIRequest aRequest, in nsISupports aContext, * in nsIInputStream aInputStream, * in unsigned long aOffset, in unsigned long aCount); */ NS_IMETHODIMP nsDeflateConverter::OnDataAvailable(nsIRequest *aRequest, nsISupports *aContext, nsIInputStream *aInputStream, PRUint32 aOffset, PRUint32 aCount) { if (!mListener) return NS_ERROR_NOT_INITIALIZED; nsAutoArrayPtr<char> buffer(new char[aCount]); NS_ENSURE_TRUE(buffer, NS_ERROR_OUT_OF_MEMORY); nsresult rv = ZW_ReadData(aInputStream, buffer.get(), aCount); NS_ENSURE_SUCCESS(rv, rv); // make sure we aren't reading too much mZstream.avail_in = aCount; mZstream.next_in = (unsigned char*)buffer.get(); int zerr = Z_OK; // deflate loop while (mZstream.avail_in > 0 && zerr == Z_OK) { zerr = deflate(&mZstream, Z_NO_FLUSH); while (mZstream.avail_out == 0) { // buffer is full, push the data out to the listener rv = PushAvailableData(aRequest, aContext); NS_ENSURE_SUCCESS(rv, rv); zerr = deflate(&mZstream, Z_NO_FLUSH); } } return NS_OK; }
/* void onDataAvailable (in nsIRequest aRequest, in nsISupports aContext, * in nsIInputStream aInputStream, * in unsigned long long aOffset, in unsigned long aCount); */ NS_IMETHODIMP nsZipDataStream::OnDataAvailable(nsIRequest *aRequest, nsISupports *aContext, nsIInputStream *aInputStream, uint64_t aOffset, uint32_t aCount) { if (!mOutput) return NS_ERROR_NOT_INITIALIZED; nsAutoArrayPtr<char> buffer(new char[aCount]); NS_ENSURE_TRUE(buffer, NS_ERROR_OUT_OF_MEMORY); nsresult rv = ZW_ReadData(aInputStream, buffer.get(), aCount); NS_ENSURE_SUCCESS(rv, rv); return ProcessData(aRequest, aContext, buffer.get(), aOffset, aCount); }
/* * Reads file entries out of an existing zip file. */ nsresult nsZipWriter::ReadFile(nsIFile *aFile) { int64_t size; nsresult rv = aFile->GetFileSize(&size); NS_ENSURE_SUCCESS(rv, rv); // If the file is too short, it cannot be a valid archive, thus we fail // without even attempting to open it NS_ENSURE_TRUE(size > ZIP_EOCDR_HEADER_SIZE, NS_ERROR_FILE_CORRUPTED); nsCOMPtr<nsIInputStream> inputStream; rv = NS_NewLocalFileInputStream(getter_AddRefs(inputStream), aFile); NS_ENSURE_SUCCESS(rv, rv); uint8_t buf[1024]; int64_t seek = size - 1024; uint32_t length = 1024; nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(inputStream); while (true) { if (seek < 0) { length += (int32_t)seek; seek = 0; } rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, seek); if (NS_FAILED(rv)) { inputStream->Close(); return rv; } rv = ZW_ReadData(inputStream, (char *)buf, length); if (NS_FAILED(rv)) { inputStream->Close(); return rv; } /* * We have to backtrack from the end of the file until we find the * CDS signature */ // We know it's at least this far from the end for (uint32_t pos = length - ZIP_EOCDR_HEADER_SIZE; (int32_t)pos >= 0; pos--) { uint32_t sig = PEEK32(buf + pos); if (sig == ZIP_EOCDR_HEADER_SIGNATURE) { // Skip down to entry count pos += 10; uint32_t entries = READ16(buf, &pos); // Skip past CDS size pos += 4; mCDSOffset = READ32(buf, &pos); uint32_t commentlen = READ16(buf, &pos); if (commentlen == 0) mComment.Truncate(); else if (pos + commentlen <= length) mComment.Assign((const char *)buf + pos, commentlen); else { if ((seek + pos + commentlen) > size) { inputStream->Close(); return NS_ERROR_FILE_CORRUPTED; } nsAutoArrayPtr<char> field(new char[commentlen]); NS_ENSURE_TRUE(field, NS_ERROR_OUT_OF_MEMORY); rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, seek + pos); if (NS_FAILED(rv)) { inputStream->Close(); return rv; } rv = ZW_ReadData(inputStream, field.get(), length); if (NS_FAILED(rv)) { inputStream->Close(); return rv; } mComment.Assign(field.get(), commentlen); } rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, mCDSOffset); if (NS_FAILED(rv)) { inputStream->Close(); return rv; } for (uint32_t entry = 0; entry < entries; entry++) { nsZipHeader* header = new nsZipHeader(); if (!header) { inputStream->Close(); mEntryHash.Clear(); mHeaders.Clear(); return NS_ERROR_OUT_OF_MEMORY; } rv = header->ReadCDSHeader(inputStream); if (NS_FAILED(rv)) { inputStream->Close(); mEntryHash.Clear(); mHeaders.Clear(); return rv; } mEntryHash.Put(header->mName, mHeaders.Count()); if (!mHeaders.AppendObject(header)) return NS_ERROR_OUT_OF_MEMORY; } return inputStream->Close(); } } if (seek == 0) { // We've reached the start with no signature found. Corrupt. inputStream->Close(); return NS_ERROR_FILE_CORRUPTED; } // Overlap by the size of the end of cdr seek -= (1024 - ZIP_EOCDR_HEADER_SIZE); } // Will never reach here in reality NS_NOTREACHED("Loop should never complete"); return NS_ERROR_UNEXPECTED; }
nsresult nsZipHeader::ReadCDSHeader(nsIInputStream *stream) { NS_ASSERTION(!mInited, "Already initalised"); PRUint8 buf[ZIP_CDS_HEADER_SIZE]; nsresult rv = ZW_ReadData(stream, (char *)buf, ZIP_CDS_HEADER_SIZE); NS_ENSURE_SUCCESS(rv, rv); PRUint32 pos = 0; PRUint32 signature = READ32(buf, &pos); if (signature != ZIP_CDS_HEADER_SIGNATURE) return NS_ERROR_FILE_CORRUPTED; mVersionMade = READ16(buf, &pos); mVersionNeeded = READ16(buf, &pos); mFlags = READ16(buf, &pos); mMethod = READ16(buf, &pos); mTime = READ16(buf, &pos); mDate = READ16(buf, &pos); mCRC = READ32(buf, &pos); mCSize = READ32(buf, &pos); mUSize = READ32(buf, &pos); PRUint16 namelength = READ16(buf, &pos); mFieldLength = READ16(buf, &pos); PRUint16 commentlength = READ16(buf, &pos); mDisk = READ16(buf, &pos); mIAttr = READ16(buf, &pos); mEAttr = READ32(buf, &pos); mOffset = READ32(buf, &pos); if (namelength > 0) { nsAutoArrayPtr<char> field(new char[namelength]); NS_ENSURE_TRUE(field, NS_ERROR_OUT_OF_MEMORY); rv = ZW_ReadData(stream, field.get(), namelength); NS_ENSURE_SUCCESS(rv, rv); mName.Assign(field, namelength); } else mName = NS_LITERAL_CSTRING(""); if (mFieldLength > 0) { mExtraField = new PRUint8[mFieldLength]; NS_ENSURE_TRUE(mExtraField, NS_ERROR_OUT_OF_MEMORY); rv = ZW_ReadData(stream, (char *)mExtraField.get(), mFieldLength); NS_ENSURE_SUCCESS(rv, rv); } if (commentlength > 0) { nsAutoArrayPtr<char> field(new char[commentlength]); NS_ENSURE_TRUE(field, NS_ERROR_OUT_OF_MEMORY); rv = ZW_ReadData(stream, field.get(), commentlength); NS_ENSURE_SUCCESS(rv, rv); mComment.Assign(field, commentlength); } else mComment = NS_LITERAL_CSTRING(""); mInited = PR_TRUE; return NS_OK; }