/src/resiprocate/resip/stack/MessageWaitingContents.cxx
Line | Count | Source |
1 | | #if defined(HAVE_CONFIG_H) |
2 | | #include "config.h" |
3 | | #endif |
4 | | |
5 | | #include <ctype.h> |
6 | | |
7 | | #include "resip/stack/MessageWaitingContents.hxx" |
8 | | #include "rutil/Logger.hxx" |
9 | | #include "rutil/ParseBuffer.hxx" |
10 | | #include "rutil/WinLeakCheck.hxx" |
11 | | |
12 | | |
13 | | using namespace resip; |
14 | | using namespace std; |
15 | | |
16 | | #define RESIPROCATE_SUBSYSTEM Subsystem::CONTENTS |
17 | | |
18 | | bool |
19 | | MessageWaitingContents::init() |
20 | 4 | { |
21 | 4 | static ContentsFactory<MessageWaitingContents> factory; |
22 | 4 | (void)factory; |
23 | 4 | return true; |
24 | 4 | } |
25 | | |
26 | | resip::MessageWaitingContents::AccountHeader resip::mw_account; |
27 | | const char* MessageHeaders[MW_MAX] = {"voice-message", |
28 | | "fax-message", |
29 | | "pager-message", |
30 | | "multimedia-message", |
31 | | "text-message", |
32 | | "none"}; |
33 | | |
34 | | MessageWaitingContents::MessageWaitingContents() |
35 | 0 | : Contents(getStaticType()), |
36 | 0 | mHasMessages(false), |
37 | 0 | mAccountUri(0) |
38 | 0 | { |
39 | 0 | for(int i = 0; i < (int)MW_MAX; i++) |
40 | 0 | { |
41 | 0 | mHeaders[i] = 0; |
42 | 0 | } |
43 | 0 | } |
44 | | |
45 | | MessageWaitingContents::MessageWaitingContents(const HeaderFieldValue& hfv, const Mime& contentType) |
46 | 5.87k | : Contents(hfv, contentType), |
47 | 5.87k | mHasMessages(false), |
48 | 5.87k | mAccountUri(0) |
49 | 5.87k | { |
50 | 41.1k | for(int i = 0; i < (int)MW_MAX; i++) |
51 | 35.2k | { |
52 | 35.2k | mHeaders[i] = 0; |
53 | 35.2k | } |
54 | 5.87k | } |
55 | | |
56 | | MessageWaitingContents::MessageWaitingContents(const Data& data, const Mime& contentType) |
57 | 0 | : Contents(contentType), |
58 | 0 | mHasMessages(false), |
59 | 0 | mAccountUri(0) |
60 | 0 | { |
61 | 0 | for(int i = 0; i < (int)MW_MAX; i++) |
62 | 0 | { |
63 | 0 | mHeaders[i] = 0; |
64 | 0 | } |
65 | 0 | resip_assert(0); |
66 | 0 | } |
67 | | |
68 | | MessageWaitingContents::MessageWaitingContents(const MessageWaitingContents& rhs) |
69 | 0 | : Contents(rhs), |
70 | 0 | mHasMessages(rhs.mHasMessages), |
71 | 0 | mAccountUri(rhs.mAccountUri ? new Uri(*rhs.mAccountUri) : 0), |
72 | 0 | mExtensions(rhs.mExtensions) |
73 | 0 | { |
74 | 0 | for(int i = 0; i < (int)MW_MAX; i++) |
75 | 0 | { |
76 | 0 | if (rhs.mHeaders[i] != 0) |
77 | 0 | { |
78 | 0 | mHeaders[i] = new Header(*rhs.mHeaders[i]); |
79 | 0 | } |
80 | 0 | else |
81 | 0 | { |
82 | 0 | mHeaders[i] = 0; |
83 | 0 | } |
84 | 0 | } |
85 | 0 | } |
86 | | |
87 | | MessageWaitingContents::~MessageWaitingContents() |
88 | 5.87k | { |
89 | 5.87k | clear(); |
90 | 5.87k | } |
91 | | |
92 | | void |
93 | | MessageWaitingContents::clear() |
94 | 5.87k | { |
95 | 5.87k | mHasMessages = false; |
96 | | |
97 | 5.87k | delete mAccountUri; |
98 | 5.87k | mAccountUri = 0; |
99 | | |
100 | 41.1k | for (int i = 0; i < (int)MW_MAX; i++) |
101 | 35.2k | { |
102 | 35.2k | delete mHeaders[i]; |
103 | 35.2k | } |
104 | 5.87k | } |
105 | | |
106 | | MessageWaitingContents& |
107 | | MessageWaitingContents::operator=(const MessageWaitingContents& rhs) |
108 | 0 | { |
109 | 0 | if (this != &rhs) |
110 | 0 | { |
111 | 0 | Contents::operator=(rhs); |
112 | 0 | clear(); |
113 | |
|
114 | 0 | mHasMessages = rhs.mHasMessages; |
115 | 0 | mAccountUri = rhs.mAccountUri ? new Uri(*rhs.mAccountUri) : 0; |
116 | 0 | mExtensions = rhs.mExtensions; |
117 | |
|
118 | 0 | for(int i = 0; i < (int)MW_MAX; i++) |
119 | 0 | { |
120 | 0 | if (rhs.mHeaders[i] != 0) |
121 | 0 | { |
122 | 0 | mHeaders[i] = new Header(*rhs.mHeaders[i]); |
123 | 0 | } |
124 | 0 | else |
125 | 0 | { |
126 | 0 | mHeaders[i] = 0; |
127 | 0 | } |
128 | 0 | } |
129 | 0 | } |
130 | 0 | return *this; |
131 | 0 | } |
132 | | |
133 | | const Mime& |
134 | | MessageWaitingContents::getStaticType() |
135 | 2 | { |
136 | 2 | static Mime type("application", "simple-message-summary"); |
137 | | //static Mime type("text", "data"); |
138 | 2 | return type; |
139 | 2 | } |
140 | | |
141 | | Contents* |
142 | | MessageWaitingContents::clone() const |
143 | 0 | { |
144 | 0 | return new MessageWaitingContents(*this); |
145 | 0 | } |
146 | | |
147 | | EncodeStream& |
148 | | MessageWaitingContents::encodeParsed(EncodeStream& s) const |
149 | 0 | { |
150 | 0 | s << "Messages-Waiting" << Symbols::COLON[0] << Symbols::SPACE[0] |
151 | 0 | << (mHasMessages ? "yes" : "no") << Symbols::CRLF; |
152 | |
|
153 | 0 | if (exists(mw_account)) |
154 | 0 | { |
155 | 0 | s << "Message-Account" << Symbols::COLON[0] << Symbols::SPACE[0]; |
156 | 0 | header(mw_account).encode(s); |
157 | 0 | s << Symbols::CRLF; |
158 | 0 | } |
159 | |
|
160 | 0 | for(int i = 0; i < (int)MW_MAX; i++) |
161 | 0 | { |
162 | 0 | if (mHeaders[i] != 0) |
163 | 0 | { |
164 | 0 | s << MessageHeaders[i] << Symbols::COLON[0] << Symbols::SPACE[0] |
165 | 0 | << mHeaders[i]->mNew << Symbols::SLASH[0] |
166 | 0 | << mHeaders[i]->mOld; |
167 | |
|
168 | 0 | if (mHeaders[i]->mHasUrgent) |
169 | 0 | { |
170 | 0 | s << Symbols::SPACE[0] << Symbols::LPAREN[0] |
171 | 0 | << mHeaders[i]->mUrgentNew << Symbols::SLASH[0] |
172 | 0 | << mHeaders[i]->mUrgentOld << Symbols::RPAREN[0]; |
173 | 0 | } |
174 | |
|
175 | 0 | s << Symbols::CRLF; |
176 | 0 | } |
177 | 0 | } |
178 | |
|
179 | 0 | if (!mExtensions.empty()) |
180 | 0 | { |
181 | 0 | s << Symbols::CRLF; |
182 | 0 | for (map<Data, Data>::const_iterator i = mExtensions.begin(); |
183 | 0 | i != mExtensions.end(); i++) |
184 | 0 | { |
185 | 0 | s << i->first << Symbols::COLON[0] << Symbols::SPACE[0] |
186 | 0 | << i->second << Symbols::CRLF; |
187 | 0 | } |
188 | 0 | } |
189 | |
|
190 | 0 | return s; |
191 | 0 | } |
192 | | |
193 | | inline |
194 | | bool |
195 | | isWhite(char c) |
196 | 0 | { |
197 | 0 | switch (c) |
198 | 0 | { |
199 | 0 | case ' ' : |
200 | 0 | case '\t' : |
201 | 0 | case '\r' : |
202 | 0 | case '\n' : |
203 | 0 | return true; |
204 | 0 | default: |
205 | 0 | return false; |
206 | 0 | } |
207 | 0 | } |
208 | | |
209 | | const char* |
210 | | resip::skipSipLWS(ParseBuffer& pb) |
211 | 0 | { |
212 | 0 | enum {WS, CR, LF, CR1}; |
213 | |
|
214 | 0 | int state = WS; |
215 | |
|
216 | 0 | while (!pb.eof()) |
217 | 0 | { |
218 | 0 | if (!isWhite(*pb.position())) |
219 | 0 | { |
220 | 0 | if (state == LF) |
221 | 0 | { |
222 | 0 | pb.reset(pb.position() - 2); |
223 | 0 | } |
224 | 0 | return pb.position(); |
225 | 0 | } |
226 | 0 | if (!pb.eof()) |
227 | 0 | { |
228 | 0 | switch (state) |
229 | 0 | { |
230 | 0 | case WS: |
231 | 0 | if (*pb.position() == Symbols::CR[0]) |
232 | 0 | { |
233 | 0 | state = CR; |
234 | 0 | } |
235 | 0 | break; |
236 | 0 | case CR: |
237 | 0 | if (*pb.position() == Symbols::CR[0]) |
238 | 0 | { |
239 | 0 | state = CR; |
240 | 0 | } |
241 | 0 | else if (*pb.position() == Symbols::LF[0]) |
242 | 0 | { |
243 | 0 | state = LF; |
244 | 0 | } |
245 | 0 | else |
246 | 0 | { |
247 | 0 | state = WS; |
248 | 0 | } |
249 | 0 | break; |
250 | 0 | case LF: |
251 | 0 | if (*pb.position() == Symbols::CR[0]) |
252 | 0 | { |
253 | 0 | state = CR1; |
254 | 0 | } |
255 | 0 | else if (!pb.eof() && *pb.position() == Symbols::LF[0]) |
256 | 0 | { |
257 | 0 | state = WS; |
258 | 0 | } |
259 | 0 | break; |
260 | 0 | case CR1: |
261 | 0 | if (*pb.position() == Symbols::CR[0]) |
262 | 0 | { |
263 | 0 | state = CR; |
264 | 0 | } |
265 | 0 | else if (*pb.position() == Symbols::LF[0]) |
266 | 0 | { |
267 | 0 | pb.reset(pb.position() - 3); |
268 | 0 | return pb.position(); |
269 | 0 | } |
270 | 0 | else |
271 | 0 | { |
272 | 0 | state = WS; |
273 | 0 | } |
274 | 0 | break; |
275 | 0 | default: |
276 | 0 | resip_assert(false); |
277 | 0 | } |
278 | 0 | } |
279 | 0 | pb.skipChar(); |
280 | 0 | } |
281 | | |
282 | 0 | if (state == LF) |
283 | 0 | { |
284 | 0 | pb.reset(pb.position() - 2); |
285 | 0 | } |
286 | 0 | return pb.position(); |
287 | 0 | } |
288 | | |
289 | | void |
290 | | MessageWaitingContents::parse(ParseBuffer& pb) |
291 | 5.87k | { |
292 | 5.87k | pb.skipChars("Messages-Waiting"); |
293 | 5.87k | pb.skipWhitespace(); |
294 | 5.87k | pb.skipChar(Symbols::COLON[0]); |
295 | 5.87k | const char* anchor = pb.skipWhitespace(); |
296 | 5.87k | pb.skipNonWhitespace(); |
297 | | |
298 | 5.87k | Data has; |
299 | 5.87k | pb.data(has, anchor); |
300 | 5.87k | if (isEqualNoCase(has, "yes")) |
301 | 0 | { |
302 | 0 | mHasMessages = true; |
303 | 0 | } |
304 | 5.87k | else if (isEqualNoCase(has, "no")) |
305 | 0 | { |
306 | 0 | mHasMessages = false; |
307 | 0 | } |
308 | 5.87k | else |
309 | 5.87k | { |
310 | 5.87k | pb.fail(__FILE__, __LINE__); |
311 | 5.87k | } |
312 | | |
313 | 5.87k | anchor = pb.skipWhitespace(); |
314 | 5.87k | if (pb.eof()) |
315 | 0 | { |
316 | 0 | return; |
317 | 0 | } |
318 | | |
319 | 5.87k | Data accountHeader; |
320 | 5.87k | pb.skipToOneOf(ParseBuffer::Whitespace, Symbols::COLON); |
321 | 5.87k | pb.data(accountHeader, anchor); |
322 | 5.87k | static const Data AccountMessage("message-account"); |
323 | 5.87k | if (isEqualNoCase(accountHeader, AccountMessage)) |
324 | 0 | { |
325 | 0 | pb.skipWhitespace(); |
326 | 0 | pb.skipChar(Symbols::COLON[0]); |
327 | 0 | pb.skipWhitespace(); |
328 | | |
329 | 0 | mAccountUri = new Uri(); |
330 | 0 | mAccountUri->parse(pb); |
331 | 0 | pb.skipChars(Symbols::CRLF); |
332 | 0 | } |
333 | 5.87k | else |
334 | 5.87k | { |
335 | 5.87k | pb.reset(anchor); |
336 | 5.87k | } |
337 | | |
338 | 5.87k | while (!pb.eof() && *pb.position() != Symbols::CR[0]) |
339 | 0 | { |
340 | 0 | int ht = -1; |
341 | 0 | switch (tolower(static_cast< unsigned char >(*pb.position()))) |
342 | 0 | { |
343 | 0 | case 'v' : |
344 | 0 | ht = mw_voice; |
345 | 0 | break; |
346 | 0 | case 'f' : |
347 | 0 | ht = mw_fax; |
348 | 0 | break; |
349 | 0 | case 'p' : |
350 | 0 | ht = mw_pager; |
351 | 0 | break; |
352 | 0 | case 'm' : |
353 | 0 | ht = mw_multimedia; |
354 | 0 | break; |
355 | 0 | case 't' : |
356 | 0 | ht = mw_text; |
357 | 0 | break; |
358 | 0 | case 'n' : |
359 | 0 | ht = mw_none; |
360 | 0 | break; |
361 | 0 | default : |
362 | 0 | pb.fail(__FILE__, __LINE__); |
363 | 0 | } |
364 | 0 | resip_assert(ht != -1); |
365 | |
|
366 | 0 | pb.skipToOneOf(ParseBuffer::Whitespace, Symbols::COLON); |
367 | 0 | pb.skipWhitespace(); |
368 | 0 | pb.skipChar(Symbols::COLON[0]); |
369 | 0 | pb.skipWhitespace(); |
370 | |
|
371 | 0 | unsigned int numNew = pb.integer(); |
372 | 0 | pb.skipWhitespace(); |
373 | 0 | pb.skipChar(Symbols::SLASH[0]); |
374 | 0 | pb.skipWhitespace(); |
375 | |
|
376 | 0 | unsigned int numOld = pb.integer(); |
377 | 0 | skipSipLWS(pb); |
378 | |
|
379 | 0 | if (!pb.eof() && *pb.position() != Symbols::LPAREN[0]) |
380 | 0 | { |
381 | 0 | if (mHeaders[ht] != 0) |
382 | 0 | { |
383 | 0 | pb.fail(__FILE__, __LINE__); |
384 | 0 | } |
385 | 0 | mHeaders[ht] = new Header(numNew, numOld); |
386 | 0 | } |
387 | 0 | else |
388 | 0 | { |
389 | 0 | pb.skipChar(); |
390 | 0 | pb.skipWhitespace(); |
391 | |
|
392 | 0 | unsigned int numUrgentNew = pb.integer(); |
393 | 0 | pb.skipWhitespace(); |
394 | 0 | pb.skipChar(Symbols::SLASH[0]); |
395 | 0 | pb.skipWhitespace(); |
396 | |
|
397 | 0 | unsigned int numUrgentOld = pb.integer(); |
398 | 0 | pb.skipWhitespace(); |
399 | 0 | pb.skipChar(Symbols::RPAREN[0]); |
400 | | // skip LWS as specified in rfc3261 |
401 | 0 | skipSipLWS(pb); |
402 | |
|
403 | 0 | if (mHeaders[ht] != 0) |
404 | 0 | { |
405 | 0 | pb.fail(__FILE__, __LINE__); |
406 | 0 | } |
407 | 0 | mHeaders[ht] = new Header(numNew, numOld, numUrgentNew, numUrgentOld); |
408 | 0 | } |
409 | | |
410 | 0 | pb.skipChars(Symbols::CRLF); |
411 | 0 | } |
412 | | |
413 | 5.87k | if (!pb.eof() && *pb.position() == Symbols::CR[0]) |
414 | 0 | { |
415 | 0 | pb.skipChars(Symbols::CRLF); |
416 | | |
417 | 0 | while (!pb.eof()) |
418 | 0 | { |
419 | 0 | anchor = pb.position(); |
420 | 0 | Data header; |
421 | 0 | pb.skipToOneOf(ParseBuffer::Whitespace, Symbols::COLON); |
422 | 0 | pb.data(header, anchor); |
423 | |
|
424 | 0 | pb.skipWhitespace(); |
425 | 0 | pb.skipChar(Symbols::COLON[0]); |
426 | 0 | anchor = pb.skipWhitespace(); |
427 | |
|
428 | 0 | while (true) |
429 | 0 | { |
430 | | // CodeWarrior isn't helpful enough to pick the "obvious" operator definition |
431 | | // so we add volatile here so CW is completely unconfused what to do. |
432 | 0 | const volatile char* pos = pb.skipToChar(Symbols::CR[0]); |
433 | 0 | skipSipLWS(pb); |
434 | 0 | if (pb.position() == pos) |
435 | 0 | { |
436 | 0 | Data content; |
437 | 0 | pb.data(content, anchor); |
438 | 0 | mExtensions[header] = content; |
439 | |
|
440 | 0 | pb.skipChars(Symbols::CRLF); |
441 | 0 | break; |
442 | 0 | } |
443 | 0 | } |
444 | 0 | } |
445 | 0 | } |
446 | 5.87k | } |
447 | | |
448 | | MessageWaitingContents::Header::Header(unsigned int numNew, |
449 | | unsigned int numOld) |
450 | 0 | : mNew(numNew), |
451 | 0 | mOld(numOld), |
452 | 0 | mHasUrgent(false), |
453 | 0 | mUrgentNew(0), |
454 | 0 | mUrgentOld(0) |
455 | 0 | {} |
456 | | |
457 | | MessageWaitingContents::Header::Header(unsigned int numNew, |
458 | | unsigned int numOld, |
459 | | unsigned int numUrgentNew, |
460 | | unsigned int numUrgentOld) |
461 | 0 | : mNew(numNew), |
462 | 0 | mOld(numOld), |
463 | 0 | mHasUrgent(true), |
464 | 0 | mUrgentNew(numUrgentNew), |
465 | 0 | mUrgentOld(numUrgentOld) |
466 | 0 | {} |
467 | | |
468 | | MessageWaitingContents::Header& |
469 | | MessageWaitingContents::header(HeaderType ht) |
470 | 0 | { |
471 | 0 | checkParsed(); |
472 | | |
473 | | /* this is a trick to allow a const method to update "this" with an empty |
474 | | Header in case there wasn't a corresponding header line in the MessageWaiting doc |
475 | | */ |
476 | 0 | if (mHeaders[ht] == 0) |
477 | 0 | { |
478 | 0 | mHeaders[ht] = new Header(0, 0); |
479 | 0 | } |
480 | 0 | return *mHeaders[ht]; |
481 | 0 | } |
482 | | |
483 | | const MessageWaitingContents::Header& |
484 | | MessageWaitingContents::header(HeaderType ht) const |
485 | 0 | { |
486 | 0 | checkParsed(); |
487 | | |
488 | | /* this is a trick to allow a const method to update "this" with an empty |
489 | | Header in case there wasn't a corresponding header line in the MessageWaiting doc |
490 | | */ |
491 | 0 | if (mHeaders[ht] == 0) |
492 | 0 | { |
493 | 0 | ErrLog(<< "You called " |
494 | 0 | "MessageWaitingContents::header(HeaderType ht) _const_ " |
495 | 0 | "without first calling exists(), and the header does not exist. Our" |
496 | 0 | " behavior in this scenario is to implicitly create the header(using const_cast!); " |
497 | 0 | "this is probably not what you want, but it is either this or " |
498 | 0 | "assert/throw an exception. Since this has been the behavior for " |
499 | 0 | "so long, we are not throwing here, _yet_. You need to fix your " |
500 | 0 | "code, before we _do_ start throwing. This is why const-correctness" |
501 | 0 | " should never be made a TODO item </rant>"); |
502 | 0 | MessageWaitingContents* ncthis = const_cast<MessageWaitingContents*>(this); |
503 | 0 | ncthis->mHeaders[ht] = new Header(0, 0); |
504 | 0 | } |
505 | 0 | return *mHeaders[ht]; |
506 | 0 | } |
507 | | |
508 | | bool |
509 | | MessageWaitingContents::exists(HeaderType ht) const |
510 | 0 | { |
511 | 0 | checkParsed(); |
512 | 0 | return mHeaders[ht] != 0; |
513 | 0 | } |
514 | | |
515 | | void |
516 | | MessageWaitingContents::remove(HeaderType ht) |
517 | 0 | { |
518 | 0 | checkParsed(); |
519 | 0 | delete mHeaders[ht]; |
520 | 0 | mHeaders[ht] = 0; |
521 | 0 | } |
522 | | |
523 | | Uri& |
524 | | MessageWaitingContents::header(const AccountHeader& ht) |
525 | 0 | { |
526 | 0 | checkParsed(); |
527 | | |
528 | | /* this is a trick to allow a const method to update "this" with an empty |
529 | | Uri in case there wasn't a Message-Account line in the MessageWaiting doc |
530 | | */ |
531 | 0 | if (mAccountUri == 0) |
532 | 0 | { |
533 | 0 | mAccountUri = new Uri(); |
534 | 0 | } |
535 | 0 | return *mAccountUri; |
536 | 0 | } |
537 | | |
538 | | const Uri& |
539 | | MessageWaitingContents::header(const AccountHeader& ht) const |
540 | 0 | { |
541 | 0 | checkParsed(); |
542 | | |
543 | | /* this is a trick to allow a const method to update "this" with an empty |
544 | | Uri in case there wasn't a Message-Account line in the MessageWaiting doc |
545 | | */ |
546 | 0 | if (mAccountUri == 0) |
547 | 0 | { |
548 | 0 | ErrLog(<< "You called " |
549 | 0 | "MessageWaitingContents::header(const AccountHeader& ht) _const_ " |
550 | 0 | "without first calling exists(), and the header does not exist. Our" |
551 | 0 | " behavior in this scenario is to implicitly create the header(using const_cast!); " |
552 | 0 | "this is probably not what you want, but it is either this or " |
553 | 0 | "assert/throw an exception. Since this has been the behavior for " |
554 | 0 | "so long, we are not throwing here, _yet_. You need to fix your " |
555 | 0 | "code, before we _do_ start throwing. This is why const-correctness" |
556 | 0 | " should never be made a TODO item </rant>"); |
557 | 0 | MessageWaitingContents* ncthis = const_cast<MessageWaitingContents*>(this); |
558 | 0 | ncthis->mAccountUri = new Uri(); |
559 | 0 | } |
560 | 0 | return *mAccountUri; |
561 | 0 | } |
562 | | |
563 | | bool |
564 | | MessageWaitingContents::exists(const AccountHeader& ht) const |
565 | 0 | { |
566 | 0 | checkParsed(); |
567 | 0 | return mAccountUri != 0; |
568 | 0 | } |
569 | | |
570 | | void |
571 | | MessageWaitingContents::remove(const AccountHeader& ht) |
572 | 0 | { |
573 | 0 | checkParsed(); |
574 | 0 | delete mAccountUri; |
575 | 0 | mAccountUri = 0; |
576 | 0 | } |
577 | | |
578 | | Data& |
579 | | MessageWaitingContents::header(const Data& hn) |
580 | 0 | { |
581 | 0 | checkParsed(); |
582 | 0 | return mExtensions[hn]; |
583 | 0 | } |
584 | | |
585 | | const Data& |
586 | | MessageWaitingContents::header(const Data& hn) const |
587 | 0 | { |
588 | 0 | checkParsed(); |
589 | 0 | std::map<Data, Data>::const_iterator h=mExtensions.find(hn); |
590 | 0 | if(h==mExtensions.end()) |
591 | 0 | { |
592 | 0 | ErrLog(<< "You called " |
593 | 0 | "MessageWaitingContents::header(const Data& hn) _const_ " |
594 | 0 | "without first calling exists(), and the header does not exist. Our" |
595 | 0 | " behavior in this scenario is to implicitly create the header(using const_cast!); " |
596 | 0 | "this is probably not what you want, but it is either this or " |
597 | 0 | "assert/throw an exception. Since this has been the behavior for " |
598 | 0 | "so long, we are not throwing here, _yet_. You need to fix your " |
599 | 0 | "code, before we _do_ start throwing. This is why const-correctness" |
600 | 0 | " should never be made a TODO item </rant>"); |
601 | 0 | MessageWaitingContents* ncthis = const_cast<MessageWaitingContents*>(this); |
602 | 0 | h=ncthis->mExtensions.insert(std::make_pair(hn,Data::Empty)).first; |
603 | 0 | } |
604 | 0 | return h->second; |
605 | 0 | } |
606 | | |
607 | | bool |
608 | | MessageWaitingContents::exists(const Data& hn) const |
609 | 0 | { |
610 | 0 | checkParsed(); |
611 | 0 | return mExtensions.find(hn) != mExtensions.end(); |
612 | 0 | } |
613 | | |
614 | | void |
615 | | MessageWaitingContents::remove(const Data& hn) |
616 | 0 | { |
617 | 0 | checkParsed(); |
618 | 0 | mExtensions.erase(hn); |
619 | 0 | } |
620 | | |
621 | | /* ==================================================================== |
622 | | * The Vovida Software License, Version 1.0 |
623 | | * |
624 | | * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. |
625 | | * |
626 | | * Redistribution and use in source and binary forms, with or without |
627 | | * modification, are permitted provided that the following conditions |
628 | | * are met: |
629 | | * |
630 | | * 1. Redistributions of source code must retain the above copyright |
631 | | * notice, this list of conditions and the following disclaimer. |
632 | | * |
633 | | * 2. Redistributions in binary form must reproduce the above copyright |
634 | | * notice, this list of conditions and the following disclaimer in |
635 | | * the documentation and/or other materials provided with the |
636 | | * distribution. |
637 | | * |
638 | | * 3. The names "VOCAL", "Vovida Open Communication Application Library", |
639 | | * and "Vovida Open Communication Application Library (VOCAL)" must |
640 | | * not be used to endorse or promote products derived from this |
641 | | * software without prior written permission. For written |
642 | | * permission, please contact vocal@vovida.org. |
643 | | * |
644 | | * 4. Products derived from this software may not be called "VOCAL", nor |
645 | | * may "VOCAL" appear in their name, without prior written |
646 | | * permission of Vovida Networks, Inc. |
647 | | * |
648 | | * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED |
649 | | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
650 | | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND |
651 | | * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA |
652 | | * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES |
653 | | * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, |
654 | | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
655 | | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
656 | | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
657 | | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
658 | | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE |
659 | | * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
660 | | * DAMAGE. |
661 | | * |
662 | | * ==================================================================== |
663 | | * |
664 | | * This software consists of voluntary contributions made by Vovida |
665 | | * Networks, Inc. and many individuals on behalf of Vovida Networks, |
666 | | * Inc. For more information on Vovida Networks, Inc., please see |
667 | | * <http://www.vovida.org/>. |
668 | | * |
669 | | */ |