Coverage Report

Created: 2023-06-07 06:03

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