vfs: check userland buffers before reading them.
[haiku.git] / src / kits / network / libnetapi / HttpHeaders.cpp
blob9895f578c5cba15ce9f99a3b8c8176b523721561
1 /*
2 * Copyright 2010 Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Christophe Huriaux, c.huriaux@gmail.com
7 */
10 #include <ctype.h>
11 #include <string.h>
12 #include <new>
14 #include <String.h>
15 #include <HttpHeaders.h>
18 // #pragma mark -- BHttpHeader
21 BHttpHeader::BHttpHeader()
23 fName(),
24 fValue(),
25 fRawHeader(),
26 fRawHeaderValid(true)
31 BHttpHeader::BHttpHeader(const char* string)
33 fRawHeaderValid(true)
35 SetHeader(string);
39 BHttpHeader::BHttpHeader(const char* name, const char* value)
41 fRawHeaderValid(false)
43 SetName(name);
44 SetValue(value);
48 BHttpHeader::BHttpHeader(const BHttpHeader& copy)
50 fName(copy.fName),
51 fValue(copy.fValue),
52 fRawHeaderValid(false)
57 void
58 BHttpHeader::SetName(const char* name)
60 fRawHeaderValid = false;
61 fName = name;
62 fName.Trim().CapitalizeEachWord();
66 void
67 BHttpHeader::SetValue(const char* value)
69 fRawHeaderValid = false;
70 fValue = value;
71 fValue.Trim();
75 bool
76 BHttpHeader::SetHeader(const char* string)
78 fRawHeaderValid = false;
79 fName.Truncate(0);
80 fValue.Truncate(0);
82 const char* separator = strchr(string, ':');
84 if (separator == NULL)
85 return false;
87 fName.SetTo(string, separator - string);
88 fName.Trim().CapitalizeEachWord();
89 SetValue(separator + 1);
90 return true;
94 const char*
95 BHttpHeader::Name() const
97 return fName.String();
101 const char*
102 BHttpHeader::Value() const
104 return fValue.String();
108 const char*
109 BHttpHeader::Header() const
111 if (!fRawHeaderValid) {
112 fRawHeaderValid = true;
114 fRawHeader.Truncate(0);
115 fRawHeader << fName << ": " << fValue;
118 return fRawHeader.String();
122 bool
123 BHttpHeader::NameIs(const char* name) const
125 return fName == BString(name).Trim().CapitalizeEachWord();
129 BHttpHeader&
130 BHttpHeader::operator=(const BHttpHeader& other)
132 fName = other.fName;
133 fValue = other.fValue;
134 fRawHeaderValid = false;
136 return *this;
140 // #pragma mark -- BHttpHeaders
143 BHttpHeaders::BHttpHeaders()
145 fHeaderList()
150 BHttpHeaders::BHttpHeaders(const BHttpHeaders& other)
152 fHeaderList()
154 *this = other;
158 BHttpHeaders::~BHttpHeaders()
160 _EraseData();
164 // #pragma mark Header access
167 const char*
168 BHttpHeaders::HeaderValue(const char* name) const
170 for (int32 i = 0; i < fHeaderList.CountItems(); i++) {
171 BHttpHeader* header
172 = reinterpret_cast<BHttpHeader*>(fHeaderList.ItemAtFast(i));
174 if (header->NameIs(name))
175 return header->Value();
178 return NULL;
182 BHttpHeader&
183 BHttpHeaders::HeaderAt(int32 index) const
185 //! Note: index _must_ be in-bounds
186 BHttpHeader* header
187 = reinterpret_cast<BHttpHeader*>(fHeaderList.ItemAtFast(index));
189 return *header;
193 // #pragma mark Header count
196 int32
197 BHttpHeaders::CountHeaders() const
199 return fHeaderList.CountItems();
203 // #pragma Header tests
206 int32
207 BHttpHeaders::HasHeader(const char* name) const
209 for (int32 i = 0; i < fHeaderList.CountItems(); i++) {
210 BHttpHeader* header
211 = reinterpret_cast<BHttpHeader*>(fHeaderList.ItemAt(i));
213 if (header->NameIs(name))
214 return i;
217 return -1;
221 // #pragma mark Header add/replace
224 bool
225 BHttpHeaders::AddHeader(const char* line)
227 return _AddOrDeleteHeader(new(std::nothrow) BHttpHeader(line));
231 bool
232 BHttpHeaders::AddHeader(const char* name, const char* value)
234 return _AddOrDeleteHeader(new(std::nothrow) BHttpHeader(name, value));
238 bool
239 BHttpHeaders::AddHeader(const char* name, int32 value)
241 BString strValue;
242 strValue << value;
244 return AddHeader(name, strValue);
248 // #pragma mark Archiving
251 void
252 BHttpHeaders::PopulateFromArchive(BMessage* archive)
254 Clear();
256 int32 index = 0;
257 char* nameFound;
258 for (;;) {
259 if (archive->GetInfo(B_STRING_TYPE, index, &nameFound, NULL) != B_OK)
260 return;
262 BString value = archive->FindString(nameFound);
263 AddHeader(nameFound, value);
265 index++;
270 void
271 BHttpHeaders::Archive(BMessage* message) const
273 int32 count = CountHeaders();
275 for (int32 i = 0; i < count; i++) {
276 BHttpHeader& header = HeaderAt(i);
277 message->AddString(header.Name(), header.Value());
282 // #pragma mark Header deletion
285 void
286 BHttpHeaders::Clear()
288 _EraseData();
289 fHeaderList.MakeEmpty();
293 // #pragma mark Overloaded operators
296 BHttpHeaders&
297 BHttpHeaders::operator=(const BHttpHeaders& other)
299 if (&other == this)
300 return *this;
302 Clear();
304 for (int32 i = 0; i < other.CountHeaders(); i++)
305 AddHeader(other.HeaderAt(i).Name(), other.HeaderAt(i).Value());
307 return *this;
311 BHttpHeader&
312 BHttpHeaders::operator[](int32 index) const
314 //! Note: Index _must_ be in-bounds
315 BHttpHeader* header
316 = reinterpret_cast<BHttpHeader*>(fHeaderList.ItemAtFast(index));
318 return *header;
322 const char*
323 BHttpHeaders::operator[](const char* name) const
325 return HeaderValue(name);
329 void
330 BHttpHeaders::_EraseData()
332 // Free allocated data;
333 for (int32 i = 0; i < fHeaderList.CountItems(); i++) {
334 BHttpHeader* header
335 = reinterpret_cast<BHttpHeader*>(fHeaderList.ItemAtFast(i));
337 delete header;
342 bool
343 BHttpHeaders::_AddOrDeleteHeader(BHttpHeader* header)
345 if (header != NULL) {
346 if (fHeaderList.AddItem(header))
347 return true;
348 delete header;
350 return false;