|
reSIProcate/stack
9694
|
00001 #if defined(HAVE_CONFIG_H) 00002 #include "config.h" 00003 #endif 00004 00005 #include "resip/stack/NameAddr.hxx" 00006 #include "rutil/ParseException.hxx" 00007 #include "resip/stack/UnknownParameter.hxx" 00008 #include "rutil/Data.hxx" 00009 #include "rutil/DnsUtil.hxx" 00010 #include "rutil/Logger.hxx" 00011 #include "rutil/ParseBuffer.hxx" 00012 //#include "rutil/WinLeakCheck.hxx" // not compatible with placement new used below 00013 00014 using namespace resip; 00015 using namespace std; 00016 00017 #define RESIPROCATE_SUBSYSTEM Subsystem::SIP 00018 00019 //==================== 00020 // NameAddr: 00021 //==================== 00022 NameAddr::NameAddr() : 00023 ParserCategory(), 00024 mAllContacts(false), 00025 mDisplayName(), 00026 mUnknownUriParametersBuffer(0) 00027 {} 00028 00029 NameAddr::NameAddr(const HeaderFieldValue& hfv, 00030 Headers::Type type, 00031 PoolBase* pool) 00032 : ParserCategory(hfv, type, pool), 00033 mAllContacts(false), 00034 mUri(pool), 00035 mDisplayName(), 00036 mUnknownUriParametersBuffer(0) 00037 {} 00038 00039 NameAddr::NameAddr(const NameAddr& rhs, 00040 PoolBase* pool) 00041 : ParserCategory(rhs, pool), 00042 mAllContacts(rhs.mAllContacts), 00043 mUri(rhs.mUri, pool), 00044 mDisplayName(rhs.mDisplayName), 00045 mUnknownUriParametersBuffer(0) 00046 {} 00047 00048 static const Data parseContext("NameAddr constructor"); 00049 NameAddr::NameAddr(const Data& unparsed, bool preCacheAor) 00050 : ParserCategory(), 00051 mAllContacts(false), 00052 mDisplayName(), 00053 mUnknownUriParametersBuffer(0) 00054 { 00055 HeaderFieldValue hfv(unparsed.data(), unparsed.size()); 00056 // must copy because parse creates overlays 00057 NameAddr tmp(hfv, Headers::UNKNOWN); 00058 tmp.checkParsed(); 00059 *this = tmp; 00060 if(preCacheAor) 00061 { 00062 mUri.getAor(); 00063 } 00064 } 00065 00066 NameAddr::NameAddr(const Uri& uri) 00067 : ParserCategory(), 00068 mAllContacts(false), 00069 mUri(uri), 00070 mDisplayName(), 00071 mUnknownUriParametersBuffer(0) 00072 {} 00073 00074 NameAddr::~NameAddr() 00075 { 00076 if(mUnknownUriParametersBuffer) 00077 { 00078 delete mUnknownUriParametersBuffer; 00079 } 00080 } 00081 00082 NameAddr& 00083 NameAddr::operator=(const NameAddr& rhs) 00084 { 00085 if (this != &rhs) 00086 { 00087 assert( &rhs != 0 ); 00088 00089 ParserCategory::operator=(rhs); 00090 mAllContacts = rhs.mAllContacts; 00091 mDisplayName = rhs.mDisplayName; 00092 mUri = rhs.mUri; 00093 } 00094 return *this; 00095 } 00096 00097 bool 00098 NameAddr::operator==(const NameAddr& other) const 00099 { 00100 return uri() == other.uri() && displayName() == other.displayName(); 00101 } 00102 00103 bool 00104 NameAddr::operator<(const NameAddr& rhs) const 00105 { 00106 return uri() < rhs.uri(); 00107 } 00108 00109 ParserCategory * 00110 NameAddr::clone() const 00111 { 00112 return new NameAddr(*this); 00113 } 00114 00115 ParserCategory * 00116 NameAddr::clone(void* location) const 00117 { 00118 return new (location) NameAddr(*this); 00119 } 00120 00121 ParserCategory* 00122 NameAddr::clone(PoolBase* pool) const 00123 { 00124 return new (pool) NameAddr(*this, pool); 00125 } 00126 00127 const Uri& 00128 NameAddr::uri() const 00129 { 00130 checkParsed(); 00131 return mUri; 00132 } 00133 00134 Uri& 00135 NameAddr::uri() 00136 { 00137 checkParsed(); 00138 return mUri; 00139 } 00140 00141 Data& 00142 NameAddr::displayName() 00143 { 00144 checkParsed(); 00145 return mDisplayName; 00146 } 00147 00148 const Data& 00149 NameAddr::displayName() const 00150 { 00151 checkParsed(); 00152 return mDisplayName; 00153 } 00154 00155 bool 00156 NameAddr::isAllContacts() const 00157 { 00158 checkParsed(); 00159 return mAllContacts; 00160 } 00161 00162 void 00163 NameAddr::setAllContacts() 00164 { 00165 mAllContacts = true; 00166 } 00167 00168 void 00169 NameAddr::parse(ParseBuffer& pb) 00170 { 00171 const char* start; 00172 start = pb.skipWhitespace(); 00173 pb.assertNotEof(); 00174 bool laQuote = false; 00175 bool starContact = false; 00176 00177 if (*pb.position() == Symbols::STAR[0]) 00178 { 00179 pb.skipChar(Symbols::STAR[0]); 00180 pb.skipWhitespace(); 00181 if (pb.eof() || *pb.position() == Symbols::SEMI_COLON[0]) 00182 { 00183 starContact = true; 00184 } 00185 } 00186 00187 if (starContact) 00188 { 00189 mAllContacts = true; 00190 // now fall through to parse header parameters 00191 } 00192 else 00193 { 00194 pb.reset(start); 00195 if (*pb.position() == Symbols::DOUBLE_QUOTE[0]) 00196 { 00197 start = pb.skipChar(Symbols::DOUBLE_QUOTE[0]); 00198 pb.skipToEndQuote(); 00199 pb.data(mDisplayName, start); 00200 pb.skipChar(Symbols::DOUBLE_QUOTE[0]); 00201 laQuote = true; 00202 pb.skipToChar(Symbols::LA_QUOTE[0]); 00203 if (pb.eof()) 00204 { 00205 throw ParseException("Expected '<'", 00206 "NameAddr", 00207 __FILE__, 00208 __LINE__); 00209 } 00210 else 00211 { 00212 pb.skipChar(Symbols::LA_QUOTE[0]); 00213 } 00214 } 00215 else if (*pb.position() == Symbols::LA_QUOTE[0]) 00216 { 00217 pb.skipChar(Symbols::LA_QUOTE[0]); 00218 laQuote = true; 00219 } 00220 else 00221 { 00222 start = pb.position(); 00223 pb.skipToChar(Symbols::LA_QUOTE[0]); 00224 if (pb.eof()) 00225 { 00226 pb.reset(start); 00227 } 00228 else 00229 { 00230 laQuote = true; 00231 pb.skipBackWhitespace(); 00232 pb.data(mDisplayName, start); 00233 pb.skipToChar(Symbols::LA_QUOTE[0]); 00234 pb.skipChar(Symbols::LA_QUOTE[0]); 00235 } 00236 } 00237 pb.skipWhitespace(); 00238 mUri.parse(pb); 00239 if (laQuote) 00240 { 00241 pb.skipChar(Symbols::RA_QUOTE[0]); 00242 pb.skipWhitespace(); 00243 // now fall through to parse header parameters 00244 } 00245 else 00246 { 00247 if(mUri.mUnknownParameters.size() > 0) 00248 { 00249 assert(!mUnknownUriParametersBuffer); 00250 mUnknownUriParametersBuffer = new Data; 00251 { // Scope stream 00252 oDataStream str(*mUnknownUriParametersBuffer); 00253 // deal with Uri/NameAddr parameter ambiguity 00254 // heuristically assign Uri parameters to the Uri 00255 for (ParameterList::iterator it = mUri.mUnknownParameters.begin(); 00256 it != mUri.mUnknownParameters.end(); ++it) 00257 { 00258 // We're just going to assume all unknown (to Uri) params really 00259 // belong on the header. This is not necessarily the case. 00260 str << ";"; 00261 (*it)->encode(str); 00262 } 00263 } 00264 mUri.clearUnknownParameters(); 00265 ParseBuffer pb2(*mUnknownUriParametersBuffer); 00266 parseParameters(pb2); 00267 } 00268 } 00269 } 00270 parseParameters(pb); 00271 } 00272 00273 EncodeStream& 00274 NameAddr::encodeParsed(EncodeStream& str) const 00275 { 00276 //bool displayName = !mDisplayName.empty(); 00277 if (mAllContacts) 00278 { 00279 str << Symbols::STAR; 00280 } 00281 else 00282 { 00283 if (!mDisplayName.empty()) 00284 { 00285 #ifndef HANDLE_EMBEDDED_QUOTES_DNAME 00286 // .dlb. doesn't deal with embedded quotes 00287 str << Symbols::DOUBLE_QUOTE << mDisplayName << Symbols::DOUBLE_QUOTE; 00288 #else 00289 // does nothing if display name is properly quoted 00290 if (mustQuoteDisplayName()) 00291 { 00292 str << Symbols::DOUBLE_QUOTE; 00293 for (unsigned int i=0; i < mDisplayName.size(); i++) 00294 { 00295 char c = mDisplayName[i]; 00296 switch(c) 00297 { 00298 case '"': 00299 case '\\': 00300 str << '\\' << c; 00301 break; 00302 default: 00303 str << c; 00304 } 00305 } 00306 str << Symbols::DOUBLE_QUOTE; 00307 } 00308 else 00309 { 00310 str << mDisplayName; 00311 } 00312 #endif 00313 } 00314 str << Symbols::LA_QUOTE; 00315 mUri.encodeParsed(str); 00316 str << Symbols::RA_QUOTE; 00317 } 00318 00319 encodeParameters(str); 00320 return str; 00321 } 00322 00323 00324 bool 00325 NameAddr::mustQuoteDisplayName() const 00326 { 00327 if (mDisplayName.empty()) 00328 { 00329 return false; 00330 } 00331 ParseBuffer pb(mDisplayName.data(), mDisplayName.size()); 00332 00333 //shouldn't really be any leading whitespace 00334 pb.skipWhitespace(); 00335 if (pb.eof()) 00336 { 00337 return false; 00338 } 00339 if ((*pb.position() == '"')) 00340 { 00341 bool escaped = false; 00342 while(!pb.eof()) 00343 { 00344 pb.skipChar(); 00345 if (escaped) 00346 { 00347 escaped = false; 00348 } 00349 else if (*pb.position() == '\\') 00350 { 00351 escaped = true; 00352 } 00353 else if (*pb.position() == '"') 00354 { 00355 break; 00356 } 00357 } 00358 if (*pb.position() == '"') 00359 { 00360 //should only have whitespace left, and really non of that 00361 pb.skipChar(); 00362 if (pb.eof()) 00363 { 00364 return false; 00365 } 00366 pb.skipWhitespace(); 00367 if (pb.eof()) 00368 { 00369 return false; //properly quoted 00370 } 00371 else 00372 { 00373 return true; 00374 } 00375 } 00376 else 00377 { 00378 return true; //imbalanced quotes 00379 } 00380 } 00381 else 00382 { 00383 while (!pb.eof()) 00384 { 00385 const char* start; 00386 start = pb.skipWhitespace(); 00387 pb.skipNonWhitespace(); 00388 const char* end = pb.position(); 00389 for (const char* c = start; c < end; c++) 00390 { 00391 if ( (*c >= 'a' && *c <= 'z') || 00392 (*c >= 'A' && *c <= 'Z') || 00393 (*c >= '0' && *c <= '9')) 00394 { 00395 continue; 00396 } 00397 switch(*c) 00398 { 00399 case '-': 00400 case '.': 00401 case '!': 00402 case '%': 00403 case '*': 00404 case '_': 00405 case '+': 00406 case '`': 00407 case '\'': 00408 case '~': 00409 break; 00410 default: 00411 return true; 00412 } 00413 } 00414 } 00415 } 00416 return false; 00417 } 00418 00419 ParameterTypes::Factory NameAddr::ParameterFactories[ParameterTypes::MAX_PARAMETER]={0}; 00420 00421 Parameter* 00422 NameAddr::createParam(ParameterTypes::Type type, ParseBuffer& pb, const std::bitset<256>& terminators, PoolBase* pool) 00423 { 00424 if(type > ParameterTypes::UNKNOWN && type < ParameterTypes::MAX_PARAMETER && ParameterFactories[type]) 00425 { 00426 return ParameterFactories[type](type, pb, terminators, pool); 00427 } 00428 return 0; 00429 } 00430 00431 bool 00432 NameAddr::exists(const Param<NameAddr>& paramType) const 00433 { 00434 checkParsed(); 00435 bool ret = getParameterByEnum(paramType.getTypeNum()) != NULL; 00436 return ret; 00437 } 00438 00439 void 00440 NameAddr::remove(const Param<NameAddr>& paramType) 00441 { 00442 checkParsed(); 00443 removeParameterByEnum(paramType.getTypeNum()); 00444 } 00445 00446 #define defineParam(_enum, _name, _type, _RFC_ref_ignored) \ 00447 _enum##_Param::DType& \ 00448 NameAddr::param(const _enum##_Param& paramType) \ 00449 { \ 00450 checkParsed(); \ 00451 _enum##_Param::Type* p = \ 00452 static_cast<_enum##_Param::Type*>(getParameterByEnum(paramType.getTypeNum())); \ 00453 if (!p) \ 00454 { \ 00455 p = new _enum##_Param::Type(paramType.getTypeNum()); \ 00456 mParameters.push_back(p); \ 00457 } \ 00458 return p->value(); \ 00459 } \ 00460 \ 00461 const _enum##_Param::DType& \ 00462 NameAddr::param(const _enum##_Param& paramType) const \ 00463 { \ 00464 checkParsed(); \ 00465 _enum##_Param::Type* p = \ 00466 static_cast<_enum##_Param::Type*>(getParameterByEnum(paramType.getTypeNum())); \ 00467 if (!p) \ 00468 { \ 00469 InfoLog(<< "Missing parameter " _name " " << ParameterTypes::ParameterNames[paramType.getTypeNum()]); \ 00470 DebugLog(<< *this); \ 00471 throw Exception("Missing parameter " _name, __FILE__, __LINE__); \ 00472 } \ 00473 return p->value(); \ 00474 } 00475 00476 defineParam(data, "data", ExistsParameter, "RFC 3840"); 00477 defineParam(control, "control", ExistsParameter, "RFC 3840"); 00478 defineParam(mobility, "mobility", QuotedDataParameter, "RFC 3840"); // mobile|fixed 00479 defineParam(description, "description", QuotedDataParameter, "RFC 3840"); // <> quoted 00480 defineParam(events, "events", QuotedDataParameter, "RFC 3840"); // list 00481 defineParam(priority, "priority", QuotedDataParameter, "RFC 3840"); // non-urgent|normal|urgent|emergency 00482 defineParam(methods, "methods", QuotedDataParameter, "RFC 3840"); // list 00483 defineParam(schemes, "schemes", QuotedDataParameter, "RFC 3840"); // list 00484 defineParam(application, "application", ExistsParameter, "RFC 3840"); 00485 defineParam(video, "video", ExistsParameter, "RFC 3840"); 00486 defineParam(language, "language", QuotedDataParameter, "RFC 3840"); // list 00487 defineParam(type, "type", QuotedDataParameter, "RFC 3840"); // list 00488 defineParam(isFocus, "isfocus", ExistsParameter, "RFC 3840"); 00489 defineParam(actor, "actor", QuotedDataParameter, "RFC 3840"); // principal|msg-taker|attendant|information 00490 defineParam(text, "text", ExistsOrDataParameter, "RFC 3840"); 00491 defineParam(extensions, "extensions", QuotedDataParameter, "RFC 3840"); //list 00492 defineParam(Instance, "+sip.instance", QuotedDataParameter, "RFC 5626"); // <> quoted 00493 defineParam(regid, "reg-id", UInt32Parameter, "RFC 5626"); 00494 defineParam(pubGruu, "pub-gruu", QuotedDataParameter, "RFC 5627"); 00495 defineParam(tempGruu, "temp-gruu", QuotedDataParameter, "RFC 5627"); 00496 defineParam(expires, "expires", UInt32Parameter, "RFC 3261"); 00497 defineParam(q, "q", QValueParameter, "RFC 3261"); 00498 defineParam(tag, "tag", DataParameter, "RFC 3261"); 00499 00500 #undef defineParam 00501 00502 /* ==================================================================== 00503 * The Vovida Software License, Version 1.0 00504 * 00505 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. 00506 * 00507 * Redistribution and use in source and binary forms, with or without 00508 * modification, are permitted provided that the following conditions 00509 * are met: 00510 * 00511 * 1. Redistributions of source code must retain the above copyright 00512 * notice, this list of conditions and the following disclaimer. 00513 * 00514 * 2. Redistributions in binary form must reproduce the above copyright 00515 * notice, this list of conditions and the following disclaimer in 00516 * the documentation and/or other materials provided with the 00517 * distribution. 00518 * 00519 * 3. The names "VOCAL", "Vovida Open Communication Application Library", 00520 * and "Vovida Open Communication Application Library (VOCAL)" must 00521 * not be used to endorse or promote products derived from this 00522 * software without prior written permission. For written 00523 * permission, please contact vocal@vovida.org. 00524 * 00525 * 4. Products derived from this software may not be called "VOCAL", nor 00526 * may "VOCAL" appear in their name, without prior written 00527 * permission of Vovida Networks, Inc. 00528 * 00529 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED 00530 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00531 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND 00532 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA 00533 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES 00534 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, 00535 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00536 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00537 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 00538 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00539 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 00540 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 00541 * DAMAGE. 00542 * 00543 * ==================================================================== 00544 * 00545 * This software consists of voluntary contributions made by Vovida 00546 * Networks, Inc. and many individuals on behalf of Vovida Networks, 00547 * Inc. For more information on Vovida Networks, Inc., please see 00548 * <http://www.vovida.org/>. 00549 * 00550 */
1.7.5.1