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