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