Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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 */
6 #include "StreamFunctions.h"
7 #include "nsDeflateConverter.h"
8 #include "nsIStringStream.h"
9 #include "nsIInputStreamPump.h"
10 #include "nsComponentManagerUtils.h"
11 #include "nsMemory.h"
12 #include "nsAutoPtr.h"
13 #include "plstr.h"
15 #define ZLIB_TYPE "deflate"
16 #define GZIP_TYPE "gzip"
17 #define X_GZIP_TYPE "x-gzip"
19 /**
20 * nsDeflateConverter is a stream converter applies the deflate compression
21 * method to the data.
22 */
23 NS_IMPL_ISUPPORTS(nsDeflateConverter, nsIStreamConverter,
24 nsIStreamListener,
25 nsIRequestObserver)
27 nsresult nsDeflateConverter::Init()
28 {
29 int zerr;
31 mOffset = 0;
33 mZstream.zalloc = Z_NULL;
34 mZstream.zfree = Z_NULL;
35 mZstream.opaque = Z_NULL;
37 int32_t window = MAX_WBITS;
38 switch (mWrapMode) {
39 case WRAP_NONE:
40 window = -window;
41 break;
42 case WRAP_GZIP:
43 window += 16;
44 break;
45 default:
46 break;
47 }
49 zerr = deflateInit2(&mZstream, mLevel, Z_DEFLATED, window, 8,
50 Z_DEFAULT_STRATEGY);
51 if (zerr != Z_OK) return NS_ERROR_OUT_OF_MEMORY;
53 mZstream.next_out = mWriteBuffer;
54 mZstream.avail_out = sizeof(mWriteBuffer);
56 // mark the input buffer as empty.
57 mZstream.avail_in = 0;
58 mZstream.next_in = Z_NULL;
60 return NS_OK;
61 }
63 /* nsIInputStream convert (in nsIInputStream aFromStream, in string aFromType
64 * in string aToType, in nsISupports aCtxt); */
65 NS_IMETHODIMP nsDeflateConverter::Convert(nsIInputStream *aFromStream,
66 const char *aFromType,
67 const char *aToType,
68 nsISupports *aCtxt,
69 nsIInputStream **_retval)
70 {
71 return NS_ERROR_NOT_IMPLEMENTED;
72 }
74 /* void asyncConvertData (in string aFromType, in string aToType,
75 * in nsIStreamListener aListener,
76 * in nsISupports aCtxt); */
77 NS_IMETHODIMP nsDeflateConverter::AsyncConvertData(const char *aFromType,
78 const char *aToType,
79 nsIStreamListener *aListener,
80 nsISupports *aCtxt)
81 {
82 if (mListener)
83 return NS_ERROR_ALREADY_INITIALIZED;
85 NS_ENSURE_ARG_POINTER(aListener);
87 if (!PL_strncasecmp(aToType, ZLIB_TYPE, sizeof(ZLIB_TYPE)-1))
88 mWrapMode = WRAP_ZLIB;
89 else if (!PL_strcasecmp(aToType, GZIP_TYPE) ||
90 !PL_strcasecmp(aToType, X_GZIP_TYPE))
91 mWrapMode = WRAP_GZIP;
92 else
93 mWrapMode = WRAP_NONE;
95 nsresult rv = Init();
96 NS_ENSURE_SUCCESS(rv, rv);
98 mListener = aListener;
99 mContext = aCtxt;
100 return rv;
101 }
103 /* void onDataAvailable (in nsIRequest aRequest, in nsISupports aContext,
104 * in nsIInputStream aInputStream,
105 * in unsigned long long aOffset,
106 * in unsigned long aCount); */
107 NS_IMETHODIMP nsDeflateConverter::OnDataAvailable(nsIRequest *aRequest,
108 nsISupports *aContext,
109 nsIInputStream *aInputStream,
110 uint64_t aOffset,
111 uint32_t aCount)
112 {
113 if (!mListener)
114 return NS_ERROR_NOT_INITIALIZED;
116 nsAutoArrayPtr<char> buffer(new char[aCount]);
117 NS_ENSURE_TRUE(buffer, NS_ERROR_OUT_OF_MEMORY);
119 nsresult rv = ZW_ReadData(aInputStream, buffer.get(), aCount);
120 NS_ENSURE_SUCCESS(rv, rv);
122 // make sure we aren't reading too much
123 mZstream.avail_in = aCount;
124 mZstream.next_in = (unsigned char*)buffer.get();
126 int zerr = Z_OK;
127 // deflate loop
128 while (mZstream.avail_in > 0 && zerr == Z_OK) {
129 zerr = deflate(&mZstream, Z_NO_FLUSH);
131 while (mZstream.avail_out == 0) {
132 // buffer is full, push the data out to the listener
133 rv = PushAvailableData(aRequest, aContext);
134 NS_ENSURE_SUCCESS(rv, rv);
135 zerr = deflate(&mZstream, Z_NO_FLUSH);
136 }
137 }
139 return NS_OK;
140 }
142 /* void onStartRequest (in nsIRequest aRequest, in nsISupports aContext); */
143 NS_IMETHODIMP nsDeflateConverter::OnStartRequest(nsIRequest *aRequest,
144 nsISupports *aContext)
145 {
146 if (!mListener)
147 return NS_ERROR_NOT_INITIALIZED;
149 return mListener->OnStartRequest(aRequest, mContext);
150 }
152 /* void onStopRequest (in nsIRequest aRequest, in nsISupports aContext,
153 * in nsresult aStatusCode); */
154 NS_IMETHODIMP nsDeflateConverter::OnStopRequest(nsIRequest *aRequest,
155 nsISupports *aContext,
156 nsresult aStatusCode)
157 {
158 if (!mListener)
159 return NS_ERROR_NOT_INITIALIZED;
161 nsresult rv;
163 int zerr;
164 do {
165 zerr = deflate(&mZstream, Z_FINISH);
166 rv = PushAvailableData(aRequest, aContext);
167 NS_ENSURE_SUCCESS(rv, rv);
168 } while (zerr == Z_OK);
170 deflateEnd(&mZstream);
172 return mListener->OnStopRequest(aRequest, mContext, aStatusCode);
173 }
175 nsresult nsDeflateConverter::PushAvailableData(nsIRequest *aRequest,
176 nsISupports *aContext)
177 {
178 uint32_t bytesToWrite = sizeof(mWriteBuffer) - mZstream.avail_out;
179 // We don't need to do anything if there isn't any data
180 if (bytesToWrite == 0)
181 return NS_OK;
183 nsresult rv;
184 nsCOMPtr<nsIStringInputStream> stream =
185 do_CreateInstance("@mozilla.org/io/string-input-stream;1", &rv);
186 NS_ENSURE_SUCCESS(rv, rv);
188 stream->ShareData((char*)mWriteBuffer, bytesToWrite);
189 rv = mListener->OnDataAvailable(aRequest, mContext, stream, mOffset,
190 bytesToWrite);
192 // now set the state for 'deflate'
193 mZstream.next_out = mWriteBuffer;
194 mZstream.avail_out = sizeof(mWriteBuffer);
196 mOffset += bytesToWrite;
197 return rv;
198 }