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