Coverage Report

Created: 2025-11-16 06:32

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/resiprocate/resip/stack/NameAddr.cxx
Line
Count
Source
1
#if defined(HAVE_CONFIG_H)
2
#include "config.h"
3
#endif
4
5
#include "resip/stack/NameAddr.hxx"
6
#include "rutil/ParseException.hxx"
7
#include "resip/stack/UnknownParameter.hxx"
8
#include "rutil/Data.hxx"
9
#include "rutil/DnsUtil.hxx"
10
#include "rutil/Logger.hxx"
11
#include "rutil/ParseBuffer.hxx"
12
//#include "rutil/WinLeakCheck.hxx"  // not compatible with placement new used below
13
14
using namespace resip;
15
using namespace std;
16
17
#define RESIPROCATE_SUBSYSTEM Subsystem::SIP
18
19
//====================
20
// NameAddr:
21
//====================
22
NameAddr::NameAddr() : 
23
0
   ParserCategory(),
24
0
   mAllContacts(false),
25
0
   mDisplayName(),
26
0
   mUnknownUriParametersBuffer(0)
27
0
{}
28
29
NameAddr::NameAddr(const HeaderFieldValue& hfv,
30
                   Headers::Type type,
31
                   PoolBase* pool)
32
5.87k
   : ParserCategory(hfv, type, pool), 
33
5.87k
     mAllContacts(false),
34
5.87k
     mUri(pool),
35
5.87k
     mDisplayName(),
36
5.87k
     mUnknownUriParametersBuffer(0)
37
5.87k
{}
38
39
NameAddr::NameAddr(const NameAddr& rhs,
40
                   PoolBase* pool)
41
0
   : ParserCategory(rhs, pool),
42
0
     mAllContacts(rhs.mAllContacts),
43
0
     mUri(rhs.mUri, pool),
44
0
     mDisplayName(rhs.mDisplayName),
45
0
     mUnknownUriParametersBuffer(0)
46
0
{}
47
48
static const Data parseContext("NameAddr constructor");
49
NameAddr::NameAddr(const Data& unparsed, bool preCacheAor)
50
5.87k
   : ParserCategory(),
51
5.87k
     mAllContacts(false),
52
5.87k
     mDisplayName(),
53
5.87k
     mUnknownUriParametersBuffer(0)
54
5.87k
{
55
5.87k
   HeaderFieldValue hfv(unparsed.data(), unparsed.size());
56
   // must copy because parse creates overlays
57
5.87k
   NameAddr tmp(hfv, Headers::UNKNOWN);
58
5.87k
   tmp.checkParsed();
59
5.87k
   *this = tmp;
60
5.87k
   if(preCacheAor)
61
0
   {
62
0
      mUri.getAor();
63
0
   }
64
5.87k
}
65
66
NameAddr::NameAddr(const Uri& uri)
67
0
   : ParserCategory(),
68
0
     mAllContacts(false),
69
0
     mUri(uri),
70
0
     mDisplayName(),
71
0
     mUnknownUriParametersBuffer(0)
72
0
{}
73
74
NameAddr::~NameAddr()
75
8.67k
{
76
8.67k
   if(mUnknownUriParametersBuffer) 
77
643
   {          
78
643
      delete mUnknownUriParametersBuffer;
79
643
   }
80
8.67k
}
81
82
NameAddr&
83
NameAddr::operator=(const NameAddr& rhs)
84
2.80k
{
85
2.80k
   if (this != &rhs)
86
2.80k
   {
87
2.80k
      resip_assert_not_null( &rhs );
88
      
89
2.80k
      ParserCategory::operator=(rhs);
90
2.80k
      mAllContacts = rhs.mAllContacts;
91
2.80k
      mDisplayName = rhs.mDisplayName;
92
2.80k
      mUri = rhs.mUri;
93
2.80k
   }
94
2.80k
   return *this;
95
2.80k
}
96
97
bool 
98
NameAddr::operator==(const NameAddr& other) const
99
0
{
100
0
    return mAllContacts == other.mAllContacts &&
101
0
           uri() == other.uri() &&
102
0
           displayName() == other.displayName();
103
0
}
104
105
bool
106
NameAddr::operator<(const NameAddr& rhs) const
107
0
{
108
0
   return uri() < rhs.uri();
109
0
}
110
111
ParserCategory *
112
NameAddr::clone() const
113
0
{
114
0
   return new NameAddr(*this);
115
0
}
116
117
ParserCategory *
118
NameAddr::clone(void* location) const
119
0
{
120
0
   return new (location) NameAddr(*this);
121
0
}
122
123
ParserCategory* 
124
NameAddr::clone(PoolBase* pool) const
125
0
{
126
0
   return new (pool) NameAddr(*this, pool);
127
0
}
128
129
const Uri&
130
NameAddr::uri() const 
131
0
{
132
0
   checkParsed(); 
133
0
   return mUri;
134
0
}
135
136
Uri&
137
NameAddr::uri()
138
0
{
139
0
   checkParsed(); 
140
0
   return mUri;
141
0
}
142
143
Data& 
144
NameAddr::displayName()
145
0
{
146
0
   checkParsed(); 
147
0
   return mDisplayName;
148
0
}
149
150
const Data& 
151
NameAddr::displayName() const 
152
0
{
153
0
   checkParsed(); 
154
0
   return mDisplayName;
155
0
}
156
157
bool 
158
NameAddr::isAllContacts() const 
159
0
{
160
0
   checkParsed(); 
161
0
   return mAllContacts;
162
0
}
163
164
void 
165
NameAddr::setAllContacts()
166
0
{
167
0
   mAllContacts = true;
168
0
}
169
170
void
171
NameAddr::parse(ParseBuffer& pb)
172
5.87k
{
173
5.87k
   const char* start;
174
5.87k
   start = pb.skipWhitespace();
175
5.87k
   pb.assertNotEof();
176
5.87k
   bool laQuote = false;
177
5.87k
   bool starContact = false;
178
   
179
5.87k
   if (*pb.position() == Symbols::STAR[0])
180
168
   {
181
168
      pb.skipChar(Symbols::STAR[0]);
182
168
      pb.skipWhitespace();
183
168
      if (pb.eof() || *pb.position() == Symbols::SEMI_COLON[0])
184
151
      {
185
151
         starContact = true;
186
151
      }
187
168
   }
188
189
5.87k
   if (starContact)
190
151
   {
191
151
      mAllContacts = true;
192
      // now fall through to parse header parameters
193
151
   }
194
5.72k
   else
195
5.72k
   {
196
5.72k
      pb.reset(start);
197
      // Check if we have a double quoted displayname
198
5.72k
      if (*pb.position() == Symbols::DOUBLE_QUOTE[0])
199
164
      {
200
164
         start = pb.skipChar(Symbols::DOUBLE_QUOTE[0]);
201
164
         pb.skipToEndQuote();
202
164
         pb.data(mDisplayName, start);
203
164
         adjustDisplayNameIfNeeded();
204
164
         pb.skipChar(Symbols::DOUBLE_QUOTE[0]);
205
164
         laQuote = true;
206
164
         pb.skipToChar(Symbols::LA_QUOTE[0]);
207
164
         if (pb.eof())
208
98
         {
209
98
            throw ParseException("Expected '<'", 
210
98
                                 "NameAddr", 
211
98
                                 __FILE__, 
212
98
                                 __LINE__);
213
98
         }
214
66
         else
215
66
         {
216
66
            pb.skipChar(Symbols::LA_QUOTE[0]);
217
66
         }
218
164
      }
219
      // Check if we have a URI without a displayname surrounded by angle brackets
220
5.55k
      else if (*pb.position() == Symbols::LA_QUOTE[0])
221
40
      {
222
40
         pb.skipChar(Symbols::LA_QUOTE[0]);
223
40
         laQuote = true;
224
40
      }
225
      // else, we could have a URI with a displayname that is not surrounded by double quotes
226
5.51k
      else
227
5.51k
      {
228
5.51k
         start = pb.position();
229
         // Note: An angle bracket can appear in a quoted parameter, we want to avoid matching those,
230
         //       so if we see a double quote before <, then we ignore the <.  If the displayname
231
         //       itself is double quoted that would have been picked off in the first condition 
232
         //       of this if statement.
233
5.51k
         pb.skipToOneOf(Symbols::LA_QUOTE, Symbols::DOUBLE_QUOTE);
234
5.51k
         if (pb.eof() || *pb.position() == Symbols::DOUBLE_QUOTE[0])
235
5.22k
         {
236
            // We must have no displayname and a URI that is not surrounded by angle brackets
237
5.22k
            pb.reset(start);
238
5.22k
         }
239
296
         else
240
296
         {
241
            // We have a displayname that is not surrounded by double quotes and a URI surround by angle brackets
242
296
            laQuote = true;
243
296
            pb.skipBackWhitespace();
244
296
            pb.data(mDisplayName, start);
245
296
            pb.skipToChar(Symbols::LA_QUOTE[0]);
246
296
            pb.skipChar(Symbols::LA_QUOTE[0]);
247
296
         }
248
5.51k
      }
249
5.62k
      pb.skipWhitespace();
250
5.62k
      mUri.setIsBetweenAngleQuotes(laQuote); // Tell Uri parser if the Uri is between angle quotes/brackets or not, so that it can relax embedded header parsing rules if so
251
5.62k
      mUri.parse(pb);
252
5.62k
      if (laQuote)
253
95
      {
254
95
         pb.skipChar(Symbols::RA_QUOTE[0]);
255
95
         pb.skipWhitespace();
256
         // now fall through to parse header parameters
257
95
      }
258
5.53k
      else
259
5.53k
      {
260
5.53k
         if(mUri.mUnknownParameters.size() > 0)
261
643
         {
262
643
            resip_assert(!mUnknownUriParametersBuffer);
263
643
            mUnknownUriParametersBuffer = new Data;
264
643
            {  // Scope stream
265
643
               oDataStream str(*mUnknownUriParametersBuffer);
266
               // deal with Uri/NameAddr parameter ambiguity
267
               // heuristically assign Uri parameters to the Uri
268
643
               for (ParameterList::iterator it = mUri.mUnknownParameters.begin(); 
269
6.64k
                  it != mUri.mUnknownParameters.end(); ++it)
270
6.00k
               {
271
                  // We're just going to assume all unknown (to Uri) params really
272
                  // belong on the header. This is not necessarily the case.
273
6.00k
                  str << ";";
274
6.00k
                  (*it)->encode(str);
275
6.00k
               }
276
643
            }
277
643
            mUri.clearUnknownParameters();
278
643
            ParseBuffer pb2(*mUnknownUriParametersBuffer);
279
643
            parseParameters(pb2);
280
643
         }
281
5.53k
      }
282
5.62k
   }
283
5.77k
   parseParameters(pb);
284
5.77k
}
285
286
EncodeStream&
287
NameAddr::encodeParsed(EncodeStream& str) const
288
0
{
289
   //bool displayName = !mDisplayName.empty();
290
0
  if (mAllContacts)
291
0
  {
292
0
     str << Symbols::STAR;
293
0
  }
294
0
  else
295
0
  {
296
0
     if (!mDisplayName.empty())
297
0
     {
298
#ifdef OMIT_DISPLAY_NAME_QUOTES_IF_NOT_REQUIRED
299
        // does nothing if display name is properly quoted
300
        if (mustQuoteDisplayName())
301
        {
302
#endif
303
0
           str << Symbols::DOUBLE_QUOTE;
304
0
           for (unsigned int i=0; i < mDisplayName.size(); i++)
305
0
           {
306
0
              char c = mDisplayName[i];
307
0
              switch(c)
308
0
              {
309
0
                 case '"':
310
0
                 case '\\':
311
0
                    str << '\\' << c;
312
0
                    break;
313
0
                 default:
314
0
                    str << c;
315
0
              }
316
0
           }
317
0
           str << Symbols::DOUBLE_QUOTE;
318
#ifdef OMIT_DISPLAY_NAME_QUOTES_IF_NOT_REQUIRED
319
        }
320
        else
321
        {
322
           str << mDisplayName;
323
        }
324
#endif
325
0
     }
326
0
     str << Symbols::LA_QUOTE;
327
0
     mUri.encodeParsed(str);
328
0
     str << Symbols::RA_QUOTE;
329
0
  }
330
  
331
0
  encodeParameters(str);
332
0
  return str;
333
0
}
334
335
336
bool 
337
NameAddr::mustQuoteDisplayName() const
338
0
{
339
0
   if (mDisplayName.empty())
340
0
   {
341
0
      return false;
342
0
   }
343
0
   ParseBuffer pb(mDisplayName.data(), mDisplayName.size());   
344
   
345
   //shouldn't really be any leading whitespace
346
0
   pb.skipWhitespace();
347
0
   if (pb.eof())
348
0
   {
349
0
      return false;
350
0
   }
351
0
   if ((*pb.position() == '"'))
352
0
   {
353
0
      bool escaped = false;
354
0
      while(!pb.eof())
355
0
      {
356
0
         pb.skipChar();
357
0
         if (escaped)
358
0
         {
359
0
            escaped = false;
360
0
         }
361
0
         else if (*pb.position() == '\\')
362
0
         {
363
0
            escaped = true;
364
0
         }
365
0
         else if (*pb.position() == '"')
366
0
         {
367
0
            break;
368
0
         }
369
0
      }
370
0
      if (*pb.position() == '"')
371
0
      {
372
         //should only have whitespace left, and really non of that
373
0
         pb.skipChar();
374
0
         if (pb.eof())
375
0
         {
376
0
            return false;
377
0
         }
378
0
         pb.skipWhitespace();
379
0
         if (pb.eof())
380
0
         {
381
0
            return false; //properly quoted
382
0
         }
383
0
         else
384
0
         {
385
0
            return true; 
386
0
         }
387
0
      }
388
0
      else
389
0
      {
390
0
         return true; //imbalanced quotes
391
0
      }
392
0
   }
393
0
   else
394
0
   {
395
0
      while (!pb.eof())
396
0
      {
397
0
         const char* start;
398
0
         start = pb.skipWhitespace();
399
0
         if (pb.eof())
400
0
         {
401
0
            return false;
402
0
         }
403
0
         pb.skipNonWhitespace();
404
0
     const char* end = pb.position();
405
0
         for (const char* c = start; c < end; c++)
406
0
         {
407
0
            if ( (*c >= 'a' && *c <= 'z') ||
408
0
                 (*c >= 'A' && *c <= 'Z') ||
409
0
                 (*c >= '0' && *c <= '9'))
410
0
            {
411
0
               continue;
412
0
            }
413
0
            switch(*c)
414
0
            {
415
0
               case '-':
416
0
               case '.':
417
0
               case '!':
418
0
               case '%':
419
0
               case '*':
420
0
               case '_':
421
0
               case '+':
422
0
               case '`':
423
0
               case '\'':
424
0
               case '~':
425
0
                  break;
426
0
               default:
427
0
                  return true;
428
0
            }
429
0
         }
430
0
      }
431
0
   }
432
0
   return false;
433
0
}
434
435
void NameAddr::adjustDisplayNameIfNeeded()
436
125
{
437
125
   if (mDisplayName.find("\\") != Data::npos)
438
108
   {
439
      // Double quotes must be encoded as \", so if displayName contains any backslashes, then we remove them
440
108
      Data adjustedDisplayName;
441
108
      {
442
108
         DataStream ds(adjustedDisplayName);
443
444
5.96M
         for (unsigned int i = 0; i < mDisplayName.size(); i++)
445
5.96M
         {
446
5.96M
            if (mDisplayName[i] == '\\')
447
1.04k
            {
448
1.04k
               i++;
449
1.04k
            }
450
5.96M
            if (i < mDisplayName.size())
451
5.96M
            {
452
5.96M
               ds << mDisplayName[i];
453
5.96M
            }
454
5.96M
         }
455
108
      }
456
108
      mDisplayName = adjustedDisplayName;
457
108
   }
458
125
}
459
460
ParameterTypes::Factory NameAddr::ParameterFactories[ParameterTypes::MAX_PARAMETER]={0};
461
462
Parameter* 
463
NameAddr::createParam(ParameterTypes::Type type, ParseBuffer& pb, const std::bitset<256>& terminators, PoolBase* pool)
464
9.64k
{
465
9.64k
   if(type > ParameterTypes::UNKNOWN && type < ParameterTypes::MAX_PARAMETER && ParameterFactories[type])
466
9.33k
   {
467
9.33k
      return ParameterFactories[type](type, pb, terminators, pool);
468
9.33k
   }
469
306
   return 0;
470
9.64k
}
471
472
bool 
473
NameAddr::exists(const Param<NameAddr>& paramType) const
474
0
{
475
0
    checkParsed();
476
0
    bool ret = getParameterByEnum(paramType.getTypeNum()) != NULL;
477
0
    return ret;
478
0
}
479
480
void 
481
NameAddr::remove(const Param<NameAddr>& paramType)
482
0
{
483
0
    checkParsed();
484
0
    removeParameterByEnum(paramType.getTypeNum());
485
0
}
486
487
#define defineParam(_enum, _name, _type, _RFC_ref_ignored)                                                      \
488
_enum##_Param::DType&                                                                                           \
489
0
NameAddr::param(const _enum##_Param& paramType)                                                           \
490
0
{                                                                                                               \
491
0
   checkParsed();                                                                                               \
492
0
   _enum##_Param::Type* p =                                                                                     \
493
0
      static_cast<_enum##_Param::Type*>(getParameterByEnum(paramType.getTypeNum()));                            \
494
0
   if (!p)                                                                                                      \
495
0
   {                                                                                                            \
496
0
      p = new _enum##_Param::Type(paramType.getTypeNum());                                                      \
497
0
      mParameters.push_back(p);                                                                                 \
498
0
   }                                                                                                            \
499
0
   return p->value();                                                                                           \
500
0
}                                                                                                               \
Unexecuted instantiation: resip::NameAddr::param(resip::data_Param const&)
Unexecuted instantiation: resip::NameAddr::param(resip::control_Param const&)
Unexecuted instantiation: resip::NameAddr::param(resip::mobility_Param const&)
Unexecuted instantiation: resip::NameAddr::param(resip::description_Param const&)
Unexecuted instantiation: resip::NameAddr::param(resip::events_Param const&)
Unexecuted instantiation: resip::NameAddr::param(resip::priority_Param const&)
Unexecuted instantiation: resip::NameAddr::param(resip::methods_Param const&)
Unexecuted instantiation: resip::NameAddr::param(resip::schemes_Param const&)
Unexecuted instantiation: resip::NameAddr::param(resip::application_Param const&)
Unexecuted instantiation: resip::NameAddr::param(resip::video_Param const&)
Unexecuted instantiation: resip::NameAddr::param(resip::language_Param const&)
Unexecuted instantiation: resip::NameAddr::param(resip::type_Param const&)
Unexecuted instantiation: resip::NameAddr::param(resip::isFocus_Param const&)
Unexecuted instantiation: resip::NameAddr::param(resip::actor_Param const&)
Unexecuted instantiation: resip::NameAddr::param(resip::text_Param const&)
Unexecuted instantiation: resip::NameAddr::param(resip::extensions_Param const&)
Unexecuted instantiation: resip::NameAddr::param(resip::Instance_Param const&)
Unexecuted instantiation: resip::NameAddr::param(resip::regid_Param const&)
Unexecuted instantiation: resip::NameAddr::param(resip::pubGruu_Param const&)
Unexecuted instantiation: resip::NameAddr::param(resip::tempGruu_Param const&)
Unexecuted instantiation: resip::NameAddr::param(resip::expires_Param const&)
Unexecuted instantiation: resip::NameAddr::param(resip::q_Param const&)
Unexecuted instantiation: resip::NameAddr::param(resip::tag_Param const&)
Unexecuted instantiation: resip::NameAddr::param(resip::index_Param const&)
Unexecuted instantiation: resip::NameAddr::param(resip::rc_Param const&)
Unexecuted instantiation: resip::NameAddr::param(resip::mp_Param const&)
Unexecuted instantiation: resip::NameAddr::param(resip::np_Param const&)
501
                                                                                                                \
502
const _enum##_Param::DType&                                                                                     \
503
0
NameAddr::param(const _enum##_Param& paramType) const                                                     \
504
0
{                                                                                                               \
505
0
   checkParsed();                                                                                               \
506
0
   _enum##_Param::Type* p =                                                                                     \
507
0
      static_cast<_enum##_Param::Type*>(getParameterByEnum(paramType.getTypeNum()));                            \
508
0
   if (!p)                                                                                                      \
509
0
   {                                                                                                            \
510
0
      InfoLog(<< "Missing parameter " _name " " << ParameterTypes::ParameterNames[paramType.getTypeNum()]);     \
511
0
      DebugLog(<< *this);                                                                                       \
512
0
      throw Exception("Missing parameter " _name, __FILE__, __LINE__);                                          \
513
0
   }                                                                                                            \
514
0
   return p->value();                                                                                           \
515
0
}
Unexecuted instantiation: resip::NameAddr::param(resip::data_Param const&) const
Unexecuted instantiation: resip::NameAddr::param(resip::control_Param const&) const
Unexecuted instantiation: resip::NameAddr::param(resip::mobility_Param const&) const
Unexecuted instantiation: resip::NameAddr::param(resip::description_Param const&) const
Unexecuted instantiation: resip::NameAddr::param(resip::events_Param const&) const
Unexecuted instantiation: resip::NameAddr::param(resip::priority_Param const&) const
Unexecuted instantiation: resip::NameAddr::param(resip::methods_Param const&) const
Unexecuted instantiation: resip::NameAddr::param(resip::schemes_Param const&) const
Unexecuted instantiation: resip::NameAddr::param(resip::application_Param const&) const
Unexecuted instantiation: resip::NameAddr::param(resip::video_Param const&) const
Unexecuted instantiation: resip::NameAddr::param(resip::language_Param const&) const
Unexecuted instantiation: resip::NameAddr::param(resip::type_Param const&) const
Unexecuted instantiation: resip::NameAddr::param(resip::isFocus_Param const&) const
Unexecuted instantiation: resip::NameAddr::param(resip::actor_Param const&) const
Unexecuted instantiation: resip::NameAddr::param(resip::text_Param const&) const
Unexecuted instantiation: resip::NameAddr::param(resip::extensions_Param const&) const
Unexecuted instantiation: resip::NameAddr::param(resip::Instance_Param const&) const
Unexecuted instantiation: resip::NameAddr::param(resip::regid_Param const&) const
Unexecuted instantiation: resip::NameAddr::param(resip::pubGruu_Param const&) const
Unexecuted instantiation: resip::NameAddr::param(resip::tempGruu_Param const&) const
Unexecuted instantiation: resip::NameAddr::param(resip::expires_Param const&) const
Unexecuted instantiation: resip::NameAddr::param(resip::q_Param const&) const
Unexecuted instantiation: resip::NameAddr::param(resip::tag_Param const&) const
Unexecuted instantiation: resip::NameAddr::param(resip::index_Param const&) const
Unexecuted instantiation: resip::NameAddr::param(resip::rc_Param const&) const
Unexecuted instantiation: resip::NameAddr::param(resip::mp_Param const&) const
Unexecuted instantiation: resip::NameAddr::param(resip::np_Param const&) const
516
517
defineParam(data, "data", ExistsParameter, "RFC 3840");
518
defineParam(control, "control", ExistsParameter, "RFC 3840");
519
defineParam(mobility, "mobility", QuotedDataParameter, "RFC 3840"); // mobile|fixed
520
defineParam(description, "description", QuotedDataParameter, "RFC 3840"); // <> quoted
521
defineParam(events, "events", QuotedDataParameter, "RFC 3840"); // list
522
defineParam(priority, "priority", QuotedDataParameter, "RFC 3840"); // non-urgent|normal|urgent|emergency
523
defineParam(methods, "methods", QuotedDataParameter, "RFC 3840"); // list
524
defineParam(schemes, "schemes", QuotedDataParameter, "RFC 3840"); // list
525
defineParam(application, "application", ExistsParameter, "RFC 3840");
526
defineParam(video, "video", ExistsParameter, "RFC 3840");
527
defineParam(language, "language", QuotedDataParameter, "RFC 3840"); // list
528
defineParam(type, "type", QuotedDataParameter, "RFC 3840"); // list
529
defineParam(isFocus, "isfocus", ExistsParameter, "RFC 3840");
530
defineParam(actor, "actor", QuotedDataParameter, "RFC 3840"); // principal|msg-taker|attendant|information
531
defineParam(text, "text", ExistsOrDataParameter, "RFC 3840");
532
defineParam(extensions, "extensions", QuotedDataParameter, "RFC 3840"); //list
533
defineParam(Instance, "+sip.instance", QuotedDataParameter, "RFC 5626");  // <> quoted
534
defineParam(regid, "reg-id", UInt32Parameter, "RFC 5626");
535
defineParam(pubGruu, "pub-gruu", QuotedDataParameter, "RFC 5627");
536
defineParam(tempGruu, "temp-gruu", QuotedDataParameter, "RFC 5627");
537
defineParam(expires, "expires", UInt32Parameter, "RFC 3261");
538
defineParam(q, "q", QValueParameter, "RFC 3261");
539
defineParam(tag, "tag", DataParameter, "RFC 3261");
540
defineParam(index, "index", DataParameter, "RFC 4244");
541
defineParam(rc, "rc", DataParameter, "RFC 4244-bis");
542
defineParam(mp, "mp", DataParameter, "RFC 4244-bis");
543
defineParam(np, "np", DataParameter, "RFC 4244-bis");
544
545
#undef defineParam
546
547
/* ====================================================================
548
 * The Vovida Software License, Version 1.0 
549
 * 
550
 * Copyright (c) 2024, SIP Spectrum, Inc. http://www.sipspectrum.com
551
 * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
552
 * 
553
 * Redistribution and use in source and binary forms, with or without
554
 * modification, are permitted provided that the following conditions
555
 * are met:
556
 * 
557
 * 1. Redistributions of source code must retain the above copyright
558
 *    notice, this list of conditions and the following disclaimer.
559
 * 
560
 * 2. Redistributions in binary form must reproduce the above copyright
561
 *    notice, this list of conditions and the following disclaimer in
562
 *    the documentation and/or other materials provided with the
563
 *    distribution.
564
 * 
565
 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
566
 *    and "Vovida Open Communication Application Library (VOCAL)" must
567
 *    not be used to endorse or promote products derived from this
568
 *    software without prior written permission. For written
569
 *    permission, please contact vocal@vovida.org.
570
 *
571
 * 4. Products derived from this software may not be called "VOCAL", nor
572
 *    may "VOCAL" appear in their name, without prior written
573
 *    permission of Vovida Networks, Inc.
574
 * 
575
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
576
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
577
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
578
 * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
579
 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
580
 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
581
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
582
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
583
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
584
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
585
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
586
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
587
 * DAMAGE.
588
 * 
589
 * ====================================================================
590
 * 
591
 * This software consists of voluntary contributions made by Vovida
592
 * Networks, Inc. and many individuals on behalf of Vovida Networks,
593
 * Inc.  For more information on Vovida Networks, Inc., please see
594
 * <http://www.vovida.org/>.
595
 *
596
 */