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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 11234 - (hide 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 fluffy 1741 #if defined(HAVE_CONFIG_H)
2 dpocock 9485 #include "config.h"
3 fluffy 1741 #endif
4    
5 derek 5283 #include "resip/stack/MessageWaitingContents.hxx"
6 bcampen 9169 #include "rutil/Logger.hxx"
7 jason 5276 #include "rutil/ParseBuffer.hxx"
8     #include "rutil/WinLeakCheck.hxx"
9 davidb 718
10 jason 3195
11 jason 1305 using namespace resip;
12 davidb 718 using namespace std;
13    
14 bcampen 9169 #define RESIPROCATE_SUBSYSTEM Subsystem::CONTENTS
15    
16 davidb 2297 bool
17     MessageWaitingContents::init()
18     {
19     static ContentsFactory<MessageWaitingContents> factory;
20     (void)factory;
21     return true;
22     }
23 davidb 718
24 jason 1305 resip::MessageWaitingContents::AccountHeader resip::mw_account;
25 davidb 718 const char* MessageHeaders[MW_MAX] = {"voice-message",
26     "fax-message",
27     "pager-message",
28     "multimedia-message",
29     "text-message",
30     "none"};
31    
32 davidb 740 MessageWaitingContents::MessageWaitingContents()
33 jason 1178 : Contents(getStaticType()),
34     mHasMessages(false),
35     mAccountUri(0)
36 davidb 718 {
37     for(int i = 0; i < (int)MW_MAX; i++)
38     {
39     mHeaders[i] = 0;
40     }
41     }
42    
43 sgodin 9367 MessageWaitingContents::MessageWaitingContents(const HeaderFieldValue& hfv, const Mime& contentType)
44 jason 1178 : Contents(hfv, contentType),
45     mHasMessages(false),
46     mAccountUri(0)
47 davidb 740 {
48     for(int i = 0; i < (int)MW_MAX; i++)
49     {
50     mHeaders[i] = 0;
51     }
52     }
53    
54 fluffy 798 MessageWaitingContents::MessageWaitingContents(const Data& data, const Mime& contentType)
55 jason 1178 : Contents(contentType),
56     mHasMessages(false),
57     mAccountUri(0)
58 fluffy 798 {
59     for(int i = 0; i < (int)MW_MAX; i++)
60     {
61     mHeaders[i] = 0;
62     }
63     assert(0);
64     }
65    
66 davidb 718 MessageWaitingContents::MessageWaitingContents(const MessageWaitingContents& rhs)
67 davidb 2297 : Contents(rhs),
68 davidb 824 mHasMessages(rhs.mHasMessages),
69 davidb 718 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 jason 1138 {
87     clear();
88     }
89 davidb 718
90     void
91     MessageWaitingContents::clear()
92     {
93 jason 1178 mHasMessages = false;
94    
95 davidb 718 delete mAccountUri;
96 jason 1178 mAccountUri = 0;
97    
98 davidb 718 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 jason 1138 Contents::operator=(rhs);
110 davidb 718 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 fluffy 1090 MessageWaitingContents::getStaticType()
133 davidb 718 {
134 derek 3710 static Mime type("application", "simple-message-summary");
135     //static Mime type("text", "data");
136 davidb 718 return type;
137     }
138    
139     Contents*
140     MessageWaitingContents::clone() const
141     {
142     return new MessageWaitingContents(*this);
143     }
144    
145 jmatthewsr 8161 EncodeStream&
146     MessageWaitingContents::encodeParsed(EncodeStream& s) const
147 davidb 718 {
148     s << "Messages-Waiting" << Symbols::COLON[0] << Symbols::SPACE[0]
149     << (mHasMessages ? "yes" : "no") << Symbols::CRLF;
150    
151     if (exists(mw_account))
152     {
153 sgodin 5633 s << "Message-Account" << Symbols::COLON[0] << Symbols::SPACE[0];
154 davidb 718 header(mw_account).encode(s);
155 sgodin 5633 s << Symbols::CRLF;
156 davidb 718 }
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 sgodin 5633
166 davidb 718 if (mHeaders[i]->mHasUrgent)
167     {
168 sgodin 5633 s << Symbols::SPACE[0] << Symbols::LPAREN[0]
169 davidb 718 << mHeaders[i]->mUrgentNew << Symbols::SLASH[0]
170 sgodin 5633 << mHeaders[i]->mUrgentOld << Symbols::RPAREN[0];
171 davidb 718 }
172 sgodin 5633
173 davidb 718 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 jason 1305 resip::skipSipLWS(ParseBuffer& pb)
209 davidb 718 {
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 alan 1171 if (!pb.eof())
225 davidb 718 {
226 alan 1171 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 davidb 718 }
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 derek 3710 if (isEqualNoCase(has, "yes"))
299 davidb 718 {
300     mHasMessages = true;
301     }
302 derek 3710 else if (isEqualNoCase(has, "no"))
303 davidb 718 {
304     mHasMessages = false;
305     }
306     else
307     {
308 davidb 1097 pb.fail(__FILE__, __LINE__);
309 davidb 718 }
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 davidb 1097 pb.fail(__FILE__, __LINE__);
361 davidb 718 }
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 alan 1171 if (!pb.eof() && *pb.position() != Symbols::LPAREN[0])
378 davidb 718 {
379     if (mHeaders[ht] != 0)
380     {
381 davidb 1097 pb.fail(__FILE__, __LINE__);
382 davidb 718 }
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 davidb 1097 pb.fail(__FILE__, __LINE__);
404 davidb 718 }
405     mHeaders[ht] = new Header(numNew, numOld, numUrgentNew, numUrgentOld);
406     }
407    
408     pb.skipChars(Symbols::CRLF);
409     }
410    
411 alan 1171 if (!pb.eof() && *pb.position() == Symbols::CR[0])
412 davidb 718 {
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 derek 2948 // 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 davidb 718 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 bcampen 9169 MessageWaitingContents::header(HeaderType ht)
468     {
469     checkParsed();
470 sgodin 9367
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 bcampen 9169 if (mHeaders[ht] == 0)
475     {
476     mHeaders[ht] = new Header(0, 0);
477     }
478     return *mHeaders[ht];
479     }
480    
481     const MessageWaitingContents::Header&
482 davidb 718 MessageWaitingContents::header(HeaderType ht) const
483     {
484     checkParsed();
485 bcampen 9169
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 davidb 718 if (mHeaders[ht] == 0)
490     {
491 bcampen 9169 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 davidb 718 }
503 bcampen 9169 return *mHeaders[ht];
504 davidb 718 }
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 bcampen 9169 MessageWaitingContents::header(const AccountHeader& ht)
523     {
524     checkParsed();
525 sgodin 9367
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 bcampen 9169 if (mAccountUri == 0)
530     {
531     mAccountUri = new Uri();
532     }
533     return *mAccountUri;
534     }
535    
536     const Uri&
537 davidb 718 MessageWaitingContents::header(const AccountHeader& ht) const
538     {
539     checkParsed();
540 bcampen 9169
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 davidb 718 if (mAccountUri == 0)
545     {
546 bcampen 9169 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 davidb 718 }
558 bcampen 9169 return *mAccountUri;
559 davidb 718 }
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 bcampen 9169 MessageWaitingContents::header(const Data& hn)
578 davidb 718 {
579     checkParsed();
580     return mExtensions[hn];
581     }
582    
583 bcampen 9169 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 dpocock 11234 h=ncthis->mExtensions.insert(std::make_pair(hn,Data::Empty)).first;
601 bcampen 9169 }
602     return h->second;
603     }
604    
605 davidb 718 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 fluffy 1796 /* ====================================================================
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