/[resiprocate]/main/resip/stack/MessageWaitingContents.cxx
ViewVC logotype

Contents of /main/resip/stack/MessageWaitingContents.cxx

Parent Directory Parent Directory | Revision Log Revision Log


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

Properties

Name Value
svn:eol-style native
svn:mime-type text/plain

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27