modules/libjar/zipwriter/src/nsZipDataStream.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
michael@0 4 */
michael@0 5
michael@0 6 #include "StreamFunctions.h"
michael@0 7 #include "nsZipDataStream.h"
michael@0 8 #include "nsIStringStream.h"
michael@0 9 #include "nsISeekableStream.h"
michael@0 10 #include "nsDeflateConverter.h"
michael@0 11 #include "nsNetUtil.h"
michael@0 12 #include "nsComponentManagerUtils.h"
michael@0 13 #include "nsMemory.h"
michael@0 14
michael@0 15 #define ZIP_METHOD_STORE 0
michael@0 16 #define ZIP_METHOD_DEFLATE 8
michael@0 17
michael@0 18 /**
michael@0 19 * nsZipDataStream handles the writing an entry's into the zip file.
michael@0 20 * It is set up to wither write the data as is, or in the event that compression
michael@0 21 * has been requested to pass it through a stream converter.
michael@0 22 * Currently only the deflate compression method is supported.
michael@0 23 * The CRC checksum for the entry's data is also generated here.
michael@0 24 */
michael@0 25 NS_IMPL_ISUPPORTS(nsZipDataStream, nsIStreamListener,
michael@0 26 nsIRequestObserver)
michael@0 27
michael@0 28 nsresult nsZipDataStream::Init(nsZipWriter *aWriter,
michael@0 29 nsIOutputStream *aStream,
michael@0 30 nsZipHeader *aHeader,
michael@0 31 int32_t aCompression)
michael@0 32 {
michael@0 33 mWriter = aWriter;
michael@0 34 mHeader = aHeader;
michael@0 35 mStream = aStream;
michael@0 36 mHeader->mCRC = crc32(0L, Z_NULL, 0);
michael@0 37
michael@0 38 nsresult rv = NS_NewSimpleStreamListener(getter_AddRefs(mOutput), aStream,
michael@0 39 nullptr);
michael@0 40 NS_ENSURE_SUCCESS(rv, rv);
michael@0 41
michael@0 42 if (aCompression > 0) {
michael@0 43 mHeader->mMethod = ZIP_METHOD_DEFLATE;
michael@0 44 nsCOMPtr<nsIStreamConverter> converter =
michael@0 45 new nsDeflateConverter(aCompression);
michael@0 46 NS_ENSURE_TRUE(converter, NS_ERROR_OUT_OF_MEMORY);
michael@0 47
michael@0 48 rv = converter->AsyncConvertData("uncompressed", "rawdeflate", mOutput,
michael@0 49 nullptr);
michael@0 50 NS_ENSURE_SUCCESS(rv, rv);
michael@0 51
michael@0 52 mOutput = do_QueryInterface(converter, &rv);
michael@0 53 NS_ENSURE_SUCCESS(rv, rv);
michael@0 54 }
michael@0 55 else {
michael@0 56 mHeader->mMethod = ZIP_METHOD_STORE;
michael@0 57 }
michael@0 58
michael@0 59 return NS_OK;
michael@0 60 }
michael@0 61
michael@0 62 /* void onDataAvailable (in nsIRequest aRequest, in nsISupports aContext,
michael@0 63 * in nsIInputStream aInputStream,
michael@0 64 * in unsigned long long aOffset, in unsigned long aCount); */
michael@0 65 NS_IMETHODIMP nsZipDataStream::OnDataAvailable(nsIRequest *aRequest,
michael@0 66 nsISupports *aContext,
michael@0 67 nsIInputStream *aInputStream,
michael@0 68 uint64_t aOffset,
michael@0 69 uint32_t aCount)
michael@0 70 {
michael@0 71 if (!mOutput)
michael@0 72 return NS_ERROR_NOT_INITIALIZED;
michael@0 73
michael@0 74 nsAutoArrayPtr<char> buffer(new char[aCount]);
michael@0 75 NS_ENSURE_TRUE(buffer, NS_ERROR_OUT_OF_MEMORY);
michael@0 76
michael@0 77 nsresult rv = ZW_ReadData(aInputStream, buffer.get(), aCount);
michael@0 78 NS_ENSURE_SUCCESS(rv, rv);
michael@0 79
michael@0 80 return ProcessData(aRequest, aContext, buffer.get(), aOffset, aCount);
michael@0 81 }
michael@0 82
michael@0 83 /* void onStartRequest (in nsIRequest aRequest, in nsISupports aContext); */
michael@0 84 NS_IMETHODIMP nsZipDataStream::OnStartRequest(nsIRequest *aRequest,
michael@0 85 nsISupports *aContext)
michael@0 86 {
michael@0 87 if (!mOutput)
michael@0 88 return NS_ERROR_NOT_INITIALIZED;
michael@0 89
michael@0 90 return mOutput->OnStartRequest(aRequest, aContext);
michael@0 91 }
michael@0 92
michael@0 93 /* void onStopRequest (in nsIRequest aRequest, in nsISupports aContext,
michael@0 94 * in nsresult aStatusCode); */
michael@0 95 NS_IMETHODIMP nsZipDataStream::OnStopRequest(nsIRequest *aRequest,
michael@0 96 nsISupports *aContext,
michael@0 97 nsresult aStatusCode)
michael@0 98 {
michael@0 99 if (!mOutput)
michael@0 100 return NS_ERROR_NOT_INITIALIZED;
michael@0 101
michael@0 102 nsresult rv = mOutput->OnStopRequest(aRequest, aContext, aStatusCode);
michael@0 103 mOutput = nullptr;
michael@0 104 if (NS_FAILED(rv)) {
michael@0 105 mWriter->EntryCompleteCallback(mHeader, rv);
michael@0 106 }
michael@0 107 else {
michael@0 108 rv = CompleteEntry();
michael@0 109 rv = mWriter->EntryCompleteCallback(mHeader, rv);
michael@0 110 }
michael@0 111
michael@0 112 mStream = nullptr;
michael@0 113 mWriter = nullptr;
michael@0 114 mHeader = nullptr;
michael@0 115
michael@0 116 return rv;
michael@0 117 }
michael@0 118
michael@0 119 inline nsresult nsZipDataStream::CompleteEntry()
michael@0 120 {
michael@0 121 nsresult rv;
michael@0 122 nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(mStream, &rv);
michael@0 123 NS_ENSURE_SUCCESS(rv, rv);
michael@0 124 int64_t pos;
michael@0 125 rv = seekable->Tell(&pos);
michael@0 126 NS_ENSURE_SUCCESS(rv, rv);
michael@0 127
michael@0 128 mHeader->mCSize = pos - mHeader->mOffset - mHeader->GetFileHeaderLength();
michael@0 129 mHeader->mWriteOnClose = true;
michael@0 130 return NS_OK;
michael@0 131 }
michael@0 132
michael@0 133 nsresult nsZipDataStream::ProcessData(nsIRequest *aRequest,
michael@0 134 nsISupports *aContext, char *aBuffer,
michael@0 135 uint64_t aOffset, uint32_t aCount)
michael@0 136 {
michael@0 137 mHeader->mCRC = crc32(mHeader->mCRC,
michael@0 138 reinterpret_cast<const unsigned char*>(aBuffer),
michael@0 139 aCount);
michael@0 140
michael@0 141 nsresult rv;
michael@0 142 nsCOMPtr<nsIStringInputStream> stream =
michael@0 143 do_CreateInstance("@mozilla.org/io/string-input-stream;1", &rv);
michael@0 144 NS_ENSURE_SUCCESS(rv, rv);
michael@0 145
michael@0 146 stream->ShareData(aBuffer, aCount);
michael@0 147 rv = mOutput->OnDataAvailable(aRequest, aContext, stream, aOffset, aCount);
michael@0 148 mHeader->mUSize += aCount;
michael@0 149
michael@0 150 return rv;
michael@0 151 }
michael@0 152
michael@0 153 nsresult nsZipDataStream::ReadStream(nsIInputStream *aStream)
michael@0 154 {
michael@0 155 if (!mOutput)
michael@0 156 return NS_ERROR_NOT_INITIALIZED;
michael@0 157
michael@0 158 nsresult rv = OnStartRequest(nullptr, nullptr);
michael@0 159 NS_ENSURE_SUCCESS(rv, rv);
michael@0 160
michael@0 161 nsAutoArrayPtr<char> buffer(new char[4096]);
michael@0 162 NS_ENSURE_TRUE(buffer, NS_ERROR_OUT_OF_MEMORY);
michael@0 163
michael@0 164 uint32_t read = 0;
michael@0 165 uint32_t offset = 0;
michael@0 166 do
michael@0 167 {
michael@0 168 rv = aStream->Read(buffer.get(), 4096, &read);
michael@0 169 if (NS_FAILED(rv)) {
michael@0 170 OnStopRequest(nullptr, nullptr, rv);
michael@0 171 return rv;
michael@0 172 }
michael@0 173
michael@0 174 if (read > 0) {
michael@0 175 rv = ProcessData(nullptr, nullptr, buffer.get(), offset, read);
michael@0 176 if (NS_FAILED(rv)) {
michael@0 177 OnStopRequest(nullptr, nullptr, rv);
michael@0 178 return rv;
michael@0 179 }
michael@0 180 offset += read;
michael@0 181 }
michael@0 182 } while (read > 0);
michael@0 183
michael@0 184 return OnStopRequest(nullptr, nullptr, NS_OK);
michael@0 185 }

mercurial