xref: /haiku/src/kits/network/libnetservices/HttpHeaders.cpp (revision 52c4471a3024d2eb81fe88e2c3982b9f8daa5e56)
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 <ctype.h>
11 #include <string.h>
12 #include <new>
13 
14 #include <String.h>
15 #include <HttpHeaders.h>
16 
17 using namespace BPrivate::Network;
18 
19 
20 // #pragma mark -- BHttpHeader
21 
22 
23 BHttpHeader::BHttpHeader()
24 	:
25 	fName(),
26 	fValue(),
27 	fRawHeader(),
28 	fRawHeaderValid(true)
29 {
30 }
31 
32 
33 BHttpHeader::BHttpHeader(const char* string)
34 	:
35 	fRawHeaderValid(true)
36 {
37 	SetHeader(string);
38 }
39 
40 
41 BHttpHeader::BHttpHeader(const char* name, const char* value)
42 	:
43 	fRawHeaderValid(false)
44 {
45 	SetName(name);
46 	SetValue(value);
47 }
48 
49 
50 BHttpHeader::BHttpHeader(const BHttpHeader& copy)
51 	:
52 	fName(copy.fName),
53 	fValue(copy.fValue),
54 	fRawHeaderValid(false)
55 {
56 }
57 
58 
59 void
60 BHttpHeader::SetName(const char* name)
61 {
62 	fRawHeaderValid = false;
63 	fName = name;
64 	fName.Trim().CapitalizeEachWord();
65 }
66 
67 
68 void
69 BHttpHeader::SetValue(const char* value)
70 {
71 	fRawHeaderValid = false;
72 	fValue = value;
73 	fValue.Trim();
74 }
75 
76 
77 bool
78 BHttpHeader::SetHeader(const char* string)
79 {
80 	fRawHeaderValid = false;
81 	fName.Truncate(0);
82 	fValue.Truncate(0);
83 
84 	const char* separator = strchr(string, ':');
85 
86 	if (separator == NULL)
87 		return false;
88 
89 	fName.SetTo(string, separator - string);
90 	fName.Trim().CapitalizeEachWord();
91 	SetValue(separator + 1);
92 	return true;
93 }
94 
95 
96 const char*
97 BHttpHeader::Name() const
98 {
99 	return fName.String();
100 }
101 
102 
103 const char*
104 BHttpHeader::Value() const
105 {
106 	return fValue.String();
107 }
108 
109 
110 const char*
111 BHttpHeader::Header() const
112 {
113 	if (!fRawHeaderValid) {
114 		fRawHeaderValid = true;
115 
116 		fRawHeader.Truncate(0);
117 		fRawHeader << fName << ": " << fValue;
118 	}
119 
120 	return fRawHeader.String();
121 }
122 
123 
124 bool
125 BHttpHeader::NameIs(const char* name) const
126 {
127 	return fName == BString(name).Trim().CapitalizeEachWord();
128 }
129 
130 
131 BHttpHeader&
132 BHttpHeader::operator=(const BHttpHeader& other)
133 {
134 	fName = other.fName;
135 	fValue = other.fValue;
136 	fRawHeaderValid = false;
137 
138 	return *this;
139 }
140 
141 
142 // #pragma mark -- BHttpHeaders
143 
144 
145 BHttpHeaders::BHttpHeaders()
146 	:
147 	fHeaderList()
148 {
149 }
150 
151 
152 BHttpHeaders::BHttpHeaders(const BHttpHeaders& other)
153 	:
154 	fHeaderList()
155 {
156 	*this = other;
157 }
158 
159 
160 BHttpHeaders::~BHttpHeaders()
161 {
162 	_EraseData();
163 }
164 
165 
166 // #pragma mark Header access
167 
168 
169 const char*
170 BHttpHeaders::HeaderValue(const char* name) const
171 {
172 	for (int32 i = 0; i < fHeaderList.CountItems(); i++) {
173 		BHttpHeader* header
174 			= reinterpret_cast<BHttpHeader*>(fHeaderList.ItemAtFast(i));
175 
176 		if (header->NameIs(name))
177 			return header->Value();
178 	}
179 
180 	return NULL;
181 }
182 
183 
184 BHttpHeader&
185 BHttpHeaders::HeaderAt(int32 index) const
186 {
187 	//! Note: index _must_ be in-bounds
188 	BHttpHeader* header
189 		= reinterpret_cast<BHttpHeader*>(fHeaderList.ItemAtFast(index));
190 
191 	return *header;
192 }
193 
194 
195 // #pragma mark Header count
196 
197 
198 int32
199 BHttpHeaders::CountHeaders() const
200 {
201 	return fHeaderList.CountItems();
202 }
203 
204 
205 // #pragma Header tests
206 
207 
208 int32
209 BHttpHeaders::HasHeader(const char* name) const
210 {
211 	for (int32 i = 0; i < fHeaderList.CountItems(); i++) {
212 		BHttpHeader* header
213 			= reinterpret_cast<BHttpHeader*>(fHeaderList.ItemAt(i));
214 
215 		if (header->NameIs(name))
216 			return i;
217 	}
218 
219 	return -1;
220 }
221 
222 
223 // #pragma mark Header add/replace
224 
225 
226 bool
227 BHttpHeaders::AddHeader(const char* line)
228 {
229 	return _AddOrDeleteHeader(new(std::nothrow) BHttpHeader(line));
230 }
231 
232 
233 bool
234 BHttpHeaders::AddHeader(const char* name, const char* value)
235 {
236 	return _AddOrDeleteHeader(new(std::nothrow) BHttpHeader(name, value));
237 }
238 
239 
240 bool
241 BHttpHeaders::AddHeader(const char* name, int32 value)
242 {
243 	BString strValue;
244 	strValue << value;
245 
246 	return AddHeader(name, strValue);
247 }
248 
249 
250 // #pragma mark Archiving
251 
252 
253 void
254 BHttpHeaders::PopulateFromArchive(BMessage* archive)
255 {
256 	Clear();
257 
258 	int32 index = 0;
259 	char* nameFound;
260 	for (;;) {
261 		if (archive->GetInfo(B_STRING_TYPE, index, &nameFound, NULL) != B_OK)
262 			return;
263 
264 		BString value = archive->FindString(nameFound);
265 		AddHeader(nameFound, value);
266 
267 		index++;
268 	}
269 }
270 
271 
272 void
273 BHttpHeaders::Archive(BMessage* message) const
274 {
275 	int32 count = CountHeaders();
276 
277 	for (int32 i = 0; i < count; i++) {
278 		BHttpHeader& header = HeaderAt(i);
279 		message->AddString(header.Name(), header.Value());
280 	}
281 }
282 
283 
284 // #pragma mark Header deletion
285 
286 
287 void
288 BHttpHeaders::Clear()
289 {
290 	_EraseData();
291 	fHeaderList.MakeEmpty();
292 }
293 
294 
295 // #pragma mark Overloaded operators
296 
297 
298 BHttpHeaders&
299 BHttpHeaders::operator=(const BHttpHeaders& other)
300 {
301 	if (&other == this)
302 		return *this;
303 
304 	Clear();
305 
306 	for (int32 i = 0; i < other.CountHeaders(); i++)
307 		AddHeader(other.HeaderAt(i).Name(), other.HeaderAt(i).Value());
308 
309 	return *this;
310 }
311 
312 
313 BHttpHeader&
314 BHttpHeaders::operator[](int32 index) const
315 {
316 	//! Note: Index _must_ be in-bounds
317 	BHttpHeader* header
318 		= reinterpret_cast<BHttpHeader*>(fHeaderList.ItemAtFast(index));
319 
320 	return *header;
321 }
322 
323 
324 const char*
325 BHttpHeaders::operator[](const char* name) const
326 {
327 	return HeaderValue(name);
328 }
329 
330 
331 void
332 BHttpHeaders::_EraseData()
333 {
334 	// Free allocated data;
335 	for (int32 i = 0; i < fHeaderList.CountItems(); i++) {
336 		BHttpHeader* header
337 			= reinterpret_cast<BHttpHeader*>(fHeaderList.ItemAtFast(i));
338 
339 		delete header;
340 	}
341 }
342 
343 
344 bool
345 BHttpHeaders::_AddOrDeleteHeader(BHttpHeader* header)
346 {
347 	if (header != NULL) {
348 		if (fHeaderList.AddItem(header))
349 			return true;
350 		delete header;
351 	}
352 	return false;
353 }
354