Coverage Report

Created: 2025-10-12 06:49

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