tor-browser

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

nsHttpRequestHead.cpp (10909B)


      1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* This Source Code Form is subject to the terms of the Mozilla Public
      3 * License, v. 2.0. If a copy of the MPL was not distributed with this
      4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      5 
      6 // HttpLog.h should generally be included first
      7 #include "HttpLog.h"
      8 
      9 #include "nsHttpRequestHead.h"
     10 #include "nsIHttpHeaderVisitor.h"
     11 #include "mozilla/net/Dictionary.h"
     12 
     13 //-----------------------------------------------------------------------------
     14 // nsHttpRequestHead
     15 //-----------------------------------------------------------------------------
     16 
     17 namespace mozilla {
     18 namespace net {
     19 
     20 nsHttpRequestHead::nsHttpRequestHead() { MOZ_COUNT_CTOR(nsHttpRequestHead); }
     21 
     22 nsHttpRequestHead::nsHttpRequestHead(const nsHttpRequestHead& aRequestHead) {
     23  MOZ_COUNT_CTOR(nsHttpRequestHead);
     24  nsHttpRequestHead& other = const_cast<nsHttpRequestHead&>(aRequestHead);
     25  RecursiveMutexAutoLock monitor(other.mRecursiveMutex);
     26 
     27  mHeaders = other.mHeaders;
     28  mMethod = other.mMethod;
     29  mVersion = other.mVersion;
     30  mRequestURI = other.mRequestURI;
     31  mPath = other.mPath;
     32  mOrigin = other.mOrigin;
     33  mParsedMethod = other.mParsedMethod;
     34  mHTTPS = other.mHTTPS;
     35  mInVisitHeaders = false;
     36 }
     37 
     38 nsHttpRequestHead::nsHttpRequestHead(nsHttpRequestHead&& aRequestHead) {
     39  MOZ_COUNT_CTOR(nsHttpRequestHead);
     40  nsHttpRequestHead& other = aRequestHead;
     41  RecursiveMutexAutoLock monitor(other.mRecursiveMutex);
     42 
     43  mHeaders = std::move(other.mHeaders);
     44  mMethod = std::move(other.mMethod);
     45  mVersion = std::move(other.mVersion);
     46  mRequestURI = std::move(other.mRequestURI);
     47  mPath = std::move(other.mPath);
     48  mOrigin = std::move(other.mOrigin);
     49  mParsedMethod = std::move(other.mParsedMethod);
     50  mHTTPS = std::move(other.mHTTPS);
     51  mInVisitHeaders = false;
     52 }
     53 
     54 nsHttpRequestHead::~nsHttpRequestHead() { MOZ_COUNT_DTOR(nsHttpRequestHead); }
     55 
     56 nsHttpRequestHead& nsHttpRequestHead::operator=(
     57    const nsHttpRequestHead& aRequestHead) {
     58  nsHttpRequestHead& other = const_cast<nsHttpRequestHead&>(aRequestHead);
     59  RecursiveMutexAutoLock monitorOther(other.mRecursiveMutex);
     60  RecursiveMutexAutoLock monitor(mRecursiveMutex);
     61 
     62  mHeaders = other.mHeaders;
     63  mMethod = other.mMethod;
     64  mVersion = other.mVersion;
     65  mRequestURI = other.mRequestURI;
     66  mPath = other.mPath;
     67  mOrigin = other.mOrigin;
     68  mParsedMethod = other.mParsedMethod;
     69  mHTTPS = other.mHTTPS;
     70  mInVisitHeaders = false;
     71  return *this;
     72 }
     73 
     74 // Don't use this function. It is only used by HttpChannelParent to avoid
     75 // copying of request headers!!!
     76 const nsHttpHeaderArray& nsHttpRequestHead::Headers() const {
     77  nsHttpRequestHead& curr = const_cast<nsHttpRequestHead&>(*this);
     78  curr.mRecursiveMutex.AssertCurrentThreadIn();
     79  return mHeaders;
     80 }
     81 
     82 void nsHttpRequestHead::SetHeaders(const nsHttpHeaderArray& aHeaders) {
     83  RecursiveMutexAutoLock mon(mRecursiveMutex);
     84  mHeaders = aHeaders;
     85 }
     86 
     87 void nsHttpRequestHead::SetVersion(HttpVersion version) {
     88  RecursiveMutexAutoLock mon(mRecursiveMutex);
     89  mVersion = version;
     90 }
     91 
     92 void nsHttpRequestHead::SetRequestURI(const nsACString& s) {
     93  RecursiveMutexAutoLock mon(mRecursiveMutex);
     94  mRequestURI = s;
     95 }
     96 
     97 void nsHttpRequestHead::SetPath(const nsACString& s) {
     98  RecursiveMutexAutoLock mon(mRecursiveMutex);
     99  mPath = s;
    100 }
    101 
    102 void nsHttpRequestHead::SetDictionary(DictionaryCacheEntry* aDict) {
    103  RecursiveMutexAutoLock mon(mRecursiveMutex);  // XXX necessary?
    104  mDict = aDict;
    105 }
    106 
    107 uint32_t nsHttpRequestHead::HeaderCount() {
    108  RecursiveMutexAutoLock mon(mRecursiveMutex);
    109  return mHeaders.Count();
    110 }
    111 
    112 nsresult nsHttpRequestHead::VisitHeaders(
    113    nsIHttpHeaderVisitor* visitor,
    114    nsHttpHeaderArray::VisitorFilter
    115        filter /* = nsHttpHeaderArray::eFilterAll*/) {
    116  RecursiveMutexAutoLock mon(mRecursiveMutex);
    117  mInVisitHeaders = true;
    118  nsresult rv = mHeaders.VisitHeaders(visitor, filter);
    119  mInVisitHeaders = false;
    120  return rv;
    121 }
    122 
    123 void nsHttpRequestHead::Method(nsACString& aMethod) {
    124  RecursiveMutexAutoLock mon(mRecursiveMutex);
    125  aMethod = mMethod;
    126 }
    127 
    128 HttpVersion nsHttpRequestHead::Version() {
    129  RecursiveMutexAutoLock mon(mRecursiveMutex);
    130  return mVersion;
    131 }
    132 
    133 void nsHttpRequestHead::RequestURI(nsACString& aRequestURI) {
    134  RecursiveMutexAutoLock mon(mRecursiveMutex);
    135  aRequestURI = mRequestURI;
    136 }
    137 
    138 void nsHttpRequestHead::Path(nsACString& aPath) {
    139  RecursiveMutexAutoLock mon(mRecursiveMutex);
    140  aPath = mPath.IsEmpty() ? mRequestURI : mPath;
    141 }
    142 
    143 void nsHttpRequestHead::SetHTTPS(bool val) {
    144  RecursiveMutexAutoLock mon(mRecursiveMutex);
    145  mHTTPS = val;
    146 }
    147 
    148 void nsHttpRequestHead::Origin(nsACString& aOrigin) {
    149  RecursiveMutexAutoLock mon(mRecursiveMutex);
    150  aOrigin = mOrigin;
    151 }
    152 
    153 nsresult nsHttpRequestHead::SetHeader(const nsACString& h, const nsACString& v,
    154                                      bool m /*= false*/) {
    155  RecursiveMutexAutoLock mon(mRecursiveMutex);
    156 
    157  if (mInVisitHeaders) {
    158    return NS_ERROR_FAILURE;
    159  }
    160 
    161  return mHeaders.SetHeader(h, v, m,
    162                            nsHttpHeaderArray::eVarietyRequestOverride);
    163 }
    164 
    165 nsresult nsHttpRequestHead::SetHeader(const nsHttpAtom& h, const nsACString& v,
    166                                      bool m /*= false*/) {
    167  RecursiveMutexAutoLock mon(mRecursiveMutex);
    168 
    169  if (mInVisitHeaders) {
    170    return NS_ERROR_FAILURE;
    171  }
    172 
    173  return mHeaders.SetHeader(h, v, m,
    174                            nsHttpHeaderArray::eVarietyRequestOverride);
    175 }
    176 
    177 nsresult nsHttpRequestHead::SetHeader(
    178    const nsHttpAtom& h, const nsACString& v, bool m,
    179    nsHttpHeaderArray::HeaderVariety variety) {
    180  RecursiveMutexAutoLock mon(mRecursiveMutex);
    181 
    182  if (mInVisitHeaders) {
    183    return NS_ERROR_FAILURE;
    184  }
    185 
    186  return mHeaders.SetHeader(h, v, m, variety);
    187 }
    188 
    189 nsresult nsHttpRequestHead::SetEmptyHeader(const nsACString& h) {
    190  RecursiveMutexAutoLock mon(mRecursiveMutex);
    191 
    192  if (mInVisitHeaders) {
    193    return NS_ERROR_FAILURE;
    194  }
    195 
    196  return mHeaders.SetEmptyHeader(h, nsHttpHeaderArray::eVarietyRequestOverride);
    197 }
    198 
    199 nsresult nsHttpRequestHead::GetHeader(const nsHttpAtom& h, nsACString& v) {
    200  v.Truncate();
    201  RecursiveMutexAutoLock mon(mRecursiveMutex);
    202  return mHeaders.GetHeader(h, v);
    203 }
    204 
    205 nsresult nsHttpRequestHead::ClearHeader(const nsHttpAtom& h) {
    206  RecursiveMutexAutoLock mon(mRecursiveMutex);
    207 
    208  if (mInVisitHeaders) {
    209    return NS_ERROR_FAILURE;
    210  }
    211 
    212  mHeaders.ClearHeader(h);
    213  return NS_OK;
    214 }
    215 
    216 void nsHttpRequestHead::ClearHeaders() {
    217  RecursiveMutexAutoLock mon(mRecursiveMutex);
    218 
    219  if (mInVisitHeaders) {
    220    return;
    221  }
    222 
    223  mHeaders.Clear();
    224 }
    225 
    226 bool nsHttpRequestHead::HasHeader(const nsHttpAtom& h) {
    227  RecursiveMutexAutoLock mon(mRecursiveMutex);
    228  return mHeaders.HasHeader(h);
    229 }
    230 
    231 bool nsHttpRequestHead::HasHeaderValue(const nsHttpAtom& h, const char* v) {
    232  RecursiveMutexAutoLock mon(mRecursiveMutex);
    233  return mHeaders.HasHeaderValue(h, v);
    234 }
    235 
    236 nsresult nsHttpRequestHead::SetHeaderOnce(const nsHttpAtom& h, const char* v,
    237                                          bool merge /*= false */) {
    238  RecursiveMutexAutoLock mon(mRecursiveMutex);
    239 
    240  if (mInVisitHeaders) {
    241    return NS_ERROR_FAILURE;
    242  }
    243 
    244  if (!merge || !mHeaders.HasHeaderValue(h, v)) {
    245    return mHeaders.SetHeader(h, nsDependentCString(v), merge,
    246                              nsHttpHeaderArray::eVarietyRequestOverride);
    247  }
    248  return NS_OK;
    249 }
    250 
    251 nsHttpRequestHead::ParsedMethodType nsHttpRequestHead::ParsedMethod() {
    252  RecursiveMutexAutoLock mon(mRecursiveMutex);
    253  return mParsedMethod;
    254 }
    255 
    256 bool nsHttpRequestHead::EqualsMethod(ParsedMethodType aType) {
    257  RecursiveMutexAutoLock mon(mRecursiveMutex);
    258  return mParsedMethod == aType;
    259 }
    260 
    261 void nsHttpRequestHead::ParseHeaderSet(const char* buffer) {
    262  RecursiveMutexAutoLock mon(mRecursiveMutex);
    263  nsHttpAtom hdr;
    264  nsAutoCString headerNameOriginal;
    265  nsAutoCString val;
    266  while (buffer) {
    267    const char* eof = strchr(buffer, '\r');
    268    if (!eof) {
    269      break;
    270    }
    271    if (NS_SUCCEEDED(nsHttpHeaderArray::ParseHeaderLine(
    272            nsDependentCSubstring(buffer, eof - buffer), &hdr,
    273            &headerNameOriginal, &val))) {
    274      DebugOnly<nsresult> rv =
    275          mHeaders.SetHeaderFromNet(hdr, headerNameOriginal, val, false);
    276      MOZ_ASSERT(NS_SUCCEEDED(rv));
    277    }
    278    buffer = eof + 1;
    279    if (*buffer == '\n') {
    280      buffer++;
    281    }
    282  }
    283 }
    284 
    285 bool nsHttpRequestHead::IsHTTPS() {
    286  RecursiveMutexAutoLock mon(mRecursiveMutex);
    287  return mHTTPS;
    288 }
    289 
    290 void nsHttpRequestHead::SetMethod(const nsACString& method) {
    291  RecursiveMutexAutoLock mon(mRecursiveMutex);
    292 
    293  mMethod = method;
    294  ParseMethod(mMethod, mParsedMethod);
    295 }
    296 
    297 // static
    298 void nsHttpRequestHead::ParseMethod(const nsCString& aRawMethod,
    299                                    ParsedMethodType& aParsedMethod) {
    300  aParsedMethod = kMethod_Custom;
    301  if (!strcmp(aRawMethod.get(), "GET")) {
    302    aParsedMethod = kMethod_Get;
    303  } else if (!strcmp(aRawMethod.get(), "POST")) {
    304    aParsedMethod = kMethod_Post;
    305  } else if (!strcmp(aRawMethod.get(), "PATCH")) {
    306    aParsedMethod = kMethod_Patch;
    307  } else if (!strcmp(aRawMethod.get(), "OPTIONS")) {
    308    aParsedMethod = kMethod_Options;
    309  } else if (!strcmp(aRawMethod.get(), "CONNECT")) {
    310    aParsedMethod = kMethod_Connect;
    311  } else if (!strcmp(aRawMethod.get(), "HEAD")) {
    312    aParsedMethod = kMethod_Head;
    313  } else if (!strcmp(aRawMethod.get(), "PUT")) {
    314    aParsedMethod = kMethod_Put;
    315  } else if (!strcmp(aRawMethod.get(), "TRACE")) {
    316    aParsedMethod = kMethod_Trace;
    317  }
    318 }
    319 
    320 void nsHttpRequestHead::SetOrigin(const nsACString& scheme,
    321                                  const nsACString& host, int32_t port) {
    322  RecursiveMutexAutoLock mon(mRecursiveMutex);
    323  mOrigin.Assign(scheme);
    324  mOrigin.AppendLiteral("://");
    325  mOrigin.Append(host);
    326  if (port >= 0) {
    327    mOrigin.AppendLiteral(":");
    328    mOrigin.AppendInt(port);
    329  }
    330 }
    331 
    332 bool nsHttpRequestHead::IsSafeMethod() {
    333  RecursiveMutexAutoLock mon(mRecursiveMutex);
    334  // This code will need to be extended for new safe methods, otherwise
    335  // they'll default to "not safe".
    336  if ((mParsedMethod == kMethod_Get) || (mParsedMethod == kMethod_Head) ||
    337      (mParsedMethod == kMethod_Options) || (mParsedMethod == kMethod_Trace)) {
    338    return true;
    339  }
    340 
    341  if (mParsedMethod != kMethod_Custom) {
    342    return false;
    343  }
    344 
    345  return (!strcmp(mMethod.get(), "PROPFIND") ||
    346          !strcmp(mMethod.get(), "REPORT") || !strcmp(mMethod.get(), "SEARCH"));
    347 }
    348 
    349 void nsHttpRequestHead::Flatten(nsACString& buf, bool pruneProxyHeaders) {
    350  RecursiveMutexAutoLock mon(mRecursiveMutex);
    351  // note: the first append is intentional.
    352 
    353  buf.Append(mMethod);
    354  buf.Append(' ');
    355  buf.Append(mRequestURI);
    356  buf.AppendLiteral(" HTTP/");
    357 
    358  switch (mVersion) {
    359    case HttpVersion::v1_1:
    360      buf.AppendLiteral("1.1");
    361      break;
    362    case HttpVersion::v0_9:
    363      buf.AppendLiteral("0.9");
    364      break;
    365    default:
    366      buf.AppendLiteral("1.0");
    367  }
    368 
    369  buf.AppendLiteral("\r\n");
    370 
    371  mHeaders.Flatten(buf, pruneProxyHeaders, false);
    372 }
    373 
    374 }  // namespace net
    375 }  // namespace mozilla