PageRenderTime 55ms CodeModel.GetById 14ms app.highlight 37ms RepoModel.GetById 1ms app.codeStats 0ms

/modules/libjar/zipwriter/src/nsZipDataStream.cpp

http://github.com/zpao/v8monkey
C++ | 219 lines | 137 code | 31 blank | 51 comment | 12 complexity | c5fd25c4ec65709aaca11819bf70920e MD5 | raw file
  1/* ***** BEGIN LICENSE BLOCK *****
  2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3 *
  4 * The contents of this file are subject to the Mozilla Public License Version
  5 * 1.1 (the "License"); you may not use this file except in compliance with
  6 * the License. You may obtain a copy of the License at
  7 * http://www.mozilla.org/MPL/
  8 *
  9 * Software distributed under the License is distributed on an "AS IS" basis,
 10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 11 * for the specific language governing rights and limitations under the
 12 * License.
 13 *
 14 * The Original Code is Zip Writer Component.
 15 *
 16 * The Initial Developer of the Original Code is
 17 * Dave Townsend <dtownsend@oxymoronical.com>.
 18 *
 19 * Portions created by the Initial Developer are Copyright (C) 2007
 20 * the Initial Developer. All Rights Reserved.
 21 *
 22 * Contributor(s):
 23 *      Mook <mook.moz+random.code@gmail.com>
 24 *
 25 * Alternatively, the contents of this file may be used under the terms of
 26 * either the GNU General Public License Version 2 or later (the "GPL"), or
 27 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 28 * in which case the provisions of the GPL or the LGPL are applicable instead
 29 * of those above. If you wish to allow use of your version of this file only
 30 * under the terms of either the GPL or the LGPL, and not to allow others to
 31 * use your version of this file under the terms of the MPL, indicate your
 32 * decision by deleting the provisions above and replace them with the notice
 33 * and other provisions required by the GPL or the LGPL. If you do not delete
 34 * the provisions above, a recipient may use your version of this file under
 35 * the terms of any one of the MPL, the GPL or the LGPL.
 36 *
 37 * ***** END LICENSE BLOCK *****
 38 */
 39
 40#include "StreamFunctions.h"
 41#include "nsZipDataStream.h"
 42#include "nsIStringStream.h"
 43#include "nsISeekableStream.h"
 44#include "nsDeflateConverter.h"
 45#include "nsNetUtil.h"
 46#include "nsComponentManagerUtils.h"
 47#include "nsMemory.h"
 48
 49#define ZIP_METHOD_STORE 0
 50#define ZIP_METHOD_DEFLATE 8
 51
 52/**
 53 * nsZipDataStream handles the writing an entry's into the zip file.
 54 * It is set up to wither write the data as is, or in the event that compression
 55 * has been requested to pass it through a stream converter.
 56 * Currently only the deflate compression method is supported.
 57 * The CRC checksum for the entry's data is also generated here.
 58 */
 59NS_IMPL_THREADSAFE_ISUPPORTS2(nsZipDataStream, nsIStreamListener,
 60                                               nsIRequestObserver)
 61
 62nsresult nsZipDataStream::Init(nsZipWriter *aWriter,
 63                               nsIOutputStream *aStream,
 64                               nsZipHeader *aHeader,
 65                               PRInt32 aCompression)
 66{
 67    mWriter = aWriter;
 68    mHeader = aHeader;
 69    mStream = aStream;
 70    mHeader->mCRC = crc32(0L, Z_NULL, 0);
 71
 72    nsresult rv = NS_NewSimpleStreamListener(getter_AddRefs(mOutput), aStream,
 73                                             nsnull);
 74    NS_ENSURE_SUCCESS(rv, rv);
 75
 76    if (aCompression > 0) {
 77        mHeader->mMethod = ZIP_METHOD_DEFLATE;
 78        nsCOMPtr<nsIStreamConverter> converter =
 79                              new nsDeflateConverter(aCompression);
 80        NS_ENSURE_TRUE(converter, NS_ERROR_OUT_OF_MEMORY);
 81
 82        rv = converter->AsyncConvertData("uncompressed", "rawdeflate", mOutput,
 83                                         nsnull);
 84        NS_ENSURE_SUCCESS(rv, rv);
 85
 86        mOutput = do_QueryInterface(converter, &rv);
 87        NS_ENSURE_SUCCESS(rv, rv);
 88    }
 89    else {
 90        mHeader->mMethod = ZIP_METHOD_STORE;
 91    }
 92
 93    return NS_OK;
 94}
 95
 96/* void onDataAvailable (in nsIRequest aRequest, in nsISupports aContext,
 97 *                       in nsIInputStream aInputStream,
 98 *                       in unsigned long aOffset, in unsigned long aCount); */
 99NS_IMETHODIMP nsZipDataStream::OnDataAvailable(nsIRequest *aRequest,
100                                               nsISupports *aContext,
101                                               nsIInputStream *aInputStream,
102                                               PRUint32 aOffset,
103                                               PRUint32 aCount)
104{
105    if (!mOutput)
106        return NS_ERROR_NOT_INITIALIZED;
107
108    nsAutoArrayPtr<char> buffer(new char[aCount]);
109    NS_ENSURE_TRUE(buffer, NS_ERROR_OUT_OF_MEMORY);
110
111    nsresult rv = ZW_ReadData(aInputStream, buffer.get(), aCount);
112    NS_ENSURE_SUCCESS(rv, rv);
113
114    return ProcessData(aRequest, aContext, buffer.get(), aOffset, aCount);
115}
116
117/* void onStartRequest (in nsIRequest aRequest, in nsISupports aContext); */
118NS_IMETHODIMP nsZipDataStream::OnStartRequest(nsIRequest *aRequest,
119                                              nsISupports *aContext)
120{
121    if (!mOutput)
122        return NS_ERROR_NOT_INITIALIZED;
123
124    return mOutput->OnStartRequest(aRequest, aContext);
125}
126
127/* void onStopRequest (in nsIRequest aRequest, in nsISupports aContext,
128 *                     in nsresult aStatusCode); */
129NS_IMETHODIMP nsZipDataStream::OnStopRequest(nsIRequest *aRequest,
130                                             nsISupports *aContext,
131                                             nsresult aStatusCode)
132{
133    if (!mOutput)
134        return NS_ERROR_NOT_INITIALIZED;
135
136    nsresult rv = mOutput->OnStopRequest(aRequest, aContext, aStatusCode);
137    mOutput = nsnull;
138    if (NS_FAILED(rv)) {
139        mWriter->EntryCompleteCallback(mHeader, rv);
140    }
141    else {
142        rv = CompleteEntry();
143        rv = mWriter->EntryCompleteCallback(mHeader, rv);
144    }
145
146    mStream = nsnull;
147    mWriter = nsnull;
148    mHeader = nsnull;
149
150    return rv;
151}
152
153inline nsresult nsZipDataStream::CompleteEntry()
154{
155    nsresult rv;
156    nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(mStream, &rv);
157    NS_ENSURE_SUCCESS(rv, rv);
158    PRInt64 pos;
159    rv = seekable->Tell(&pos);
160    NS_ENSURE_SUCCESS(rv, rv);
161
162    mHeader->mCSize = pos - mHeader->mOffset - mHeader->GetFileHeaderLength();
163    mHeader->mWriteOnClose = true;
164    return NS_OK;
165}
166
167nsresult nsZipDataStream::ProcessData(nsIRequest *aRequest,
168                                      nsISupports *aContext, char *aBuffer,
169                                      PRUint32 aOffset, PRUint32 aCount)
170{
171    mHeader->mCRC = crc32(mHeader->mCRC,
172                          reinterpret_cast<const unsigned char*>(aBuffer),
173                          aCount);
174
175    nsresult rv;
176    nsCOMPtr<nsIStringInputStream> stream =
177             do_CreateInstance("@mozilla.org/io/string-input-stream;1", &rv);
178    NS_ENSURE_SUCCESS(rv, rv);
179
180    stream->ShareData(aBuffer, aCount);
181    rv = mOutput->OnDataAvailable(aRequest, aContext, stream, aOffset, aCount);
182    mHeader->mUSize += aCount;
183
184    return rv;
185}
186
187nsresult nsZipDataStream::ReadStream(nsIInputStream *aStream)
188{
189    if (!mOutput)
190        return NS_ERROR_NOT_INITIALIZED;
191
192    nsresult rv = OnStartRequest(nsnull, nsnull);
193    NS_ENSURE_SUCCESS(rv, rv);
194
195    nsAutoArrayPtr<char> buffer(new char[4096]);
196    NS_ENSURE_TRUE(buffer, NS_ERROR_OUT_OF_MEMORY);
197
198    PRUint32 read = 0;
199    PRUint32 offset = 0;
200    do
201    {
202        rv = aStream->Read(buffer.get(), 4096, &read);
203        if (NS_FAILED(rv)) {
204            OnStopRequest(nsnull, nsnull, rv);
205            return rv;
206        }
207
208        if (read > 0) {
209            rv = ProcessData(nsnull, nsnull, buffer.get(), offset, read);
210            if (NS_FAILED(rv)) {
211                OnStopRequest(nsnull, nsnull, rv);
212                return rv;
213            }
214            offset += read;
215        }
216    } while (read > 0);
217
218    return OnStopRequest(nsnull, nsnull, NS_OK);
219}