reSIProcate/stack  9694
NameAddr.cxx
Go to the documentation of this file.
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  */