/* AString convertFromByteArray([const,array,size_is(aCount)] in octet aData,
                                in unsigned long aCount);
 */
NS_IMETHODIMP
nsScriptableUnicodeConverter::ConvertFromByteArray(const uint8_t* aData,
                                                   uint32_t aCount,
                                                   nsAString& _retval)
{
  if (!mDecoder)
    return NS_ERROR_FAILURE;

  nsresult rv = NS_OK;
  int32_t inLength = aCount;
  int32_t outLength;
  rv = mDecoder->GetMaxLength(reinterpret_cast<const char*>(aData),
                              inLength, &outLength);
  if (NS_SUCCEEDED(rv))
  {
    PRUnichar* buf = (PRUnichar*)moz_malloc((outLength+1)*sizeof(PRUnichar));
    if (!buf)
      return NS_ERROR_OUT_OF_MEMORY;

    rv = mDecoder->Convert(reinterpret_cast<const char*>(aData),
                           &inLength, buf, &outLength);
    if (NS_SUCCEEDED(rv))
    {
      buf[outLength] = 0;
      _retval.Assign(buf, outLength);
    }
    moz_free(buf);
    return rv;
  }
  return NS_ERROR_FAILURE;

}
/* void convertToByteArray(in AString aString,
                          [optional] out unsigned long aLen,
                          [array, size_is(aLen),retval] out octet aData);
 */
NS_IMETHODIMP
nsScriptableUnicodeConverter::ConvertToByteArray(const nsAString& aString,
                                                 uint32_t* aLen,
                                                 uint8_t** _aData)
{
  char* data;
  int32_t len;
  nsresult rv = ConvertFromUnicodeWithLength(aString, &len, &data);
  if (NS_FAILED(rv))
    return rv;
  nsXPIDLCString str;
  str.Adopt(data, len); // NOTE: This uses the XPIDLCString as a byte array

  rv = FinishWithLength(&data, &len);
  if (NS_FAILED(rv))
    return rv;

  str.Append(data, len);
  moz_free(data);
  // NOTE: this being a byte array, it needs no null termination
  *_aData = reinterpret_cast<uint8_t*>(moz_malloc(str.Length()));
  if (!*_aData)
    return NS_ERROR_OUT_OF_MEMORY;
  memcpy(*_aData, str.get(), str.Length());
  *aLen = str.Length();
  return NS_OK;
}
Beispiel #3
0
NS_IMETHODIMP
nsBinaryOutputStream::WriteWStringZ(const char16_t* aString)
{
    uint32_t length, byteCount;
    nsresult rv;

    length = NS_strlen(aString);
    rv = Write32(length);
    if (NS_FAILED(rv)) return rv;

    if (length == 0)
        return NS_OK;
    byteCount = length * sizeof(char16_t);

#ifdef IS_BIG_ENDIAN
    rv = WriteBytes(reinterpret_cast<const char*>(aString), byteCount);
#else
    // XXX use WriteSegments here to avoid copy!
    char16_t *copy, temp[64];
    if (length <= 64) {
        copy = temp;
    } else {
        copy = reinterpret_cast<char16_t*>(moz_malloc(byteCount));
        if (!copy)
            return NS_ERROR_OUT_OF_MEMORY;
    }
    NS_ASSERTION((uintptr_t(aString) & 0x1) == 0, "aString not properly aligned");
    mozilla::NativeEndian::copyAndSwapToBigEndian(copy, aString, length);
    rv = WriteBytes(reinterpret_cast<const char*>(copy), byteCount);
    if (copy != temp)
        moz_free(copy);
#endif

    return rv;
}
nsresult
nsScriptableUnicodeConverter::ConvertFromUnicodeWithLength(const nsAString& aSrc,
                                                           int32_t* aOutLen,
                                                           char **_retval)
{
  if (!mEncoder)
    return NS_ERROR_FAILURE;

  nsresult rv = NS_OK;
  int32_t inLength = aSrc.Length();
  const nsAFlatString& flatSrc = PromiseFlatString(aSrc);
  rv = mEncoder->GetMaxLength(flatSrc.get(), inLength, aOutLen);
  if (NS_SUCCEEDED(rv)) {
    *_retval = (char*)moz_malloc(*aOutLen+1);
    if (!*_retval)
      return NS_ERROR_OUT_OF_MEMORY;

    rv = mEncoder->Convert(flatSrc.get(), &inLength, *_retval, aOutLen);
    if (NS_SUCCEEDED(rv))
    {
      (*_retval)[*aOutLen] = '\0';
      return NS_OK;
    }
    moz_free(*_retval);
  }
  *_retval = nullptr;
  return NS_ERROR_FAILURE;
}
already_AddRefed<nsIDOMBlob>
EncodedBufferCache::ExtractBlob(const nsAString &aContentType)
{
  MutexAutoLock lock(mMutex);
  nsCOMPtr<nsIDOMBlob> blob;
  if (mTempFileEnabled) {
    // generate new temporary file to write
    blob = new nsDOMTemporaryFileBlob(mFD, 0, mDataSize, aContentType);
    // fallback to memory blob
    mTempFileEnabled = false;
    mDataSize = 0;
    mFD = nullptr;
  } else {
    void* blobData = moz_malloc(mDataSize);
    NS_ASSERTION(blobData, "out of memory!!");

    if (blobData) {
      for (uint32_t i = 0, offset = 0; i < mEncodedBuffers.Length(); i++) {
        memcpy((uint8_t*)blobData + offset, mEncodedBuffers.ElementAt(i).Elements(),
               mEncodedBuffers.ElementAt(i).Length());
        offset += mEncodedBuffers.ElementAt(i).Length();
      }
      blob = new nsDOMMemoryFile(blobData, mDataSize,
                                 aContentType);
      mEncodedBuffers.Clear();
    } else
      return nullptr;
  }
  mDataSize = 0;
  return blob.forget();
}
NS_IMETHODIMP
nsScriptableInputStream::Read(uint32_t aCount, char** aResult)
{
  nsresult rv = NS_OK;
  uint64_t count64 = 0;
  char* buffer = nullptr;

  if (!mInputStream) {
    return NS_ERROR_NOT_INITIALIZED;
  }

  rv = mInputStream->Available(&count64);
  if (NS_FAILED(rv)) {
    return rv;
  }

  // bug716556 - Ensure count+1 doesn't overflow
  uint32_t count = XPCOM_MIN(uint32_t(XPCOM_MIN<uint64_t>(count64, aCount)), uint32_t(UINT32_MAX - 1));
  buffer = (char*)moz_malloc(count + 1);  // make room for '\0'
  if (!buffer) {
    return NS_ERROR_OUT_OF_MEMORY;
  }

  rv = ReadHelper(buffer, count);
  if (NS_FAILED(rv)) {
    nsMemory::Free(buffer);
    return rv;
  }

  buffer[count] = '\0';
  *aResult = buffer;
  return NS_OK;
}
Beispiel #7
0
nsresult imgFrame::Init(int32_t aX, int32_t aY, int32_t aWidth, int32_t aHeight,
                        SurfaceFormat aFormat, uint8_t aPaletteDepth /* = 0 */)
{
  // assert for properties that should be verified by decoders, warn for properties related to bad content
  if (!AllowedImageSize(aWidth, aHeight)) {
    NS_WARNING("Should have legal image size");
    return NS_ERROR_FAILURE;
  }

  mOffset.MoveTo(aX, aY);
  mSize.SizeTo(aWidth, aHeight);

  mFormat = aFormat;
  mPaletteDepth = aPaletteDepth;

  if (aPaletteDepth != 0) {
    // We're creating for a paletted image.
    if (aPaletteDepth > 8) {
      NS_WARNING("Should have legal palette depth");
      NS_ERROR("This Depth is not supported");
      return NS_ERROR_FAILURE;
    }

    // Use the fallible allocator here
    mPalettedImageData = (uint8_t*)moz_malloc(PaletteDataLength() + GetImageDataLength());
    if (!mPalettedImageData)
      NS_WARNING("moz_malloc for paletted image data should succeed");
    NS_ENSURE_TRUE(mPalettedImageData, NS_ERROR_OUT_OF_MEMORY);
  } else {
    // Inform the discard tracker that we are going to allocate some memory.
    if (!DiscardTracker::TryAllocation(4 * mSize.width * mSize.height)) {
      NS_WARNING("Exceed the hard limit of decode image size");
      return NS_ERROR_OUT_OF_MEMORY;
    }
    if (!mImageSurface) {
      mVBuf = AllocateBufferForImage(mSize, mFormat);
      if (!mVBuf) {
        return NS_ERROR_OUT_OF_MEMORY;
      }
      if (mVBuf->OnHeap()) {
        int32_t stride = VolatileSurfaceStride(mSize, mFormat);
        VolatileBufferPtr<uint8_t> ptr(mVBuf);
        memset(ptr, 0, stride * mSize.height);
      }
      mImageSurface = CreateLockedSurface(mVBuf, mSize, mFormat);
    }

    if (!mImageSurface) {
      NS_WARNING("Failed to create VolatileDataSourceSurface");
      // Image surface allocation is failed, need to return
      // the booked buffer size.
      DiscardTracker::InformDeallocation(4 * mSize.width * mSize.height);
      return NS_ERROR_OUT_OF_MEMORY;
    }
    mInformedDiscardTracker = true;
  }

  return NS_OK;
}
 GenerateBlobRunnable(nsTArray<nsRefPtr<PhotoCallback>>& aCallbacks,
                      uint8_t* aData,
                      uint32_t aLength,
                      const nsAString& aMimeType)
   : mPhotoDataLength(aLength)
 {
   mCallbacks.SwapElements(aCallbacks);
   mPhotoData = (uint8_t*) moz_malloc(aLength);
   memcpy(mPhotoData, aData, mPhotoDataLength);
   mMimeType = aMimeType;
 }
Beispiel #9
0
NS_Alloc(PRSize size)
{
    if (size > PR_INT32_MAX)
        return nsnull;

    void* result = moz_malloc(size);
    if (! result) {
        // Request an asynchronous flush
        sGlobalMemory.FlushMemory(NS_LITERAL_STRING("alloc-failure").get(), PR_FALSE);
    }
    return result;
}
Beispiel #10
0
static void
GetDataFrom(const T& aObject, uint8_t*& aBuffer, uint32_t& aLength)
{
  MOZ_ASSERT(!aBuffer);
  aObject.ComputeLengthAndData();
  // We use moz_malloc here rather than a FallibleTArray or fallible
  // operator new[] since the gfxUserFontEntry will be calling moz_free
  // on it.
  aBuffer = (uint8_t*) moz_malloc(aObject.Length());
  if (!aBuffer) {
    return;
  }
  memcpy((void*) aBuffer, aObject.Data(), aObject.Length());
  aLength = aObject.Length();
}
SECItem*
CryptoBuffer::ToSECItem()
{
  uint8_t* data = (uint8_t*) moz_malloc(Length());
  if (!data) {
    return nullptr;
  }

  SECItem* item = new SECItem();
  item->type = siBuffer;
  item->data = data;
  item->len = Length();

  memcpy(item->data, Elements(), Length());

  return item;
}
nsresult
XULContentSinkImpl::AddText(const PRUnichar* aText, 
                            int32_t aLength)
{
  // Create buffer when we first need it
  if (0 == mTextSize) {
      mText = (PRUnichar *) moz_malloc(sizeof(PRUnichar) * 4096);
      if (nullptr == mText) {
          return NS_ERROR_OUT_OF_MEMORY;
      }
      mTextSize = 4096;
  }

  // Copy data from string into our buffer; flush buffer when it fills up
  int32_t offset = 0;
  while (0 != aLength) {
    int32_t amount = mTextSize - mTextLength;
    if (amount > aLength) {
        amount = aLength;
    }
    if (0 == amount) {
      if (mConstrainSize) {
        nsresult rv = FlushText();
        if (NS_OK != rv) {
            return rv;
        }
      }
      else {
        mTextSize += aLength;
        mText = (PRUnichar *) moz_realloc(mText, sizeof(PRUnichar) * mTextSize);
        if (nullptr == mText) {
            return NS_ERROR_OUT_OF_MEMORY;
        }
      }
    }
    memcpy(&mText[mTextLength],aText + offset, sizeof(PRUnichar) * amount);
    
    mTextLength += amount;
    offset += amount;
    aLength -= amount;
  }

  return NS_OK;
}
Beispiel #13
0
bool
nsGIFDecoder2::SetHold(const uint8_t* buf1, uint32_t count1, const uint8_t* buf2 /* = nullptr */, uint32_t count2 /* = 0 */)
{
  // We have to handle the case that buf currently points to hold
  uint8_t* newHold = (uint8_t *) moz_malloc(std::max(uint32_t(MIN_HOLD_SIZE), count1 + count2));
  if (!newHold) {
    mGIFStruct.state = gif_error;
    return false;
  }

  memcpy(newHold, buf1, count1);
  if (buf2) {
    memcpy(newHold + count1, buf2, count2);
  }

  moz_free(mGIFStruct.hold);
  mGIFStruct.hold = newHold;
  mGIFStruct.bytes_in_hold = count1 + count2;
  return true;
}
nsresult
nsScriptableUnicodeConverter::FinishWithLength(char **_retval, int32_t* aLength)
{
  if (!mEncoder)
    return NS_ERROR_FAILURE;

  int32_t finLength = 32;

  *_retval = (char *)moz_malloc(finLength);
  if (!*_retval)
    return NS_ERROR_OUT_OF_MEMORY;

  nsresult rv = mEncoder->Finish(*_retval, &finLength);
  if (NS_SUCCEEDED(rv))
    *aLength = finLength;
  else
    moz_free(*_retval);

  return rv;

}
nsresult nsCollationMacUC::ConvertLocaleICU(nsILocale* aNSLocale, char** aICULocale)
{
  NS_ENSURE_ARG_POINTER(aNSLocale);
  NS_ENSURE_ARG_POINTER(aICULocale);

  nsAutoString localeString;
  nsresult res = aNSLocale->GetCategory(NS_LITERAL_STRING("NSILOCALE_COLLATE"), localeString);
  NS_ENSURE_TRUE(NS_SUCCEEDED(res) && !localeString.IsEmpty(),
                 NS_ERROR_FAILURE);
  NS_LossyConvertUTF16toASCII tmp(localeString);
  tmp.ReplaceChar('-', '_');
  char* locale = (char*)moz_malloc(tmp.Length() + 1);
  if (!locale) {
    return NS_ERROR_OUT_OF_MEMORY;
  }
  strcpy(locale, tmp.get());

  *aICULocale = locale;

  return NS_OK;
}
Beispiel #16
0
bool
AnalyserNode::FFTAnalysis()
{
  float* inputBuffer;
  bool allocated = false;
  if (mWriteIndex == 0) {
    inputBuffer = mBuffer.Elements();
  } else {
    inputBuffer = static_cast<float*>(moz_malloc(FftSize() * sizeof(float)));
    if (!inputBuffer) {
      return false;
    }
    memcpy(inputBuffer, mBuffer.Elements() + mWriteIndex, sizeof(float) * (FftSize() - mWriteIndex));
    memcpy(inputBuffer + FftSize() - mWriteIndex, mBuffer.Elements(), sizeof(float) * mWriteIndex);
    allocated = true;
  }

  ApplyBlackmanWindow(inputBuffer, FftSize());

  mAnalysisBlock.PerformFFT(inputBuffer);

  // Normalize so than an input sine wave at 0dBfs registers as 0dBfs (undo FFT scaling factor).
  const double magnitudeScale = 1.0 / FftSize();

  for (uint32_t i = 0; i < mOutputBuffer.Length(); ++i) {
    double scalarMagnitude = NS_hypot(mAnalysisBlock.RealData(i),
                                      mAnalysisBlock.ImagData(i)) *
                             magnitudeScale;
    mOutputBuffer[i] = mSmoothingTimeConstant * mOutputBuffer[i] +
                       (1.0 - mSmoothingTimeConstant) * scalarMagnitude;
  }

  if (allocated) {
    moz_free(inputBuffer);
  }
  return true;
}
Beispiel #17
0
NS_IMETHODIMP
nsBinaryInputStream::ReadBytes(uint32_t aLength, char* *_rval)
{
    nsresult rv;
    uint32_t bytesRead;
    char* s;

    s = reinterpret_cast<char*>(moz_malloc(aLength));
    if (!s)
        return NS_ERROR_OUT_OF_MEMORY;

    rv = Read(s, aLength, &bytesRead);
    if (NS_FAILED(rv)) {
        moz_free(s);
        return rv;
    }
    if (bytesRead != aLength) {
        moz_free(s);
        return NS_ERROR_FAILURE;
    }

    *_rval = s;
    return NS_OK;
}
NS_IMETHODIMP
nsBinaryOutputStream::WriteWStringZ(const PRUnichar* aString)
{
    PRUint32 length, byteCount;
    nsresult rv;

    length = NS_strlen(aString);
    rv = Write32(length);
    if (NS_FAILED(rv)) return rv;

    if (length == 0)
        return NS_OK;
    byteCount = length * sizeof(PRUnichar);

#ifdef IS_BIG_ENDIAN
    rv = WriteBytes(reinterpret_cast<const char*>(aString), byteCount);
#else
    // XXX use WriteSegments here to avoid copy!
    PRUnichar *copy, temp[64];
    if (length <= 64) {
        copy = temp;
    } else {
        copy = reinterpret_cast<PRUnichar*>(moz_malloc(byteCount));
        if (!copy)
            return NS_ERROR_OUT_OF_MEMORY;
    }
    NS_ASSERTION((PRUptrdiff(aString) & 0x1) == 0, "aString not properly aligned");
    for (PRUint32 i = 0; i < length; i++)
        copy[i] = NS_SWAP16(aString[i]);
    rv = WriteBytes(reinterpret_cast<const char*>(copy), byteCount);
    if (copy != temp)
        moz_free(copy);
#endif

    return rv;
}
Beispiel #19
0
already_AddRefed<Promise>
Request::ConsumeBody(ConsumeType aType, ErrorResult& aRv)
{
  nsRefPtr<Promise> promise = Promise::Create(mOwner, aRv);
  if (aRv.Failed()) {
    return nullptr;
  }

  if (BodyUsed()) {
    aRv.ThrowTypeError(MSG_REQUEST_BODY_CONSUMED_ERROR);
    return nullptr;
  }

  SetBodyUsed();

  // While the spec says to do this asynchronously, all the body constructors
  // right now only accept bodies whose streams are backed by an in-memory
  // buffer that can be read without blocking. So I think this is fine.
  nsCOMPtr<nsIInputStream> stream;
  mRequest->GetBody(getter_AddRefs(stream));

  if (!stream) {
    aRv = NS_NewByteInputStream(getter_AddRefs(stream), "", 0,
                                NS_ASSIGNMENT_COPY);
    if (aRv.Failed()) {
      return nullptr;
    }
  }

  AutoJSAPI api;
  api.Init(mOwner);
  JSContext* cx = api.cx();

  // We can make this assertion because for now we only support memory backed
  // structures for the body argument for a Request.
  MOZ_ASSERT(NS_InputStreamIsBuffered(stream));
  nsCString buffer;
  uint64_t len;
  aRv = stream->Available(&len);
  if (aRv.Failed()) {
    return nullptr;
  }

  aRv = NS_ReadInputStreamToString(stream, buffer, len);
  if (aRv.Failed()) {
    return nullptr;
  }

  buffer.SetLength(len);

  switch (aType) {
    case CONSUME_ARRAYBUFFER: {
      JS::Rooted<JSObject*> arrayBuffer(cx);
      arrayBuffer =
        ArrayBuffer::Create(cx, buffer.Length(),
                            reinterpret_cast<const uint8_t*>(buffer.get()));
      JS::Rooted<JS::Value> val(cx);
      val.setObjectOrNull(arrayBuffer);
      promise->MaybeResolve(cx, val);
      return promise.forget();
    }
    case CONSUME_BLOB: {
      // XXXnsm it is actually possible to avoid these duplicate allocations
      // for the Blob case by having the Blob adopt the stream's memory
      // directly, but I've not added a special case for now.
      //
      // This is similar to nsContentUtils::CreateBlobBuffer, but also deals
      // with worker wrapping.
      uint32_t blobLen = buffer.Length();
      void* blobData = moz_malloc(blobLen);
      nsRefPtr<File> blob;
      if (blobData) {
        memcpy(blobData, buffer.BeginReading(), blobLen);
        blob = File::CreateMemoryFile(GetParentObject(), blobData, blobLen,
                                      NS_ConvertUTF8toUTF16(mMimeType));
      } else {
        aRv = NS_ERROR_OUT_OF_MEMORY;
        return nullptr;
      }

      promise->MaybeResolve(blob);
      return promise.forget();
    }
    case CONSUME_JSON: {
      nsString decoded;
      aRv = DecodeUTF8(buffer, decoded);
      if (aRv.Failed()) {
        return nullptr;
      }

      JS::Rooted<JS::Value> json(cx);
      if (!JS_ParseJSON(cx, decoded.get(), decoded.Length(), &json)) {
        JS::Rooted<JS::Value> exn(cx);
        if (JS_GetPendingException(cx, &exn)) {
          JS_ClearPendingException(cx);
          promise->MaybeReject(cx, exn);
        }
      }
      promise->MaybeResolve(cx, json);
      return promise.forget();
    }
    case CONSUME_TEXT: {
      nsString decoded;
      aRv = DecodeUTF8(buffer, decoded);
      if (aRv.Failed()) {
        return nullptr;
      }

      promise->MaybeResolve(decoded);
      return promise.forget();
    }
  }

  NS_NOTREACHED("Unexpected consume body type");
  // Silence warnings.
  return nullptr;
}
nsresult
nsIndexedToHTML::FormatInputStream(nsIRequest* aRequest, nsISupports *aContext, const nsAString &aBuffer) 
{
    nsresult rv = NS_OK;

    // set up unicode encoder
    if (!mUnicodeEncoder) {
      nsXPIDLCString encoding;
      rv = mParser->GetEncoding(getter_Copies(encoding));
      if (NS_SUCCEEDED(rv)) {
        nsCOMPtr<nsICharsetConverterManager> charsetConverterManager;
        charsetConverterManager = do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &rv);
        rv = charsetConverterManager->GetUnicodeEncoder(encoding.get(), 
                                                          getter_AddRefs(mUnicodeEncoder));
        if (NS_SUCCEEDED(rv))
            rv = mUnicodeEncoder->SetOutputErrorBehavior(nsIUnicodeEncoder::kOnError_Replace, 
                                                       nullptr, (char16_t)'?');
      }
    }

    // convert the data with unicode encoder
    char *buffer = nullptr;
    int32_t dstLength;
    if (NS_SUCCEEDED(rv)) {
      int32_t unicharLength = aBuffer.Length();
      rv = mUnicodeEncoder->GetMaxLength(PromiseFlatString(aBuffer).get(), 
                                         unicharLength, &dstLength);
      if (NS_SUCCEEDED(rv)) {
        buffer = (char *) moz_malloc(dstLength);
        NS_ENSURE_TRUE(buffer, NS_ERROR_OUT_OF_MEMORY);

        rv = mUnicodeEncoder->Convert(PromiseFlatString(aBuffer).get(), &unicharLength, 
                                      buffer, &dstLength);
        if (NS_SUCCEEDED(rv)) {
          int32_t finLen = 0;
          rv = mUnicodeEncoder->Finish(buffer + dstLength, &finLen);
          if (NS_SUCCEEDED(rv))
            dstLength += finLen;
        }
      }
    }

    // if conversion error then fallback to UTF-8
    if (NS_FAILED(rv)) {
      rv = NS_OK;
      if (buffer) {
        nsMemory::Free(buffer);
        buffer = nullptr;
      }
    }

    nsCOMPtr<nsIInputStream> inputData;
    if (buffer) {
      rv = NS_NewCStringInputStream(getter_AddRefs(inputData), Substring(buffer, dstLength));
      nsMemory::Free(buffer);
      NS_ENSURE_SUCCESS(rv, rv);
      rv = mListener->OnDataAvailable(aRequest, aContext,
                                      inputData, 0, dstLength);
    }
    else {
      NS_ConvertUTF16toUTF8 utf8Buffer(aBuffer);
      rv = NS_NewCStringInputStream(getter_AddRefs(inputData), utf8Buffer);
      NS_ENSURE_SUCCESS(rv, rv);
      rv = mListener->OnDataAvailable(aRequest, aContext,
                                      inputData, 0, utf8Buffer.Length());
    }
    return (rv);
}
Beispiel #21
0
void
nsPNGDecoder::info_callback(png_structp png_ptr, png_infop info_ptr)
{
/*  int number_passes;   NOT USED  */
  png_uint_32 width, height;
  int bit_depth, color_type, interlace_type, compression_type, filter_type;
  unsigned int channels;

  png_bytep trans = nullptr;
  int num_trans = 0;

  nsPNGDecoder *decoder =
               static_cast<nsPNGDecoder*>(png_get_progressive_ptr(png_ptr));

  /* always decode to 24-bit RGB or 32-bit RGBA  */
  png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
               &interlace_type, &compression_type, &filter_type);

  /* Are we too big? */
  if (width > MOZ_PNG_MAX_DIMENSION || height > MOZ_PNG_MAX_DIMENSION)
    longjmp(png_jmpbuf(decoder->mPNG), 1);

  // Post our size to the superclass
  decoder->PostSize(width, height);
  if (decoder->HasError()) {
    // Setting the size led to an error.
    longjmp(png_jmpbuf(decoder->mPNG), 1);
  }

  if (color_type == PNG_COLOR_TYPE_PALETTE)
    png_set_expand(png_ptr);

  if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
    png_set_expand(png_ptr);

  if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
    int sample_max = (1 << bit_depth);
    png_color_16p trans_values;
    png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, &trans_values);
    /* libpng doesn't reject a tRNS chunk with out-of-range samples
       so we check it here to avoid setting up a useless opacity
       channel or producing unexpected transparent pixels when using
       libpng-1.2.19 through 1.2.26 (bug #428045) */
    if ((color_type == PNG_COLOR_TYPE_GRAY &&
       (int)trans_values->gray > sample_max) ||
       (color_type == PNG_COLOR_TYPE_RGB &&
       ((int)trans_values->red > sample_max ||
       (int)trans_values->green > sample_max ||
       (int)trans_values->blue > sample_max)))
      {
        /* clear the tRNS valid flag and release tRNS memory */
        png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0);
      }
    else
      png_set_expand(png_ptr);
  }

  if (bit_depth == 16)
    png_set_scale_16(png_ptr);

  qcms_data_type inType = QCMS_DATA_RGBA_8;
  uint32_t intent = -1;
  uint32_t pIntent;
  if (decoder->mCMSMode != eCMSMode_Off) {
    intent = gfxPlatform::GetRenderingIntent();
    decoder->mInProfile = PNGGetColorProfile(png_ptr, info_ptr,
                                             color_type, &inType, &pIntent);
    /* If we're not mandating an intent, use the one from the image. */
    if (intent == uint32_t(-1))
      intent = pIntent;
  }
  if (decoder->mInProfile && gfxPlatform::GetCMSOutputProfile()) {
    qcms_data_type outType;

    if (color_type & PNG_COLOR_MASK_ALPHA || num_trans)
      outType = QCMS_DATA_RGBA_8;
    else
      outType = QCMS_DATA_RGB_8;

    decoder->mTransform = qcms_transform_create(decoder->mInProfile,
                                           inType,
                                           gfxPlatform::GetCMSOutputProfile(),
                                           outType,
                                           (qcms_intent)intent);
  } else {
    png_set_gray_to_rgb(png_ptr);

    // only do gamma correction if CMS isn't entirely disabled
    if (decoder->mCMSMode != eCMSMode_Off)
      PNGDoGammaCorrection(png_ptr, info_ptr);

    if (decoder->mCMSMode == eCMSMode_All) {
      if (color_type & PNG_COLOR_MASK_ALPHA || num_trans)
        decoder->mTransform = gfxPlatform::GetCMSRGBATransform();
      else
        decoder->mTransform = gfxPlatform::GetCMSRGBTransform();
    }
  }

  /* let libpng expand interlaced images */
  if (interlace_type == PNG_INTERLACE_ADAM7) {
    /* number_passes = */
    png_set_interlace_handling(png_ptr);
  }

  /* now all of those things we set above are used to update various struct
   * members and whatnot, after which we can get channels, rowbytes, etc. */
  png_read_update_info(png_ptr, info_ptr);
  decoder->mChannels = channels = png_get_channels(png_ptr, info_ptr);

  /*---------------------------------------------------------------*/
  /* copy PNG info into imagelib structs (formerly png_set_dims()) */
  /*---------------------------------------------------------------*/

  // This code is currently unused, but it will be needed for bug 517713.
#if 0
  int32_t alpha_bits = 1;

  if (channels == 2 || channels == 4) {
    /* check if alpha is coming from a tRNS chunk and is binary */
    if (num_trans) {
      /* if it's not an indexed color image, tRNS means binary */
      if (color_type == PNG_COLOR_TYPE_PALETTE) {
        for (int i=0; i<num_trans; i++) {
          if ((trans[i] != 0) && (trans[i] != 255)) {
            alpha_bits = 8;
            break;
          }
        }
      }
    } else {
      alpha_bits = 8;
    }
  }
#endif

  if (channels == 1 || channels == 3)
    decoder->format = gfx::SurfaceFormat::B8G8R8X8;
  else if (channels == 2 || channels == 4)
    decoder->format = gfx::SurfaceFormat::B8G8R8A8;

#ifdef PNG_APNG_SUPPORTED
  if (png_get_valid(png_ptr, info_ptr, PNG_INFO_acTL))
    png_set_progressive_frame_fn(png_ptr, nsPNGDecoder::frame_info_callback,
                                 nullptr);

  if (png_get_first_frame_is_hidden(png_ptr, info_ptr)) {
    decoder->mFrameIsHidden = true;
  } else {
#endif
    decoder->CreateFrame(0, 0, width, height, decoder->format);
#ifdef PNG_APNG_SUPPORTED
  }
#endif

  if (decoder->mTransform &&
      (channels <= 2 || interlace_type == PNG_INTERLACE_ADAM7)) {
    uint32_t bpp[] = { 0, 3, 4, 3, 4 };
    decoder->mCMSLine =
      (uint8_t *)moz_malloc(bpp[channels] * width);
    if (!decoder->mCMSLine) {
      longjmp(png_jmpbuf(decoder->mPNG), 5); // NS_ERROR_OUT_OF_MEMORY
    }
  }

  if (interlace_type == PNG_INTERLACE_ADAM7) {
    if (height < INT32_MAX / (width * channels))
      decoder->interlacebuf = (uint8_t *)moz_malloc(channels * width * height);
    if (!decoder->interlacebuf) {
      longjmp(png_jmpbuf(decoder->mPNG), 5); // NS_ERROR_OUT_OF_MEMORY
    }
  }

  if (decoder->NeedsNewFrame()) {
    /* We know that we need a new frame, so pause input so the decoder
     * infrastructure can give it to us.
     */
    png_process_data_pause(png_ptr, /* save = */ 1);
  }
}
NS_IMETHODIMP nsCollationMacUC::AllocateRawSortKey(int32_t strength, const nsAString& stringIn,
                                                   uint8_t** key, uint32_t* outLen)
{
  NS_ENSURE_TRUE(mInit, NS_ERROR_NOT_INITIALIZED);
  NS_ENSURE_ARG_POINTER(key);
  NS_ENSURE_ARG_POINTER(outLen);

  nsresult res = EnsureCollator(strength);
  NS_ENSURE_SUCCESS(res, res);

  uint32_t stringInLen = stringIn.Length();

  if (mUseICU) {
    const UChar* str = (const UChar*)PromiseFlatString(stringIn).get();

    int32_t keyLength = ucol_getSortKey(mCollatorICU, str, stringInLen, nullptr, 0);
    NS_ENSURE_TRUE((stringInLen == 0 || keyLength > 0), NS_ERROR_FAILURE);

    // Since key is freed elsewhere with PR_Free, allocate with PR_Malloc.
    uint8_t* newKey = (uint8_t*)PR_Malloc(keyLength + 1);
    if (!newKey) {
      return NS_ERROR_OUT_OF_MEMORY;
    }

    keyLength = ucol_getSortKey(mCollatorICU, str, stringInLen, newKey, keyLength + 1);
    NS_ENSURE_TRUE((stringInLen == 0 || keyLength > 0), NS_ERROR_FAILURE);

    *key = newKey;
    *outLen = keyLength;

    return NS_OK;
  }

  uint32_t maxKeyLen = (1 + stringInLen) * kCollationValueSizeFactor * sizeof(UCCollationValue);
  if (maxKeyLen > mBufferLen) {
    uint32_t newBufferLen = mBufferLen;
    do {
      newBufferLen *= 2;
    } while (newBufferLen < maxKeyLen);
    void* newBuffer = moz_malloc(newBufferLen);
    if (!newBuffer) {
      return NS_ERROR_OUT_OF_MEMORY;
    }

    if (mBuffer) {
      moz_free(mBuffer);
      mBuffer = nullptr;
    }
    mBuffer = newBuffer;
    mBufferLen = newBufferLen;
  }

  ItemCount actual;
  OSStatus err = ::UCGetCollationKey(mCollator, (const UniChar*) PromiseFlatString(stringIn).get(),
                                     (UniCharCount) stringInLen,
                                     (ItemCount) (mBufferLen / sizeof(UCCollationValue)),
                                     &actual, (UCCollationValue *)mBuffer);
  NS_ENSURE_TRUE((err == noErr), NS_ERROR_FAILURE);

  uint32_t keyLength = actual * sizeof(UCCollationValue);
  // Since key is freed elsewhere with PR_Free, allocate with PR_Malloc.
  void* newKey = PR_Malloc(keyLength);
  if (!newKey) {
    return NS_ERROR_OUT_OF_MEMORY;
  }

  memcpy(newKey, mBuffer, keyLength);
  *key = (uint8_t *)newKey;
  *outLen = keyLength;

  return NS_OK;
}
Beispiel #23
0
void
nsPNGDecoder::info_callback(png_structp png_ptr, png_infop info_ptr)
{
/*  int number_passes;   NOT USED  */
  png_uint_32 width, height;
  int bit_depth, color_type, interlace_type, compression_type, filter_type;
  unsigned int channels;

  png_bytep trans = NULL;
  int num_trans = 0;

  nsPNGDecoder *decoder =
               static_cast<nsPNGDecoder*>(png_get_progressive_ptr(png_ptr));

  /* always decode to 24-bit RGB or 32-bit RGBA  */
  png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
               &interlace_type, &compression_type, &filter_type);

  /* Are we too big? */
  if (width > MOZ_PNG_MAX_DIMENSION || height > MOZ_PNG_MAX_DIMENSION)
    longjmp(png_jmpbuf(decoder->mPNG), 1);

  // Post our size to the superclass
  decoder->PostSize(width, height);
  if (decoder->HasError()) {
    // Setting the size lead to an error; this can happen when for example
    // a multipart channel sends an image of a different size.
    longjmp(png_jmpbuf(decoder->mPNG), 1);
  }

  if (color_type == PNG_COLOR_TYPE_PALETTE)
    png_set_expand(png_ptr);

  if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
    png_set_expand(png_ptr);

  if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
    int sample_max = (1 << bit_depth);
    png_color_16p trans_values;
    png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, &trans_values);
    /* libpng doesn't reject a tRNS chunk with out-of-range samples
       so we check it here to avoid setting up a useless opacity
       channel or producing unexpected transparent pixels when using
       libpng-1.2.19 through 1.2.26 (bug #428045) */
    if ((color_type == PNG_COLOR_TYPE_GRAY &&
       (int)trans_values->gray > sample_max) ||
       (color_type == PNG_COLOR_TYPE_RGB &&
       ((int)trans_values->red > sample_max ||
       (int)trans_values->green > sample_max ||
       (int)trans_values->blue > sample_max)))
      {
        /* clear the tRNS valid flag and release tRNS memory */
        png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0);
      }
    else
      png_set_expand(png_ptr);
  }

  if (bit_depth == 16)
    png_set_strip_16(png_ptr);

  qcms_data_type inType;
  PRUint32 intent = -1;
  PRUint32 pIntent;
  if (decoder->mCMSMode != eCMSMode_Off) {
    intent = gfxPlatform::GetRenderingIntent();
    decoder->mInProfile = PNGGetColorProfile(png_ptr, info_ptr,
                                             color_type, &inType, &pIntent);
    /* If we're not mandating an intent, use the one from the image. */
    if (intent == PRUint32(-1))
      intent = pIntent;
  }
  if (decoder->mInProfile && gfxPlatform::GetCMSOutputProfile()) {
    qcms_data_type outType;

    if (color_type & PNG_COLOR_MASK_ALPHA || num_trans)
      outType = QCMS_DATA_RGBA_8;
    else
      outType = QCMS_DATA_RGB_8;

    decoder->mTransform = qcms_transform_create(decoder->mInProfile,
                                           inType,
                                           gfxPlatform::GetCMSOutputProfile(),
                                           outType,
                                           (qcms_intent)intent);
  } else {
    png_set_gray_to_rgb(png_ptr);

    // only do gamma correction if CMS isn't entirely disabled
    if (decoder->mCMSMode != eCMSMode_Off)
      PNGDoGammaCorrection(png_ptr, info_ptr);

    if (decoder->mCMSMode == eCMSMode_All) {
      if (color_type & PNG_COLOR_MASK_ALPHA || num_trans)
        decoder->mTransform = gfxPlatform::GetCMSRGBATransform();
      else
        decoder->mTransform = gfxPlatform::GetCMSRGBTransform();
    }
  }

  /* let libpng expand interlaced images */
  if (interlace_type == PNG_INTERLACE_ADAM7) {
    /* number_passes = */
    png_set_interlace_handling(png_ptr);
  }

  /* now all of those things we set above are used to update various struct
   * members and whatnot, after which we can get channels, rowbytes, etc. */
  png_read_update_info(png_ptr, info_ptr);
  decoder->mChannels = channels = png_get_channels(png_ptr, info_ptr);

  /*---------------------------------------------------------------*/
  /* copy PNG info into imagelib structs (formerly png_set_dims()) */
  /*---------------------------------------------------------------*/

  PRInt32 alpha_bits = 1;

  if (channels == 2 || channels == 4) {
    /* check if alpha is coming from a tRNS chunk and is binary */
    if (num_trans) {
      /* if it's not an indexed color image, tRNS means binary */
      if (color_type == PNG_COLOR_TYPE_PALETTE) {
        for (int i=0; i<num_trans; i++) {
          if ((trans[i] != 0) && (trans[i] != 255)) {
            alpha_bits = 8;
            break;
          }
        }
      }
    } else {
      alpha_bits = 8;
    }
  }

  if (channels == 1 || channels == 3)
    decoder->format = gfxASurface::ImageFormatRGB24;
  else if (channels == 2 || channels == 4)
    decoder->format = gfxASurface::ImageFormatARGB32;

#ifdef PNG_APNG_SUPPORTED
  if (png_get_valid(png_ptr, info_ptr, PNG_INFO_acTL))
    png_set_progressive_frame_fn(png_ptr, nsPNGDecoder::frame_info_callback, NULL);

  if (png_get_first_frame_is_hidden(png_ptr, info_ptr)) {
    decoder->mFrameIsHidden = PR_TRUE;
  } else {
#endif
    decoder->CreateFrame(0, 0, width, height, decoder->format);
#ifdef PNG_APNG_SUPPORTED
  }
#endif

  if (decoder->mTransform &&
      (channels <= 2 || interlace_type == PNG_INTERLACE_ADAM7)) {
    PRUint32 bpp[] = { 0, 3, 4, 3, 4 };
    decoder->mCMSLine =
      (PRUint8 *)moz_malloc(bpp[channels] * width);
    if (!decoder->mCMSLine) {
      longjmp(png_jmpbuf(decoder->mPNG), 5); // NS_ERROR_OUT_OF_MEMORY
    }
  }

  if (interlace_type == PNG_INTERLACE_ADAM7) {
    if (height < PR_INT32_MAX / (width * channels))
      decoder->interlacebuf = (PRUint8 *)moz_malloc(channels * width * height);
    if (!decoder->interlacebuf) {
      longjmp(png_jmpbuf(decoder->mPNG), 5); // NS_ERROR_OUT_OF_MEMORY
    }
  }

  /* Reject any ancillary chunk after IDAT with a bad CRC (bug #397593).
   * It would be better to show the default frame (if one has already been
   * successfully decoded) before bailing, but it's simpler to just bail
   * out with an error message.
   */
  png_set_crc_action(png_ptr, PNG_CRC_NO_CHANGE, PNG_CRC_ERROR_QUIT);

  return;
}
 void* Allocate(uint32_t /* unused */, size_t aSize)
 {
   return moz_malloc(aSize);
 }
Beispiel #25
0
nsresult imgFrame::Init(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight, 
                        gfxASurface::gfxImageFormat aFormat, PRUint8 aPaletteDepth /* = 0 */)
{
  // assert for properties that should be verified by decoders, warn for properties related to bad content
  if (!AllowedImageSize(aWidth, aHeight))
    return NS_ERROR_FAILURE;

  mOffset.MoveTo(aX, aY);
  mSize.SizeTo(aWidth, aHeight);

  mFormat = aFormat;
  mPaletteDepth = aPaletteDepth;

  if (aPaletteDepth != 0) {
    // We're creating for a paletted image.
    if (aPaletteDepth > 8) {
      NS_ERROR("This Depth is not supported");
      return NS_ERROR_FAILURE;
    }

    // Use the fallible allocator here
    mPalettedImageData = (PRUint8*)moz_malloc(PaletteDataLength() + GetImageDataLength());
    NS_ENSURE_TRUE(mPalettedImageData, NS_ERROR_OUT_OF_MEMORY);
  } else {
    // For Windows, we must create the device surface first (if we're
    // going to) so that the image surface can wrap it.  Can't be done
    // the other way around.
#ifdef USE_WIN_SURFACE
    if (!mNeverUseDeviceSurface && !ShouldUseImageSurfaces()) {
      mWinSurface = new gfxWindowsSurface(gfxIntSize(mSize.width, mSize.height), mFormat);
      if (mWinSurface && mWinSurface->CairoStatus() == 0) {
        // no error
        mImageSurface = mWinSurface->GetAsImageSurface();
      } else {
        mWinSurface = nsnull;
      }
    }
#endif

    // For other platforms we create the image surface first and then
    // possibly wrap it in a device surface.  This branch is also used
    // on Windows if we're not using device surfaces or if we couldn't
    // create one.
    if (!mImageSurface)
      mImageSurface = new gfxImageSurface(gfxIntSize(mSize.width, mSize.height), mFormat);

    if (!mImageSurface || mImageSurface->CairoStatus()) {
      mImageSurface = nsnull;
      // guess
      return NS_ERROR_OUT_OF_MEMORY;
    }

#ifdef XP_MACOSX
    if (!mNeverUseDeviceSurface && !ShouldUseImageSurfaces()) {
      mQuartzSurface = new gfxQuartzImageSurface(mImageSurface);
    }
#endif
  }

  return NS_OK;
}
NS_IMETHODIMP
nsHTTPCompressConv::OnDataAvailable(nsIRequest* request,
                                    nsISupports *aContext,
                                    nsIInputStream *iStr,
                                    uint64_t aSourceOffset,
                                    uint32_t aCount)
{
    nsresult rv = NS_ERROR_INVALID_CONTENT_ENCODING;
    uint32_t streamLen = aCount;

    if (streamLen == 0)
    {
        NS_ERROR("count of zero passed to OnDataAvailable");
        return NS_ERROR_UNEXPECTED;
    }

    if (mStreamEnded)
    {
        // Hmm... this may just indicate that the data stream is done and that
        // what's left is either metadata or padding of some sort.... throwing
        // it out is probably the safe thing to do.
        uint32_t n;
        return iStr->ReadSegments(NS_DiscardSegment, nullptr, streamLen, &n);
    }

    switch (mMode)
    {
    case HTTP_COMPRESS_GZIP:
        streamLen = check_header(iStr, streamLen, &rv);

        if (rv != NS_OK)
            return rv;

        if (streamLen == 0)
            return NS_OK;

    // FALLTHROUGH

    case HTTP_COMPRESS_DEFLATE:

        if (mInpBuffer != nullptr && streamLen > mInpBufferLen)
        {
            mInpBuffer = (unsigned char *) moz_realloc(mInpBuffer, mInpBufferLen = streamLen);

            if (mOutBufferLen < streamLen * 2)
                mOutBuffer = (unsigned char *) moz_realloc(mOutBuffer, mOutBufferLen = streamLen * 3);

            if (mInpBuffer == nullptr || mOutBuffer == nullptr)
                return NS_ERROR_OUT_OF_MEMORY;
        }

        if (mInpBuffer == nullptr)
            mInpBuffer = (unsigned char *) moz_malloc(mInpBufferLen = streamLen);

        if (mOutBuffer == nullptr)
            mOutBuffer = (unsigned char *) moz_malloc(mOutBufferLen = streamLen * 3);

        if (mInpBuffer == nullptr || mOutBuffer == nullptr)
            return NS_ERROR_OUT_OF_MEMORY;

        uint32_t unused;
        iStr->Read((char *)mInpBuffer, streamLen, &unused);

        if (mMode == HTTP_COMPRESS_DEFLATE)
        {
            if (!mStreamInitialized)
            {
                memset(&d_stream, 0, sizeof (d_stream));

                if (inflateInit(&d_stream) != Z_OK)
                    return NS_ERROR_FAILURE;

                mStreamInitialized = true;
            }
            d_stream.next_in = mInpBuffer;
            d_stream.avail_in = (uInt)streamLen;

            mDummyStreamInitialised = false;
            for (;;)
            {
                d_stream.next_out = mOutBuffer;
                d_stream.avail_out = (uInt)mOutBufferLen;

                int code = inflate(&d_stream, Z_NO_FLUSH);
                unsigned bytesWritten = (uInt)mOutBufferLen - d_stream.avail_out;

                if (code == Z_STREAM_END)
                {
                    if (bytesWritten)
                    {
                        rv = do_OnDataAvailable(request, aContext, aSourceOffset, (char *)mOutBuffer, bytesWritten);
                        if (NS_FAILED (rv))
                            return rv;
                    }

                    inflateEnd(&d_stream);
                    mStreamEnded = true;
                    break;
                }
                else if (code == Z_OK)
                {
                    if (bytesWritten)
                    {
                        rv = do_OnDataAvailable(request, aContext, aSourceOffset, (char *)mOutBuffer, bytesWritten);
                        if (NS_FAILED (rv))
                            return rv;
                    }
                }
                else if (code == Z_BUF_ERROR)
                {
                    if (bytesWritten)
                    {
                        rv = do_OnDataAvailable(request, aContext, aSourceOffset, (char *)mOutBuffer, bytesWritten);
                        if (NS_FAILED (rv))
                            return rv;
                    }
                    break;
                }
                else if (code == Z_DATA_ERROR)
                {
                    // some servers (notably Apache with mod_deflate) don't generate zlib headers
                    // insert a dummy header and try again
                    static char dummy_head[2] =
                    {
                        0x8 + 0x7 * 0x10,
                        (((0x8 + 0x7 * 0x10) * 0x100 + 30) / 31 * 31) & 0xFF,
                    };
                    inflateReset(&d_stream);
                    d_stream.next_in = (Bytef*) dummy_head;
                    d_stream.avail_in = sizeof(dummy_head);

                    code = inflate(&d_stream, Z_NO_FLUSH);
                    if (code != Z_OK)
                        return NS_ERROR_FAILURE;

                    // stop an endless loop caused by non-deflate data being labelled as deflate
                    if (mDummyStreamInitialised) {
                        NS_WARNING("endless loop detected"
                                   " - invalid deflate");
                        return NS_ERROR_INVALID_CONTENT_ENCODING;
                    }
                    mDummyStreamInitialised = true;
                    // reset stream pointers to our original data
                    d_stream.next_in = mInpBuffer;
                    d_stream.avail_in = (uInt)streamLen;
                }
                else
                    return NS_ERROR_INVALID_CONTENT_ENCODING;
            } /* for */
        }
        else
        {
            if (!mStreamInitialized)
            {
                memset(&d_stream, 0, sizeof (d_stream));

                if (inflateInit2(&d_stream, -MAX_WBITS) != Z_OK)
                    return NS_ERROR_FAILURE;

                mStreamInitialized = true;
            }

            d_stream.next_in  = mInpBuffer;
            d_stream.avail_in = (uInt)streamLen;

            for (;;)
            {
                d_stream.next_out  = mOutBuffer;
                d_stream.avail_out = (uInt)mOutBufferLen;

                int code = inflate (&d_stream, Z_NO_FLUSH);
                unsigned bytesWritten = (uInt)mOutBufferLen - d_stream.avail_out;

                if (code == Z_STREAM_END)
                {
                    if (bytesWritten)
                    {
                        rv = do_OnDataAvailable(request, aContext, aSourceOffset, (char *)mOutBuffer, bytesWritten);
                        if (NS_FAILED (rv))
                            return rv;
                    }

                    inflateEnd(&d_stream);
                    mStreamEnded = true;
                    break;
                }
                else if (code == Z_OK)
                {
                    if (bytesWritten)
                    {
                        rv = do_OnDataAvailable(request, aContext, aSourceOffset, (char *)mOutBuffer, bytesWritten);
                        if (NS_FAILED (rv))
                            return rv;
                    }
                }
                else if (code == Z_BUF_ERROR)
                {
                    if (bytesWritten)
                    {
                        rv = do_OnDataAvailable(request, aContext, aSourceOffset, (char *)mOutBuffer, bytesWritten);
                        if (NS_FAILED (rv))
                            return rv;
                    }
                    break;
                }
                else
                    return NS_ERROR_INVALID_CONTENT_ENCODING;
            } /* for */
        } /* gzip */
        break;

    default:
        rv = mListener->OnDataAvailable(request, aContext, iStr, aSourceOffset, aCount);
        if (NS_FAILED (rv))
            return rv;
    } /* switch */

    return NS_OK;
} /* OnDataAvailable */