/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim:set ts=4 sw=2 sts=2 ci et: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// HttpLog.h should generally be included first #include"HttpLog.h"
nsresult nsHttpHeaderArray::SetHeader( const nsHttpAtom& header, const nsACString& headerName, const nsACString& value, bool merge,
nsHttpHeaderArray::HeaderVariety variety) {
MOZ_ASSERT(
(variety == eVarietyResponse) || (variety == eVarietyRequestDefault) ||
(variety == eVarietyRequestOverride) ||
(variety == eVarietyRequestEnforceDefault), "Net original headers can only be set using SetHeader_internal().");
nsEntry* entry = nullptr;
int32_t index = LookupEntry(header, &entry);
// If an empty value is received and we aren't merging headers discard it if (value.IsEmpty() && header != nsHttp::X_Frame_Options) { if (!merge && entry) { if (entry->variety == eVarietyResponseNetOriginalAndResponse) {
MOZ_ASSERT(variety == eVarietyResponse);
entry->variety = eVarietyResponseNetOriginal;
} else {
mHeaders.RemoveElementAt(index);
}
} return NS_OK;
}
MOZ_ASSERT((variety == eVarietyRequestEnforceDefault) ||
(!entry || variety != eVarietyRequestDefault), "Cannot set default entry which overrides existing entry!");
// Set the variety to default if we are enforcing it. if (variety == eVarietyRequestEnforceDefault) {
variety = eVarietyRequestDefault;
} if (!entry) { return SetHeader_internal(header, headerName, value, variety);
} if (merge && !IsSingletonHeader(header)) { return MergeHeader(header, entry, value, variety);
} if (!IsIgnoreMultipleHeader(header)) { // Replace the existing string with the new value if (entry->variety == eVarietyResponseNetOriginalAndResponse) {
MOZ_ASSERT(variety == eVarietyResponse);
entry->variety = eVarietyResponseNetOriginal; return SetHeader_internal(header, headerName, value, variety);
}
entry->value = value;
entry->variety = variety;
}
return NS_OK;
}
nsresult nsHttpHeaderArray::SetHeader_internal( const nsHttpAtom& header, const nsACString& headerName, const nsACString& value, nsHttpHeaderArray::HeaderVariety variety) {
nsEntry* entry = mHeaders.AppendElement(); if (!entry) { return NS_ERROR_OUT_OF_MEMORY;
}
entry->header = header; // Only save original form of a header if it is different than the header // atom string. if (!headerName.Equals(header.get())) {
entry->headerNameOriginal = headerName;
}
entry->value = value;
entry->variety = variety; return NS_OK;
}
MOZ_ASSERT((variety == eVarietyResponse) ||
(variety == eVarietyRequestDefault) ||
(variety == eVarietyRequestOverride), "Original headers can only be set using SetHeader_internal().");
nsEntry* entry = nullptr;
nsresult nsHttpHeaderArray::SetHeaderFromNet( const nsHttpAtom& header, const nsACString& headerNameOriginal, const nsACString& value, bool response) { // mHeader holds the consolidated (merged or updated) headers. // mHeader for response header will keep the original heades as well.
nsEntry* entry = nullptr;
LookupEntry(header, &entry);
if (!entry) {
HeaderVariety variety = eVarietyRequestOverride; if (response) {
variety = eVarietyResponseNetOriginalAndResponse;
} return SetHeader_internal(header, headerNameOriginal, value, variety);
} if (!IsSingletonHeader(header)) {
HeaderVariety variety = eVarietyRequestOverride; if (response) {
variety = eVarietyResponse;
}
nsresult rv = MergeHeader(header, entry, value, variety); if (NS_FAILED(rv)) { return rv;
} if (response) {
rv = SetHeader_internal(header, headerNameOriginal, value,
eVarietyResponseNetOriginal);
} return rv;
} if (!IsIgnoreMultipleHeader(header)) { // Multiple instances of non-mergeable header received from network // - ignore if same value if (header == nsHttp::Content_Length) { // Content length header needs special handling. // For e.g. for CL all the below headers evaluates to value of X // Content-Length: X // Content-Length: X, X, X // Content-Length: X \n\r Content-Length: X // remove duplicate values from the header-values for comparison
nsAutoCString entryValue;
RemoveDuplicateHeaderValues(entry->value, entryValue); if (entryValue != headerValue) { // reply may be corrupt/hacked (ex: CLRF injection attacks) return NS_ERROR_CORRUPTED_CONTENT;
}
} elseif (!entry->value.Equals(value)) { // compare remaining headers if (IsSuspectDuplicateHeader(header)) { // reply may be corrupt/hacked (ex: CLRF injection attacks) return NS_ERROR_CORRUPTED_CONTENT;
} // else silently drop value: keep value from 1st header seen
LOG(("Header %s silently dropped as non mergeable header\n",
header.get()));
}
if (response) { return SetHeader_internal(header, headerNameOriginal, value,
eVarietyResponseNetOriginal);
}
}
return NS_OK;
}
nsresult nsHttpHeaderArray::SetResponseHeaderFromCache( const nsHttpAtom& header, const nsACString& headerNameOriginal, const nsACString& value, nsHttpHeaderArray::HeaderVariety variety) {
MOZ_ASSERT(
(variety == eVarietyResponse) || (variety == eVarietyResponseNetOriginal), "Headers from cache can only be eVarietyResponse and " "eVarietyResponseNetOriginal");
if (variety == eVarietyResponseNetOriginal) { return SetHeader_internal(header, headerNameOriginal, value,
eVarietyResponseNetOriginal);
}
nsTArray<nsEntry>::index_type index = 0; do {
index = mHeaders.IndexOf(header, index, nsEntry::MatchHeader()); if (index !=
CopyableTArray<mozilla::net::nsHttpHeaderArray::nsEntry>::NoIndex) {
nsEntry& entry = mHeaders[index]; if (value.Equals(entry.value)) {
MOZ_ASSERT(
(entry.variety == eVarietyResponseNetOriginal) ||
(entry.variety == eVarietyResponseNetOriginalAndResponse), "This array must contain only eVarietyResponseNetOriginal" " and eVarietyResponseNetOriginalAndRespons headers!");
entry.variety = eVarietyResponseNetOriginalAndResponse; return NS_OK;
}
index++;
}
} while (index !=
CopyableTArray<mozilla::net::nsHttpHeaderArray::nsEntry>::NoIndex); // If we are here, we have not found an entry so add a new one. return SetHeader_internal(header, headerNameOriginal, value,
eVarietyResponse);
}
rv = NS_OK; if (NS_FAILED(aVisitor->VisitHeader(hdr, entry.value))) { break;
}
} else { // if there is no such a header, it will return // NS_ERROR_NOT_AVAILABLE or NS_OK otherwise. return rv;
}
} return NS_OK;
}
/*static*/
nsresult nsHttpHeaderArray::ParseHeaderLine(const nsACString& line,
nsHttpAtom* hdr,
nsACString* headerName,
nsACString* val) { // // BNF from section 4.2 of RFC 2616: // // message-header = field-name ":" [ field-value ] // field-name = token // field-value = *( field-content | LWS ) // field-content = <the OCTETs making up the field-value // and consisting of either *TEXT or combinations // of token, separators, and quoted-string> //
// We skip over mal-formed headers in the hope that we'll still be able to // do something useful with the response.
int32_t split = line.FindChar(':');
if (split == kNotFound) {
LOG(("malformed header [%s]: no colon\n", PromiseFlatCString(line).get())); return NS_ERROR_FAILURE;
}
// make sure we have a valid token for the field-name if (!nsHttp::IsValidToken(sub)) {
LOG(("malformed header [%s]: field-name not a token\n",
PromiseFlatCString(line).get())); return NS_ERROR_FAILURE;
}
nsHttpAtom atom = nsHttp::ResolveAtom(sub); if (!atom) {
LOG(("failed to resolve atom [%s]\n", PromiseFlatCString(line).get())); return NS_ERROR_FAILURE;
}
// skip over whitespace char* p =
net_FindCharNotInSet(sub2.BeginReading(), sub2.EndReading(), HTTP_LWS);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.