1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/modules/libjar/zipwriter/src/nsZipDataStream.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,185 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. 1.7 + */ 1.8 + 1.9 +#include "StreamFunctions.h" 1.10 +#include "nsZipDataStream.h" 1.11 +#include "nsIStringStream.h" 1.12 +#include "nsISeekableStream.h" 1.13 +#include "nsDeflateConverter.h" 1.14 +#include "nsNetUtil.h" 1.15 +#include "nsComponentManagerUtils.h" 1.16 +#include "nsMemory.h" 1.17 + 1.18 +#define ZIP_METHOD_STORE 0 1.19 +#define ZIP_METHOD_DEFLATE 8 1.20 + 1.21 +/** 1.22 + * nsZipDataStream handles the writing an entry's into the zip file. 1.23 + * It is set up to wither write the data as is, or in the event that compression 1.24 + * has been requested to pass it through a stream converter. 1.25 + * Currently only the deflate compression method is supported. 1.26 + * The CRC checksum for the entry's data is also generated here. 1.27 + */ 1.28 +NS_IMPL_ISUPPORTS(nsZipDataStream, nsIStreamListener, 1.29 + nsIRequestObserver) 1.30 + 1.31 +nsresult nsZipDataStream::Init(nsZipWriter *aWriter, 1.32 + nsIOutputStream *aStream, 1.33 + nsZipHeader *aHeader, 1.34 + int32_t aCompression) 1.35 +{ 1.36 + mWriter = aWriter; 1.37 + mHeader = aHeader; 1.38 + mStream = aStream; 1.39 + mHeader->mCRC = crc32(0L, Z_NULL, 0); 1.40 + 1.41 + nsresult rv = NS_NewSimpleStreamListener(getter_AddRefs(mOutput), aStream, 1.42 + nullptr); 1.43 + NS_ENSURE_SUCCESS(rv, rv); 1.44 + 1.45 + if (aCompression > 0) { 1.46 + mHeader->mMethod = ZIP_METHOD_DEFLATE; 1.47 + nsCOMPtr<nsIStreamConverter> converter = 1.48 + new nsDeflateConverter(aCompression); 1.49 + NS_ENSURE_TRUE(converter, NS_ERROR_OUT_OF_MEMORY); 1.50 + 1.51 + rv = converter->AsyncConvertData("uncompressed", "rawdeflate", mOutput, 1.52 + nullptr); 1.53 + NS_ENSURE_SUCCESS(rv, rv); 1.54 + 1.55 + mOutput = do_QueryInterface(converter, &rv); 1.56 + NS_ENSURE_SUCCESS(rv, rv); 1.57 + } 1.58 + else { 1.59 + mHeader->mMethod = ZIP_METHOD_STORE; 1.60 + } 1.61 + 1.62 + return NS_OK; 1.63 +} 1.64 + 1.65 +/* void onDataAvailable (in nsIRequest aRequest, in nsISupports aContext, 1.66 + * in nsIInputStream aInputStream, 1.67 + * in unsigned long long aOffset, in unsigned long aCount); */ 1.68 +NS_IMETHODIMP nsZipDataStream::OnDataAvailable(nsIRequest *aRequest, 1.69 + nsISupports *aContext, 1.70 + nsIInputStream *aInputStream, 1.71 + uint64_t aOffset, 1.72 + uint32_t aCount) 1.73 +{ 1.74 + if (!mOutput) 1.75 + return NS_ERROR_NOT_INITIALIZED; 1.76 + 1.77 + nsAutoArrayPtr<char> buffer(new char[aCount]); 1.78 + NS_ENSURE_TRUE(buffer, NS_ERROR_OUT_OF_MEMORY); 1.79 + 1.80 + nsresult rv = ZW_ReadData(aInputStream, buffer.get(), aCount); 1.81 + NS_ENSURE_SUCCESS(rv, rv); 1.82 + 1.83 + return ProcessData(aRequest, aContext, buffer.get(), aOffset, aCount); 1.84 +} 1.85 + 1.86 +/* void onStartRequest (in nsIRequest aRequest, in nsISupports aContext); */ 1.87 +NS_IMETHODIMP nsZipDataStream::OnStartRequest(nsIRequest *aRequest, 1.88 + nsISupports *aContext) 1.89 +{ 1.90 + if (!mOutput) 1.91 + return NS_ERROR_NOT_INITIALIZED; 1.92 + 1.93 + return mOutput->OnStartRequest(aRequest, aContext); 1.94 +} 1.95 + 1.96 +/* void onStopRequest (in nsIRequest aRequest, in nsISupports aContext, 1.97 + * in nsresult aStatusCode); */ 1.98 +NS_IMETHODIMP nsZipDataStream::OnStopRequest(nsIRequest *aRequest, 1.99 + nsISupports *aContext, 1.100 + nsresult aStatusCode) 1.101 +{ 1.102 + if (!mOutput) 1.103 + return NS_ERROR_NOT_INITIALIZED; 1.104 + 1.105 + nsresult rv = mOutput->OnStopRequest(aRequest, aContext, aStatusCode); 1.106 + mOutput = nullptr; 1.107 + if (NS_FAILED(rv)) { 1.108 + mWriter->EntryCompleteCallback(mHeader, rv); 1.109 + } 1.110 + else { 1.111 + rv = CompleteEntry(); 1.112 + rv = mWriter->EntryCompleteCallback(mHeader, rv); 1.113 + } 1.114 + 1.115 + mStream = nullptr; 1.116 + mWriter = nullptr; 1.117 + mHeader = nullptr; 1.118 + 1.119 + return rv; 1.120 +} 1.121 + 1.122 +inline nsresult nsZipDataStream::CompleteEntry() 1.123 +{ 1.124 + nsresult rv; 1.125 + nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(mStream, &rv); 1.126 + NS_ENSURE_SUCCESS(rv, rv); 1.127 + int64_t pos; 1.128 + rv = seekable->Tell(&pos); 1.129 + NS_ENSURE_SUCCESS(rv, rv); 1.130 + 1.131 + mHeader->mCSize = pos - mHeader->mOffset - mHeader->GetFileHeaderLength(); 1.132 + mHeader->mWriteOnClose = true; 1.133 + return NS_OK; 1.134 +} 1.135 + 1.136 +nsresult nsZipDataStream::ProcessData(nsIRequest *aRequest, 1.137 + nsISupports *aContext, char *aBuffer, 1.138 + uint64_t aOffset, uint32_t aCount) 1.139 +{ 1.140 + mHeader->mCRC = crc32(mHeader->mCRC, 1.141 + reinterpret_cast<const unsigned char*>(aBuffer), 1.142 + aCount); 1.143 + 1.144 + nsresult rv; 1.145 + nsCOMPtr<nsIStringInputStream> stream = 1.146 + do_CreateInstance("@mozilla.org/io/string-input-stream;1", &rv); 1.147 + NS_ENSURE_SUCCESS(rv, rv); 1.148 + 1.149 + stream->ShareData(aBuffer, aCount); 1.150 + rv = mOutput->OnDataAvailable(aRequest, aContext, stream, aOffset, aCount); 1.151 + mHeader->mUSize += aCount; 1.152 + 1.153 + return rv; 1.154 +} 1.155 + 1.156 +nsresult nsZipDataStream::ReadStream(nsIInputStream *aStream) 1.157 +{ 1.158 + if (!mOutput) 1.159 + return NS_ERROR_NOT_INITIALIZED; 1.160 + 1.161 + nsresult rv = OnStartRequest(nullptr, nullptr); 1.162 + NS_ENSURE_SUCCESS(rv, rv); 1.163 + 1.164 + nsAutoArrayPtr<char> buffer(new char[4096]); 1.165 + NS_ENSURE_TRUE(buffer, NS_ERROR_OUT_OF_MEMORY); 1.166 + 1.167 + uint32_t read = 0; 1.168 + uint32_t offset = 0; 1.169 + do 1.170 + { 1.171 + rv = aStream->Read(buffer.get(), 4096, &read); 1.172 + if (NS_FAILED(rv)) { 1.173 + OnStopRequest(nullptr, nullptr, rv); 1.174 + return rv; 1.175 + } 1.176 + 1.177 + if (read > 0) { 1.178 + rv = ProcessData(nullptr, nullptr, buffer.get(), offset, read); 1.179 + if (NS_FAILED(rv)) { 1.180 + OnStopRequest(nullptr, nullptr, rv); 1.181 + return rv; 1.182 + } 1.183 + offset += read; 1.184 + } 1.185 + } while (read > 0); 1.186 + 1.187 + return OnStopRequest(nullptr, nullptr, NS_OK); 1.188 +}