tor-browser

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

BodyExtractor.cpp (6285B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "BodyExtractor.h"
      8 
      9 #include "mozilla/UniquePtr.h"
     10 #include "mozilla/dom/File.h"
     11 #include "mozilla/dom/FormData.h"
     12 #include "mozilla/dom/ShadowRoot.h"
     13 #include "mozilla/dom/TypedArray.h"
     14 #include "mozilla/dom/URLSearchParams.h"
     15 #include "mozilla/dom/XMLHttpRequest.h"
     16 #include "nsContentUtils.h"
     17 #include "nsDOMSerializer.h"
     18 #include "nsIGlobalObject.h"
     19 #include "nsIInputStream.h"
     20 #include "nsIOutputStream.h"
     21 #include "nsIStorageStream.h"
     22 #include "nsStringStream.h"
     23 
     24 namespace mozilla::dom {
     25 
     26 static nsresult GetBufferDataAsStream(Vector<uint8_t>&& aData,
     27                                      nsIInputStream** aResult,
     28                                      uint64_t* aContentLength,
     29                                      nsACString& aContentType,
     30                                      nsACString& aCharset) {
     31  aContentType.SetIsVoid(true);
     32  aCharset.Truncate();
     33 
     34  *aContentLength = aData.length();
     35 
     36  nsCOMPtr<nsIInputStream> stream;
     37  nsresult rv = NS_NewByteInputStream(
     38      getter_AddRefs(stream),
     39      AsChars(Span(aData.extractOrCopyRawBuffer(), *aContentLength)),
     40      NS_ASSIGNMENT_ADOPT);
     41  NS_ENSURE_SUCCESS(rv, rv);
     42 
     43  stream.forget(aResult);
     44 
     45  return NS_OK;
     46 }
     47 
     48 template <>
     49 nsresult BodyExtractor<const ArrayBuffer>::GetAsStream(
     50    nsIInputStream** aResult, uint64_t* aContentLength,
     51    nsACString& aContentTypeWithCharset, nsACString& aCharset) const {
     52  Maybe<Vector<uint8_t>> body = mBody->CreateFromData<Vector<uint8_t>>();
     53  if (body.isNothing()) {
     54    return NS_ERROR_OUT_OF_MEMORY;
     55  }
     56  return GetBufferDataAsStream(body.extract(), aResult, aContentLength,
     57                               aContentTypeWithCharset, aCharset);
     58 }
     59 
     60 template <>
     61 nsresult BodyExtractor<const ArrayBufferView>::GetAsStream(
     62    nsIInputStream** aResult, uint64_t* aContentLength,
     63    nsACString& aContentTypeWithCharset, nsACString& aCharset) const {
     64  Maybe<Vector<uint8_t>> body = mBody->CreateFromData<Vector<uint8_t>>();
     65  if (body.isNothing()) {
     66    return NS_ERROR_OUT_OF_MEMORY;
     67  }
     68  return GetBufferDataAsStream(body.extract(), aResult, aContentLength,
     69                               aContentTypeWithCharset, aCharset);
     70 }
     71 
     72 template <>
     73 nsresult BodyExtractor<Document>::GetAsStream(
     74    nsIInputStream** aResult, uint64_t* aContentLength,
     75    nsACString& aContentTypeWithCharset, nsACString& aCharset) const {
     76  NS_ENSURE_STATE(mBody);
     77  aCharset.AssignLiteral("UTF-8");
     78 
     79  nsresult rv;
     80  nsCOMPtr<nsIStorageStream> storStream;
     81  rv = NS_NewStorageStream(4096, UINT32_MAX, getter_AddRefs(storStream));
     82  NS_ENSURE_SUCCESS(rv, rv);
     83 
     84  nsCOMPtr<nsIOutputStream> output;
     85  rv = storStream->GetOutputStream(0, getter_AddRefs(output));
     86  NS_ENSURE_SUCCESS(rv, rv);
     87 
     88  if (mBody->IsHTMLDocument()) {
     89    aContentTypeWithCharset.AssignLiteral("text/html;charset=UTF-8");
     90 
     91    nsString serialized;
     92    if (!nsContentUtils::SerializeNodeToMarkup(mBody, true, serialized, false,
     93                                               {})) {
     94      return NS_ERROR_OUT_OF_MEMORY;
     95    }
     96 
     97    nsAutoCString utf8Serialized;
     98    if (!AppendUTF16toUTF8(serialized, utf8Serialized, fallible)) {
     99      return NS_ERROR_OUT_OF_MEMORY;
    100    }
    101 
    102    uint32_t written;
    103    rv = output->Write(utf8Serialized.get(), utf8Serialized.Length(), &written);
    104    NS_ENSURE_SUCCESS(rv, rv);
    105 
    106    MOZ_ASSERT(written == utf8Serialized.Length());
    107  } else {
    108    aContentTypeWithCharset.AssignLiteral("application/xml;charset=UTF-8");
    109 
    110    auto serializer = MakeUnique<nsDOMSerializer>();
    111 
    112    // Make sure to use the encoding we'll send
    113    ErrorResult res;
    114    serializer->SerializeToStream(*mBody, output, u"UTF-8"_ns, res);
    115    if (NS_WARN_IF(res.Failed())) {
    116      return res.StealNSResult();
    117    }
    118  }
    119 
    120  output->Close();
    121 
    122  uint32_t length;
    123  rv = storStream->GetLength(&length);
    124  NS_ENSURE_SUCCESS(rv, rv);
    125  *aContentLength = length;
    126 
    127  rv = storStream->NewInputStream(0, aResult);
    128  NS_ENSURE_SUCCESS(rv, rv);
    129  return NS_OK;
    130 }
    131 
    132 template <>
    133 nsresult BodyExtractor<const nsAString>::GetAsStream(
    134    nsIInputStream** aResult, uint64_t* aContentLength,
    135    nsACString& aContentTypeWithCharset, nsACString& aCharset) const {
    136  nsCString encoded;
    137  if (!CopyUTF16toUTF8(*mBody, encoded, fallible)) {
    138    return NS_ERROR_OUT_OF_MEMORY;
    139  }
    140 
    141  uint32_t encodedLength = encoded.Length();
    142  nsresult rv = NS_NewCStringInputStream(aResult, std::move(encoded));
    143  if (NS_WARN_IF(NS_FAILED(rv))) {
    144    return rv;
    145  }
    146 
    147  *aContentLength = encodedLength;
    148  aContentTypeWithCharset.AssignLiteral("text/plain;charset=UTF-8");
    149  aCharset.AssignLiteral("UTF-8");
    150  return NS_OK;
    151 }
    152 
    153 template <>
    154 nsresult BodyExtractor<nsIInputStream>::GetAsStream(
    155    nsIInputStream** aResult, uint64_t* aContentLength,
    156    nsACString& aContentTypeWithCharset, nsACString& aCharset) const {
    157  aContentTypeWithCharset.AssignLiteral("text/plain");
    158  aCharset.Truncate();
    159 
    160  nsresult rv = mBody->Available(aContentLength);
    161  NS_ENSURE_SUCCESS(rv, rv);
    162 
    163  nsCOMPtr<nsIInputStream> stream(mBody);
    164  stream.forget(aResult);
    165  return NS_OK;
    166 }
    167 
    168 template <>
    169 nsresult BodyExtractor<const Blob>::GetAsStream(
    170    nsIInputStream** aResult, uint64_t* aContentLength,
    171    nsACString& aContentTypeWithCharset, nsACString& aCharset) const {
    172  return mBody->GetSendInfo(aResult, aContentLength, aContentTypeWithCharset,
    173                            aCharset);
    174 }
    175 
    176 template <>
    177 nsresult BodyExtractor<const FormData>::GetAsStream(
    178    nsIInputStream** aResult, uint64_t* aContentLength,
    179    nsACString& aContentTypeWithCharset, nsACString& aCharset) const {
    180  return mBody->GetSendInfo(aResult, aContentLength, aContentTypeWithCharset,
    181                            aCharset);
    182 }
    183 
    184 template <>
    185 nsresult BodyExtractor<const URLSearchParams>::GetAsStream(
    186    nsIInputStream** aResult, uint64_t* aContentLength,
    187    nsACString& aContentTypeWithCharset, nsACString& aCharset) const {
    188  return mBody->GetSendInfo(aResult, aContentLength, aContentTypeWithCharset,
    189                            aCharset);
    190 }
    191 
    192 }  // namespace mozilla::dom