modules/libjar/zipwriter/src/nsZipDataStream.cpp

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

mercurial