/[resiprocate]/branches/b-identity-0505/MessageWaitingContents.cxx
ViewVC logotype

Contents of /branches/b-identity-0505/MessageWaitingContents.cxx

Parent Directory Parent Directory | Revision Log Revision Log


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

Properties

Name Value
svn:eol-style LF

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27