summaryrefslogtreecommitdiff
path: root/netwerk/protocol
diff options
context:
space:
mode:
authorMoonchild <mcwerewolf@gmail.com>2018-09-27 00:59:51 +0200
committerGitHub <noreply@github.com>2018-09-27 00:59:51 +0200
commitb92dbaf6a1da5e06e9c0eb818288c0db1b6e45e2 (patch)
tree61462bdb3c34813d3cbd32c87628854a48392cea /netwerk/protocol
parent63875408947b0e5551f41e4de1e0ca44dd970c36 (diff)
parentc5c9445e3adf6b65c98f6810551d7c3d64133134 (diff)
downloaduxp-b92dbaf6a1da5e06e9c0eb818288c0db1b6e45e2.tar.gz
Merge pull request #791 from g4jc/session_supercookie
Issue #792 - backport mozbug 1334776 - CVE-2017-7797 Header name interning leaks across origins
Diffstat (limited to 'netwerk/protocol')
-rw-r--r--netwerk/protocol/http/HttpBaseChannel.cpp18
-rw-r--r--netwerk/protocol/http/PHttpChannelParams.h15
-rw-r--r--netwerk/protocol/http/nsHttpHeaderArray.cpp99
-rw-r--r--netwerk/protocol/http/nsHttpHeaderArray.h36
-rw-r--r--netwerk/protocol/http/nsHttpRequestHead.cpp23
-rw-r--r--netwerk/protocol/http/nsHttpRequestHead.h4
-rw-r--r--netwerk/protocol/http/nsHttpResponseHead.cpp50
-rw-r--r--netwerk/protocol/http/nsHttpResponseHead.h6
8 files changed, 194 insertions, 57 deletions
diff --git a/netwerk/protocol/http/HttpBaseChannel.cpp b/netwerk/protocol/http/HttpBaseChannel.cpp
index c4e764d26d..03123ceb08 100644
--- a/netwerk/protocol/http/HttpBaseChannel.cpp
+++ b/netwerk/protocol/http/HttpBaseChannel.cpp
@@ -1665,13 +1665,7 @@ HttpBaseChannel::SetRequestHeader(const nsACString& aHeader,
return NS_ERROR_INVALID_ARG;
}
- nsHttpAtom atom = nsHttp::ResolveAtom(flatHeader.get());
- if (!atom) {
- NS_WARNING("failed to resolve atom");
- return NS_ERROR_NOT_AVAILABLE;
- }
-
- return mRequestHead.SetHeader(atom, flatValue, aMerge);
+ return mRequestHead.SetHeader(aHeader, flatValue, aMerge);
}
NS_IMETHODIMP
@@ -1688,13 +1682,7 @@ HttpBaseChannel::SetEmptyRequestHeader(const nsACString& aHeader)
return NS_ERROR_INVALID_ARG;
}
- nsHttpAtom atom = nsHttp::ResolveAtom(flatHeader.get());
- if (!atom) {
- NS_WARNING("failed to resolve atom");
- return NS_ERROR_NOT_AVAILABLE;
- }
-
- return mRequestHead.SetEmptyHeader(atom);
+ return mRequestHead.SetEmptyHeader(aHeader);
}
NS_IMETHODIMP
@@ -1750,7 +1738,7 @@ HttpBaseChannel::SetResponseHeader(const nsACString& header,
mResponseHeadersModified = true;
- return mResponseHead->SetHeader(atom, value, merge);
+ return mResponseHead->SetHeader(header, value, merge);
}
NS_IMETHODIMP
diff --git a/netwerk/protocol/http/PHttpChannelParams.h b/netwerk/protocol/http/PHttpChannelParams.h
index 4df5c7832e..b04f57306c 100644
--- a/netwerk/protocol/http/PHttpChannelParams.h
+++ b/netwerk/protocol/http/PHttpChannelParams.h
@@ -98,7 +98,11 @@ struct ParamTraits<mozilla::net::nsHttpHeaderArray::nsEntry>
static void Write(Message* aMsg, const paramType& aParam)
{
- WriteParam(aMsg, aParam.header);
+ if (aParam.headerNameOriginal.IsEmpty()) {
+ WriteParam(aMsg, aParam.header);
+ } else {
+ WriteParam(aMsg, aParam.headerNameOriginal);
+ }
WriteParam(aMsg, aParam.value);
switch (aParam.variety) {
case mozilla::net::nsHttpHeaderArray::eVarietyUnknown:
@@ -124,11 +128,18 @@ struct ParamTraits<mozilla::net::nsHttpHeaderArray::nsEntry>
static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
{
uint8_t variety;
- if (!ReadParam(aMsg, aIter, &aResult->header) ||
+ nsAutoCString header;
+ if (!ReadParam(aMsg, aIter, &header) ||
!ReadParam(aMsg, aIter, &aResult->value) ||
!ReadParam(aMsg, aIter, &variety))
return false;
+ mozilla::net::nsHttpAtom atom = mozilla::net::nsHttp::ResolveAtom(header);
+ aResult->header = atom;
+ if (!header.Equals(atom.get())) {
+ aResult->headerNameOriginal = header;
+ }
+
switch (variety) {
case 0:
aResult->variety = mozilla::net::nsHttpHeaderArray::eVarietyUnknown;
diff --git a/netwerk/protocol/http/nsHttpHeaderArray.cpp b/netwerk/protocol/http/nsHttpHeaderArray.cpp
index 670300dea5..1030bc91ee 100644
--- a/netwerk/protocol/http/nsHttpHeaderArray.cpp
+++ b/netwerk/protocol/http/nsHttpHeaderArray.cpp
@@ -18,12 +18,37 @@ namespace net {
//-----------------------------------------------------------------------------
// nsHttpHeaderArray <public>
//-----------------------------------------------------------------------------
+
+nsresult
+nsHttpHeaderArray::SetHeader(const nsACString &headerName,
+ const nsACString &value,
+ bool merge,
+ nsHttpHeaderArray::HeaderVariety variety)
+{
+ nsHttpAtom header = nsHttp::ResolveAtom(PromiseFlatCString(headerName).get());
+ if (!header) {
+ NS_WARNING("failed to resolve atom");
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+ return SetHeader(header, headerName, value, merge, variety);
+}
+
nsresult
nsHttpHeaderArray::SetHeader(nsHttpAtom header,
const nsACString &value,
bool merge,
nsHttpHeaderArray::HeaderVariety variety)
{
+ return SetHeader(header, EmptyCString(), value, merge, variety);
+}
+
+nsresult
+nsHttpHeaderArray::SetHeader(nsHttpAtom header,
+ const nsACString &headerName,
+ const nsACString &value,
+ bool merge,
+ nsHttpHeaderArray::HeaderVariety variety)
+{
MOZ_ASSERT((variety == eVarietyResponse) ||
(variety == eVarietyRequestDefault) ||
(variety == eVarietyRequestOverride),
@@ -51,7 +76,7 @@ nsHttpHeaderArray::SetHeader(nsHttpAtom header,
MOZ_ASSERT(!entry || variety != eVarietyRequestDefault,
"Cannot set default entry which overrides existing entry!");
if (!entry) {
- return SetHeader_internal(header, value, variety);
+ return SetHeader_internal(header, headerName, value, variety);
} else if (merge && !IsSingletonHeader(header)) {
return MergeHeader(header, entry, value, variety);
} else {
@@ -59,7 +84,7 @@ nsHttpHeaderArray::SetHeader(nsHttpAtom header,
if (entry->variety == eVarietyResponseNetOriginalAndResponse) {
MOZ_ASSERT(variety == eVarietyResponse);
entry->variety = eVarietyResponseNetOriginal;
- return SetHeader_internal(header, value, variety);
+ return SetHeader_internal(header, headerName, value, variety);
} else {
entry->value = value;
entry->variety = variety;
@@ -71,6 +96,7 @@ nsHttpHeaderArray::SetHeader(nsHttpAtom header,
nsresult
nsHttpHeaderArray::SetHeader_internal(nsHttpAtom header,
+ const nsACString &headerName,
const nsACString &value,
nsHttpHeaderArray::HeaderVariety variety)
{
@@ -79,14 +105,26 @@ nsHttpHeaderArray::SetHeader_internal(nsHttpAtom header,
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;
}
nsresult
-nsHttpHeaderArray::SetEmptyHeader(nsHttpAtom header, HeaderVariety variety)
+nsHttpHeaderArray::SetEmptyHeader(const nsACString &headerName,
+ HeaderVariety variety)
{
+ nsHttpAtom header = nsHttp::ResolveAtom(PromiseFlatCString(headerName).get());
+ if (!header) {
+ NS_WARNING("failed to resolve atom");
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+
MOZ_ASSERT((variety == eVarietyResponse) ||
(variety == eVarietyRequestDefault) ||
(variety == eVarietyRequestOverride),
@@ -104,11 +142,12 @@ nsHttpHeaderArray::SetEmptyHeader(nsHttpAtom header, HeaderVariety variety)
entry->variety = eVarietyResponseNetOriginal;
}
- return SetHeader_internal(header, EmptyCString(), variety);
+ return SetHeader_internal(header, headerName, EmptyCString(), variety);
}
nsresult
nsHttpHeaderArray::SetHeaderFromNet(nsHttpAtom header,
+ const nsACString &headerNameOriginal,
const nsACString &value,
bool response)
{
@@ -125,7 +164,7 @@ nsHttpHeaderArray::SetHeaderFromNet(nsHttpAtom header,
LOG(("Ignoring Empty Header: %s\n", header.get()));
if (response) {
// Set header as original but not as response header.
- return SetHeader_internal(header, value,
+ return SetHeader_internal(header, headerNameOriginal, value,
eVarietyResponseNetOriginal);
}
return NS_OK; // ignore empty headers by default
@@ -135,7 +174,7 @@ nsHttpHeaderArray::SetHeaderFromNet(nsHttpAtom header,
if (response) {
variety = eVarietyResponseNetOriginalAndResponse;
}
- return SetHeader_internal(header, value, variety);
+ return SetHeader_internal(header, headerNameOriginal, value, variety);
} else if (!IsSingletonHeader(header)) {
HeaderVariety variety = eVarietyRequestOverride;
@@ -147,7 +186,7 @@ nsHttpHeaderArray::SetHeaderFromNet(nsHttpAtom header,
return rv;
}
if (response) {
- rv = SetHeader_internal(header, value,
+ rv = SetHeader_internal(header, headerNameOriginal, value,
eVarietyResponseNetOriginal);
}
return rv;
@@ -164,7 +203,7 @@ nsHttpHeaderArray::SetHeaderFromNet(nsHttpAtom header,
}
if (response) {
- return SetHeader_internal(header, value,
+ return SetHeader_internal(header, headerNameOriginal, value,
eVarietyResponseNetOriginal);
}
}
@@ -174,6 +213,7 @@ nsHttpHeaderArray::SetHeaderFromNet(nsHttpAtom header,
nsresult
nsHttpHeaderArray::SetResponseHeaderFromCache(nsHttpAtom header,
+ const nsACString &headerNameOriginal,
const nsACString &value,
nsHttpHeaderArray::HeaderVariety variety)
{
@@ -183,7 +223,7 @@ nsHttpHeaderArray::SetResponseHeaderFromCache(nsHttpAtom header,
"eVarietyResponseNetOriginal");
if (variety == eVarietyResponseNetOriginal) {
- return SetHeader_internal(header, value,
+ return SetHeader_internal(header, headerNameOriginal, value,
eVarietyResponseNetOriginal);
} else {
nsTArray<nsEntry>::index_type index = 0;
@@ -203,7 +243,8 @@ nsHttpHeaderArray::SetResponseHeaderFromCache(nsHttpAtom header,
}
} while (index != mHeaders.NoIndex);
// If we are here, we have not found an entry so add a new one.
- return SetHeader_internal(header, value, eVarietyResponse);
+ return SetHeader_internal(header, headerNameOriginal, value,
+ eVarietyResponse);
}
}
@@ -260,8 +301,16 @@ nsHttpHeaderArray::GetOriginalHeader(nsHttpAtom aHeader,
if (entry.variety == eVarietyResponse) {
continue;
}
+
+ nsAutoCString hdr;
+ if (entry.headerNameOriginal.IsEmpty()) {
+ hdr = nsDependentCString(entry.header);
+ } else {
+ hdr = entry.headerNameOriginal;
+ }
+
rv = NS_OK;
- if (NS_FAILED(aVisitor->VisitHeader(nsDependentCString(entry.header),
+ if (NS_FAILED(aVisitor->VisitHeader(hdr,
entry.value))) {
break;
}
@@ -298,8 +347,14 @@ nsHttpHeaderArray::VisitHeaders(nsIHttpHeaderVisitor *visitor, nsHttpHeaderArray
} else if (filter == eFilterResponseOriginal && entry.variety == eVarietyResponse) {
continue;
}
- rv = visitor->VisitHeader(
- nsDependentCString(entry.header), entry.value);
+
+ nsAutoCString hdr;
+ if (entry.headerNameOriginal.IsEmpty()) {
+ hdr = nsDependentCString(entry.header);
+ } else {
+ hdr = entry.headerNameOriginal;
+ }
+ rv = visitor->VisitHeader(hdr, entry.value);
if NS_FAILED(rv) {
return rv;
}
@@ -310,6 +365,7 @@ nsHttpHeaderArray::VisitHeaders(nsIHttpHeaderVisitor *visitor, nsHttpHeaderArray
/*static*/ nsresult
nsHttpHeaderArray::ParseHeaderLine(const nsACString& line,
nsHttpAtom *hdr,
+ nsACString *headerName,
nsACString *val)
{
//
@@ -360,6 +416,7 @@ nsHttpHeaderArray::ParseHeaderLine(const nsACString& line,
// assign return values
if (hdr) *hdr = atom;
if (val) val->Assign(p, p2 - p + 1);
+ if (headerName) headerName->Assign(sub);
return NS_OK;
}
@@ -397,7 +454,11 @@ nsHttpHeaderArray::Flatten(nsACString &buf, bool pruneProxyHeaders,
continue;
}
- buf.Append(entry.header);
+ if (entry.headerNameOriginal.IsEmpty()) {
+ buf.Append(entry.header);
+ } else {
+ buf.Append(entry.headerNameOriginal);
+ }
buf.AppendLiteral(": ");
buf.Append(entry.value);
buf.AppendLiteral("\r\n");
@@ -415,7 +476,11 @@ nsHttpHeaderArray::FlattenOriginalHeader(nsACString &buf)
continue;
}
- buf.Append(entry.header);
+ if (entry.headerNameOriginal.IsEmpty()) {
+ buf.Append(entry.header);
+ } else {
+ buf.Append(entry.headerNameOriginal);
+ }
buf.AppendLiteral(": ");
buf.Append(entry.value);
buf.AppendLiteral("\r\n");
@@ -423,11 +488,13 @@ nsHttpHeaderArray::FlattenOriginalHeader(nsACString &buf)
}
const char *
-nsHttpHeaderArray::PeekHeaderAt(uint32_t index, nsHttpAtom &header) const
+nsHttpHeaderArray::PeekHeaderAt(uint32_t index, nsHttpAtom &header,
+ nsACString &headerNameOriginal) const
{
const nsEntry &entry = mHeaders[index];
header = entry.header;
+ headerNameOriginal = entry.headerNameOriginal;
return entry.value.get();
}
diff --git a/netwerk/protocol/http/nsHttpHeaderArray.h b/netwerk/protocol/http/nsHttpHeaderArray.h
index 91b91f04aa..3ffdfa8146 100644
--- a/netwerk/protocol/http/nsHttpHeaderArray.h
+++ b/netwerk/protocol/http/nsHttpHeaderArray.h
@@ -49,19 +49,30 @@ public:
};
// Used by internal setters: to set header from network use SetHeaderFromNet
+ nsresult SetHeader(const nsACString &headerName,
+ const nsACString &value,
+ bool merge, HeaderVariety variety);
nsresult SetHeader(nsHttpAtom header, const nsACString &value,
bool merge, HeaderVariety variety);
+ nsresult SetHeader(nsHttpAtom header,
+ const nsACString &headerName,
+ const nsACString &value,
+ bool merge, HeaderVariety variety);
// Used by internal setters to set an empty header
- nsresult SetEmptyHeader(nsHttpAtom header, HeaderVariety variety);
+ nsresult SetEmptyHeader(const nsACString &headerName, HeaderVariety variety);
// Merges supported headers. For other duplicate values, determines if error
// needs to be thrown or 1st value kept.
// For the response header we keep the original headers as well.
- nsresult SetHeaderFromNet(nsHttpAtom header, const nsACString &value,
+ nsresult SetHeaderFromNet(nsHttpAtom header,
+ const nsACString &headerNameOriginal,
+ const nsACString &value,
bool response);
- nsresult SetResponseHeaderFromCache(nsHttpAtom header, const nsACString &value,
+ nsresult SetResponseHeaderFromCache(nsHttpAtom header,
+ const nsACString &headerNameOriginal,
+ const nsACString &value,
HeaderVariety variety);
nsresult GetHeader(nsHttpAtom header, nsACString &value) const;
@@ -97,15 +108,17 @@ public:
// parse a header line, return the header atom and a pointer to the
// header value (the substring of the header line -- do not free).
static nsresult ParseHeaderLine(const nsACString& line,
- nsHttpAtom *header=nullptr,
- nsACString* value=nullptr);
+ nsHttpAtom *header = nullptr,
+ nsACString *headerNameOriginal = nullptr,
+ nsACString *value = nullptr);
void Flatten(nsACString &, bool pruneProxyHeaders, bool pruneTransients);
void FlattenOriginalHeader(nsACString &);
uint32_t Count() const { return mHeaders.Length(); }
- const char *PeekHeaderAt(uint32_t i, nsHttpAtom &header) const;
+ const char *PeekHeaderAt(uint32_t i, nsHttpAtom &header,
+ nsACString &headerNameOriginal) const;
void Clear();
@@ -113,6 +126,7 @@ public:
struct nsEntry
{
nsHttpAtom header;
+ nsCString headerNameOriginal;
nsCString value;
HeaderVariety variety = eVarietyUnknown;
@@ -140,7 +154,9 @@ private:
int32_t LookupEntry(nsHttpAtom header, nsEntry **);
nsresult MergeHeader(nsHttpAtom header, nsEntry *entry,
const nsACString &value, HeaderVariety variety);
- nsresult SetHeader_internal(nsHttpAtom header, const nsACString &value,
+ nsresult SetHeader_internal(nsHttpAtom header,
+ const nsACString &headerName,
+ const nsACString &value,
HeaderVariety variety);
// Header cannot be merged: only one value possible
@@ -257,7 +273,11 @@ nsHttpHeaderArray::MergeHeader(nsHttpAtom header,
if (entry->variety == eVarietyResponseNetOriginalAndResponse) {
MOZ_ASSERT(variety == eVarietyResponse);
entry->variety = eVarietyResponseNetOriginal;
- nsresult rv = SetHeader_internal(header, newValue, eVarietyResponse);
+ // Copy entry->headerNameOriginal because in SetHeader_internal we are going
+ // to a new one and a realocation can happen.
+ nsCString headerNameOriginal = entry->headerNameOriginal;
+ nsresult rv = SetHeader_internal(header, headerNameOriginal,
+ newValue, eVarietyResponse);
if (NS_FAILED(rv)) {
return rv;
}
diff --git a/netwerk/protocol/http/nsHttpRequestHead.cpp b/netwerk/protocol/http/nsHttpRequestHead.cpp
index 094a794570..b366a8d542 100644
--- a/netwerk/protocol/http/nsHttpRequestHead.cpp
+++ b/netwerk/protocol/http/nsHttpRequestHead.cpp
@@ -131,6 +131,20 @@ nsHttpRequestHead::Origin(nsACString &aOrigin)
}
nsresult
+nsHttpRequestHead::SetHeader(const nsACString &h, const nsACString &v,
+ bool m /*= false*/)
+{
+ ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+
+ if (mInVisitHeaders) {
+ return NS_ERROR_FAILURE;
+ }
+
+ return mHeaders.SetHeader(h, v, m,
+ nsHttpHeaderArray::eVarietyRequestOverride);
+}
+
+nsresult
nsHttpRequestHead::SetHeader(nsHttpAtom h, const nsACString &v,
bool m /*= false*/)
{
@@ -158,7 +172,7 @@ nsHttpRequestHead::SetHeader(nsHttpAtom h, const nsACString &v, bool m,
}
nsresult
-nsHttpRequestHead::SetEmptyHeader(nsHttpAtom h)
+nsHttpRequestHead::SetEmptyHeader(const nsACString &h)
{
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
@@ -253,6 +267,7 @@ nsHttpRequestHead::ParseHeaderSet(const char *buffer)
{
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
nsHttpAtom hdr;
+ nsAutoCString headerNameOriginal;
nsAutoCString val;
while (buffer) {
const char *eof = strchr(buffer, '\r');
@@ -262,9 +277,13 @@ nsHttpRequestHead::ParseHeaderSet(const char *buffer)
if (NS_SUCCEEDED(nsHttpHeaderArray::ParseHeaderLine(
nsDependentCSubstring(buffer, eof - buffer),
&hdr,
+ &headerNameOriginal,
&val))) {
- mHeaders.SetHeaderFromNet(hdr, val, false);
+ mHeaders.SetHeaderFromNet(hdr,
+ headerNameOriginal,
+ val,
+ false);
}
buffer = eof + 1;
if (*buffer == '\n') {
diff --git a/netwerk/protocol/http/nsHttpRequestHead.h b/netwerk/protocol/http/nsHttpRequestHead.h
index 4159680834..b7020d33a0 100644
--- a/netwerk/protocol/http/nsHttpRequestHead.h
+++ b/netwerk/protocol/http/nsHttpRequestHead.h
@@ -57,10 +57,12 @@ public:
int32_t port);
void Origin(nsACString &aOrigin);
+ nsresult SetHeader(const nsACString &h, const nsACString &v,
+ bool m=false);
nsresult SetHeader(nsHttpAtom h, const nsACString &v, bool m=false);
nsresult SetHeader(nsHttpAtom h, const nsACString &v, bool m,
nsHttpHeaderArray::HeaderVariety variety);
- nsresult SetEmptyHeader(nsHttpAtom h);
+ nsresult SetEmptyHeader(const nsACString &h);
nsresult GetHeader(nsHttpAtom h, nsACString &v);
nsresult ClearHeader(nsHttpAtom h);
diff --git a/netwerk/protocol/http/nsHttpResponseHead.cpp b/netwerk/protocol/http/nsHttpResponseHead.cpp
index 6d384c4887..fa6430b823 100644
--- a/netwerk/protocol/http/nsHttpResponseHead.cpp
+++ b/netwerk/protocol/http/nsHttpResponseHead.cpp
@@ -137,6 +137,26 @@ nsHttpResponseHead::Immutable()
}
nsresult
+nsHttpResponseHead::SetHeader(const nsACString &hdr,
+ const nsACString &val,
+ bool merge)
+{
+ ReentrantMonitorAutoEnter monitor(mReentrantMonitor);
+
+ if (mInVisitHeaders) {
+ return NS_ERROR_FAILURE;
+ }
+
+ nsHttpAtom atom = nsHttp::ResolveAtom(PromiseFlatCString(hdr).get());
+ if (!atom) {
+ NS_WARNING("failed to resolve atom");
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+
+ return SetHeader_locked(atom, hdr, val, merge);
+}
+
+nsresult
nsHttpResponseHead::SetHeader(nsHttpAtom hdr,
const nsACString &val,
bool merge)
@@ -147,24 +167,25 @@ nsHttpResponseHead::SetHeader(nsHttpAtom hdr,
return NS_ERROR_FAILURE;
}
- return SetHeader_locked(hdr, val, merge);
+ return SetHeader_locked(hdr, EmptyCString(), val, merge);
}
nsresult
-nsHttpResponseHead::SetHeader_locked(nsHttpAtom hdr,
+nsHttpResponseHead::SetHeader_locked(nsHttpAtom atom,
+ const nsACString &hdr,
const nsACString &val,
bool merge)
{
- nsresult rv = mHeaders.SetHeader(hdr, val, merge,
+ nsresult rv = mHeaders.SetHeader(atom, hdr, val, merge,
nsHttpHeaderArray::eVarietyResponse);
if (NS_FAILED(rv)) return rv;
// respond to changes in these headers. we need to reparse the entire
// header since the change may have merged in additional values.
- if (hdr == nsHttp::Cache_Control)
- ParseCacheControl(mHeaders.PeekHeader(hdr));
- else if (hdr == nsHttp::Pragma)
- ParsePragma(mHeaders.PeekHeader(hdr));
+ if (atom == nsHttp::Cache_Control)
+ ParseCacheControl(mHeaders.PeekHeader(atom));
+ else if (atom == nsHttp::Pragma)
+ ParsePragma(mHeaders.PeekHeader(atom));
return NS_OK;
}
@@ -316,6 +337,7 @@ nsHttpResponseHead::ParseCachedOriginalHeaders(char *block)
char *p = block;
nsHttpAtom hdr = {0};
+ nsAutoCString headerNameOriginal;
nsAutoCString val;
nsresult rv;
@@ -331,12 +353,13 @@ nsHttpResponseHead::ParseCachedOriginalHeaders(char *block)
*p = 0;
if (NS_FAILED(nsHttpHeaderArray::ParseHeaderLine(
- nsDependentCString(block, p - block), &hdr, &val))) {
+ nsDependentCString(block, p - block), &hdr, &headerNameOriginal, &val))) {
return NS_OK;
}
rv = mHeaders.SetResponseHeaderFromCache(hdr,
+ headerNameOriginal,
val,
nsHttpHeaderArray::eVarietyResponseNetOriginal);
@@ -567,18 +590,21 @@ nsresult
nsHttpResponseHead::ParseHeaderLine_locked(const nsACString &line, bool originalFromNetHeaders)
{
nsHttpAtom hdr = {0};
+ nsAutoCString headerNameOriginal;
nsAutoCString val;
- if (NS_FAILED(nsHttpHeaderArray::ParseHeaderLine(line, &hdr, &val))) {
+ if (NS_FAILED(nsHttpHeaderArray::ParseHeaderLine(line, &hdr, &headerNameOriginal, &val))) {
return NS_OK;
}
nsresult rv;
if (originalFromNetHeaders) {
rv = mHeaders.SetHeaderFromNet(hdr,
+ headerNameOriginal,
val,
true);
} else {
rv = mHeaders.SetResponseHeaderFromCache(hdr,
+ headerNameOriginal,
val,
nsHttpHeaderArray::eVarietyResponse);
}
@@ -856,7 +882,8 @@ nsHttpResponseHead::UpdateHeaders(nsHttpResponseHead *aOther)
uint32_t i, count = aOther->mHeaders.Count();
for (i=0; i<count; ++i) {
nsHttpAtom header;
- const char *val = aOther->mHeaders.PeekHeaderAt(i, header);
+ nsAutoCString headerNameOriginal;
+ const char *val = aOther->mHeaders.PeekHeaderAt(i, header, headerNameOriginal);
if (!val) {
continue;
@@ -890,7 +917,8 @@ nsHttpResponseHead::UpdateHeaders(nsHttpResponseHead *aOther)
LOG(("new response header [%s: %s]\n", header.get(), val));
// overwrite the current header value with the new value...
- SetHeader_locked(header, nsDependentCString(val));
+ SetHeader_locked(header, headerNameOriginal,
+ nsDependentCString(val));
}
}
diff --git a/netwerk/protocol/http/nsHttpResponseHead.h b/netwerk/protocol/http/nsHttpResponseHead.h
index 0a912f4b40..8b51386ea2 100644
--- a/netwerk/protocol/http/nsHttpResponseHead.h
+++ b/netwerk/protocol/http/nsHttpResponseHead.h
@@ -65,6 +65,8 @@ public:
*/
int64_t TotalEntitySize();
+ nsresult SetHeader(const nsACString &h, const nsACString &v,
+ bool m=false);
nsresult SetHeader(nsHttpAtom h, const nsACString &v, bool m=false);
nsresult GetHeader(nsHttpAtom h, nsACString &v);
void ClearHeader(nsHttpAtom h);
@@ -137,8 +139,8 @@ public:
bool HasContentType();
bool HasContentCharset();
private:
- nsresult SetHeader_locked(nsHttpAtom h, const nsACString &v,
- bool m=false);
+ nsresult SetHeader_locked(nsHttpAtom atom, const nsACString &h,
+ const nsACString &v, bool m=false);
void AssignDefaultStatusText();
void ParseVersion(const char *);
void ParseCacheControl(const char *);