tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

nsZipDataStream.cpp (4807B)


      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 "nsStringStream.h"
      9 #include "nsISeekableStream.h"
     10 #include "nsDeflateConverter.h"
     11 #include "nsNetUtil.h"
     12 #include "nsComponentManagerUtils.h"
     13 
     14 #define ZIP_METHOD_STORE 0
     15 #define ZIP_METHOD_DEFLATE 8
     16 
     17 using namespace mozilla;
     18 
     19 /**
     20 * nsZipDataStream handles the writing an entry's into the zip file.
     21 * It is set up to wither write the data as is, or in the event that compression
     22 * has been requested to pass it through a stream converter.
     23 * Currently only the deflate compression method is supported.
     24 * The CRC checksum for the entry's data is also generated here.
     25 */
     26 NS_IMPL_ISUPPORTS(nsZipDataStream, nsIStreamListener, nsIRequestObserver)
     27 
     28 nsresult nsZipDataStream::Init(nsZipWriter* aWriter, nsIOutputStream* aStream,
     29                               nsZipHeader* aHeader, int32_t aCompression) {
     30  mWriter = aWriter;
     31  mHeader = aHeader;
     32  mStream = aStream;
     33  mHeader->mCRC = crc32(0L, Z_NULL, 0);
     34 
     35  nsresult rv =
     36      NS_NewSimpleStreamListener(getter_AddRefs(mOutput), aStream, nullptr);
     37  NS_ENSURE_SUCCESS(rv, rv);
     38 
     39  if (aCompression > 0) {
     40    mHeader->mMethod = ZIP_METHOD_DEFLATE;
     41    nsCOMPtr<nsIStreamConverter> converter =
     42        new nsDeflateConverter(aCompression);
     43    NS_ENSURE_TRUE(converter, NS_ERROR_OUT_OF_MEMORY);
     44 
     45    rv = converter->AsyncConvertData("uncompressed", "rawdeflate", mOutput,
     46                                     nullptr);
     47    NS_ENSURE_SUCCESS(rv, rv);
     48 
     49    mOutput = converter;
     50  } else {
     51    mHeader->mMethod = ZIP_METHOD_STORE;
     52  }
     53 
     54  return NS_OK;
     55 }
     56 
     57 NS_IMETHODIMP nsZipDataStream::OnDataAvailable(nsIRequest* aRequest,
     58                                               nsIInputStream* aInputStream,
     59                                               uint64_t aOffset,
     60                                               uint32_t aCount) {
     61  if (!mOutput) return NS_ERROR_NOT_INITIALIZED;
     62 
     63  auto buffer = MakeUnique<char[]>(aCount);
     64  NS_ENSURE_TRUE(buffer, NS_ERROR_OUT_OF_MEMORY);
     65 
     66  nsresult rv = ZW_ReadData(aInputStream, buffer.get(), aCount);
     67  NS_ENSURE_SUCCESS(rv, rv);
     68 
     69  return ProcessData(aRequest, nullptr, buffer.get(), aOffset, aCount);
     70 }
     71 
     72 NS_IMETHODIMP nsZipDataStream::OnStartRequest(nsIRequest* aRequest) {
     73  if (!mOutput) return NS_ERROR_NOT_INITIALIZED;
     74 
     75  return mOutput->OnStartRequest(aRequest);
     76 }
     77 
     78 NS_IMETHODIMP nsZipDataStream::OnStopRequest(nsIRequest* aRequest,
     79                                             nsresult aStatusCode) {
     80  if (!mOutput) return NS_ERROR_NOT_INITIALIZED;
     81 
     82  nsresult rv = mOutput->OnStopRequest(aRequest, aStatusCode);
     83  mOutput = nullptr;
     84  if (NS_FAILED(rv)) {
     85    mWriter->EntryCompleteCallback(mHeader, rv);
     86  } else {
     87    rv = CompleteEntry();
     88    rv = mWriter->EntryCompleteCallback(mHeader, rv);
     89  }
     90 
     91  mStream = nullptr;
     92  mWriter = nullptr;
     93  mHeader = nullptr;
     94 
     95  return rv;
     96 }
     97 
     98 inline nsresult nsZipDataStream::CompleteEntry() {
     99  nsresult rv;
    100  nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(mStream, &rv);
    101  NS_ENSURE_SUCCESS(rv, rv);
    102  int64_t pos;
    103  rv = seekable->Tell(&pos);
    104  NS_ENSURE_SUCCESS(rv, rv);
    105 
    106  mHeader->mCSize = pos - mHeader->mOffset - mHeader->GetFileHeaderLength();
    107  mHeader->mWriteOnClose = true;
    108  return NS_OK;
    109 }
    110 
    111 nsresult nsZipDataStream::ProcessData(nsIRequest* aRequest,
    112                                      nsISupports* aContext, char* aBuffer,
    113                                      uint64_t aOffset, uint32_t aCount) {
    114  mHeader->mCRC = crc32(
    115      mHeader->mCRC, reinterpret_cast<const unsigned char*>(aBuffer), aCount);
    116 
    117  MOZ_ASSERT(aCount <= INT32_MAX);
    118  nsCOMPtr<nsIInputStream> stream;
    119  nsresult rv = NS_NewByteInputStream(
    120      getter_AddRefs(stream), Span(aBuffer, aCount), NS_ASSIGNMENT_DEPEND);
    121  NS_ENSURE_SUCCESS(rv, rv);
    122 
    123  rv = mOutput->OnDataAvailable(aRequest, stream, aOffset, aCount);
    124  mHeader->mUSize += aCount;
    125 
    126  return rv;
    127 }
    128 
    129 nsresult nsZipDataStream::ReadStream(nsIInputStream* aStream) {
    130  if (!mOutput) return NS_ERROR_NOT_INITIALIZED;
    131 
    132  nsresult rv = OnStartRequest(nullptr);
    133  NS_ENSURE_SUCCESS(rv, rv);
    134 
    135  auto buffer = MakeUnique<char[]>(4096);
    136  NS_ENSURE_TRUE(buffer, NS_ERROR_OUT_OF_MEMORY);
    137 
    138  uint32_t read = 0;
    139  uint32_t offset = 0;
    140  do {
    141    rv = aStream->Read(buffer.get(), 4096, &read);
    142    if (NS_FAILED(rv)) {
    143      OnStopRequest(nullptr, rv);
    144      return rv;
    145    }
    146 
    147    if (read > 0) {
    148      rv = ProcessData(nullptr, nullptr, buffer.get(), offset, read);
    149      if (NS_FAILED(rv)) {
    150        OnStopRequest(nullptr, rv);
    151        return rv;
    152      }
    153      offset += read;
    154    }
    155  } while (read > 0);
    156 
    157  return OnStopRequest(nullptr, NS_OK);
    158 }