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

     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 "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"
    15 #define ZIP_METHOD_STORE 0
    16 #define ZIP_METHOD_DEFLATE 8
    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)
    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);
    38     nsresult rv = NS_NewSimpleStreamListener(getter_AddRefs(mOutput), aStream,
    39                                              nullptr);
    40     NS_ENSURE_SUCCESS(rv, rv);
    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);
    48         rv = converter->AsyncConvertData("uncompressed", "rawdeflate", mOutput,
    49                                          nullptr);
    50         NS_ENSURE_SUCCESS(rv, rv);
    52         mOutput = do_QueryInterface(converter, &rv);
    53         NS_ENSURE_SUCCESS(rv, rv);
    54     }
    55     else {
    56         mHeader->mMethod = ZIP_METHOD_STORE;
    57     }
    59     return NS_OK;
    60 }
    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;
    74     nsAutoArrayPtr<char> buffer(new char[aCount]);
    75     NS_ENSURE_TRUE(buffer, NS_ERROR_OUT_OF_MEMORY);
    77     nsresult rv = ZW_ReadData(aInputStream, buffer.get(), aCount);
    78     NS_ENSURE_SUCCESS(rv, rv);
    80     return ProcessData(aRequest, aContext, buffer.get(), aOffset, aCount);
    81 }
    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;
    90     return mOutput->OnStartRequest(aRequest, aContext);
    91 }
    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;
   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     }
   112     mStream = nullptr;
   113     mWriter = nullptr;
   114     mHeader = nullptr;
   116     return rv;
   117 }
   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);
   128     mHeader->mCSize = pos - mHeader->mOffset - mHeader->GetFileHeaderLength();
   129     mHeader->mWriteOnClose = true;
   130     return NS_OK;
   131 }
   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);
   141     nsresult rv;
   142     nsCOMPtr<nsIStringInputStream> stream =
   143              do_CreateInstance("@mozilla.org/io/string-input-stream;1", &rv);
   144     NS_ENSURE_SUCCESS(rv, rv);
   146     stream->ShareData(aBuffer, aCount);
   147     rv = mOutput->OnDataAvailable(aRequest, aContext, stream, aOffset, aCount);
   148     mHeader->mUSize += aCount;
   150     return rv;
   151 }
   153 nsresult nsZipDataStream::ReadStream(nsIInputStream *aStream)
   154 {
   155     if (!mOutput)
   156         return NS_ERROR_NOT_INITIALIZED;
   158     nsresult rv = OnStartRequest(nullptr, nullptr);
   159     NS_ENSURE_SUCCESS(rv, rv);
   161     nsAutoArrayPtr<char> buffer(new char[4096]);
   162     NS_ENSURE_TRUE(buffer, NS_ERROR_OUT_OF_MEMORY);
   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         }
   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);
   184     return OnStopRequest(nullptr, nullptr, NS_OK);
   185 }

mercurial