1/*
2 * Copyright 2010 Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Christophe Huriaux, c.huriaux@gmail.com
7 */
8
9
10#include <cstring>
11#include <new>
12
13#include <String.h>
14#include <HttpHeaders.h>
15
16
17// #pragma mark -- BHttpHeader
18
19
20BHttpHeader::BHttpHeader()
21	:
22	fName(),
23	fValue(),
24	fRawHeader(),
25	fRawHeaderValid(true)
26{
27}
28
29
30BHttpHeader::BHttpHeader(const char* string)
31	:
32	fRawHeaderValid(true)
33{
34	SetHeader(string);
35}
36
37
38BHttpHeader::BHttpHeader(const char* name, const char* value)
39	:
40	fName(name),
41	fValue(value),
42	fRawHeaderValid(false)
43{
44}
45
46
47BHttpHeader::BHttpHeader(const BHttpHeader& copy)
48	:
49	fName(copy.fName),
50	fValue(copy.fValue),
51	fRawHeaderValid(false)
52{
53}
54
55
56void
57BHttpHeader::SetName(const char* name)
58{
59	fRawHeaderValid = false;
60	fName = name;
61}
62
63
64void
65BHttpHeader::SetValue(const char* value)
66{
67	fRawHeaderValid = false;
68	fValue = value;
69}
70
71
72bool
73BHttpHeader::SetHeader(const char* string)
74{
75	BString strLine(string);
76
77	fRawHeaderValid = false;
78	fName.Truncate(0);
79	fValue.Truncate(0);
80
81	int32 separatorLocation = strLine.FindFirst(": ");
82
83	if (separatorLocation == B_ERROR)
84		return false;
85
86	strLine.MoveInto(fName, 0, separatorLocation);
87	strLine.Remove(0, 2);
88	fValue = strLine;
89
90	return true;
91}
92
93
94const char*
95BHttpHeader::Name() const
96{
97	return fName.String();
98}
99
100
101const char*
102BHttpHeader::Value() const
103{
104	return fValue.String();
105}
106
107
108const char*
109BHttpHeader::Header() const
110{
111	if (!fRawHeaderValid) {
112		fRawHeaderValid = true;
113
114		fRawHeader.Truncate(0);
115		fRawHeader << fName << ": " << fValue;
116	}
117
118	return fRawHeader.String();
119}
120
121
122bool
123BHttpHeader::NameIs(const char* name) const
124{
125	return fName == BString(name);
126}
127
128
129BHttpHeader&
130BHttpHeader::operator=(const BHttpHeader& other)
131{
132	fName = other.fName;
133	fValue = other.fValue;
134	fRawHeaderValid = false;
135
136	return *this;
137}
138
139
140// #pragma mark -- BHttpHeaders
141
142
143BHttpHeaders::BHttpHeaders()
144	:
145	fHeaderList()
146{
147}
148
149
150BHttpHeaders::BHttpHeaders(const BHttpHeaders& copy)
151	:
152	fHeaderList()
153{
154	for (int32 i = 0; i < copy.CountHeaders(); i++)
155		AddHeader(copy.HeaderAt(i).Name(), copy.HeaderAt(i).Value());
156}
157
158
159BHttpHeaders::~BHttpHeaders()
160{
161	_EraseData();
162}
163
164
165// #pragma mark Header access
166
167
168const char*
169BHttpHeaders::HeaderValue(const char* name) const
170{
171	for (int32 i = 0; i < fHeaderList.CountItems(); i++) {
172		BHttpHeader* header
173			= reinterpret_cast<BHttpHeader*>(fHeaderList.ItemAtFast(i));
174
175		if (header->NameIs(name))
176			return header->Value();
177	}
178
179	return NULL;
180}
181
182
183BHttpHeader&
184BHttpHeaders::HeaderAt(int32 index) const
185{
186	//! Note: index _must_ be in-bounds
187	BHttpHeader* header
188		= reinterpret_cast<BHttpHeader*>(fHeaderList.ItemAtFast(index));
189
190	return *header;
191}
192
193
194// #pragma mark Header count
195
196
197int32
198BHttpHeaders::CountHeaders() const
199{
200	return fHeaderList.CountItems();
201}
202
203
204// #pragma Header tests
205
206
207int32
208BHttpHeaders::HasHeader(const char* name) const
209{
210	for (int32 i = 0; i < fHeaderList.CountItems(); i++) {
211		BHttpHeader* header
212			= reinterpret_cast<BHttpHeader*>(fHeaderList.ItemAt(i));
213
214		if (header->NameIs(name))
215			return i;
216	}
217
218	return B_ERROR;
219}
220
221
222// #pragma mark Header add/replace
223
224
225bool
226BHttpHeaders::AddHeader(const char* line)
227{
228	BHttpHeader* heapHeader = new(std::nothrow) BHttpHeader(line);
229
230	if (heapHeader != NULL) {
231		fHeaderList.AddItem(heapHeader);
232		return true;
233	}
234
235	return false;
236}
237
238
239bool
240BHttpHeaders::AddHeader(const char* name, const char* value)
241{
242	BHttpHeader* heapHeader = new(std::nothrow) BHttpHeader(name, value);
243
244	if (heapHeader != NULL) {
245		fHeaderList.AddItem(heapHeader);
246		return true;
247	}
248
249	return false;
250}
251
252
253bool
254BHttpHeaders::AddHeader(const char* name, int32 value)
255{
256	BString strValue;
257	strValue << value;
258
259	return AddHeader(name, strValue);
260}
261
262
263// #pragma mark Header deletion
264
265
266void
267BHttpHeaders::Clear()
268{
269	_EraseData();
270	fHeaderList.MakeEmpty();
271}
272
273
274// #pragma mark Overloaded operators
275
276
277BHttpHeaders&
278BHttpHeaders::operator=(const BHttpHeaders& other)
279{
280	for (int32 i = 0; i < other.CountHeaders(); i++)
281		AddHeader(other.HeaderAt(i).Name(), other.HeaderAt(i).Value());
282
283	return *this;
284}
285
286
287BHttpHeader&
288BHttpHeaders::operator[](int32 index) const
289{
290	//! Note: Index _must_ be in-bounds
291	BHttpHeader* header
292		= reinterpret_cast<BHttpHeader*>(fHeaderList.ItemAtFast(index));
293
294	return *header;
295}
296
297
298const char*
299BHttpHeaders::operator[](const char* name) const
300{
301	return HeaderValue(name);
302}
303
304
305void
306BHttpHeaders::_EraseData()
307{
308	// Free allocated data;
309	for (int32 i = 0; i < fHeaderList.CountItems(); i++) {
310		BHttpHeader* header
311			= reinterpret_cast<BHttpHeader*>(fHeaderList.ItemAtFast(i));
312
313		delete header;
314	}
315}
316