Coverage Report

Created: 2025-07-23 06:03

/src/resiprocate/resip/stack/Uri.cxx
Line
Count
Source (jump to first uncovered line)
1
#if defined(HAVE_CONFIG_H)
2
#include "config.h"
3
#endif
4
5
#include <set>
6
7
#include "resip/stack/Embedded.hxx"
8
#include "resip/stack/Helper.hxx"
9
#include "resip/stack/NameAddr.hxx" 
10
#include "resip/stack/SipMessage.hxx"
11
#include "resip/stack/Symbols.hxx"
12
#include "resip/stack/UnknownParameter.hxx"
13
#include "resip/stack/Uri.hxx"
14
#include "rutil/DataStream.hxx"
15
#include "rutil/DnsUtil.hxx"
16
#include "rutil/Logger.hxx"
17
#include "rutil/ParseBuffer.hxx"
18
//#include "rutil/WinLeakCheck.hxx"  // not compatible with placement new used below
19
20
using namespace resip;
21
22
#define RESIPROCATE_SUBSYSTEM Subsystem::SIP
23
#define HANDLE_CHARACTER_ESCAPING //undef for old behaviour
24
25
static bool initAllTables()
26
2
{
27
2
   Uri::getUserEncodingTable();
28
2
   Uri::getPasswordEncodingTable();
29
2
   Uri::getLocalNumberTable();
30
2
   Uri::getGlobalNumberTable();
31
2
   return true;
32
2
}
33
34
const bool Uri::tablesMightBeInitialized(initAllTables());
35
36
Uri::Uri(PoolBase* pool) 
37
25.1k
   : ParserCategory(pool),
38
25.1k
     mScheme(Data::Share, Symbols::DefaultSipScheme),
39
25.1k
     mPort(0),
40
25.1k
     mHostCanonicalized(false),
41
25.1k
     mIsBetweenAngleQuotes(false)
42
25.1k
{
43
25.1k
}
44
45
Uri::Uri(const HeaderFieldValue& hfv, Headers::Type type, PoolBase* pool) :
46
6.13k
   ParserCategory(hfv, type, pool),
47
6.13k
   mPort(0),
48
6.13k
   mHostCanonicalized(false),
49
6.13k
   mIsBetweenAngleQuotes(false)
50
6.13k
{}
51
52
53
static const Data parseContext("Uri constructor");
54
Uri::Uri(const Data& data)
55
0
   : ParserCategory(), 
56
0
     mScheme(Symbols::DefaultSipScheme),
57
0
     mPort(0),
58
0
     mHostCanonicalized(false),
59
0
     mIsBetweenAngleQuotes(false)
60
0
{
61
0
   HeaderFieldValue hfv(data.data(), data.size());
62
   // must copy because parse creates overlays
63
0
   Uri tmp(hfv, Headers::UNKNOWN);
64
0
   tmp.checkParsed();
65
0
   *this = tmp;
66
0
}
67
68
Uri::Uri(const Uri& rhs,
69
         PoolBase* pool)
70
0
   : ParserCategory(rhs, pool),
71
0
     mScheme(rhs.mScheme),
72
0
     mHost(rhs.mHost),
73
0
     mUser(rhs.mUser),
74
0
     mUserParameters(rhs.mUserParameters),
75
0
     mPort(rhs.mPort),
76
0
     mPassword(rhs.mPassword),
77
0
     mNetNs(rhs.mNetNs),
78
0
     mPath(rhs.mPath),
79
0
     mHostCanonicalized(rhs.mHostCanonicalized),
80
0
     mCanonicalHost(rhs.mCanonicalHost),
81
0
     mIsBetweenAngleQuotes(rhs.mIsBetweenAngleQuotes),
82
0
     mEmbeddedHeadersText(rhs.mEmbeddedHeadersText.get() ? new Data(*rhs.mEmbeddedHeadersText) : 0),
83
0
     mEmbeddedHeaders(rhs.mEmbeddedHeaders.get() ? new SipMessage(*rhs.mEmbeddedHeaders) : 0)
84
0
{}
85
86
87
Uri::~Uri()
88
31.2k
{}
89
90
// RFC 3261 19.1.6
91
#if 0  // deprecated
92
Uri
93
Uri::fromTel(const Uri& tel, const Data& host)
94
{
95
   resip_assert(tel.scheme() == Symbols::Tel);
96
97
   Uri u;
98
   u.scheme() = Symbols::Sip;
99
   u.user() = tel.user();
100
   u.host() = host;
101
   u.param(p_user) = Symbols::Phone;
102
103
   // need to sort the user parameters
104
   if (!tel.userParameters().empty())
105
   {
106
      DebugLog(<< "Uri::fromTel: " << tel.userParameters());
107
      Data isub;
108
      Data postd;
109
110
      int totalSize  = 0;
111
      std::set<Data> userParameters;
112
113
      ParseBuffer pb(tel.userParameters().data(), tel.userParameters().size());
114
      while (true)
115
      {
116
         const char* anchor = pb.position();
117
         pb.skipToChar(Symbols::SEMI_COLON[0]);
118
         Data param = pb.data(anchor);
119
         // !dlb! not supposed to lowercase extension parameters
120
         param.lowercase();
121
         totalSize += param.size() + 1;
122
123
         if (param.prefix(Symbols::Isub))
124
         {
125
            isub = param;
126
         }
127
         else if (param.prefix(Symbols::Postd))
128
         {
129
            postd = param;
130
         }
131
         else
132
         {
133
            userParameters.insert(param);
134
         }
135
         if (pb.eof())
136
         {
137
            break;
138
         }
139
         else
140
         {
141
            pb.skipChar();
142
         }
143
      }
144
145
      u.userParameters().reserve(totalSize);
146
      if (!isub.empty())
147
      {
148
         u.userParameters() = isub;
149
      }
150
      if (!postd.empty())
151
      {
152
         if (!u.userParameters().empty())
153
         {
154
            u.userParameters() += Symbols::SEMI_COLON[0];
155
         }
156
         u.userParameters() += postd;
157
      }
158
      
159
      for(std::set<Data>::const_iterator i = userParameters.begin();
160
          i != userParameters.end(); ++i)
161
      {
162
         DebugLog(<< "Adding param: " << *i);
163
         if (!u.userParameters().empty())
164
         {
165
            u.userParameters() += Symbols::SEMI_COLON[0];
166
         }
167
         u.userParameters() += *i;
168
      }
169
   }
170
171
   return u;
172
}
173
#endif // deprecated
174
175
Uri
176
Uri::fromTel(const Uri& tel, const Uri& hostUri)
177
0
{
178
0
   resip_assert(tel.scheme() == Symbols::Tel);
179
180
0
   Uri u(hostUri);
181
0
   u.scheme() = Symbols::Sip;
182
0
   u.user() = tel.user();
183
0
   u.param(p_user) = Symbols::Phone;
184
185
   // need to sort the user parameters
186
0
   if (!tel.userParameters().empty())
187
0
   {
188
0
      DebugLog(<< "Uri::fromTel: " << tel.userParameters());
189
0
      Data isub;
190
0
      Data postd;
191
192
0
      int totalSize  = 0;
193
0
      std::set<Data> userParameters;
194
195
0
      ParseBuffer pb(tel.userParameters().data(), tel.userParameters().size());
196
0
      while (true)
197
0
      {
198
0
         const char* anchor = pb.position();
199
0
         pb.skipToChar(Symbols::SEMI_COLON[0]);
200
0
         Data param = pb.data(anchor);
201
         // !dlb! not supposed to lowercase extension parameters
202
0
         param.lowercase();
203
0
         totalSize += (int)param.size() + 1;
204
205
0
         if (param.prefix(Symbols::Isub))
206
0
         {
207
0
            isub = param;
208
0
         }
209
0
         else if (param.prefix(Symbols::Postd))
210
0
         {
211
0
            postd = param;
212
0
         }
213
0
         else
214
0
         {
215
0
            userParameters.insert(param);
216
0
         }
217
0
         if (pb.eof())
218
0
         {
219
0
            break;
220
0
         }
221
0
         else
222
0
         {
223
0
            pb.skipChar();
224
0
         }
225
0
      }
226
227
0
      u.userParameters().reserve(totalSize);
228
0
      if (!isub.empty())
229
0
      {
230
0
         u.userParameters() = isub;
231
0
      }
232
0
      if (!postd.empty())
233
0
      {
234
0
         if (!u.userParameters().empty())
235
0
         {
236
0
            u.userParameters() += Symbols::SEMI_COLON[0];
237
0
         }
238
0
         u.userParameters() += postd;
239
0
      }
240
      
241
0
      for(std::set<Data>::const_iterator i = userParameters.begin();
242
0
          i != userParameters.end(); ++i)
243
0
      {
244
0
         DebugLog(<< "Adding param: " << *i);
245
0
         if (!u.userParameters().empty())
246
0
         {
247
0
            u.userParameters() += Symbols::SEMI_COLON[0];
248
0
         }
249
0
         u.userParameters() += *i;
250
0
      }
251
0
   }
252
253
0
   return u;
254
0
}
255
256
bool
257
Uri::isEnumSearchable() const
258
0
{
259
0
   checkParsed();
260
0
   int digits = 0;
261
262
0
   if(mScheme != Symbols::Tel)
263
0
   {
264
0
      StackLog(<< "not a tel Uri");
265
0
      return false;
266
0
   }
267
268
0
   if(mUser.size() < 4)
269
0
   {
270
0
      StackLog(<< "user part of Uri empty or too short for E.164");
271
0
      return false;
272
0
   }
273
274
   // E.164 numbers must begin with a + and have at least
275
   // 3 digits
276
0
   if(mUser[0] != '+')
277
0
   {
278
0
      StackLog(<< "user part of Uri does not begin with `+' or too short");
279
0
      return false;
280
0
   }
281
282
   // count the digits (skip the leading `+')
283
0
   for(const char* i=user().begin() + 1; i!= user().end(); i++)
284
0
   {
285
0
      if (isdigit(*i))
286
0
      {
287
0
         digits++;
288
0
      }
289
0
      else
290
0
      {
291
0
         if (*i != '-')
292
0
         {
293
0
            StackLog(<< "user part of Uri contains non-digit: " << *i);
294
0
            return false; // Only digits and '-' permitted
295
0
         }
296
0
      }
297
0
   }
298
0
   if(digits > 15)
299
0
   {
300
      // E.164 only permits 15 digits in a phone number
301
0
      StackLog(<< "user part of Uri contains more than 15 digits");
302
0
      return false;
303
0
   }
304
305
0
   DebugLog(<< "is in E.164 format for ENUM: " << mUser);
306
0
   return true;
307
0
}
308
309
std::vector<Data> 
310
Uri::getEnumLookups(const std::vector<Data>& suffixes) const
311
0
{
312
0
   std::vector<Data> results;
313
0
   Data prefix;
314
0
   if (isEnumSearchable())
315
0
   {
316
      // skip the leading +
317
0
      for (const char* i=user().end()-1 ; i!= user().begin(); --i)
318
0
      {
319
0
         if (isdigit(*i))
320
0
         {
321
0
            prefix += *i;
322
0
            prefix += Symbols::DOT;
323
0
         }
324
0
      }
325
0
      StackLog(<< "E.164 number reversed for ENUM query: " << prefix);
326
0
      for (std::vector<Data>::const_iterator j=suffixes.begin(); j != suffixes.end(); ++j)
327
0
      {
328
0
         results.push_back(prefix + *j);
329
0
      }
330
0
   }
331
0
   return results;
332
0
}
333
334
bool
335
Uri::hasEmbedded() const
336
0
{
337
0
   checkParsed(); 
338
0
   return (mEmbeddedHeadersText.get() && !mEmbeddedHeadersText->empty()) || mEmbeddedHeaders.get() != 0;
339
0
}
340
341
void 
342
Uri::removeEmbedded()
343
0
{
344
0
   checkParsed();
345
0
   mEmbeddedHeaders.reset();
346
0
   mEmbeddedHeadersText.reset();
347
0
}
348
349
Uri&
350
Uri::operator=(const Uri& rhs)
351
2.86k
{
352
2.86k
   if (this != &rhs)
353
2.86k
   {
354
2.86k
      ParserCategory::operator=(rhs);
355
2.86k
      mScheme = rhs.mScheme;
356
2.86k
      mHost = rhs.mHost;
357
2.86k
      mPath = rhs.mPath;
358
2.86k
      mHostCanonicalized = rhs.mHostCanonicalized;
359
2.86k
      mCanonicalHost = rhs.mCanonicalHost;
360
2.86k
      mUser = rhs.mUser;
361
2.86k
      mUserParameters = rhs.mUserParameters;
362
2.86k
      mPort = rhs.mPort;
363
2.86k
      mPassword = rhs.mPassword;
364
2.86k
      mNetNs = rhs.mNetNs;
365
2.86k
      if (rhs.mEmbeddedHeaders.get() != 0)
366
0
      {
367
0
         mEmbeddedHeaders.reset(new SipMessage(*rhs.mEmbeddedHeaders));
368
0
      }
369
2.86k
      else if(rhs.mEmbeddedHeadersText.get() != 0)
370
1.09k
      {
371
1.09k
         if(!mEmbeddedHeadersText.get())
372
1.09k
         {
373
1.09k
            mEmbeddedHeadersText.reset(new Data(*rhs.mEmbeddedHeadersText));
374
1.09k
         }
375
0
         else
376
0
         {
377
            // !bwc! Data::operator= is smart enough to handle this safely.
378
0
            *mEmbeddedHeadersText = *rhs.mEmbeddedHeadersText;
379
0
         }
380
1.09k
      }
381
2.86k
   }
382
2.86k
   return *this;
383
2.86k
}
384
385
/**
386
  @class OrderUnknownParameters
387
  @brief used as a comparator for sorting purposes
388
  */
389
class OrderUnknownParameters
390
{
391
   public:
392
      /**
393
        @brief constructor ; never called explicitly
394
        */
395
0
      OrderUnknownParameters() { notUsed=false; };
396
397
      /**
398
        @brief empty destructor
399
        */
400
0
      ~OrderUnknownParameters() {};
401
402
      /**
403
        @brief used as a comparator for sorting purposes
404
         This does a straight Data comparison for name and returns true/false
405
        @param p1 pointer to parameter 1
406
        @param p2 pointer to parameter 2
407
        @return true if p1->getName() is less than p2->getName() 
408
         else return false
409
        */
410
      bool operator()(const Parameter* p1, const Parameter* p2) const
411
0
      {
412
0
         return dynamic_cast<const UnknownParameter*>(p1)->getName() < dynamic_cast<const UnknownParameter*>(p2)->getName();
413
0
      }
414
415
   private:
416
      bool notUsed;
417
};
418
419
bool Uri::compareUriParametersEqual(Parameter* param1, Parameter* param2)
420
0
{
421
0
   if (!param1 || !param2)
422
0
   {
423
0
      return false;
424
0
   }
425
426
0
   switch (param1->getType()) {
427
0
      case ParameterTypes::user:
428
0
      case ParameterTypes::method:
429
0
      case ParameterTypes::maddr:
430
0
      case ParameterTypes::transport:
431
0
         return isEqualNoCase(dynamic_cast<DataParameter*>(param1)->value(),
432
0
                              dynamic_cast<DataParameter*>(param2)->value());
433
434
0
      case ParameterTypes::ttl:
435
0
         return dynamic_cast<UInt32Parameter*>(param1)->value() ==
436
0
                dynamic_cast<UInt32Parameter*>(param2)->value();
437
438
0
      case ParameterTypes::gr:
439
0
         return isEqualNoCase(dynamic_cast<ExistsOrDataParameter*>(param1)->value(),
440
0
                              dynamic_cast<ExistsOrDataParameter*>(param2)->value());
441
442
0
      case ParameterTypes::lr:
443
         // Exists parameters are equal.
444
0
         return true;
445
446
0
      default:
447
         // Other parameters are not considered.
448
         // Parameters may be added accordingly to RFCs.
449
0
         return true;
450
0
   }
451
0
}
452
453
bool Uri::compareUriParametersLessThan(Parameter* param1, Parameter* param2)
454
0
{
455
0
   if (!param1 || !param2)
456
0
   {
457
0
      return false;
458
0
   }
459
460
0
   switch (param1->getType()) {
461
0
      case ParameterTypes::user:
462
0
      case ParameterTypes::method:
463
0
      case ParameterTypes::maddr:
464
0
      case ParameterTypes::transport:
465
0
         return isLessThanNoCase(dynamic_cast<DataParameter*>(param1)->value(),
466
0
                                 dynamic_cast<DataParameter*>(param2)->value());
467
468
0
      case ParameterTypes::ttl:
469
0
         return dynamic_cast<UInt32Parameter*>(param1)->value() <
470
0
                dynamic_cast<UInt32Parameter*>(param2)->value();
471
472
0
      case ParameterTypes::gr:
473
0
         return isLessThanNoCase(dynamic_cast<ExistsOrDataParameter*>(param1)->value(),
474
0
                                 dynamic_cast<ExistsOrDataParameter*>(param2)->value());
475
476
0
      case ParameterTypes::lr:
477
         // Exists parameters are equal.
478
0
         return false;
479
480
0
      default:
481
         // Other parameters are not considered.
482
         // Parameters may be added accordingly to RFCs.
483
0
         return false;
484
0
   }
485
0
}
486
487
bool Uri::isSignificantUriParameter(const ParameterTypes::Type type) noexcept
488
0
{
489
0
   return type == ParameterTypes::user ||
490
0
          type == ParameterTypes::ttl ||
491
0
          type == ParameterTypes::method ||
492
0
          type == ParameterTypes::maddr ||
493
0
          type == ParameterTypes::transport;
494
0
}
495
496
bool 
497
Uri::operator==(const Uri& other) const
498
0
{
499
0
   checkParsed();
500
0
   other.checkParsed();
501
502
   // compare hosts
503
0
   if (DnsUtil::isIpV6Address(mHost) &&
504
0
       DnsUtil::isIpV6Address(other.mHost))
505
0
   {
506
      // compare canonicalized IPV6 addresses
507
508
      // update canonicalized if host changed
509
0
      if (!mHostCanonicalized)
510
0
      {
511
0
         mCanonicalHost = DnsUtil::canonicalizeIpV6Address(mHost);
512
0
         mHostCanonicalized=true;
513
0
      }
514
515
      // update canonicalized if host changed
516
0
      if (!other.mHostCanonicalized)
517
0
      {
518
0
         other.mCanonicalHost = DnsUtil::canonicalizeIpV6Address(other.mHost);
519
0
         other.mHostCanonicalized=true;
520
0
      }
521
522
0
      if (mCanonicalHost != other.mCanonicalHost)
523
0
      {
524
0
         return false;
525
0
      }
526
0
   }
527
0
   else
528
0
   {
529
0
      if (!isEqualNoCase(mHost, other.mHost))
530
0
      {
531
0
         return false;
532
0
      }
533
0
   }
534
   
535
0
   if (isEqualNoCase(mScheme, other.mScheme) &&
536
0
       ((isEqualNoCase(mScheme, Symbols::Sip) || isEqualNoCase(mScheme, Symbols::Sips)) ? mUser == other.mUser : isEqualNoCase(mUser, other.mUser)) &&
537
0
       isEqualNoCase(mUserParameters,other.mUserParameters) &&
538
0
       mPassword == other.mPassword &&
539
0
       mPort == other.mPort &&
540
0
       mNetNs == other.mNetNs &&
541
0
       mPath == mPath)
542
0
   {
543
0
      for (ParameterList::const_iterator it = mParameters.begin(); it != mParameters.end(); ++it)
544
0
      {
545
0
         Parameter* otherParam = other.getParameterByEnum((*it)->getType());
546
547
0
         if (Uri::isSignificantUriParameter((*it)->getType()) || otherParam)
548
0
         {
549
0
            if (!Uri::compareUriParametersEqual(*it, otherParam))
550
0
            {
551
0
               return false;
552
0
            }
553
0
         }
554
0
      }         
555
556
      // now check the other way, sigh
557
0
      for (ParameterList::const_iterator it = other.mParameters.begin(); it != other.mParameters.end(); ++it)
558
0
      {
559
0
         Parameter* param = getParameterByEnum((*it)->getType());
560
561
0
         if (Uri::isSignificantUriParameter((*it)->getType()) || param)
562
0
         {
563
0
            if (!Uri::compareUriParametersEqual(*it, param))
564
0
            {
565
0
               return false;
566
0
            }
567
0
         }
568
0
      }
569
0
   }
570
0
   else
571
0
   {
572
0
      return false;
573
0
   }
574
575
0
   OrderUnknownParameters orderUnknown;
576
577
#if defined(__SUNPRO_CC) || defined(WIN32) || defined(__sun__)
578
   // The Solaris Forte STL implementation does not support the
579
   // notion of a list.sort() function taking a BinaryPredicate.
580
   // The hacky workaround is to load the Parameter pointers into
581
   // an STL set which does support an ordering function.
582
583
   typedef std::set<Parameter*, OrderUnknownParameters> ParameterSet;
584
   ParameterSet unA, unB;
585
586
   for (ParameterList::const_iterator i = mUnknownParameters.begin();
587
        i != mUnknownParameters.end(); ++i)
588
   {
589
      unA.insert(*i);
590
   }
591
   for (ParameterList::const_iterator i = other.mUnknownParameters.begin();
592
        i != other.mUnknownParameters.end(); ++i)
593
   {
594
      unB.insert(*i);
595
   }
596
597
   ParameterSet::iterator a = unA.begin();
598
   ParameterSet::iterator b = unB.begin();
599
#else
600
   // .dlb. more efficient to copy to vector for sorting?
601
   // Uri comparison is expensive; consider caching? ugh
602
0
   ParameterList unA = mUnknownParameters;
603
0
   ParameterList unB = other.mUnknownParameters;
604
605
0
   sort(unA.begin(), unA.end(), orderUnknown);
606
0
   sort(unB.begin(), unB.end(), orderUnknown);
607
 
608
0
   ParameterList::iterator a = unA.begin();
609
0
   ParameterList::iterator b = unB.begin();
610
0
#endif
611
612
0
   while(a != unA.end() && b != unB.end())
613
0
   {
614
0
      if (orderUnknown(*a, *b))
615
0
      {
616
0
         ++a;
617
0
      }
618
0
      else if (orderUnknown(*b, *a))
619
0
      {
620
0
         ++b;
621
0
      }
622
0
      else
623
0
      {
624
0
         if (!isEqualNoCase(dynamic_cast<UnknownParameter*>(*a)->value(),
625
0
                            dynamic_cast<UnknownParameter*>(*b)->value()))
626
0
         {
627
0
            return false;
628
0
         }
629
0
         ++a;
630
0
         ++b;
631
0
      }
632
0
   }
633
0
   return true;
634
0
}
635
636
bool 
637
Uri::operator!=(const Uri& other) const
638
0
{
639
0
   return !(*this == other);
640
0
}
641
642
bool
643
Uri::operator<(const Uri& other) const
644
0
{
645
0
   other.checkParsed();
646
0
   checkParsed();
647
0
   if (mUser < other.mUser)
648
0
   {
649
0
      return true;
650
0
   }
651
652
0
   if (mUser > other.mUser)
653
0
   {
654
0
      return false;
655
0
   }
656
657
0
   if (mUserParameters < other.mUserParameters)
658
0
   {
659
0
      return true;
660
0
   }
661
662
0
   if (mUserParameters > other.mUserParameters)
663
0
   {
664
0
      return false;
665
0
   }
666
667
   // !bwc! Canonicalize before we compare! Jeez...
668
0
   if (!mHostCanonicalized)
669
0
   {
670
0
      if(DnsUtil::isIpV6Address(mHost))
671
0
      {
672
0
         mCanonicalHost = DnsUtil::canonicalizeIpV6Address(mHost);
673
0
      }
674
0
      else
675
0
      {
676
0
         mCanonicalHost = mHost;
677
0
         mCanonicalHost.lowercase();
678
0
      }
679
0
      mHostCanonicalized=true;
680
0
   }
681
   
682
0
   if (!other.mHostCanonicalized)
683
0
   {
684
0
      if(DnsUtil::isIpV6Address(other.mHost))
685
0
      {
686
0
         other.mCanonicalHost = DnsUtil::canonicalizeIpV6Address(other.mHost);
687
0
      }
688
0
      else
689
0
      {
690
0
         other.mCanonicalHost = other.mHost;
691
0
         other.mCanonicalHost.lowercase();
692
0
      }
693
0
      other.mHostCanonicalized=true;
694
0
   }
695
696
0
   if (mCanonicalHost < other.mCanonicalHost)
697
0
   {
698
0
      return true;
699
0
   }
700
701
0
   if (mCanonicalHost > other.mCanonicalHost)
702
0
   {
703
0
      return false;
704
0
   }
705
706
0
   if (mPort < other.mPort)
707
0
   {
708
0
      return true;
709
0
   }
710
711
0
   if (mPort > other.mPort)
712
0
   {
713
0
      return false;
714
0
   }
715
716
0
   for (ParameterList::const_iterator it = mParameters.begin(); it != mParameters.end(); ++it)
717
0
      {
718
0
         Parameter* otherParam = other.getParameterByEnum((*it)->getType());
719
720
0
         if (otherParam)
721
0
         {
722
0
            if (Uri::compareUriParametersLessThan(*it, otherParam)) {
723
0
               return true;
724
0
            }
725
726
0
            if (Uri::compareUriParametersLessThan(otherParam, *it)) {
727
0
               return false;
728
0
            }
729
0
         }
730
0
         else if (Uri::isSignificantUriParameter((*it)->getType()))
731
0
         {
732
0
            return true;  // Significant URI params should not be ignored.
733
0
         }
734
0
      }
735
736
   // Sort unknown parameters from both URIs by their name using comparator class.
737
0
   OrderUnknownParameters orderUnknown;
738
739
#if defined(__SUNPRO_CC) || defined(WIN32) || defined(__sun__)
740
   // The Solaris Forte STL implementation does not support the
741
   // notion of a list.sort() function taking a BinaryPredicate.
742
   // The hacky workaround is to load the Parameter pointers into
743
   // an STL set which does support an ordering function.
744
745
   typedef std::set<Parameter*, OrderUnknownParameters> ParameterSet;
746
   ParameterSet thisUriParamList, otherUriParamList;
747
748
   for (ParameterList::const_iterator i = mUnknownParameters.begin();
749
        i != mUnknownParameters.end(); ++i)
750
   {
751
      thisUriParamList.insert(*i);
752
   }
753
   for (ParameterList::const_iterator i = other.mUnknownParameters.begin();
754
        i != other.mUnknownParameters.end(); ++i)
755
   {
756
      otherUriParamList.insert(*i);
757
   }
758
#else
759
0
   ParameterList thisUriParamList = mUnknownParameters;
760
0
   ParameterList otherUriParamList = other.mUnknownParameters;
761
762
0
   sort(thisUriParamList.begin(), thisUriParamList.end(), orderUnknown);
763
0
   sort(otherUriParamList.begin(), otherUriParamList.end(), orderUnknown);
764
0
#endif
765
766
0
   auto thisUriParam = thisUriParamList.begin();
767
0
   auto otherUriParam = otherUriParamList.begin();
768
769
   // Iterate through unknown parameters of both URIs.
770
   // Advance iterators to compare values of parameters with matching names.
771
0
   while(thisUriParam != thisUriParamList.end() && otherUriParam != otherUriParamList.end())
772
0
   {
773
0
      if (orderUnknown(*thisUriParam, *otherUriParam))
774
0
      {
775
         // this < other param name.
776
0
         ++thisUriParam;
777
0
      }
778
0
      else if (orderUnknown(*otherUriParam, *thisUriParam))
779
0
      {
780
         // other < this param name.
781
0
         ++otherUriParam;
782
0
      }
783
0
      else
784
0
      {
785
         // this == other param name.
786
         // Unknown parameter names are the same. Compare their values.
787
0
         const Data& thisParamValue = dynamic_cast<UnknownParameter*>(*thisUriParam)->value();
788
0
         const Data& otherParamValue = dynamic_cast<UnknownParameter*>(*otherUriParam)->value();
789
790
0
         if (isLessThanNoCase(thisParamValue,
791
0
                              otherParamValue))
792
0
         {
793
0
            return true;
794
0
         }
795
796
0
         if (isLessThanNoCase(otherParamValue,
797
0
                              thisParamValue))
798
0
         {
799
0
            return false;
800
0
         }
801
802
         // Move iterators to the next position.
803
0
         ++thisUriParam;
804
0
         ++otherUriParam;
805
0
      }
806
0
   }
807
808
0
   return false;
809
0
}
810
811
bool
812
Uri::aorEqual(const resip::Uri& rhs) const
813
0
{
814
0
   checkParsed();
815
0
   rhs.checkParsed();
816
817
0
   if (!mHostCanonicalized)
818
0
   {
819
0
      if(DnsUtil::isIpV6Address(mHost))
820
0
      {
821
0
         mCanonicalHost = DnsUtil::canonicalizeIpV6Address(mHost);
822
0
      }
823
0
      else
824
0
      {
825
0
         mCanonicalHost = mHost;
826
0
         mCanonicalHost.lowercase();
827
0
      }
828
0
      mHostCanonicalized=true;
829
0
   }
830
   
831
0
   if (!rhs.mHostCanonicalized)
832
0
   {
833
0
      if(DnsUtil::isIpV6Address(rhs.mHost))
834
0
      {
835
0
         rhs.mCanonicalHost = DnsUtil::canonicalizeIpV6Address(rhs.mHost);
836
0
      }
837
0
      else
838
0
      {
839
0
         rhs.mCanonicalHost = rhs.mHost;
840
0
         rhs.mCanonicalHost.lowercase();
841
0
      }
842
0
      rhs.mHostCanonicalized=true;
843
0
   }
844
   
845
0
   return (mUser == rhs.mUser) && (mCanonicalHost == rhs.mCanonicalHost) && (mPort == rhs.mPort) &&
846
0
           isEqualNoCase(mScheme, rhs.mScheme) && (mNetNs == rhs.mNetNs);
847
0
}
848
849
void 
850
Uri::getAorInternal(bool dropScheme, bool addPort, Data& aor) const
851
0
{
852
0
   checkParsed();
853
   // canonicalize host
854
855
0
   addPort = addPort && mPort!=0;
856
857
0
   bool hostIsIpV6Address = DnsUtil::isIpV6Address(mHost);
858
0
   if(!mHostCanonicalized)
859
0
   {
860
0
      if (hostIsIpV6Address)
861
0
      {
862
0
         mCanonicalHost = DnsUtil::canonicalizeIpV6Address(mHost);
863
0
      }
864
0
      else
865
0
      {
866
0
         mCanonicalHost = mHost;
867
0
         mCanonicalHost.lowercase();
868
0
      }
869
0
      mHostCanonicalized = true;
870
0
   }
871
872
   // !bwc! Maybe reintroduce caching of aor. (Would use a bool instead of the
873
   // mOldX cruft)
874
   //                                                  @:10000
875
0
   aor.clear();
876
0
   aor.reserve((dropScheme ? 0 : mScheme.size()+1)
877
0
       + mUser.size() + mCanonicalHost.size() + 7);
878
0
   if(!dropScheme)
879
0
   {
880
0
      aor += mScheme;
881
0
      aor += ':';
882
0
   }
883
884
0
   if (!mUser.empty())
885
0
   {
886
0
#ifdef HANDLE_CHARACTER_ESCAPING
887
0
      {
888
0
         oDataStream str(aor);
889
0
         mUser.escapeToStream(str, getUserEncodingTable()); 
890
0
      }
891
#else
892
      aor += mUser;
893
#endif
894
0
      if(!mCanonicalHost.empty())
895
0
      {
896
0
         aor += Symbols::AT_SIGN;
897
0
      }
898
0
   }
899
900
0
   if(hostIsIpV6Address && addPort)
901
0
   {
902
0
      aor += Symbols::LS_BRACKET;
903
0
      aor += mCanonicalHost;
904
0
      aor += Symbols::RS_BRACKET;
905
0
   }
906
0
   else
907
0
   {
908
0
      aor += mCanonicalHost;
909
0
   }
910
911
0
   if(addPort)
912
0
   {
913
0
      aor += Symbols::COLON;
914
0
      aor += Data(mPort);
915
0
   }
916
0
}
917
918
Data 
919
Uri::getAOR(bool addPort) const
920
0
{
921
0
   Data result;
922
0
   getAorInternal(false, addPort, result);
923
0
   return result;
924
0
}
925
926
bool 
927
Uri::userIsTelephoneSubscriber() const
928
0
{
929
0
   try
930
0
   {
931
0
      ParseBuffer pb(mUser);
932
0
      pb.assertNotEof();
933
0
      const char* anchor=pb.position();
934
0
      bool local=false;
935
0
      if(*pb.position()=='+')
936
0
      {
937
         // Might be a global phone number
938
0
         pb.skipChar();
939
0
         pb.skipChars(getGlobalNumberTable());
940
0
      }
941
0
      else
942
0
      {
943
0
         pb.skipChars(getLocalNumberTable());
944
0
         local=true;
945
0
      }
946
947
0
      Data dialString(pb.data(anchor));
948
0
      if(dialString.empty())
949
0
      {
950
0
         pb.fail(__FILE__, __LINE__, "Dial string is empty.");
951
0
      }
952
953
      // ?bwc? More dial-string checking? For instance, +/ (or simply /) is not 
954
      // a valid dial-string according to the BNF; the string must contain at 
955
      // least one actual digit (or in the local number case, one hex digit or 
956
      // '*' or '#'. Interestingly, this means that stuff like ///*/// is 
957
      // valid)
958
959
      // Dial string looks ok so far; now look for params (there must be a 
960
      // phone-context param if this is a local number, otherwise there might 
961
      // or might not be one)
962
0
      if(local || !pb.eof())
963
0
      {
964
         // The only thing that can be here is a ';'. If it does, we're going 
965
         // to say it is good enough for us. If something in the parameter 
966
         // string is malformed, it'll get caught when/if 
967
         // getUserAsTelephoneSubscriber() is called.
968
0
         pb.skipChar(';');
969
0
      }
970
971
0
      return true;
972
0
   }
973
0
   catch(ParseException& /*e*/)
974
0
   {
975
0
      return false;
976
0
   }
977
0
}
978
979
Token 
980
Uri::getUserAsTelephoneSubscriber() const
981
0
{
982
   // !bwc! Ugly. Someday, refactor all this lazy-parser stuff and make it 
983
   // possible to control ownership explicitly.
984
   // Set this up as lazy-parsed, to prevent exceptions from being thrown.
985
0
   HeaderFieldValue temp(mUser.data(), mUser.size());
986
0
   Token tempToken(temp, Headers::NONE);
987
   // tempToken does not own the HeaderFieldValue temp, and temp does not own 
988
   // its buffer.
989
990
   // Here's the voodoo; invoking operator= makes a deep copy of the stuff in
991
   // tempToken, with result owning the memory, and result is in the unparsed 
992
   // state.
993
0
   Token result = tempToken;
994
0
   return result;
995
0
}
996
997
void 
998
Uri::setUserAsTelephoneSubscriber(const Token& telephoneSubscriber)
999
0
{
1000
0
   mUser.clear();
1001
0
   oDataStream str(mUser);
1002
0
   str << telephoneSubscriber;
1003
0
}
1004
1005
Data
1006
Uri::getAorNoPort() const
1007
0
{
1008
0
   Data result;
1009
0
   getAorInternal(true, false, result);
1010
0
   return result;
1011
0
}
1012
1013
Data
1014
Uri::getAor() const
1015
0
{
1016
0
   Data result;
1017
0
   getAorInternal(true, true, result);
1018
0
   return result;
1019
0
}
1020
1021
Uri 
1022
Uri::getAorAsUri(TransportType transportTypeToRemoveDefaultPort) const
1023
0
{   
1024
   //.dcm. -- tel conversion?
1025
0
   checkParsed();
1026
0
   Uri ret;
1027
0
   ret.scheme() = mScheme;   
1028
0
   ret.user() = mUser;
1029
0
   ret.host() = mHost;
1030
1031
   // Remove any default ports (if required)
1032
0
   if(transportTypeToRemoveDefaultPort == UDP || 
1033
0
       transportTypeToRemoveDefaultPort == TCP)
1034
0
   {
1035
0
      if(mPort != Symbols::DefaultSipPort)
1036
0
      {
1037
0
         ret.port() = mPort;
1038
0
      }
1039
0
   }
1040
0
   else if (transportTypeToRemoveDefaultPort == TLS || 
1041
0
            transportTypeToRemoveDefaultPort == DTLS)
1042
0
   {
1043
0
      if(mPort != Symbols::DefaultSipsPort)
1044
0
      {
1045
0
         ret.port() = mPort;
1046
0
      }
1047
0
   }
1048
0
   else
1049
0
   {
1050
0
      ret.port() = mPort;
1051
0
   }
1052
1053
0
   return ret;
1054
0
}
1055
1056
void
1057
Uri::parse(ParseBuffer& pb)
1058
18.1k
{
1059
18.1k
   pb.skipWhitespace();
1060
18.1k
   const char* start = pb.position();
1061
1062
   // Relative URLs (typically HTTP) start with a slash.  These
1063
   // are seen when parsing the WebSocket handshake.
1064
18.1k
   if (*pb.position() == Symbols::SLASH[0])
1065
825
   {
1066
825
      mScheme.clear();
1067
825
      pb.skipToOneOf("?;", ParseBuffer::Whitespace);
1068
825
      pb.data(mPath, start);
1069
825
      if (!pb.eof() && !ParseBuffer::oneOf(*pb.position(), ParseBuffer::Whitespace))
1070
660
      {
1071
660
         parseParameters(pb);
1072
660
      }
1073
825
      return;
1074
825
   }
1075
1076
17.2k
   pb.skipToOneOf(":@");
1077
1078
17.2k
   pb.assertNotEof();
1079
1080
17.2k
   pb.data(mScheme, start);
1081
17.2k
   pb.skipChar(Symbols::COLON[0]);
1082
17.2k
   mScheme.schemeLowercase();
1083
1084
17.2k
   if (mScheme==Symbols::Tel)
1085
47
   {
1086
47
      const char* anchor = pb.position();
1087
47
      static std::bitset<256> delimiter=Data::toBitset("\r\n\t ;>");
1088
47
      pb.skipToOneOf(delimiter);
1089
47
      pb.data(mUser, anchor);
1090
47
      if (!pb.eof() && *pb.position() == Symbols::SEMI_COLON[0])
1091
18
      {
1092
18
         anchor = pb.skipChar();
1093
18
         pb.skipToOneOf(ParseBuffer::Whitespace, Symbols::RA_QUOTE);
1094
18
         pb.data(mUserParameters, anchor);
1095
18
      }
1096
47
      return;
1097
47
   }
1098
   
1099
17.2k
   start = pb.position();
1100
17.2k
   static std::bitset<256> userPortOrPasswordDelim(Data::toBitset("@:\""));
1101
   // stop at double-quote to prevent matching an '@' in a quoted string param. 
1102
17.2k
   pb.skipToOneOf(userPortOrPasswordDelim);
1103
17.2k
   if (!pb.eof())
1104
3.45k
   {
1105
3.45k
      const char* atSign=0;
1106
3.45k
      if (*pb.position() == Symbols::COLON[0])
1107
2.49k
      {
1108
         // Either a password, or a port
1109
2.49k
         const char* afterColon = pb.skipChar();
1110
2.49k
         pb.skipToOneOf("@\"");
1111
2.49k
         if(!pb.eof() && *pb.position() == Symbols::AT_SIGN[0])
1112
265
         {
1113
265
            atSign=pb.position();
1114
            // password
1115
265
#ifdef HANDLE_CHARACTER_ESCAPING
1116
265
            pb.dataUnescaped(mPassword, afterColon);
1117
#else
1118
            pb.data(mPassword, afterColon);
1119
#endif
1120
265
            pb.reset(afterColon-1);
1121
265
         }
1122
2.23k
         else
1123
2.23k
         {
1124
            // port. No user part.
1125
2.23k
            pb.reset(start);
1126
2.23k
         }
1127
2.49k
      }
1128
962
      else if(*pb.position() == Symbols::AT_SIGN[0])
1129
483
      {
1130
483
         atSign=pb.position();
1131
483
      }
1132
479
      else
1133
479
      {
1134
         // Only a hostpart
1135
479
         pb.reset(start);
1136
479
      }
1137
1138
3.45k
      if(atSign)
1139
678
      {
1140
678
#ifdef HANDLE_CHARACTER_ESCAPING
1141
678
         pb.dataUnescaped(mUser, start);
1142
#else
1143
         pb.data(mUser, start);
1144
#endif
1145
678
         pb.reset(atSign);
1146
678
         start = pb.skipChar();
1147
678
      }
1148
3.45k
   }
1149
13.7k
   else
1150
13.7k
   {
1151
13.7k
      pb.reset(start);
1152
13.7k
   }
1153
1154
17.2k
   if (pb.eof())
1155
441
   {
1156
441
      return;
1157
441
   }
1158
1159
16.7k
   mHostCanonicalized=false;
1160
16.7k
   static std::bitset<256> hostDelimiter(Data::toBitset("\r\n\t :;?>"));
1161
16.7k
   if (*start == '[')
1162
142
   {
1163
142
      start = pb.skipChar();
1164
142
      pb.skipToChar(']');
1165
142
      pb.data(mHost, start);
1166
142
      mCanonicalHost = DnsUtil::canonicalizeIpV6Address(mHost);
1167
142
      if (mCanonicalHost.empty())
1168
43
      {
1169
         // .bwc. So the V6 addy is garbage.
1170
43
         throw ParseException("Unparsable V6 address (note, this might"
1171
43
                                    " be unparsable because IPV6 support is not"
1172
43
                                    " enabled)","Uri",__FILE__,
1173
43
                                       __LINE__);
1174
43
      }
1175
99
      mHostCanonicalized = true;
1176
99
      pb.skipChar();
1177
99
      pb.skipToOneOf(hostDelimiter);
1178
99
   }
1179
16.6k
   else
1180
16.6k
   {
1181
16.6k
      pb.skipToOneOf(hostDelimiter);
1182
16.6k
      pb.data(mHost, start);
1183
16.6k
   }
1184
1185
16.7k
   if (!pb.eof() && *pb.position() == ':')
1186
340
   {
1187
340
      start = pb.skipChar();
1188
340
      mPort = pb.uInt32();
1189
340
   }
1190
16.4k
   else
1191
16.4k
   {
1192
16.4k
      mPort = 0;
1193
16.4k
   }
1194
1195
16.7k
   parseParameters(pb);
1196
1197
16.7k
   if (!pb.eof() && *pb.position() == Symbols::QUESTION[0])
1198
2.55k
   {
1199
2.55k
      const char* anchor = pb.position();
1200
1201
2.55k
      if (mIsBetweenAngleQuotes)
1202
50
      {
1203
         // Embedded headers will either end at the angle bracket (when Uri is in a NameAddr that uses angle 
1204
         // brackets) or at a semi-colon (when Uri is in a NameAddr that doesn't use angle brackets and has 
1205
         // NameAddr parameters following the embedded headers), or in Whitespace.
1206
         // We used to just look for either of the 3 terminators, however to be more tolerant of endpoints 
1207
         // that do not properly escape ;'s in the embedded headers, we relax the rules, only when the uri
1208
         // falls between angle quotes/brackets - in this case we will allow non-escaped semi-colons by only
1209
         // looking for > and whitespace as a terminator.
1210
50
         pb.skipToOneOf(">", ParseBuffer::Whitespace);
1211
50
      }
1212
2.50k
      else
1213
2.50k
      {
1214
2.50k
         pb.skipToOneOf(">;", ParseBuffer::Whitespace);
1215
2.50k
      }
1216
1217
2.55k
      if(!mEmbeddedHeadersText.get()) mEmbeddedHeadersText.reset(new Data);
1218
2.55k
      pb.data(*mEmbeddedHeadersText, anchor);
1219
2.55k
   }
1220
16.7k
}
1221
1222
ParserCategory*
1223
Uri::clone() const
1224
0
{
1225
0
   return new Uri(*this);
1226
0
}
1227
1228
ParserCategory*
1229
Uri::clone(void* location) const
1230
0
{
1231
0
   return new (location) Uri(*this);
1232
0
}
1233
1234
ParserCategory*
1235
Uri::clone(PoolBase* pool) const
1236
0
{
1237
0
   return new (pool) Uri(*this);
1238
0
}
1239
1240
void Uri::setUriUserEncoding(unsigned char c, bool encode) 
1241
0
{
1242
0
   getUserEncodingTable()[c] = encode; 
1243
0
}
1244
1245
void Uri::setUriPasswordEncoding(unsigned char c, bool encode)
1246
0
{
1247
0
   getPasswordEncodingTable()[c] = encode;
1248
0
}
1249
1250
// should not encode user parameters unless its a tel?
1251
EncodeStream& 
1252
Uri::encodeParsed(EncodeStream& str) const
1253
0
{
1254
   // Relative URIs may not have the scheme
1255
0
   if (!mScheme.empty())
1256
0
   {
1257
0
      str << mScheme << Symbols::COLON;
1258
0
   }
1259
1260
0
   if (!mUser.empty())
1261
0
   {
1262
0
#ifdef HANDLE_CHARACTER_ESCAPING
1263
0
      mUser.escapeToStream(str, getUserEncodingTable()); 
1264
#else
1265
      str << mUser;
1266
#endif
1267
0
      if (!mUserParameters.empty())
1268
0
      {
1269
0
         str << Symbols::SEMI_COLON[0] << mUserParameters;
1270
0
      }
1271
0
      if (!mPassword.empty())
1272
0
      {
1273
0
         str << Symbols::COLON;
1274
0
#ifdef HANDLE_CHARACTER_ESCAPING
1275
0
         mPassword.escapeToStream(str, getPasswordEncodingTable());
1276
#else
1277
         str << mPassword;
1278
#endif
1279
0
      }
1280
0
   }
1281
0
   if (!mHost.empty())
1282
0
   {
1283
0
     if (!mUser.empty())
1284
0
     {
1285
0
       str << Symbols::AT_SIGN;
1286
0
     }
1287
0
     if (DnsUtil::isIpV6Address(mHost))
1288
0
     {
1289
0
        str << '[' << mHost << ']';
1290
0
     }
1291
0
     else
1292
0
     {
1293
0
        str << mHost;
1294
0
     }
1295
0
   }
1296
0
   if (mPort != 0)
1297
0
   {
1298
0
      str << Symbols::COLON << mPort;
1299
0
   }
1300
0
   if (!mPath.empty())
1301
0
   {
1302
0
      str << mPath;
1303
0
   }
1304
0
   encodeParameters(str);
1305
0
   encodeEmbeddedHeaders(str);
1306
1307
0
   return str;
1308
0
}
1309
1310
SipMessage&
1311
Uri::embedded()
1312
6.13k
{
1313
6.13k
   checkParsed();
1314
6.13k
   if (mEmbeddedHeaders.get() == 0)
1315
3.16k
   {
1316
3.16k
      this->mEmbeddedHeaders.reset(new SipMessage());
1317
3.16k
      if (mEmbeddedHeadersText.get() && !mEmbeddedHeadersText->empty())
1318
1.24k
      {
1319
1.24k
         ParseBuffer pb(mEmbeddedHeadersText->data(), mEmbeddedHeadersText->size());
1320
1.24k
         this->parseEmbeddedHeaders(pb);
1321
1.24k
      }
1322
3.16k
   }
1323
1324
6.13k
   return *mEmbeddedHeaders;
1325
6.13k
}
1326
1327
const SipMessage&
1328
Uri::embedded() const
1329
0
{
1330
0
   Uri* ncthis = const_cast<Uri*>(this);
1331
0
   return ncthis->embedded();
1332
0
}
1333
1334
static const Data bodyData("Body");
1335
void
1336
Uri::parseEmbeddedHeaders(ParseBuffer& pb)
1337
1.24k
{
1338
1.24k
   DebugLog(<< "Uri::parseEmbeddedHeaders");
1339
1.24k
   if (!pb.eof() && *pb.position() == Symbols::QUESTION[0])
1340
1.24k
   {
1341
1.24k
      pb.skipChar();
1342
1.24k
   }
1343
1344
1.24k
   const char* anchor;
1345
1.24k
   Data headerName;
1346
1.24k
   Data headerContents;
1347
1348
1.24k
   bool first = true;
1349
1.87M
   while (!pb.eof())
1350
1.87M
   {
1351
1.87M
      if (first)
1352
1.20k
      {
1353
1.20k
         first = false;
1354
1.20k
      }
1355
1.87M
      else
1356
1.87M
      {
1357
1.87M
         pb.skipChar(Symbols::AMPERSAND[0]);
1358
1.87M
      }
1359
1360
1.87M
      anchor = pb.position();
1361
1.87M
      pb.skipToChar(Symbols::EQUALS[0]);
1362
1.87M
      pb.data(headerName, anchor);
1363
      // .dlb. in theory, need to decode header name
1364
1365
1.87M
      anchor = pb.skipChar(Symbols::EQUALS[0]);
1366
1.87M
      pb.skipToChar(Symbols::AMPERSAND[0]);
1367
1.87M
      pb.data(headerContents, anchor);
1368
1369
1.87M
      unsigned int len;
1370
1.87M
      char* decodedContents = Embedded::decode(headerContents, len);
1371
1.87M
      mEmbeddedHeaders->addBuffer(decodedContents);
1372
1373
1.87M
      if (isEqualNoCase(bodyData, headerName))
1374
27.9k
      {
1375
27.9k
         mEmbeddedHeaders->setBody(decodedContents, len); 
1376
27.9k
      }
1377
1.84M
      else
1378
1.84M
      {
1379
1.84M
         DebugLog(<< "Uri::parseEmbeddedHeaders(" << headerName << ", " << Data(decodedContents, len) << ")");
1380
1.84M
         mEmbeddedHeaders->addHeader(Headers::getType(headerName.data(), headerName.size()),
1381
1.84M
                                     headerName.data(), (int)headerName.size(),
1382
1.84M
                                     decodedContents, len);
1383
1.84M
      }
1384
1.87M
   }
1385
1.24k
}
1386
1387
EncodeStream& 
1388
Uri::encodeEmbeddedHeaders(EncodeStream& str) const
1389
0
{
1390
0
   if (mEmbeddedHeaders.get())
1391
0
   {
1392
0
      mEmbeddedHeaders->encodeEmbedded(str);
1393
0
   }
1394
0
   else if(mEmbeddedHeadersText.get())
1395
0
   {
1396
      // never decoded
1397
0
      str << *mEmbeddedHeadersText;
1398
0
   }
1399
0
   return str;
1400
0
}
1401
1402
Data 
1403
Uri::toString() const
1404
0
{
1405
0
   Data out;
1406
0
   {
1407
0
      oDataStream dataStream(out);
1408
0
      this->encodeParsed(dataStream);
1409
0
   }
1410
0
   return out;
1411
0
}
1412
1413
ParameterTypes::Factory Uri::ParameterFactories[ParameterTypes::MAX_PARAMETER]={0};
1414
1415
Parameter* 
1416
Uri::createParam(ParameterTypes::Type type, ParseBuffer& pb, const std::bitset<256>& terminators, PoolBase* pool)
1417
20.5k
{
1418
20.5k
   if(type > ParameterTypes::UNKNOWN && type < ParameterTypes::MAX_PARAMETER && ParameterFactories[type])
1419
11.3k
   {
1420
11.3k
      return ParameterFactories[type](type, pb, terminators, pool);
1421
11.3k
   }
1422
9.20k
   return 0;
1423
20.5k
}
1424
1425
bool 
1426
Uri::exists(const Param<Uri>& paramType) const
1427
0
{
1428
0
    checkParsed();
1429
0
    bool ret = getParameterByEnum(paramType.getTypeNum()) != NULL;
1430
0
    return ret;
1431
0
}
1432
1433
void 
1434
Uri::remove(const Param<Uri>& paramType)
1435
0
{
1436
0
    checkParsed();
1437
0
    removeParameterByEnum(paramType.getTypeNum());
1438
0
}
1439
1440
#define defineParam(_enum, _name, _type, _RFC_ref_ignored)                                                      \
1441
_enum##_Param::DType&                                                                                           \
1442
0
Uri::param(const _enum##_Param& paramType)                                                           \
1443
0
{                                                                                                               \
1444
0
   checkParsed();                                                                                               \
1445
0
   _enum##_Param::Type* p =                                                                                     \
1446
0
      static_cast<_enum##_Param::Type*>(getParameterByEnum(paramType.getTypeNum()));                            \
1447
0
   if (!p)                                                                                                      \
1448
0
   {                                                                                                            \
1449
0
      p = new _enum##_Param::Type(paramType.getTypeNum());                                                      \
1450
0
      mParameters.push_back(p);                                                                                 \
1451
0
   }                                                                                                            \
1452
0
   return p->value();                                                                                           \
1453
0
}                                                                                                               \
Unexecuted instantiation: resip::Uri::param(resip::ob_Param const&)
Unexecuted instantiation: resip::Uri::param(resip::gr_Param const&)
Unexecuted instantiation: resip::Uri::param(resip::comp_Param const&)
Unexecuted instantiation: resip::Uri::param(resip::duration_Param const&)
Unexecuted instantiation: resip::Uri::param(resip::lr_Param const&)
Unexecuted instantiation: resip::Uri::param(resip::maddr_Param const&)
Unexecuted instantiation: resip::Uri::param(resip::method_Param const&)
Unexecuted instantiation: resip::Uri::param(resip::transport_Param const&)
Unexecuted instantiation: resip::Uri::param(resip::ttl_Param const&)
Unexecuted instantiation: resip::Uri::param(resip::user_Param const&)
Unexecuted instantiation: resip::Uri::param(resip::extension_Param const&)
Unexecuted instantiation: resip::Uri::param(resip::sigcompId_Param const&)
Unexecuted instantiation: resip::Uri::param(resip::rinstance_Param const&)
Unexecuted instantiation: resip::Uri::param(resip::addTransport_Param const&)
Unexecuted instantiation: resip::Uri::param(resip::wsSrcIp_Param const&)
Unexecuted instantiation: resip::Uri::param(resip::wsSrcPort_Param const&)
1454
                                                                                                                \
1455
const _enum##_Param::DType&                                                                                     \
1456
0
Uri::param(const _enum##_Param& paramType) const                                                     \
1457
0
{                                                                                                               \
1458
0
   checkParsed();                                                                                               \
1459
0
   _enum##_Param::Type* p =                                                                                     \
1460
0
      static_cast<_enum##_Param::Type*>(getParameterByEnum(paramType.getTypeNum()));                            \
1461
0
   if (!p)                                                                                                      \
1462
0
   {                                                                                                            \
1463
0
      InfoLog(<< "Missing parameter " _name " " << ParameterTypes::ParameterNames[paramType.getTypeNum()]);     \
1464
0
      DebugLog(<< *this);                                                                                       \
1465
0
      throw Exception("Missing parameter " _name, __FILE__, __LINE__);                                          \
1466
0
   }                                                                                                            \
1467
0
   return p->value();                                                                                           \
1468
0
}
Unexecuted instantiation: resip::Uri::param(resip::ob_Param const&) const
Unexecuted instantiation: resip::Uri::param(resip::gr_Param const&) const
Unexecuted instantiation: resip::Uri::param(resip::comp_Param const&) const
Unexecuted instantiation: resip::Uri::param(resip::duration_Param const&) const
Unexecuted instantiation: resip::Uri::param(resip::lr_Param const&) const
Unexecuted instantiation: resip::Uri::param(resip::maddr_Param const&) const
Unexecuted instantiation: resip::Uri::param(resip::method_Param const&) const
Unexecuted instantiation: resip::Uri::param(resip::transport_Param const&) const
Unexecuted instantiation: resip::Uri::param(resip::ttl_Param const&) const
Unexecuted instantiation: resip::Uri::param(resip::user_Param const&) const
Unexecuted instantiation: resip::Uri::param(resip::extension_Param const&) const
Unexecuted instantiation: resip::Uri::param(resip::sigcompId_Param const&) const
Unexecuted instantiation: resip::Uri::param(resip::rinstance_Param const&) const
Unexecuted instantiation: resip::Uri::param(resip::addTransport_Param const&) const
Unexecuted instantiation: resip::Uri::param(resip::wsSrcIp_Param const&) const
Unexecuted instantiation: resip::Uri::param(resip::wsSrcPort_Param const&) const
1469
1470
defineParam(ob,"ob",ExistsParameter,"RFC 5626");
1471
defineParam(gr, "gr", ExistsOrDataParameter, "RFC 5627");
1472
defineParam(comp, "comp", DataParameter, "RFC 3486");
1473
defineParam(duration, "duration", UInt32Parameter, "RFC 4240");
1474
defineParam(lr, "lr", ExistsParameter, "RFC 3261");
1475
defineParam(maddr, "maddr", DataParameter, "RFC 3261");
1476
defineParam(method, "method", DataParameter, "RFC 3261");
1477
defineParam(transport, "transport", DataParameter, "RFC 3261");
1478
defineParam(ttl, "ttl", UInt32Parameter, "RFC 3261");
1479
defineParam(user, "user", DataParameter, "RFC 3261, 4967");
1480
defineParam(extension, "ext", DataParameter, "RFC 3966"); // Token is used when ext is a user-parameter
1481
defineParam(sigcompId, "sigcomp-id", QuotedDataParameter, "RFC 5049");
1482
defineParam(rinstance, "rinstance", DataParameter, "proprietary (resip)");
1483
defineParam(addTransport, "addTransport", ExistsParameter, "RESIP INTERNAL");
1484
defineParam(wsSrcIp, "ws-src-ip", DataParameter, "RESIP INTERNAL (WebSocket)");
1485
defineParam(wsSrcPort, "ws-src-port", UInt32Parameter, "RESIP INTERNAL (WebSocket)");
1486
1487
#undef defineParam
1488
1489
HashValueImp(resip::Uri, resip::Data::from(data).hash());
1490
1491
/* ====================================================================
1492
 * The Vovida Software License, Version 1.0 
1493
 * 
1494
 * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
1495
 * 
1496
 * Redistribution and use in source and binary forms, with or without
1497
 * modification, are permitted provided that the following conditions
1498
 * are met:
1499
 * 
1500
 * 1. Redistributions of source code must retain the above copyright
1501
 *    notice, this list of conditions and the following disclaimer.
1502
 * 
1503
 * 2. Redistributions in binary form must reproduce the above copyright
1504
 *    notice, this list of conditions and the following disclaimer in
1505
 *    the documentation and/or other materials provided with the
1506
 *    distribution.
1507
 * 
1508
 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
1509
 *    and "Vovida Open Communication Application Library (VOCAL)" must
1510
 *    not be used to endorse or promote products derived from this
1511
 *    software without prior written permission. For written
1512
 *    permission, please contact vocal@vovida.org.
1513
 *
1514
 * 4. Products derived from this software may not be called "VOCAL", nor
1515
 *    may "VOCAL" appear in their name, without prior written
1516
 *    permission of Vovida Networks, Inc.
1517
 * 
1518
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
1519
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1520
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
1521
 * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
1522
 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
1523
 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
1524
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
1525
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
1526
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
1527
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1528
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
1529
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
1530
 * DAMAGE.
1531
 * 
1532
 * ====================================================================
1533
 * 
1534
 * This software consists of voluntary contributions made by Vovida
1535
 * Networks, Inc. and many individuals on behalf of Vovida Networks,
1536
 * Inc.  For more information on Vovida Networks, Inc., please see
1537
 * <http://www.vovida.org/>.
1538
 *
1539
 */