mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-22 07:07:30 +09:00
[Network, DOM] Align our implementation with the current CORS/Fetch spec.
This commit is contained in:
parent
bf19c2087b
commit
37f0199c79
9 changed files with 366 additions and 31 deletions
|
|
@ -7058,16 +7058,26 @@ nsContentUtils::HasDistributedChildren(nsIContent* aContent)
|
|||
|
||||
// static
|
||||
bool
|
||||
nsContentUtils::IsForbiddenRequestHeader(const nsACString& aHeader)
|
||||
nsContentUtils::IsForbiddenRequestHeader(const nsACString& aHeader,
|
||||
const nsACString& aValue)
|
||||
{
|
||||
if (IsForbiddenSystemRequestHeader(aHeader)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((nsContentUtils::IsOverrideMethodHeader(aHeader) &&
|
||||
nsContentUtils::ContainsForbiddenMethod(aValue))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return StringBeginsWith(aHeader, NS_LITERAL_CSTRING("proxy-"),
|
||||
nsCaseInsensitiveCStringComparator()) ||
|
||||
StringBeginsWith(aHeader, NS_LITERAL_CSTRING("sec-"),
|
||||
nsCaseInsensitiveCStringComparator());
|
||||
if (StringBeginsWith(aHeader, NS_LITERAL_CSTRING("proxy-"),
|
||||
nsCaseInsensitiveCStringComparator()) ||
|
||||
StringBeginsWith(aHeader, NS_LITERAL_CSTRING("sec-"),
|
||||
nsCaseInsensitiveCStringComparator())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
@ -7096,6 +7106,64 @@ nsContentUtils::IsForbiddenResponseHeader(const nsACString& aHeader)
|
|||
aHeader.LowerCaseEqualsASCII("set-cookie2"));
|
||||
}
|
||||
|
||||
// static
|
||||
bool
|
||||
nsContentUtils::IsOverrideMethodHeader(const nsACString& headerName) {
|
||||
return headerName.LowerCaseEqualsASCII("x-http-method-override") ||
|
||||
headerName.LowerCaseEqualsASCII("x-http-method") ||
|
||||
headerName.LowerCaseEqualsASCII("x-method-override");
|
||||
}
|
||||
|
||||
// static
|
||||
bool
|
||||
nsContentUtils::ContainsForbiddenMethod(const nsACString& headerValue) {
|
||||
bool hasInsecureMethod = false;
|
||||
nsCCharSeparatedTokenizer tokenizer(headerValue, ',');
|
||||
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
const nsDependentCSubstring& value = tokenizer.nextToken();
|
||||
|
||||
if (value.LowerCaseEqualsASCII("connect") ||
|
||||
value.LowerCaseEqualsASCII("trace") ||
|
||||
value.LowerCaseEqualsASCII("track")) {
|
||||
hasInsecureMethod = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return hasInsecureMethod;
|
||||
}
|
||||
|
||||
// static
|
||||
bool nsContentUtils::IsCorsUnsafeRequestHeaderValue(
|
||||
const nsACString& aHeaderValue) {
|
||||
const char* cur = aHeaderValue.BeginReading();
|
||||
const char* end = aHeaderValue.EndReading();
|
||||
|
||||
while (cur != end) {
|
||||
// Implementation of
|
||||
// https://fetch.spec.whatwg.org/#cors-unsafe-request-header-byte Is less
|
||||
// than a space but not a horizontal tab
|
||||
if ((*cur < ' ' && *cur != '\t') || *cur == '"' || *cur == '(' ||
|
||||
*cur == ')' || *cur == ':' || *cur == '<' || *cur == '>' ||
|
||||
*cur == '?' || *cur == '@' || *cur == '[' || *cur == '\\' ||
|
||||
*cur == ']' || *cur == '{' || *cur == '}' ||
|
||||
*cur == 0x7F) { // 0x75 is DEL
|
||||
return true;
|
||||
}
|
||||
cur++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// static
|
||||
bool nsContentUtils::IsAllowedNonCorsAccept(const nsACString& aHeaderValue) {
|
||||
if (IsCorsUnsafeRequestHeaderValue(aHeaderValue)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// static
|
||||
bool
|
||||
nsContentUtils::IsAllowedNonCorsContentType(const nsACString& aHeaderValue)
|
||||
|
|
@ -7103,6 +7171,10 @@ nsContentUtils::IsAllowedNonCorsContentType(const nsACString& aHeaderValue)
|
|||
nsAutoCString contentType;
|
||||
nsAutoCString unused;
|
||||
|
||||
if (IsCorsUnsafeRequestHeaderValue(aHeaderValue)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsresult rv = NS_ParseRequestContentType(aHeaderValue, contentType, unused);
|
||||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
|
|
@ -7113,6 +7185,41 @@ nsContentUtils::IsAllowedNonCorsContentType(const nsACString& aHeaderValue)
|
|||
contentType.LowerCaseEqualsLiteral("multipart/form-data");
|
||||
}
|
||||
|
||||
// static
|
||||
bool nsContentUtils::IsAllowedNonCorsLanguage(const nsACString& aHeaderValue) {
|
||||
const char* cur = aHeaderValue.BeginReading();
|
||||
const char* end = aHeaderValue.EndReading();
|
||||
|
||||
while (cur != end) {
|
||||
if ((*cur >= '0' && *cur <= '9') || (*cur >= 'A' && *cur <= 'Z') ||
|
||||
(*cur >= 'a' && *cur <= 'z') || *cur == ' ' || *cur == '*' ||
|
||||
*cur == ',' || *cur == '-' || *cur == '.' || *cur == ';' ||
|
||||
*cur == '=') {
|
||||
cur++;
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// static
|
||||
bool nsContentUtils::IsCORSSafelistedRequestHeader(const nsACString& aName,
|
||||
const nsACString& aValue) {
|
||||
// See https://fetch.spec.whatwg.org/#cors-safelisted-request-header
|
||||
if (aValue.Length() > 128) {
|
||||
return false;
|
||||
}
|
||||
return (aName.LowerCaseEqualsLiteral("accept") &&
|
||||
nsContentUtils::IsAllowedNonCorsAccept(aValue)) ||
|
||||
(aName.LowerCaseEqualsLiteral("accept-language") &&
|
||||
nsContentUtils::IsAllowedNonCorsLanguage(aValue)) ||
|
||||
(aName.LowerCaseEqualsLiteral("content-language") &&
|
||||
nsContentUtils::IsAllowedNonCorsLanguage(aValue)) ||
|
||||
(aName.LowerCaseEqualsLiteral("content-type") &&
|
||||
nsContentUtils::IsAllowedNonCorsContentType(aValue));
|
||||
}
|
||||
|
||||
bool
|
||||
nsContentUtils::DOMWindowDumpEnabled()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2425,7 +2425,8 @@ public:
|
|||
* Returns whether a given header is forbidden for an XHR or fetch
|
||||
* request.
|
||||
*/
|
||||
static bool IsForbiddenRequestHeader(const nsACString& aHeader);
|
||||
static bool IsForbiddenRequestHeader(const nsACString& aHeader,
|
||||
const nsACString& aValue);
|
||||
|
||||
/**
|
||||
* Returns whether a given header is forbidden for a system XHR
|
||||
|
|
@ -2433,18 +2434,50 @@ public:
|
|||
*/
|
||||
static bool IsForbiddenSystemRequestHeader(const nsACString& aHeader);
|
||||
|
||||
/**
|
||||
* Returns whether a given header has characters that aren't permitted
|
||||
*/
|
||||
static bool IsCorsUnsafeRequestHeaderValue(const nsACString& aHeaderValue);
|
||||
|
||||
/**
|
||||
* Returns whether a given Accept header value is allowed
|
||||
* for a non-CORS XHR or fetch request.
|
||||
*/
|
||||
static bool IsAllowedNonCorsAccept(const nsACString& aHeaderValue);
|
||||
|
||||
/**
|
||||
* Returns whether a given Content-Type header value is allowed
|
||||
* for a non-CORS XHR or fetch request.
|
||||
*/
|
||||
static bool IsAllowedNonCorsContentType(const nsACString& aHeaderValue);
|
||||
|
||||
/**
|
||||
* Returns whether a given Content-Language or accept-language header value is
|
||||
* allowed for a non-CORS XHR or fetch request.
|
||||
*/
|
||||
static bool IsAllowedNonCorsLanguage(const nsACString& aHeaderValue);
|
||||
|
||||
/**
|
||||
* Returns whether a given header and value is a CORS-safelisted request
|
||||
* header per https://fetch.spec.whatwg.org/#cors-safelisted-request-header
|
||||
*/
|
||||
static bool IsCORSSafelistedRequestHeader(const nsACString& aName,
|
||||
const nsACString& aValue);
|
||||
|
||||
/**
|
||||
* Returns whether a given header is forbidden for an XHR or fetch
|
||||
* response.
|
||||
*/
|
||||
static bool IsForbiddenResponseHeader(const nsACString& aHeader);
|
||||
|
||||
/**
|
||||
* Checks whether the header overrides any http methods
|
||||
*/
|
||||
static bool IsOverrideMethodHeader(const nsACString& headerName);
|
||||
/**
|
||||
* Checks whether the header value contains any forbidden method
|
||||
*/
|
||||
static bool ContainsForbiddenMethod(const nsACString& headerValue);
|
||||
/**
|
||||
* Returns the inner window ID for the window associated with a request,
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "mozilla/dom/InternalHeaders.h"
|
||||
|
||||
#include "FetchUtil.h"
|
||||
#include "mozilla/dom/FetchTypes.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
|
||||
|
|
@ -46,20 +47,112 @@ InternalHeaders::ToIPC(nsTArray<HeadersEntry>& aIPCHeaders,
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
InternalHeaders::IsValidHeaderValue(const nsCString& aLowerName,
|
||||
const nsCString& aNormalizedValue,
|
||||
ErrorResult& aRv) {
|
||||
// Steps 2 to 6 for ::Set() and ::Append() in the spec.
|
||||
|
||||
// Step 2
|
||||
if (IsInvalidName(aLowerName, aRv) || IsInvalidValue(aNormalizedValue, aRv)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 3
|
||||
if (IsImmutable(aRv)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 4
|
||||
if (mGuard == HeadersGuardEnum::Request) {
|
||||
if (IsForbiddenRequestHeader(aLowerName, aNormalizedValue)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 5
|
||||
if (mGuard == HeadersGuardEnum::Request_no_cors) {
|
||||
nsAutoCString tempValue;
|
||||
Get(aLowerName, tempValue, aRv);
|
||||
|
||||
if (tempValue.IsVoid()) {
|
||||
tempValue = aNormalizedValue;
|
||||
} else {
|
||||
tempValue.Append(", ");
|
||||
tempValue.Append(aNormalizedValue);
|
||||
}
|
||||
|
||||
if (!nsContentUtils::IsCORSSafelistedRequestHeader(aLowerName, tempValue)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 6
|
||||
else if (IsForbiddenResponseHeader(aLowerName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
InternalHeaders::Append(const nsACString& aName, const nsACString& aValue,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
// Step 1
|
||||
nsAutoCString trimValue;
|
||||
NS_TrimHTTPWhitespace(aValue, trimValue);
|
||||
|
||||
// Steps 2 to 6
|
||||
nsAutoCString lowerName;
|
||||
ToLowerCase(aName, lowerName);
|
||||
|
||||
if (IsInvalidMutableHeader(lowerName, aValue, aRv)) {
|
||||
if (!IsValidHeaderValue(lowerName, trimValue, aRv)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 7
|
||||
SetListDirty();
|
||||
|
||||
mList.AppendElement(Entry(lowerName, aValue));
|
||||
|
||||
// Step 8
|
||||
if (mGuard == HeadersGuardEnum::Request_no_cors) {
|
||||
RemovePrivilegedNoCorsRequestHeaders();
|
||||
}
|
||||
}
|
||||
|
||||
void InternalHeaders::RemovePrivilegedNoCorsRequestHeaders() {
|
||||
bool dirty = false;
|
||||
|
||||
// remove in reverse order to minimize copying
|
||||
for (int32_t i = mList.Length() - 1; i >= 0; --i) {
|
||||
if (IsPrivilegedNoCorsRequestHeaderName(mList[i].mName)) {
|
||||
mList.RemoveElementAt(i);
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (dirty) {
|
||||
SetListDirty();
|
||||
}
|
||||
}
|
||||
|
||||
bool InternalHeaders::DeleteInternal(const nsCString& aLowerName,
|
||||
ErrorResult& aRv) {
|
||||
bool dirty = false;
|
||||
|
||||
// remove in reverse order to minimize copying
|
||||
for (int32_t i = mList.Length() - 1; i >= 0; --i) {
|
||||
if (mList[i].mName.EqualsIgnoreCase(aLowerName.get())) {
|
||||
mList.RemoveElementAt(i);
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (dirty) {
|
||||
SetListDirty();
|
||||
}
|
||||
|
||||
return dirty;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -68,17 +161,43 @@ InternalHeaders::Delete(const nsACString& aName, ErrorResult& aRv)
|
|||
nsAutoCString lowerName;
|
||||
ToLowerCase(aName, lowerName);
|
||||
|
||||
if (IsInvalidMutableHeader(lowerName, aRv)) {
|
||||
// Step 1
|
||||
if (IsInvalidName(lowerName, aRv)) {
|
||||
return;
|
||||
}
|
||||
|
||||
SetListDirty();
|
||||
// Step 2
|
||||
if (IsImmutable(aRv)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// remove in reverse order to minimize copying
|
||||
for (int32_t i = mList.Length() - 1; i >= 0; --i) {
|
||||
if (lowerName == mList[i].mName) {
|
||||
mList.RemoveElementAt(i);
|
||||
}
|
||||
// Step 3
|
||||
nsAutoCString value;
|
||||
GetInternal(lowerName, value, aRv);
|
||||
if (IsForbiddenRequestHeader(lowerName, value)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 4
|
||||
if (mGuard == HeadersGuardEnum::Request_no_cors &&
|
||||
!IsNoCorsSafelistedRequestHeaderName(lowerName) &&
|
||||
!IsPrivilegedNoCorsRequestHeaderName(lowerName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 5
|
||||
if (IsForbiddenResponseHeader(lowerName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Steps 6 and 7
|
||||
if (!DeleteInternal(lowerName, aRv)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 8
|
||||
if (mGuard == HeadersGuardEnum::Request_no_cors) {
|
||||
RemovePrivilegedNoCorsRequestHeaders();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -91,12 +210,18 @@ InternalHeaders::Get(const nsACString& aName, nsACString& aValue, ErrorResult& a
|
|||
if (IsInvalidName(lowerName, aRv)) {
|
||||
return;
|
||||
}
|
||||
GetInternal(lowerName, aValue, aRv);
|
||||
}
|
||||
|
||||
void
|
||||
InternalHeaders::GetInternal(const nsCString& aLowerName,
|
||||
nsACString& aValue,
|
||||
ErrorResult& aRv) const {
|
||||
const char* delimiter = ",";
|
||||
bool firstValueFound = false;
|
||||
|
||||
for (uint32_t i = 0; i < mList.Length(); ++i) {
|
||||
if (lowerName == mList[i].mName) {
|
||||
if (aLowerName == mList[i].mName) {
|
||||
if (firstValueFound) {
|
||||
aValue += delimiter;
|
||||
}
|
||||
|
|
@ -153,13 +278,18 @@ InternalHeaders::Has(const nsACString& aName, ErrorResult& aRv) const
|
|||
void
|
||||
InternalHeaders::Set(const nsACString& aName, const nsACString& aValue, ErrorResult& aRv)
|
||||
{
|
||||
// Step 1
|
||||
nsAutoCString trimValue;
|
||||
NS_TrimHTTPWhitespace(aValue, trimValue);
|
||||
|
||||
// Steps 2 to 6
|
||||
nsAutoCString lowerName;
|
||||
ToLowerCase(aName, lowerName);
|
||||
|
||||
if (IsInvalidMutableHeader(lowerName, aValue, aRv)) {
|
||||
if (!IsValidHeaderValue(lowerName, trimValue, aRv)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 7
|
||||
SetListDirty();
|
||||
|
||||
int32_t firstIndex = INT32_MAX;
|
||||
|
|
@ -179,6 +309,11 @@ InternalHeaders::Set(const nsACString& aName, const nsACString& aValue, ErrorRes
|
|||
} else {
|
||||
mList.AppendElement(Entry(lowerName, aValue));
|
||||
}
|
||||
|
||||
// Step 8
|
||||
if (mGuard == HeadersGuardEnum::Request_no_cors) {
|
||||
RemovePrivilegedNoCorsRequestHeaders();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -200,6 +335,22 @@ InternalHeaders::~InternalHeaders()
|
|||
{
|
||||
}
|
||||
|
||||
// static
|
||||
bool
|
||||
InternalHeaders::IsNoCorsSafelistedRequestHeaderName(const nsCString& aName) {
|
||||
return aName.EqualsIgnoreCase("accept") ||
|
||||
aName.EqualsIgnoreCase("accept-language") ||
|
||||
aName.EqualsIgnoreCase("content-language") ||
|
||||
aName.EqualsIgnoreCase("content-type");
|
||||
}
|
||||
|
||||
// static
|
||||
bool
|
||||
InternalHeaders::IsPrivilegedNoCorsRequestHeaderName(
|
||||
const nsCString& aName) {
|
||||
return aName.EqualsIgnoreCase("range");
|
||||
}
|
||||
|
||||
// static
|
||||
bool
|
||||
InternalHeaders::IsSimpleHeader(const nsACString& aName, const nsACString& aValue)
|
||||
|
|
@ -207,9 +358,12 @@ InternalHeaders::IsSimpleHeader(const nsACString& aName, const nsACString& aValu
|
|||
// Note, we must allow a null content-type value here to support
|
||||
// get("content-type"), but the IsInvalidValue() check will prevent null
|
||||
// from being set or appended.
|
||||
return aName.EqualsLiteral("accept") ||
|
||||
aName.EqualsLiteral("accept-language") ||
|
||||
aName.EqualsLiteral("content-language") ||
|
||||
return (aName.EqualsLiteral("accept") &&
|
||||
nsContentUtils::IsAllowedNonCorsAccept(aValue)) ||
|
||||
(aName.EqualsLiteral("accept-language") &&
|
||||
nsContentUtils::IsAllowedNonCorsLanguage(aValue))||
|
||||
(aName.EqualsLiteral("content-language") &&
|
||||
nsContentUtils::IsAllowedNonCorsLanguage(aValue))||
|
||||
(aName.EqualsLiteral("content-type") &&
|
||||
nsContentUtils::IsAllowedNonCorsContentType(aValue));
|
||||
}
|
||||
|
|
@ -261,10 +415,11 @@ InternalHeaders::IsImmutable(ErrorResult& aRv) const
|
|||
}
|
||||
|
||||
bool
|
||||
InternalHeaders::IsForbiddenRequestHeader(const nsACString& aName) const
|
||||
InternalHeaders::IsForbiddenRequestHeader(const nsACString& aName,
|
||||
const nsACString& aValue) const
|
||||
{
|
||||
return mGuard == HeadersGuardEnum::Request &&
|
||||
nsContentUtils::IsForbiddenRequestHeader(aName);
|
||||
nsContentUtils::IsForbiddenRequestHeader(aName, aValue);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -370,7 +525,7 @@ InternalHeaders::CORSHeaders(InternalHeaders* aHeaders, RequestCredentials aCred
|
|||
ErrorResult result;
|
||||
|
||||
nsAutoCString acExposedNames;
|
||||
aHeaders->GetFirst(NS_LITERAL_CSTRING("Access-Control-Expose-Headers"), acExposedNames, result);
|
||||
aHeaders->Get(NS_LITERAL_CSTRING("Access-Control-Expose-Headers"), acExposedNames, result);
|
||||
MOZ_ASSERT(!result.Failed());
|
||||
|
||||
bool allowAllHeaders = false;
|
||||
|
|
|
|||
|
|
@ -136,8 +136,11 @@ private:
|
|||
|
||||
static bool IsInvalidName(const nsACString& aName, ErrorResult& aRv);
|
||||
static bool IsInvalidValue(const nsACString& aValue, ErrorResult& aRv);
|
||||
bool IsValidHeaderValue(const nsCString& aLowerName,
|
||||
const nsCString& aNormalizedValue, ErrorResult& aRv);
|
||||
bool IsImmutable(ErrorResult& aRv) const;
|
||||
bool IsForbiddenRequestHeader(const nsACString& aName) const;
|
||||
bool IsForbiddenRequestHeader(const nsACString& aName,
|
||||
const nsACString& aValue) const;
|
||||
bool IsForbiddenRequestNoCorsHeader(const nsACString& aName) const;
|
||||
bool IsForbiddenRequestNoCorsHeader(const nsACString& aName,
|
||||
const nsACString& aValue) const;
|
||||
|
|
@ -156,11 +159,22 @@ private:
|
|||
return IsInvalidName(aName, aRv) ||
|
||||
IsInvalidValue(aValue, aRv) ||
|
||||
IsImmutable(aRv) ||
|
||||
IsForbiddenRequestHeader(aName) ||
|
||||
IsForbiddenRequestHeader(aName, aValue) ||
|
||||
IsForbiddenRequestNoCorsHeader(aName, aValue) ||
|
||||
IsForbiddenResponseHeader(aName);
|
||||
}
|
||||
|
||||
void RemovePrivilegedNoCorsRequestHeaders();
|
||||
|
||||
void GetInternal(const nsCString& aLowerName, nsACString& aValue,
|
||||
ErrorResult& aRv) const;
|
||||
|
||||
bool DeleteInternal(const nsCString& aLowerName, ErrorResult& aRv);
|
||||
|
||||
static bool IsNoCorsSafelistedRequestHeaderName(const nsCString& aName);
|
||||
|
||||
static bool IsPrivilegedNoCorsRequestHeaderName(const nsCString& aName);
|
||||
|
||||
static bool IsSimpleHeader(const nsACString& aName,
|
||||
const nsACString& aValue);
|
||||
|
||||
|
|
|
|||
|
|
@ -3071,9 +3071,8 @@ XMLHttpRequestMainThread::SetRequestHeader(const nsACString& aName,
|
|||
}
|
||||
|
||||
// Step 3
|
||||
nsAutoCString value(aValue);
|
||||
static const char kHTTPWhitespace[] = "\n\t\r ";
|
||||
value.Trim(kHTTPWhitespace);
|
||||
nsAutoCString value;
|
||||
NS_TrimHTTPWhitespace(aValue, value);
|
||||
|
||||
// Step 4
|
||||
if (!NS_IsValidHTTPToken(aName) || !NS_IsReasonableHTTPHeaderValue(value)) {
|
||||
|
|
@ -3082,7 +3081,7 @@ XMLHttpRequestMainThread::SetRequestHeader(const nsACString& aName,
|
|||
|
||||
// Step 5
|
||||
bool isPrivilegedCaller = IsSystemXHR();
|
||||
bool isForbiddenHeader = nsContentUtils::IsForbiddenRequestHeader(aName);
|
||||
bool isForbiddenHeader = nsContentUtils::IsForbiddenRequestHeader(aName, aValue);
|
||||
if (!isPrivilegedCaller && isForbiddenHeader) {
|
||||
NS_ConvertUTF8toUTF16 name(aName);
|
||||
const char16_t* params[] = { name.get() };
|
||||
|
|
|
|||
|
|
@ -520,6 +520,12 @@ bool NS_IsValidHTTPToken(const nsACString &aToken)
|
|||
return mozilla::net::nsHttp::IsValidToken(aToken);
|
||||
}
|
||||
|
||||
void
|
||||
NS_TrimHTTPWhitespace(const nsACString& aSource, nsACString& aDest)
|
||||
{
|
||||
mozilla::net::nsHttp::TrimHTTPWhitespace(aSource, aDest);
|
||||
}
|
||||
|
||||
nsresult
|
||||
NS_NewLoadGroup(nsILoadGroup **aResult, nsIPrincipal *aPrincipal)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -959,6 +959,11 @@ bool NS_IsReasonableHTTPHeaderValue(const nsACString &aValue);
|
|||
*/
|
||||
bool NS_IsValidHTTPToken(const nsACString &aToken);
|
||||
|
||||
/**
|
||||
* Strip the leading or trailing HTTP whitespace per fetch spec section 2.2.
|
||||
*/
|
||||
void NS_TrimHTTPWhitespace(const nsACString& aSource, nsACString& aDest);
|
||||
|
||||
/**
|
||||
* Return true if the given request must be upgraded to HTTPS.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -245,6 +245,18 @@ nsHttp::GetProtocolVersion(uint32_t pv)
|
|||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
nsHttp::TrimHTTPWhitespace(const nsACString& aSource, nsACString& aDest)
|
||||
{
|
||||
nsAutoCString str(aSource);
|
||||
|
||||
// HTTP whitespace 0x09: '\t', 0x0A: '\n', 0x0D: '\r', 0x20: ' '
|
||||
static const char kHTTPWhitespace[] = "\t\n\r ";
|
||||
str.Trim(kHTTPWhitespace);
|
||||
aDest.Assign(str);
|
||||
}
|
||||
|
||||
// static
|
||||
bool
|
||||
nsHttp::IsReasonableHeaderValue(const nsACString &s)
|
||||
|
|
|
|||
|
|
@ -148,6 +148,10 @@ struct nsHttp
|
|||
static inline bool IsValidToken(const nsACString &s) {
|
||||
return IsValidToken(s.BeginReading(), s.EndReading());
|
||||
}
|
||||
|
||||
// Strip the leading or trailing HTTP whitespace per fetch spec section 2.2.
|
||||
static void TrimHTTPWhitespace(const nsACString& aSource,
|
||||
nsACString& aDest);
|
||||
|
||||
// Returns true if the specified value is reasonable given the defintion
|
||||
// in RFC 2616 section 4.2. Full strict validation is not performed
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue