Thu, 15 Jan 2015 21:03:48 +0100
Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* vim: set sw=4 ts=8 et 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/. */
7 #ifndef nsHttpHeaderArray_h__
8 #define nsHttpHeaderArray_h__
10 #include "nsHttp.h"
11 #include "nsTArray.h"
12 #include "nsString.h"
14 class nsIHttpHeaderVisitor;
16 namespace mozilla { namespace net {
18 class nsHttpHeaderArray
19 {
20 public:
21 const char *PeekHeader(nsHttpAtom header) const;
23 // Used by internal setters: to set header from network use SetHeaderFromNet
24 nsresult SetHeader(nsHttpAtom header, const nsACString &value,
25 bool merge = false);
27 // Merges supported headers. For other duplicate values, determines if error
28 // needs to be thrown or 1st value kept.
29 nsresult SetHeaderFromNet(nsHttpAtom header, const nsACString &value);
31 nsresult GetHeader(nsHttpAtom header, nsACString &value) const;
32 void ClearHeader(nsHttpAtom h);
34 // Find the location of the given header value, or null if none exists.
35 const char *FindHeaderValue(nsHttpAtom header, const char *value) const
36 {
37 return nsHttp::FindToken(PeekHeader(header), value,
38 HTTP_HEADER_VALUE_SEPS);
39 }
41 // Determine if the given header value exists.
42 bool HasHeaderValue(nsHttpAtom header, const char *value) const
43 {
44 return FindHeaderValue(header, value) != nullptr;
45 }
47 nsresult VisitHeaders(nsIHttpHeaderVisitor *visitor);
49 // parse a header line, return the header atom and a pointer to the
50 // header value (the substring of the header line -- do not free).
51 nsresult ParseHeaderLine(const char *line,
52 nsHttpAtom *header=nullptr,
53 char **value=nullptr);
55 void Flatten(nsACString &, bool pruneProxyHeaders=false);
57 uint32_t Count() const { return mHeaders.Length(); }
59 const char *PeekHeaderAt(uint32_t i, nsHttpAtom &header) const;
61 void Clear();
63 // Must be copy-constructable and assignable
64 struct nsEntry
65 {
66 nsHttpAtom header;
67 nsCString value;
69 struct MatchHeader {
70 bool Equals(const nsEntry &entry, const nsHttpAtom &header) const {
71 return entry.header == header;
72 }
73 };
74 };
76 private:
77 int32_t LookupEntry(nsHttpAtom header, const nsEntry **) const;
78 int32_t LookupEntry(nsHttpAtom header, nsEntry **);
79 void MergeHeader(nsHttpAtom header, nsEntry *entry, const nsACString &value);
81 // Header cannot be merged: only one value possible
82 bool IsSingletonHeader(nsHttpAtom header);
83 // For some headers we want to track empty values to prevent them being
84 // combined with non-empty ones as a CRLF attack vector
85 bool TrackEmptyHeader(nsHttpAtom header);
87 // Subset of singleton headers: should never see multiple, different
88 // instances of these, else something fishy may be going on (like CLRF
89 // injection)
90 bool IsSuspectDuplicateHeader(nsHttpAtom header);
92 // All members must be copy-constructable and assignable
93 nsTArray<nsEntry> mHeaders;
95 friend struct IPC::ParamTraits<nsHttpHeaderArray>;
96 };
99 //-----------------------------------------------------------------------------
100 // nsHttpHeaderArray <private>: inline functions
101 //-----------------------------------------------------------------------------
103 inline int32_t
104 nsHttpHeaderArray::LookupEntry(nsHttpAtom header, const nsEntry **entry) const
105 {
106 uint32_t index = mHeaders.IndexOf(header, 0, nsEntry::MatchHeader());
107 if (index != UINT32_MAX)
108 *entry = &mHeaders[index];
109 return index;
110 }
112 inline int32_t
113 nsHttpHeaderArray::LookupEntry(nsHttpAtom header, nsEntry **entry)
114 {
115 uint32_t index = mHeaders.IndexOf(header, 0, nsEntry::MatchHeader());
116 if (index != UINT32_MAX)
117 *entry = &mHeaders[index];
118 return index;
119 }
121 inline bool
122 nsHttpHeaderArray::IsSingletonHeader(nsHttpAtom header)
123 {
124 return header == nsHttp::Content_Type ||
125 header == nsHttp::Content_Disposition ||
126 header == nsHttp::Content_Length ||
127 header == nsHttp::User_Agent ||
128 header == nsHttp::Referer ||
129 header == nsHttp::Host ||
130 header == nsHttp::Authorization ||
131 header == nsHttp::Proxy_Authorization ||
132 header == nsHttp::If_Modified_Since ||
133 header == nsHttp::If_Unmodified_Since ||
134 header == nsHttp::From ||
135 header == nsHttp::Location ||
136 header == nsHttp::Max_Forwards;
137 }
139 inline bool
140 nsHttpHeaderArray::TrackEmptyHeader(nsHttpAtom header)
141 {
142 return header == nsHttp::Content_Length ||
143 header == nsHttp::Location;
144 }
146 inline void
147 nsHttpHeaderArray::MergeHeader(nsHttpAtom header,
148 nsEntry *entry,
149 const nsACString &value)
150 {
151 if (value.IsEmpty())
152 return; // merge of empty header = no-op
154 // Append the new value to the existing value
155 if (header == nsHttp::Set_Cookie ||
156 header == nsHttp::WWW_Authenticate ||
157 header == nsHttp::Proxy_Authenticate)
158 {
159 // Special case these headers and use a newline delimiter to
160 // delimit the values from one another as commas may appear
161 // in the values of these headers contrary to what the spec says.
162 entry->value.Append('\n');
163 } else {
164 // Delimit each value from the others using a comma (per HTTP spec)
165 entry->value.AppendLiteral(", ");
166 }
167 entry->value.Append(value);
168 }
170 inline bool
171 nsHttpHeaderArray::IsSuspectDuplicateHeader(nsHttpAtom header)
172 {
173 bool retval = header == nsHttp::Content_Length ||
174 header == nsHttp::Content_Disposition ||
175 header == nsHttp::Location;
177 MOZ_ASSERT(!retval || IsSingletonHeader(header),
178 "Only non-mergeable headers should be in this list\n");
180 return retval;
181 }
183 }} // namespace mozilla::net
185 #endif