📄 uri.cxx
字号:
while(a != unA.end() && b != unB.end())
{
if (orderUnknown(*a, *b))
{
++a;
}
else if (orderUnknown(*b, *a))
{
++b;
}
else
{
if (!isEqualNoCase(dynamic_cast<UnknownParameter*>(*a)->value(),
dynamic_cast<UnknownParameter*>(*b)->value()))
{
return false;
}
++a;
++b;
}
}
return true;
}
bool
Uri::operator!=(const Uri& other) const
{
return !(*this == other);
}
bool
Uri::operator<(const Uri& other) const
{
other.checkParsed();
checkParsed();
if (mUser < other.mUser)
{
return true;
}
if (mUser > other.mUser)
{
return false;
}
if (mUserParameters < other.mUserParameters)
{
return true;
}
if (mUserParameters > other.mUserParameters)
{
return false;
}
if (mHost < other.mHost)
{
return true;
}
if (mHost > other.mHost)
{
return false;
}
return mPort < other.mPort;
}
bool
Uri::GreaterQ::operator()(const Uri& lhs, const Uri& rhs) const
{
if (lhs.exists(p_q) && rhs.exists(p_q))
{
return lhs.param(p_q) > rhs.param(p_q);
}
if (lhs.exists(p_q))
{
return lhs.param(p_q) > 1000; // > 1.0
}
if (rhs.exists(p_q))
{
return rhs.param(p_q) < 1000; // < 1.0
}
return false;
}
const Data
Uri::getAorNoPort() const
{
// CJ - TODO - check this in inline with the getAor code (see v6 stuff)
checkParsed();
getAor();
Data aor;
aor.reserve(mUser.size() + mCanonicalHost.size() + 2 /* for @ */ );
if (mUser.empty())
{
aor += mCanonicalHost;
}
else
{
aor += mUser;
if (!mCanonicalHost.empty())
{
aor += Symbols::AT_SIGN;
aor += mCanonicalHost;
}
}
return aor;
}
const Data&
Uri::getAor() const
{
checkParsed();
// did anything change?
if (mOldUser != mUser ||
mOldHost != mHost ||
mOldPort != mPort)
{
mOldHost = mHost;
// canonicalize host
if (DnsUtil::isIpV6Address(mOldHost))
{
mCanonicalHost = DnsUtil::canonicalizeIpV6Address(mHost);
}
else
{
mCanonicalHost = mHost;
mCanonicalHost.lowercase();
}
mOldUser = mUser;
mOldPort = mPort;
mAor.clear();
// @:10000
mAor.reserve(mUser.size() + mCanonicalHost.size() + 10);
if (mOldUser.empty())
{
mAor += mCanonicalHost;
}
else
{
mAor += mOldUser;
if (!mCanonicalHost.empty())
{
mAor += Symbols::AT_SIGN;
mAor += mCanonicalHost;
}
}
if (mPort != 0)
{
mAor += Symbols::COLON;
mAor += Data(mPort);
}
}
return mAor;
}
Uri
Uri::getAorAsUri() const
{
//.dcm. -- tel conversion?
checkParsed();
Uri ret;
ret.scheme() = mScheme;
ret.user() = mUser;
ret.host() = mHost;
ret.port() = mPort;
return ret;
}
void
Uri::parse(ParseBuffer& pb)
{
pb.skipWhitespace();
const char* start = pb.position();
pb.skipToOneOf(":@"); // make sure the colon precedes
pb.assertNotEof();
pb.data(mScheme, start);
pb.skipChar(Symbols::COLON[0]);
mScheme.lowercase();
if (isEqualNoCase(mScheme, Symbols::Tel))
{
const char* anchor = pb.position();
pb.skipToOneOf(ParseBuffer::Whitespace, ";>");
pb.data(mUser, anchor);
if (!pb.eof() && *pb.position() == Symbols::SEMI_COLON[0])
{
anchor = pb.skipChar();
pb.skipToOneOf(ParseBuffer::Whitespace, Symbols::RA_QUOTE);
pb.data(mUserParameters, anchor);
}
return;
}
start = pb.position();
pb.skipToChar(Symbols::AT_SIGN[0]);
if (!pb.eof())
{
pb.reset(start);
start = pb.position();
pb.skipToOneOf(":@");
#ifdef HANDLE_CHARACTER_ESCAPING
pb.dataUnescaped(mUser, start);
#else
pb.data(mUser, start);
#endif
if (!pb.eof() && *pb.position() == Symbols::COLON[0])
{
start = pb.skipChar();
pb.skipToChar(Symbols::AT_SIGN[0]);
#ifdef HANDLE_CHARACTER_ESCAPING
pb.dataUnescaped(mPassword, start);
#else
pb.data(mPassword, start);
#endif
}
start = pb.skipChar();
}
else
{
pb.reset(start);
}
if (*start == '[')
{
start = pb.skipChar();
pb.skipToChar(']');
pb.data(mHost, start);
if(DnsUtil::isIpV6Address(mHost))
{
DnsUtil::canonicalizeIpV6Address(mHost);
}
else
{
// !bwc! Should the parse fail here, or do we just shrug it off?
}
pb.skipChar();
}
else
{
pb.skipToOneOf(ParseBuffer::Whitespace, ":;?>");
pb.data(mHost, start);
}
pb.skipToOneOf(ParseBuffer::Whitespace, ":;?>");
if (!pb.eof() && *pb.position() == ':')
{
start = pb.skipChar();
mPort = pb.integer();
pb.skipToOneOf(ParseBuffer::Whitespace, ";?>");
}
else
{
mPort = 0;
}
parseParameters(pb);
if (!pb.eof() && *pb.position() == Symbols::QUESTION[0])
{
const char* anchor = pb.position();
pb.skipToOneOf(Symbols::RA_QUOTE, Symbols::SEMI_COLON);
pb.data(mEmbeddedHeadersText, anchor);
}
}
ParserCategory*
Uri::clone() const
{
return new Uri(*this);
}
void Uri::setUriUserEncoding(char c, bool encode)
{
if(c < 0)
{
ErrLog(<< "unable to change encoding for character '" << c << "', table size = " << URI_ENCODING_TABLE_SIZE);
return;
}
mUriEncodingUserTable[c] = encode;
}
void Uri::setUriPasswordEncoding(char c, bool encode)
{
if(c < 0)
{
ErrLog(<< "unable to change encoding for character '" << c << "', table size = " << URI_ENCODING_TABLE_SIZE);
return;
}
mUriEncodingPasswordTable[c] = encode;
}
void Uri::initialiseEncodingTables() {
// set all bits
mUriEncodingUserTable.set();
mUriEncodingPasswordTable.set();
for(Data::size_type i = 0; i < mUriNonEncodingUserChars.size(); i++)
{
char& c = mUriNonEncodingUserChars.at(i);
if(c >= 0)
{
mUriEncodingUserTable[c] = false;
}
}
for(Data::size_type i = 0; i < mUriNonEncodingPasswordChars.size(); i++)
{
char& c = mUriNonEncodingPasswordChars.at(i);
if(c >= 0)
{
mUriEncodingPasswordTable[c] = false;
}
}
mEncodingReady = true;
}
inline bool
Uri::shouldEscapeUserChar(char c)
{
if(!mEncodingReady)
{
initialiseEncodingTables();
}
if(c < 0)
{
return false;
}
return mUriEncodingUserTable[c];
}
inline bool
Uri::shouldEscapePasswordChar(char c)
{
if(!mEncodingReady)
{
initialiseEncodingTables();
}
if(c < 0)
{
return false;
}
return mUriEncodingPasswordTable[c];
}
// should not encode user parameters unless its a tel?
std::ostream&
Uri::encodeParsed(std::ostream& str) const
{
str << mScheme << Symbols::COLON;
if (!mUser.empty())
{
#ifdef HANDLE_CHARACTER_ESCAPING
mUser.escapeToStream(str, shouldEscapeUserChar);
#else
str << mUser;
#endif
if (!mUserParameters.empty())
{
str << Symbols::SEMI_COLON[0] << mUserParameters;
}
if (!mPassword.empty())
{
str << Symbols::COLON;
#ifdef HANDLE_CHARACTER_ESCAPING
mPassword.escapeToStream(str, shouldEscapePasswordChar);
#else
str << mPassword;
#endif
}
}
if (!mHost.empty())
{
if (!mUser.empty())
{
str << Symbols::AT_SIGN;
}
if (DnsUtil::isIpV6Address(mHost))
{
str << '[' << mHost << ']';
}
else
{
str << mHost;
}
}
if (mPort != 0)
{
str << Symbols::COLON << mPort;
}
encodeParameters(str);
encodeEmbeddedHeaders(str);
return str;
}
SipMessage&
Uri::embedded()
{
checkParsed();
if (mEmbeddedHeaders == 0)
{
this->mEmbeddedHeaders = new SipMessage();
if (!mEmbeddedHeadersText.empty())
{
ParseBuffer pb(mEmbeddedHeadersText.data(), mEmbeddedHeadersText.size());
this->parseEmbeddedHeaders(pb);
}
}
return *mEmbeddedHeaders;
}
const SipMessage&
Uri::embedded() const
{
Uri* ncthis = const_cast<Uri*>(this);
return ncthis->embedded();
}
void
Uri::parseEmbeddedHeaders(ParseBuffer& pb)
{
DebugLog(<< "Uri::parseEmbeddedHeaders");
if (!pb.eof() && *pb.position() == Symbols::QUESTION[0])
{
pb.skipChar();
}
const char* anchor;
Data headerName;
Data headerContents;
bool first = true;
while (!pb.eof())
{
if (first)
{
first = false;
}
else
{
pb.skipChar(Symbols::AMPERSAND[0]);
}
anchor = pb.position();
pb.skipToChar(Symbols::EQUALS[0]);
pb.data(headerName, anchor);
// .dlb. in theory, need to decode header name
anchor = pb.skipChar(Symbols::EQUALS[0]);
pb.skipToChar(Symbols::AMPERSAND[0]);
pb.data(headerContents, anchor);
unsigned int len;
char* decodedContents = Embedded::decode(headerContents, len);
mEmbeddedHeaders->addBuffer(decodedContents);
static const Data body("Body");
if (isEqualNoCase(body, headerName))
{
mEmbeddedHeaders->setBody(decodedContents, len);
}
else
{
DebugLog(<< "Uri::parseEmbeddedHeaders(" << headerName << ", " << Data(decodedContents, len) << ")");
mEmbeddedHeaders->addHeader(Headers::getType(headerName.data(), headerName.size()),
headerName.data(), headerName.size(),
decodedContents, len);
}
}
}
std::ostream&
Uri::encodeEmbeddedHeaders(std::ostream& str) const
{
if (mEmbeddedHeaders)
{
mEmbeddedHeaders->encodeEmbedded(str);
}
else
{
// never decoded
str << mEmbeddedHeadersText;
}
return str;
}
HashValueImp(resip::Uri, resip::Data::from(data).hash());
/* ====================================================================
* The Vovida Software License, Version 1.0
*
* Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The names "VOCAL", "Vovida Open Communication Application Library",
* and "Vovida Open Communication Application Library (VOCAL)" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact vocal@vovida.org.
*
* 4. Products derived from this software may not be called "VOCAL", nor
* may "VOCAL" appear in their name, without prior written
* permission of Vovida Networks, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
* NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
* IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* ====================================================================
*
* This software consists of voluntary contributions made by Vovida
* Networks, Inc. and many individuals on behalf of Vovida Networks,
* Inc. For more information on Vovida Networks, Inc., please see
* <http://www.vovida.org/>.
*
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -