Moved header classes and some utilities from SIP to MIME. Updated SIP module and library to reflect the changes.
git-svn-id: http://voip.null.ro/svn/yate@1599 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
parent
836471ed6e
commit
648b9c82b1
269
engine/Mime.cpp
269
engine/Mime.cpp
|
@ -30,10 +30,277 @@ static bool isContinuationBlank(char c)
|
||||||
return ((c == ' ') || (c == '\t'));
|
return ((c == ' ') || (c == '\t'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MimeHeaderLine
|
||||||
|
*/
|
||||||
|
MimeHeaderLine::MimeHeaderLine(const char* name, const String& value, char sep)
|
||||||
|
: NamedString(name), m_separator(sep ? sep : ';')
|
||||||
|
{
|
||||||
|
if (value.null())
|
||||||
|
return;
|
||||||
|
XDebug(DebugAll,"MimeHeaderLine::MimeHeaderLine('%s','%s') [%p]",name,value.c_str(),this);
|
||||||
|
int sp = findSep(value,m_separator);
|
||||||
|
if (sp < 0) {
|
||||||
|
assign(value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
assign(value,sp);
|
||||||
|
trimBlanks();
|
||||||
|
while (sp < (int)value.length()) {
|
||||||
|
int ep = findSep(value,m_separator,sp+1);
|
||||||
|
if (ep <= sp)
|
||||||
|
ep = value.length();
|
||||||
|
int eq = value.find('=',sp+1);
|
||||||
|
if ((eq > 0) && (eq < ep)) {
|
||||||
|
String pname(value.substr(sp+1,eq-sp-1));
|
||||||
|
String pvalue(value.substr(eq+1,ep-eq-1));
|
||||||
|
pname.trimBlanks();
|
||||||
|
pvalue.trimBlanks();
|
||||||
|
if (!pname.null()) {
|
||||||
|
XDebug(DebugAll,"hdr param name='%s' value='%s'",pname.c_str(),pvalue.c_str());
|
||||||
|
m_params.append(new NamedString(pname,pvalue));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
String pname(value.substr(sp+1,ep-sp-1));
|
||||||
|
pname.trimBlanks();
|
||||||
|
if (!pname.null()) {
|
||||||
|
XDebug(DebugAll,"hdr param name='%s' (no value)",pname.c_str());
|
||||||
|
m_params.append(new NamedString(pname));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sp = ep;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MimeHeaderLine::MimeHeaderLine(const MimeHeaderLine& original, const char* newName)
|
||||||
|
: NamedString(newName ? newName : original.name().c_str(),original),
|
||||||
|
m_separator(original.separator())
|
||||||
|
{
|
||||||
|
XDebug(DebugAll,"MimeHeaderLine::MimeHeaderLine(%p '%s') [%p]",&original,name().c_str(),this);
|
||||||
|
const ObjList* l = &original.params();
|
||||||
|
for (; l; l = l->next()) {
|
||||||
|
const NamedString* t = static_cast<const NamedString*>(l->get());
|
||||||
|
if (t)
|
||||||
|
m_params.append(new NamedString(t->name(),*t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MimeHeaderLine::~MimeHeaderLine()
|
||||||
|
{
|
||||||
|
XDebug(DebugAll,"MimeHeaderLine::~MimeHeaderLine() [%p]",this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* MimeHeaderLine::getObject(const String& name) const
|
||||||
|
{
|
||||||
|
if (name == "MimeHeaderLine")
|
||||||
|
return const_cast<MimeHeaderLine*>(this);
|
||||||
|
return NamedString::getObject(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
MimeHeaderLine* MimeHeaderLine::clone(const char* newName) const
|
||||||
|
{
|
||||||
|
return new MimeHeaderLine(*this,newName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MimeHeaderLine::buildLine(String& line) const
|
||||||
|
{
|
||||||
|
line << name() << ": " << *this;
|
||||||
|
const ObjList* p = &m_params;
|
||||||
|
for (; p; p = p->next()) {
|
||||||
|
NamedString* s = static_cast<NamedString*>(p->get());
|
||||||
|
if (s) {
|
||||||
|
line << separator() << s->name();
|
||||||
|
if (!s->null())
|
||||||
|
line << "=" << *s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const NamedString* MimeHeaderLine::getParam(const char* name) const
|
||||||
|
{
|
||||||
|
if (!(name && *name))
|
||||||
|
return 0;
|
||||||
|
const ObjList* l = &m_params;
|
||||||
|
for (; l; l = l->next()) {
|
||||||
|
const NamedString* t = static_cast<const NamedString*>(l->get());
|
||||||
|
if (t && (t->name() &= name))
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MimeHeaderLine::setParam(const char* name, const char* value)
|
||||||
|
{
|
||||||
|
ObjList* p = m_params.find(name);
|
||||||
|
if (p)
|
||||||
|
*static_cast<NamedString*>(p->get()) = value;
|
||||||
|
else
|
||||||
|
m_params.append(new NamedString(name,value));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MimeHeaderLine::delParam(const char* name)
|
||||||
|
{
|
||||||
|
ObjList* p = m_params.find(name);
|
||||||
|
if (p)
|
||||||
|
p->remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Utility function, puts quotes around a string
|
||||||
|
void MimeHeaderLine::addQuotes(String& str)
|
||||||
|
{
|
||||||
|
str.trimBlanks();
|
||||||
|
int l = str.length();
|
||||||
|
if ((l < 2) || (str[0] != '"') || (str[l-1] != '"'))
|
||||||
|
str = "\"" + str + "\"";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Utility function, removes quotes around a string
|
||||||
|
void MimeHeaderLine::delQuotes(String& str)
|
||||||
|
{
|
||||||
|
str.trimBlanks();
|
||||||
|
int l = str.length();
|
||||||
|
if ((l >= 2) && (str[0] == '"') && (str[l-1] == '"')) {
|
||||||
|
str = str.substr(1,l-2);
|
||||||
|
str.trimBlanks();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Utility function, puts quotes around a string
|
||||||
|
String MimeHeaderLine::quote(const String& str)
|
||||||
|
{
|
||||||
|
String tmp(str);
|
||||||
|
addQuotes(tmp);
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Utility function to find a separator not in "quotes" or inside <uri>
|
||||||
|
int MimeHeaderLine::findSep(const char* str, char sep, int offs)
|
||||||
|
{
|
||||||
|
if (!(str && sep))
|
||||||
|
return -1;
|
||||||
|
str += offs;
|
||||||
|
bool inQ = false;
|
||||||
|
bool inU = false;
|
||||||
|
char c;
|
||||||
|
for (; (c = *str++) ; offs++) {
|
||||||
|
if (inQ) {
|
||||||
|
if (c == '"')
|
||||||
|
inQ = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (inU) {
|
||||||
|
if (c == '>')
|
||||||
|
inU = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (c == sep)
|
||||||
|
return offs;
|
||||||
|
switch (c) {
|
||||||
|
case '"':
|
||||||
|
inQ = true;
|
||||||
|
break;
|
||||||
|
case '<':
|
||||||
|
inU = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MimeAuthLine
|
||||||
|
*/
|
||||||
|
MimeAuthLine::MimeAuthLine(const char* name, const String& value)
|
||||||
|
: MimeHeaderLine(name,String::empty(),',')
|
||||||
|
{
|
||||||
|
XDebug(DebugAll,"MimeAuthLine::MimeAuthLine('%s','%s') [%p]",name,value.c_str(),this);
|
||||||
|
if (value.null())
|
||||||
|
return;
|
||||||
|
int sp = value.find(' ');
|
||||||
|
if (sp < 0) {
|
||||||
|
assign(value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
assign(value,sp);
|
||||||
|
trimBlanks();
|
||||||
|
while (sp < (int)value.length()) {
|
||||||
|
int ep = value.find(m_separator,sp+1);
|
||||||
|
int quot = value.find('"',sp+1);
|
||||||
|
if ((quot > sp) && (quot < ep)) {
|
||||||
|
quot = value.find('"',quot+1);
|
||||||
|
if (quot > sp)
|
||||||
|
ep = value.find(m_separator,quot+1);
|
||||||
|
}
|
||||||
|
if (ep <= sp)
|
||||||
|
ep = value.length();
|
||||||
|
int eq = value.find('=',sp+1);
|
||||||
|
if ((eq > 0) && (eq < ep)) {
|
||||||
|
String pname(value.substr(sp+1,eq-sp-1));
|
||||||
|
String pvalue(value.substr(eq+1,ep-eq-1));
|
||||||
|
pname.trimBlanks();
|
||||||
|
pvalue.trimBlanks();
|
||||||
|
if (!pname.null()) {
|
||||||
|
XDebug(DebugAll,"auth param name='%s' value='%s'",pname.c_str(),pvalue.c_str());
|
||||||
|
m_params.append(new NamedString(pname,pvalue));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
String pname(value.substr(sp+1,ep-sp-1));
|
||||||
|
pname.trimBlanks();
|
||||||
|
if (!pname.null()) {
|
||||||
|
XDebug(DebugAll,"auth param name='%s' (no value)",pname.c_str());
|
||||||
|
m_params.append(new NamedString(pname));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sp = ep;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MimeAuthLine::MimeAuthLine(const MimeAuthLine& original, const char* newName)
|
||||||
|
: MimeHeaderLine(original,newName)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void* MimeAuthLine::getObject(const String& name) const
|
||||||
|
{
|
||||||
|
if (name == "MimeAuthLine")
|
||||||
|
return const_cast<MimeAuthLine*>(this);
|
||||||
|
return MimeHeaderLine::getObject(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
MimeHeaderLine* MimeAuthLine::clone(const char* newName) const
|
||||||
|
{
|
||||||
|
return new MimeAuthLine(*this,newName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MimeAuthLine::buildLine(String& line) const
|
||||||
|
{
|
||||||
|
line << name() << ": " << *this;
|
||||||
|
const ObjList* p = &m_params;
|
||||||
|
for (bool first = true; p; p = p->next()) {
|
||||||
|
NamedString* s = static_cast<NamedString*>(p->get());
|
||||||
|
if (s) {
|
||||||
|
if (first)
|
||||||
|
first = false;
|
||||||
|
else
|
||||||
|
line << separator();
|
||||||
|
line << " " << s->name();
|
||||||
|
if (!s->null())
|
||||||
|
line << "=" << *s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MimeBody
|
||||||
|
*/
|
||||||
YCLASSIMP(MimeBody,GenObject)
|
YCLASSIMP(MimeBody,GenObject)
|
||||||
|
|
||||||
MimeBody::MimeBody(const String& type)
|
MimeBody::MimeBody(const String& type)
|
||||||
: m_type(type)
|
: m_type("Content-Type",type)
|
||||||
{
|
{
|
||||||
DDebug(DebugAll,"MimeBody::MimeBody('%s') [%p]",m_type.c_str(),this);
|
DDebug(DebugAll,"MimeBody::MimeBody('%s') [%p]",m_type.c_str(),this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -192,7 +192,7 @@ SIPTransaction* SIPEngine::addMessage(SIPMessage* message)
|
||||||
if (message->isOutgoing())
|
if (message->isOutgoing())
|
||||||
message->complete(this);
|
message->complete(this);
|
||||||
// locate the branch parameter of last Via header - added by the UA
|
// locate the branch parameter of last Via header - added by the UA
|
||||||
const SIPHeaderLine* hl = message->getLastHeader("Via");
|
const MimeHeaderLine* hl = message->getLastHeader("Via");
|
||||||
if (!hl)
|
if (!hl)
|
||||||
#ifdef SIP_STRICT
|
#ifdef SIP_STRICT
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -465,10 +465,10 @@ int SIPEngine::authUser(const SIPMessage* message, String& user, bool proxy, Gen
|
||||||
const ObjList* l = &message->header;
|
const ObjList* l = &message->header;
|
||||||
for (; l; l = l->next()) {
|
for (; l; l = l->next()) {
|
||||||
const GenObject* o = l->get();
|
const GenObject* o = l->get();
|
||||||
const SIPHeaderLine* t = o ? static_cast<const SIPHeaderLine*>(o->getObject("SIPHeaderLine")) : 0;
|
const MimeHeaderLine* t = o ? static_cast<const MimeHeaderLine*>(o->getObject("MimeHeaderLine")) : 0;
|
||||||
if (t && (t->name() &= hdr) && (*t &= "Digest")) {
|
if (t && (t->name() &= hdr) && (*t &= "Digest")) {
|
||||||
String usr(t->getParam("username"));
|
String usr(t->getParam("username"));
|
||||||
delQuotes(usr);
|
MimeHeaderLine::delQuotes(usr);
|
||||||
if (usr.null())
|
if (usr.null())
|
||||||
continue;
|
continue;
|
||||||
XDebug(this,DebugAll,"authUser found user '%s'",usr.c_str());
|
XDebug(this,DebugAll,"authUser found user '%s'",usr.c_str());
|
||||||
|
@ -476,7 +476,7 @@ int SIPEngine::authUser(const SIPMessage* message, String& user, bool proxy, Gen
|
||||||
if (user && (usr != user))
|
if (user && (usr != user))
|
||||||
continue;
|
continue;
|
||||||
String nonce(t->getParam("nonce"));
|
String nonce(t->getParam("nonce"));
|
||||||
delQuotes(nonce);
|
MimeHeaderLine::delQuotes(nonce);
|
||||||
// TODO: implement a nonce cache for the stupid clients that don't send it back
|
// TODO: implement a nonce cache for the stupid clients that don't send it back
|
||||||
if (nonce.null())
|
if (nonce.null())
|
||||||
continue;
|
continue;
|
||||||
|
@ -487,15 +487,15 @@ int SIPEngine::authUser(const SIPMessage* message, String& user, bool proxy, Gen
|
||||||
noUser = false;
|
noUser = false;
|
||||||
XDebug(this,DebugAll,"authUser nonce age is %ld",age);
|
XDebug(this,DebugAll,"authUser nonce age is %ld",age);
|
||||||
String res(t->getParam("response"));
|
String res(t->getParam("response"));
|
||||||
delQuotes(res);
|
MimeHeaderLine::delQuotes(res);
|
||||||
if (res.null())
|
if (res.null())
|
||||||
continue;
|
continue;
|
||||||
String uri(t->getParam("uri"));
|
String uri(t->getParam("uri"));
|
||||||
delQuotes(uri);
|
MimeHeaderLine::delQuotes(uri);
|
||||||
if (uri.null())
|
if (uri.null())
|
||||||
uri = message->uri;
|
uri = message->uri;
|
||||||
String realm(t->getParam("realm"));
|
String realm(t->getParam("realm"));
|
||||||
delQuotes(realm);
|
MimeHeaderLine::delQuotes(realm);
|
||||||
|
|
||||||
if (!checkUser(usr,realm,nonce,message->method,uri,res,message,userData))
|
if (!checkUser(usr,realm,nonce,message->method,uri,res,message,userData))
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -30,200 +30,6 @@
|
||||||
|
|
||||||
using namespace TelEngine;
|
using namespace TelEngine;
|
||||||
|
|
||||||
SIPHeaderLine::SIPHeaderLine(const char* name, const String& value, char sep)
|
|
||||||
: NamedString(name), m_separator(sep ? sep : ';')
|
|
||||||
{
|
|
||||||
if (value.null())
|
|
||||||
return;
|
|
||||||
XDebug(DebugAll,"SIPHeaderLine::SIPHeaderLine('%s','%s') [%p]",name,value.c_str(),this);
|
|
||||||
int sp = findSep(value,m_separator);
|
|
||||||
if (sp < 0) {
|
|
||||||
assign(value);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
assign(value,sp);
|
|
||||||
trimBlanks();
|
|
||||||
while (sp < (int)value.length()) {
|
|
||||||
int ep = findSep(value,m_separator,sp+1);
|
|
||||||
if (ep <= sp)
|
|
||||||
ep = value.length();
|
|
||||||
int eq = value.find('=',sp+1);
|
|
||||||
if ((eq > 0) && (eq < ep)) {
|
|
||||||
String pname(value.substr(sp+1,eq-sp-1));
|
|
||||||
String pvalue(value.substr(eq+1,ep-eq-1));
|
|
||||||
pname.trimBlanks();
|
|
||||||
pvalue.trimBlanks();
|
|
||||||
if (!pname.null()) {
|
|
||||||
XDebug(DebugAll,"hdr param name='%s' value='%s'",pname.c_str(),pvalue.c_str());
|
|
||||||
m_params.append(new NamedString(pname,pvalue));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
String pname(value.substr(sp+1,ep-sp-1));
|
|
||||||
pname.trimBlanks();
|
|
||||||
if (!pname.null()) {
|
|
||||||
XDebug(DebugAll,"hdr param name='%s' (no value)",pname.c_str());
|
|
||||||
m_params.append(new NamedString(pname));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sp = ep;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SIPHeaderLine::SIPHeaderLine(const SIPHeaderLine& original, const char* newName)
|
|
||||||
: NamedString(newName ? newName : original.name().c_str(),original),
|
|
||||||
m_separator(original.separator())
|
|
||||||
{
|
|
||||||
XDebug(DebugAll,"SIPHeaderLine::SIPHeaderLine(%p '%s') [%p]",&original,name().c_str(),this);
|
|
||||||
const ObjList* l = &original.params();
|
|
||||||
for (; l; l = l->next()) {
|
|
||||||
const NamedString* t = static_cast<const NamedString*>(l->get());
|
|
||||||
if (t)
|
|
||||||
m_params.append(new NamedString(t->name(),*t));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SIPHeaderLine::~SIPHeaderLine()
|
|
||||||
{
|
|
||||||
XDebug(DebugAll,"SIPHeaderLine::~SIPHeaderLine() [%p]",this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void* SIPHeaderLine::getObject(const String& name) const
|
|
||||||
{
|
|
||||||
if (name == "SIPHeaderLine")
|
|
||||||
return const_cast<SIPHeaderLine*>(this);
|
|
||||||
return NamedString::getObject(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
SIPHeaderLine* SIPHeaderLine::clone(const char* newName) const
|
|
||||||
{
|
|
||||||
return new SIPHeaderLine(*this,newName);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SIPHeaderLine::buildLine(String& line) const
|
|
||||||
{
|
|
||||||
line << name() << ": " << *this;
|
|
||||||
const ObjList* p = &m_params;
|
|
||||||
for (; p; p = p->next()) {
|
|
||||||
NamedString* s = static_cast<NamedString*>(p->get());
|
|
||||||
if (s) {
|
|
||||||
line << separator() << s->name();
|
|
||||||
if (!s->null())
|
|
||||||
line << "=" << *s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const NamedString* SIPHeaderLine::getParam(const char* name) const
|
|
||||||
{
|
|
||||||
if (!(name && *name))
|
|
||||||
return 0;
|
|
||||||
const ObjList* l = &m_params;
|
|
||||||
for (; l; l = l->next()) {
|
|
||||||
const NamedString* t = static_cast<const NamedString*>(l->get());
|
|
||||||
if (t && (t->name() &= name))
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SIPHeaderLine::setParam(const char* name, const char* value)
|
|
||||||
{
|
|
||||||
ObjList* p = m_params.find(name);
|
|
||||||
if (p)
|
|
||||||
*static_cast<NamedString*>(p->get()) = value;
|
|
||||||
else
|
|
||||||
m_params.append(new NamedString(name,value));
|
|
||||||
}
|
|
||||||
|
|
||||||
void SIPHeaderLine::delParam(const char* name)
|
|
||||||
{
|
|
||||||
ObjList* p = m_params.find(name);
|
|
||||||
if (p)
|
|
||||||
p->remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
SIPAuthLine::SIPAuthLine(const char* name, const String& value)
|
|
||||||
: SIPHeaderLine(name,String::empty(),',')
|
|
||||||
{
|
|
||||||
XDebug(DebugAll,"SIPAuthLine::SIPAuthLine('%s','%s') [%p]",name,value.c_str(),this);
|
|
||||||
if (value.null())
|
|
||||||
return;
|
|
||||||
int sp = value.find(' ');
|
|
||||||
if (sp < 0) {
|
|
||||||
assign(value);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
assign(value,sp);
|
|
||||||
trimBlanks();
|
|
||||||
while (sp < (int)value.length()) {
|
|
||||||
int ep = value.find(m_separator,sp+1);
|
|
||||||
int quot = value.find('"',sp+1);
|
|
||||||
if ((quot > sp) && (quot < ep)) {
|
|
||||||
quot = value.find('"',quot+1);
|
|
||||||
if (quot > sp)
|
|
||||||
ep = value.find(m_separator,quot+1);
|
|
||||||
}
|
|
||||||
if (ep <= sp)
|
|
||||||
ep = value.length();
|
|
||||||
int eq = value.find('=',sp+1);
|
|
||||||
if ((eq > 0) && (eq < ep)) {
|
|
||||||
String pname(value.substr(sp+1,eq-sp-1));
|
|
||||||
String pvalue(value.substr(eq+1,ep-eq-1));
|
|
||||||
pname.trimBlanks();
|
|
||||||
pvalue.trimBlanks();
|
|
||||||
if (!pname.null()) {
|
|
||||||
XDebug(DebugAll,"auth param name='%s' value='%s'",pname.c_str(),pvalue.c_str());
|
|
||||||
m_params.append(new NamedString(pname,pvalue));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
String pname(value.substr(sp+1,ep-sp-1));
|
|
||||||
pname.trimBlanks();
|
|
||||||
if (!pname.null()) {
|
|
||||||
XDebug(DebugAll,"auth param name='%s' (no value)",pname.c_str());
|
|
||||||
m_params.append(new NamedString(pname));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sp = ep;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SIPAuthLine::SIPAuthLine(const SIPAuthLine& original, const char* newName)
|
|
||||||
: SIPHeaderLine(original,newName)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void* SIPAuthLine::getObject(const String& name) const
|
|
||||||
{
|
|
||||||
if (name == "SIPAuthLine")
|
|
||||||
return const_cast<SIPAuthLine*>(this);
|
|
||||||
return SIPHeaderLine::getObject(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
SIPHeaderLine* SIPAuthLine::clone(const char* newName) const
|
|
||||||
{
|
|
||||||
return new SIPAuthLine(*this,newName);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SIPAuthLine::buildLine(String& line) const
|
|
||||||
{
|
|
||||||
line << name() << ": " << *this;
|
|
||||||
const ObjList* p = &m_params;
|
|
||||||
for (bool first = true; p; p = p->next()) {
|
|
||||||
NamedString* s = static_cast<NamedString*>(p->get());
|
|
||||||
if (s) {
|
|
||||||
if (first)
|
|
||||||
first = false;
|
|
||||||
else
|
|
||||||
line << separator();
|
|
||||||
line << " " << s->name();
|
|
||||||
if (!s->null())
|
|
||||||
line << "=" << *s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SIPMessage::SIPMessage(const SIPMessage& original)
|
SIPMessage::SIPMessage(const SIPMessage& original)
|
||||||
: version(original.version), method(original.method), uri(original.uri),
|
: version(original.version), method(original.method), uri(original.uri),
|
||||||
code(original.code), reason(original.reason),
|
code(original.code), reason(original.reason),
|
||||||
|
@ -240,13 +46,13 @@ SIPMessage::SIPMessage(const SIPMessage& original)
|
||||||
bool via1 = true;
|
bool via1 = true;
|
||||||
const ObjList* l = &original.header;
|
const ObjList* l = &original.header;
|
||||||
for (; l; l = l->next()) {
|
for (; l; l = l->next()) {
|
||||||
const SIPHeaderLine* hl = static_cast<SIPHeaderLine*>(l->get());
|
const MimeHeaderLine* hl = static_cast<MimeHeaderLine*>(l->get());
|
||||||
if (!hl)
|
if (!hl)
|
||||||
continue;
|
continue;
|
||||||
// CSeq must not be copied, a new one will be built by complete()
|
// CSeq must not be copied, a new one will be built by complete()
|
||||||
if (hl->name() &= "CSeq")
|
if (hl->name() &= "CSeq")
|
||||||
continue;
|
continue;
|
||||||
SIPHeaderLine* nl = hl->clone();
|
MimeHeaderLine* nl = hl->clone();
|
||||||
// this is a new transaction so let complete() add randomness
|
// this is a new transaction so let complete() add randomness
|
||||||
if (via1 && (nl->name() &= "Via")) {
|
if (via1 && (nl->name() &= "Via")) {
|
||||||
via1 = false;
|
via1 = false;
|
||||||
|
@ -323,19 +129,19 @@ SIPMessage::SIPMessage(const SIPMessage* original, const SIPMessage* answer)
|
||||||
version = original->version;
|
version = original->version;
|
||||||
uri = original->uri;
|
uri = original->uri;
|
||||||
copyAllHeaders(original,"Via");
|
copyAllHeaders(original,"Via");
|
||||||
SIPHeaderLine* hl = const_cast<SIPHeaderLine*>(getHeader("Via"));
|
MimeHeaderLine* hl = const_cast<MimeHeaderLine*>(getHeader("Via"));
|
||||||
if (!hl) {
|
if (!hl) {
|
||||||
String tmp;
|
String tmp;
|
||||||
tmp << version << "/" << getParty()->getProtoName();
|
tmp << version << "/" << getParty()->getProtoName();
|
||||||
tmp << " " << getParty()->getLocalAddr() << ":" << getParty()->getLocalPort();
|
tmp << " " << getParty()->getLocalAddr() << ":" << getParty()->getLocalPort();
|
||||||
hl = new SIPHeaderLine("Via",tmp);
|
hl = new MimeHeaderLine("Via",tmp);
|
||||||
header.append(hl);
|
header.append(hl);
|
||||||
}
|
}
|
||||||
if (answer && (answer->code == 200) && (original->method &= "INVITE")) {
|
if (answer && (answer->code == 200) && (original->method &= "INVITE")) {
|
||||||
String tmp("z9hG4bK");
|
String tmp("z9hG4bK");
|
||||||
tmp << (int)::random();
|
tmp << (int)::random();
|
||||||
hl->setParam("branch",tmp);
|
hl->setParam("branch",tmp);
|
||||||
const SIPHeaderLine* co = answer->getHeader("Contact");
|
const MimeHeaderLine* co = answer->getHeader("Contact");
|
||||||
if (co) {
|
if (co) {
|
||||||
uri = *co;
|
uri = *co;
|
||||||
Regexp r("^[^<]*<\\([^>]*\\)>.*$");
|
Regexp r("^[^<]*<\\([^>]*\\)>.*$");
|
||||||
|
@ -397,7 +203,7 @@ void SIPMessage::complete(SIPEngine* engine, const char* user, const char* domai
|
||||||
|
|
||||||
// only set the dialog tag on ACK
|
// only set the dialog tag on ACK
|
||||||
if (isACK()) {
|
if (isACK()) {
|
||||||
SIPHeaderLine* hl = const_cast<SIPHeaderLine*>(getHeader("To"));
|
MimeHeaderLine* hl = const_cast<MimeHeaderLine*>(getHeader("To"));
|
||||||
if (dlgTag && hl && !hl->getParam("tag"))
|
if (dlgTag && hl && !hl->getParam("tag"))
|
||||||
hl->setParam("tag",dlgTag);
|
hl->setParam("tag",dlgTag);
|
||||||
return;
|
return;
|
||||||
|
@ -406,12 +212,12 @@ void SIPMessage::complete(SIPEngine* engine, const char* user, const char* domai
|
||||||
if (!domain)
|
if (!domain)
|
||||||
domain = getParty()->getLocalAddr();
|
domain = getParty()->getLocalAddr();
|
||||||
|
|
||||||
SIPHeaderLine* hl = const_cast<SIPHeaderLine*>(getHeader("Via"));
|
MimeHeaderLine* hl = const_cast<MimeHeaderLine*>(getHeader("Via"));
|
||||||
if (!hl) {
|
if (!hl) {
|
||||||
String tmp;
|
String tmp;
|
||||||
tmp << version << "/" << getParty()->getProtoName();
|
tmp << version << "/" << getParty()->getProtoName();
|
||||||
tmp << " " << getParty()->getLocalAddr() << ":" << getParty()->getLocalPort();
|
tmp << " " << getParty()->getLocalAddr() << ":" << getParty()->getLocalPort();
|
||||||
hl = new SIPHeaderLine("Via",tmp);
|
hl = new MimeHeaderLine("Via",tmp);
|
||||||
if (!(isAnswer() || isACK()))
|
if (!(isAnswer() || isACK()))
|
||||||
hl->setParam("rport");
|
hl->setParam("rport");
|
||||||
header.append(hl);
|
header.append(hl);
|
||||||
|
@ -427,24 +233,24 @@ void SIPMessage::complete(SIPEngine* engine, const char* user, const char* domai
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isAnswer()) {
|
if (!isAnswer()) {
|
||||||
hl = const_cast<SIPHeaderLine*>(getHeader("From"));
|
hl = const_cast<MimeHeaderLine*>(getHeader("From"));
|
||||||
if (!hl) {
|
if (!hl) {
|
||||||
String tmp = "<sip:";
|
String tmp = "<sip:";
|
||||||
if (user)
|
if (user)
|
||||||
tmp << user << "@";
|
tmp << user << "@";
|
||||||
tmp << domain << ">";
|
tmp << domain << ">";
|
||||||
hl = new SIPHeaderLine("From",tmp);
|
hl = new MimeHeaderLine("From",tmp);
|
||||||
header.append(hl);
|
header.append(hl);
|
||||||
}
|
}
|
||||||
if (!hl->getParam("tag"))
|
if (!hl->getParam("tag"))
|
||||||
hl->setParam("tag",String((int)::random()));
|
hl->setParam("tag",String((int)::random()));
|
||||||
}
|
}
|
||||||
|
|
||||||
hl = const_cast<SIPHeaderLine*>(getHeader("To"));
|
hl = const_cast<MimeHeaderLine*>(getHeader("To"));
|
||||||
if (!(isAnswer() || hl)) {
|
if (!(isAnswer() || hl)) {
|
||||||
String tmp;
|
String tmp;
|
||||||
tmp << "<" << uri << ">";
|
tmp << "<" << uri << ">";
|
||||||
hl = new SIPHeaderLine("To",tmp);
|
hl = new MimeHeaderLine("To",tmp);
|
||||||
header.append(hl);
|
header.append(hl);
|
||||||
}
|
}
|
||||||
if (hl && dlgTag && !hl->getParam("tag"))
|
if (hl && dlgTag && !hl->getParam("tag"))
|
||||||
|
@ -499,7 +305,7 @@ void SIPMessage::complete(SIPEngine* engine, const char* user, const char* domai
|
||||||
|
|
||||||
bool SIPMessage::copyHeader(const SIPMessage* message, const char* name, const char* newName)
|
bool SIPMessage::copyHeader(const SIPMessage* message, const char* name, const char* newName)
|
||||||
{
|
{
|
||||||
const SIPHeaderLine* hl = message ? message->getHeader(name) : 0;
|
const MimeHeaderLine* hl = message ? message->getHeader(name) : 0;
|
||||||
if (hl) {
|
if (hl) {
|
||||||
header.append(hl->clone(newName));
|
header.append(hl->clone(newName));
|
||||||
return true;
|
return true;
|
||||||
|
@ -514,7 +320,7 @@ int SIPMessage::copyAllHeaders(const SIPMessage* message, const char* name, cons
|
||||||
int c = 0;
|
int c = 0;
|
||||||
const ObjList* l = &message->header;
|
const ObjList* l = &message->header;
|
||||||
for (; l; l = l->next()) {
|
for (; l; l = l->next()) {
|
||||||
const SIPHeaderLine* hl = static_cast<const SIPHeaderLine*>(l->get());
|
const MimeHeaderLine* hl = static_cast<const MimeHeaderLine*>(l->get());
|
||||||
if (hl && (hl->name() &= name)) {
|
if (hl && (hl->name() &= name)) {
|
||||||
++c;
|
++c;
|
||||||
header.append(hl->clone(newName));
|
header.append(hl->clone(newName));
|
||||||
|
@ -606,9 +412,9 @@ bool SIPMessage::parse(const char* buf, int len)
|
||||||
(name &= "Proxy-Authenticate") ||
|
(name &= "Proxy-Authenticate") ||
|
||||||
(name &= "Authorization") ||
|
(name &= "Authorization") ||
|
||||||
(name &= "Proxy-Authorization"))
|
(name &= "Proxy-Authorization"))
|
||||||
header.append(new SIPAuthLine(name,*line));
|
header.append(new MimeAuthLine(name,*line));
|
||||||
else
|
else
|
||||||
header.append(new SIPHeaderLine(name,*line));
|
header.append(new MimeHeaderLine(name,*line));
|
||||||
|
|
||||||
if (content.null() && (name &= "Content-Type")) {
|
if (content.null() && (name &= "Content-Type")) {
|
||||||
content = *line;
|
content = *line;
|
||||||
|
@ -650,27 +456,27 @@ SIPMessage* SIPMessage::fromParsing(SIPParty* ep, const char* buf, int len)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SIPHeaderLine* SIPMessage::getHeader(const char* name) const
|
const MimeHeaderLine* SIPMessage::getHeader(const char* name) const
|
||||||
{
|
{
|
||||||
if (!(name && *name))
|
if (!(name && *name))
|
||||||
return 0;
|
return 0;
|
||||||
const ObjList* l = &header;
|
const ObjList* l = &header;
|
||||||
for (; l; l = l->next()) {
|
for (; l; l = l->next()) {
|
||||||
const SIPHeaderLine* t = static_cast<const SIPHeaderLine*>(l->get());
|
const MimeHeaderLine* t = static_cast<const MimeHeaderLine*>(l->get());
|
||||||
if (t && (t->name() &= name))
|
if (t && (t->name() &= name))
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SIPHeaderLine* SIPMessage::getLastHeader(const char* name) const
|
const MimeHeaderLine* SIPMessage::getLastHeader(const char* name) const
|
||||||
{
|
{
|
||||||
if (!(name && *name))
|
if (!(name && *name))
|
||||||
return 0;
|
return 0;
|
||||||
const SIPHeaderLine* res = 0;
|
const MimeHeaderLine* res = 0;
|
||||||
const ObjList* l = &header;
|
const ObjList* l = &header;
|
||||||
for (; l; l = l->next()) {
|
for (; l; l = l->next()) {
|
||||||
const SIPHeaderLine* t = static_cast<const SIPHeaderLine*>(l->get());
|
const MimeHeaderLine* t = static_cast<const MimeHeaderLine*>(l->get());
|
||||||
if (t && (t->name() &= name))
|
if (t && (t->name() &= name))
|
||||||
res = t;
|
res = t;
|
||||||
}
|
}
|
||||||
|
@ -683,7 +489,7 @@ void SIPMessage::clearHeaders(const char* name)
|
||||||
return;
|
return;
|
||||||
ObjList* l = &header;
|
ObjList* l = &header;
|
||||||
while (l) {
|
while (l) {
|
||||||
const SIPHeaderLine* t = static_cast<const SIPHeaderLine*>(l->get());
|
const MimeHeaderLine* t = static_cast<const MimeHeaderLine*>(l->get());
|
||||||
if (t && (t->name() &= name))
|
if (t && (t->name() &= name))
|
||||||
l->remove();
|
l->remove();
|
||||||
else
|
else
|
||||||
|
@ -698,7 +504,7 @@ int SIPMessage::countHeaders(const char* name) const
|
||||||
int res = 0;
|
int res = 0;
|
||||||
const ObjList* l = &header;
|
const ObjList* l = &header;
|
||||||
for (; l; l = l->next()) {
|
for (; l; l = l->next()) {
|
||||||
const SIPHeaderLine* t = static_cast<const SIPHeaderLine*>(l->get());
|
const MimeHeaderLine* t = static_cast<const MimeHeaderLine*>(l->get());
|
||||||
if (t && (t->name() &= name))
|
if (t && (t->name() &= name))
|
||||||
++res;
|
++res;
|
||||||
}
|
}
|
||||||
|
@ -707,13 +513,13 @@ int SIPMessage::countHeaders(const char* name) const
|
||||||
|
|
||||||
const NamedString* SIPMessage::getParam(const char* name, const char* param) const
|
const NamedString* SIPMessage::getParam(const char* name, const char* param) const
|
||||||
{
|
{
|
||||||
const SIPHeaderLine* hl = getHeader(name);
|
const MimeHeaderLine* hl = getHeader(name);
|
||||||
return hl ? hl->getParam(param) : 0;
|
return hl ? hl->getParam(param) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const String& SIPMessage::getHeaderValue(const char* name) const
|
const String& SIPMessage::getHeaderValue(const char* name) const
|
||||||
{
|
{
|
||||||
const SIPHeaderLine* hl = getHeader(name);
|
const MimeHeaderLine* hl = getHeader(name);
|
||||||
return hl ? *static_cast<const String*>(hl) : String::empty();
|
return hl ? *static_cast<const String*>(hl) : String::empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -733,7 +539,7 @@ const String& SIPMessage::getHeaders() const
|
||||||
|
|
||||||
const ObjList* l = &header;
|
const ObjList* l = &header;
|
||||||
for (; l; l = l->next()) {
|
for (; l; l = l->next()) {
|
||||||
SIPHeaderLine* t = static_cast<SIPHeaderLine*>(l->get());
|
MimeHeaderLine* t = static_cast<MimeHeaderLine*>(l->get());
|
||||||
if (t) {
|
if (t) {
|
||||||
t->buildLine(m_string);
|
t->buildLine(m_string);
|
||||||
m_string << "\r\n";
|
m_string << "\r\n";
|
||||||
|
@ -749,8 +555,8 @@ const DataBlock& SIPMessage::getBuffer() const
|
||||||
m_data.assign((void*)(getHeaders().c_str()),getHeaders().length());
|
m_data.assign((void*)(getHeaders().c_str()),getHeaders().length());
|
||||||
if (body) {
|
if (body) {
|
||||||
String s;
|
String s;
|
||||||
s << "Content-Type: " << body->getType() << "\r\n";
|
body->getType().buildLine(s);
|
||||||
s << "Content-Length: " << body->getBody().length() << "\r\n\r\n";
|
s << "\r\nContent-Length: " << body->getBody().length() << "\r\n\r\n";
|
||||||
m_data += s;
|
m_data += s;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -787,30 +593,30 @@ void SIPMessage::setParty(SIPParty* ep)
|
||||||
m_ep->ref();
|
m_ep->ref();
|
||||||
}
|
}
|
||||||
|
|
||||||
SIPAuthLine* SIPMessage::buildAuth(const String& username, const String& password,
|
MimeAuthLine* SIPMessage::buildAuth(const String& username, const String& password,
|
||||||
const String& meth, const String& uri, bool proxy) const
|
const String& meth, const String& uri, bool proxy) const
|
||||||
{
|
{
|
||||||
const char* hdr = proxy ? "Proxy-Authenticate" : "WWW-Authenticate";
|
const char* hdr = proxy ? "Proxy-Authenticate" : "WWW-Authenticate";
|
||||||
const ObjList* l = &header;
|
const ObjList* l = &header;
|
||||||
for (; l; l = l->next()) {
|
for (; l; l = l->next()) {
|
||||||
const SIPAuthLine* t = YOBJECT(SIPAuthLine,l->get());
|
const MimeAuthLine* t = YOBJECT(MimeAuthLine,l->get());
|
||||||
if (t && (t->name() &= hdr) && (*t &= "Digest")) {
|
if (t && (t->name() &= hdr) && (*t &= "Digest")) {
|
||||||
String nonce(t->getParam("nonce"));
|
String nonce(t->getParam("nonce"));
|
||||||
delQuotes(nonce);
|
MimeHeaderLine::delQuotes(nonce);
|
||||||
if (nonce.null())
|
if (nonce.null())
|
||||||
continue;
|
continue;
|
||||||
String realm(t->getParam("realm"));
|
String realm(t->getParam("realm"));
|
||||||
delQuotes(realm);
|
MimeHeaderLine::delQuotes(realm);
|
||||||
int par = uri.find(';');
|
int par = uri.find(';');
|
||||||
String msguri = uri.substr(0,par);
|
String msguri = uri.substr(0,par);
|
||||||
String response;
|
String response;
|
||||||
SIPEngine::buildAuth(username,realm,password,nonce,meth,msguri,response);
|
SIPEngine::buildAuth(username,realm,password,nonce,meth,msguri,response);
|
||||||
SIPAuthLine* auth = new SIPAuthLine(proxy ? "Proxy-Authorization" : "Authorization","Digest");
|
MimeAuthLine* auth = new MimeAuthLine(proxy ? "Proxy-Authorization" : "Authorization","Digest");
|
||||||
auth->setParam("username",quote(username));
|
auth->setParam("username",MimeHeaderLine::quote(username));
|
||||||
auth->setParam("realm",quote(realm));
|
auth->setParam("realm",MimeHeaderLine::quote(realm));
|
||||||
auth->setParam("nonce",quote(nonce));
|
auth->setParam("nonce",MimeHeaderLine::quote(nonce));
|
||||||
auth->setParam("uri",quote(msguri));
|
auth->setParam("uri",MimeHeaderLine::quote(msguri));
|
||||||
auth->setParam("response",quote(response));
|
auth->setParam("response",MimeHeaderLine::quote(response));
|
||||||
auth->setParam("algorithm","MD5");
|
auth->setParam("algorithm","MD5");
|
||||||
// copy opaque data as-is, only if present
|
// copy opaque data as-is, only if present
|
||||||
const NamedString* opaque = t->getParam("opaque");
|
const NamedString* opaque = t->getParam("opaque");
|
||||||
|
@ -822,7 +628,7 @@ SIPAuthLine* SIPMessage::buildAuth(const String& username, const String& passwor
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SIPAuthLine* SIPMessage::buildAuth(const SIPMessage& original) const
|
MimeAuthLine* SIPMessage::buildAuth(const SIPMessage& original) const
|
||||||
{
|
{
|
||||||
if (original.getAuthUsername().null())
|
if (original.getAuthUsername().null())
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -835,18 +641,18 @@ ObjList* SIPMessage::getRoutes() const
|
||||||
ObjList* list = 0;
|
ObjList* list = 0;
|
||||||
const ObjList* l = &header;
|
const ObjList* l = &header;
|
||||||
for (; l; l = l->next()) {
|
for (; l; l = l->next()) {
|
||||||
const SIPHeaderLine* h = YOBJECT(SIPHeaderLine,l->get());
|
const MimeHeaderLine* h = YOBJECT(MimeHeaderLine,l->get());
|
||||||
if (h && (h->name() &= "Record-Route")) {
|
if (h && (h->name() &= "Record-Route")) {
|
||||||
int p = 0;
|
int p = 0;
|
||||||
while (p >= 0) {
|
while (p >= 0) {
|
||||||
SIPHeaderLine* line = 0;
|
MimeHeaderLine* line = 0;
|
||||||
int s = findSep(*h,',',p);
|
int s = MimeHeaderLine::findSep(*h,',',p);
|
||||||
String tmp;
|
String tmp;
|
||||||
if (s < 0) {
|
if (s < 0) {
|
||||||
if (p)
|
if (p)
|
||||||
tmp = h->substr(p);
|
tmp = h->substr(p);
|
||||||
else
|
else
|
||||||
line = new SIPHeaderLine(*h,"Route");
|
line = new MimeHeaderLine(*h,"Route");
|
||||||
p = -1;
|
p = -1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -856,7 +662,7 @@ ObjList* SIPMessage::getRoutes() const
|
||||||
}
|
}
|
||||||
tmp.trimBlanks();
|
tmp.trimBlanks();
|
||||||
if (tmp)
|
if (tmp)
|
||||||
line = new SIPHeaderLine("Route",tmp);
|
line = new MimeHeaderLine("Route",tmp);
|
||||||
if (!line)
|
if (!line)
|
||||||
continue;
|
continue;
|
||||||
if (!list)
|
if (!list)
|
||||||
|
@ -877,7 +683,7 @@ void SIPMessage::addRoutes(const ObjList* routes)
|
||||||
{
|
{
|
||||||
if (isAnswer() || !routes)
|
if (isAnswer() || !routes)
|
||||||
return;
|
return;
|
||||||
SIPHeaderLine* hl = YOBJECT(SIPHeaderLine,routes->get());
|
MimeHeaderLine* hl = YOBJECT(MimeHeaderLine,routes->get());
|
||||||
if (hl) {
|
if (hl) {
|
||||||
// check if first route is to a RFC 2543 proxy
|
// check if first route is to a RFC 2543 proxy
|
||||||
String tmp = *hl;
|
String tmp = *hl;
|
||||||
|
@ -886,7 +692,7 @@ void SIPMessage::addRoutes(const ObjList* routes)
|
||||||
tmp = tmp.matchString(1);
|
tmp = tmp.matchString(1);
|
||||||
if (tmp.find(";lr") < 0) {
|
if (tmp.find(";lr") < 0) {
|
||||||
// prepare a new final route
|
// prepare a new final route
|
||||||
hl = new SIPHeaderLine("Route","<" + uri + ">");
|
hl = new MimeHeaderLine("Route","<" + uri + ">");
|
||||||
// set the first route as Request-URI and then skip it
|
// set the first route as Request-URI and then skip it
|
||||||
uri = tmp;
|
uri = tmp;
|
||||||
routes = routes->next();
|
routes = routes->next();
|
||||||
|
@ -897,7 +703,7 @@ void SIPMessage::addRoutes(const ObjList* routes)
|
||||||
|
|
||||||
// add (remaining) routes
|
// add (remaining) routes
|
||||||
for (; routes; routes = routes->next()) {
|
for (; routes; routes = routes->next()) {
|
||||||
const SIPHeaderLine* h = YOBJECT(SIPHeaderLine,routes->get());
|
const MimeHeaderLine* h = YOBJECT(MimeHeaderLine,routes->get());
|
||||||
if (h)
|
if (h)
|
||||||
addHeader(h->clone());
|
addHeader(h->clone());
|
||||||
}
|
}
|
||||||
|
@ -949,7 +755,7 @@ SIPDialog::SIPDialog(const SIPMessage& message)
|
||||||
{
|
{
|
||||||
Regexp r("<\\([^>]\\+\\)>");
|
Regexp r("<\\([^>]\\+\\)>");
|
||||||
bool local = message.isOutgoing() ^ message.isAnswer();
|
bool local = message.isOutgoing() ^ message.isAnswer();
|
||||||
const SIPHeaderLine* hl = message.getHeader(local ? "From" : "To");
|
const MimeHeaderLine* hl = message.getHeader(local ? "From" : "To");
|
||||||
localURI = hl;
|
localURI = hl;
|
||||||
if (localURI.matches(r))
|
if (localURI.matches(r))
|
||||||
localURI = localURI.matchString(1);
|
localURI = localURI.matchString(1);
|
||||||
|
@ -972,7 +778,7 @@ SIPDialog& SIPDialog::operator=(const SIPMessage& message)
|
||||||
String::operator=(cid);
|
String::operator=(cid);
|
||||||
Regexp r("<\\([^>]\\+\\)>");
|
Regexp r("<\\([^>]\\+\\)>");
|
||||||
bool local = message.isOutgoing() ^ message.isAnswer();
|
bool local = message.isOutgoing() ^ message.isAnswer();
|
||||||
const SIPHeaderLine* hl = message.getHeader(local ? "From" : "To");
|
const MimeHeaderLine* hl = message.getHeader(local ? "From" : "To");
|
||||||
localURI = hl;
|
localURI = hl;
|
||||||
if (localURI.matches(r))
|
if (localURI.matches(r))
|
||||||
localURI = localURI.matchString(1);
|
localURI = localURI.matchString(1);
|
||||||
|
|
|
@ -48,7 +48,7 @@ SIPTransaction::SIPTransaction(SIPMessage* message, SIPEngine* engine, bool outg
|
||||||
if (ns)
|
if (ns)
|
||||||
m_tag = *ns;
|
m_tag = *ns;
|
||||||
|
|
||||||
const SIPHeaderLine* hl = message->getHeader("Call-ID");
|
const MimeHeaderLine* hl = message->getHeader("Call-ID");
|
||||||
if (hl)
|
if (hl)
|
||||||
m_callid = *hl;
|
m_callid = *hl;
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ SIPTransaction::SIPTransaction(SIPTransaction& original, SIPMessage* answer)
|
||||||
&original,answer,this);
|
&original,answer,this);
|
||||||
|
|
||||||
SIPMessage* msg = new SIPMessage(*original.m_firstMessage);
|
SIPMessage* msg = new SIPMessage(*original.m_firstMessage);
|
||||||
SIPAuthLine* auth = answer->buildAuth(*original.m_firstMessage);
|
MimeAuthLine* auth = answer->buildAuth(*original.m_firstMessage);
|
||||||
m_firstMessage->setAutoAuth();
|
m_firstMessage->setAutoAuth();
|
||||||
msg->complete(m_engine);
|
msg->complete(m_engine);
|
||||||
msg->addHeader(auth);
|
msg->addHeader(auth);
|
||||||
|
@ -370,7 +370,7 @@ void SIPTransaction::requestAuth(const String& realm, const String& domain, bool
|
||||||
if (realm) {
|
if (realm) {
|
||||||
String tmp;
|
String tmp;
|
||||||
tmp << "Digest realm=\"" << realm << "\"";
|
tmp << "Digest realm=\"" << realm << "\"";
|
||||||
SIPHeaderLine* line = new SIPHeaderLine(hdr,tmp,',');
|
MimeHeaderLine* line = new MimeHeaderLine(hdr,tmp,',');
|
||||||
if (domain)
|
if (domain)
|
||||||
line->setParam(" domain","\"" + domain + "\"");
|
line->setParam(" domain","\"" + domain + "\"");
|
||||||
m_engine->nonceGet(tmp);
|
m_engine->nonceGet(tmp);
|
||||||
|
|
|
@ -75,68 +75,6 @@ const char* compactForm(const char* header)
|
||||||
return header;
|
return header;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Utility function, puts quotes around a string
|
|
||||||
void addQuotes(String& str)
|
|
||||||
{
|
|
||||||
str.trimBlanks();
|
|
||||||
int l = str.length();
|
|
||||||
if ((l < 2) || (str[0] != '"') || (str[l-1] != '"'))
|
|
||||||
str = "\"" + str + "\"";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Utility function, removes quotes around a string
|
|
||||||
void delQuotes(String& str)
|
|
||||||
{
|
|
||||||
str.trimBlanks();
|
|
||||||
int l = str.length();
|
|
||||||
if ((l >= 2) && (str[0] == '"') && (str[l-1] == '"')) {
|
|
||||||
str = str.substr(1,l-2);
|
|
||||||
str.trimBlanks();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Utility function, puts quotes around a string
|
|
||||||
String quote(const String& str)
|
|
||||||
{
|
|
||||||
String tmp(str);
|
|
||||||
addQuotes(tmp);
|
|
||||||
return tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Utility function to find a separator not in "quotes" or inside <uri>
|
|
||||||
int findSep(const char* str, char sep, int offs)
|
|
||||||
{
|
|
||||||
if (!(str && sep))
|
|
||||||
return -1;
|
|
||||||
str += offs;
|
|
||||||
bool inQ = false;
|
|
||||||
bool inU = false;
|
|
||||||
char c;
|
|
||||||
for (; (c = *str++) ; offs++) {
|
|
||||||
if (inQ) {
|
|
||||||
if (c == '"')
|
|
||||||
inQ = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (inU) {
|
|
||||||
if (c == '>')
|
|
||||||
inU = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (c == sep)
|
|
||||||
return offs;
|
|
||||||
switch (c) {
|
|
||||||
case '"':
|
|
||||||
inQ = true;
|
|
||||||
break;
|
|
||||||
case '<':
|
|
||||||
inU = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* vi: set ts=8 sw=4 sts=4 noet: */
|
/* vi: set ts=8 sw=4 sts=4 noet: */
|
||||||
|
|
|
@ -31,18 +31,6 @@ const char* uncompactForm(const char* header);
|
||||||
// Utility function, returns a compacted header name
|
// Utility function, returns a compacted header name
|
||||||
const char* compactForm(const char* header);
|
const char* compactForm(const char* header);
|
||||||
|
|
||||||
// Utility function, puts quotes around a string
|
|
||||||
void addQuotes(String& str);
|
|
||||||
|
|
||||||
// Utility function, removes quotes around a string
|
|
||||||
void delQuotes(String& str);
|
|
||||||
|
|
||||||
// Utility function, puts quotes around a string
|
|
||||||
String quote(const String& str);
|
|
||||||
|
|
||||||
// Utility function to find a separator not in "quotes" or inside <uri>
|
|
||||||
int findSep(const char* str, char sep, int offs = 0);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* vi: set ts=8 sw=4 sts=4 noet: */
|
/* vi: set ts=8 sw=4 sts=4 noet: */
|
||||||
|
|
|
@ -84,39 +84,6 @@ protected:
|
||||||
int m_partyPort;
|
int m_partyPort;
|
||||||
};
|
};
|
||||||
|
|
||||||
class YSIP_API SIPHeaderLine : public NamedString
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SIPHeaderLine(const char* name, const String& value, char sep = 0);
|
|
||||||
SIPHeaderLine(const SIPHeaderLine& original, const char* newName = 0);
|
|
||||||
virtual ~SIPHeaderLine();
|
|
||||||
virtual void* getObject(const String& name) const;
|
|
||||||
virtual SIPHeaderLine* clone(const char* newName = 0) const;
|
|
||||||
virtual void buildLine(String& line) const;
|
|
||||||
inline SIPHeaderLine& operator=(const char* value)
|
|
||||||
{ NamedString::operator=(value); return *this; }
|
|
||||||
inline const ObjList& params() const
|
|
||||||
{ return m_params; }
|
|
||||||
inline char separator() const
|
|
||||||
{ return m_separator; }
|
|
||||||
void setParam(const char* name, const char* value = 0);
|
|
||||||
void delParam(const char* name);
|
|
||||||
const NamedString* getParam(const char* name) const;
|
|
||||||
protected:
|
|
||||||
ObjList m_params;
|
|
||||||
char m_separator;
|
|
||||||
};
|
|
||||||
|
|
||||||
class YSIP_API SIPAuthLine : public SIPHeaderLine
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SIPAuthLine(const char* name, const String& value);
|
|
||||||
SIPAuthLine(const SIPAuthLine& original, const char* newName = 0);
|
|
||||||
virtual void* getObject(const String& name) const;
|
|
||||||
virtual SIPHeaderLine* clone(const char* newName = 0) const;
|
|
||||||
virtual void buildLine(String& line) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An object that holds the sip message parsed into this library model.
|
* An object that holds the sip message parsed into this library model.
|
||||||
* This class can be used to parse a sip message from a text buffer, or it
|
* This class can be used to parse a sip message from a text buffer, or it
|
||||||
|
@ -241,14 +208,14 @@ public:
|
||||||
* @param name Name of the header to locate
|
* @param name Name of the header to locate
|
||||||
* @return A pointer to the first matching header line or 0 if not found
|
* @return A pointer to the first matching header line or 0 if not found
|
||||||
*/
|
*/
|
||||||
const SIPHeaderLine* getHeader(const char* name) const;
|
const MimeHeaderLine* getHeader(const char* name) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the last header line that matches a given name name
|
* Find the last header line that matches a given name name
|
||||||
* @param name Name of the header to locate
|
* @param name Name of the header to locate
|
||||||
* @return A pointer to the last matching header line or 0 if not found
|
* @return A pointer to the last matching header line or 0 if not found
|
||||||
*/
|
*/
|
||||||
const SIPHeaderLine* getLastHeader(const char* name) const;
|
const MimeHeaderLine* getLastHeader(const char* name) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Count the header lines matching a specific name
|
* Count the header lines matching a specific name
|
||||||
|
@ -286,13 +253,13 @@ public:
|
||||||
* @param value Content of the new header line
|
* @param value Content of the new header line
|
||||||
*/
|
*/
|
||||||
inline void addHeader(const char* name, const char* value = 0)
|
inline void addHeader(const char* name, const char* value = 0)
|
||||||
{ header.append(new SIPHeaderLine(name,value)); }
|
{ header.append(new MimeHeaderLine(name,value)); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Append an already constructed header line
|
* Append an already constructed header line
|
||||||
* @param line Header line to add
|
* @param line Header line to add
|
||||||
*/
|
*/
|
||||||
inline void addHeader(SIPHeaderLine* line)
|
inline void addHeader(MimeHeaderLine* line)
|
||||||
{ header.append(line); }
|
{ header.append(line); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -316,7 +283,7 @@ public:
|
||||||
* @param proxy Set to true to authenticate to a proxy, false to a server
|
* @param proxy Set to true to authenticate to a proxy, false to a server
|
||||||
* @return A new authorization line to be used in a new transaction
|
* @return A new authorization line to be used in a new transaction
|
||||||
*/
|
*/
|
||||||
SIPAuthLine* buildAuth(const String& username, const String& password,
|
MimeAuthLine* buildAuth(const String& username, const String& password,
|
||||||
const String& meth, const String& uri, bool proxy = false) const;
|
const String& meth, const String& uri, bool proxy = false) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -324,7 +291,7 @@ public:
|
||||||
* @param original Origianl outgoing message
|
* @param original Origianl outgoing message
|
||||||
* @return A new authorization line to be used in a new transaction
|
* @return A new authorization line to be used in a new transaction
|
||||||
*/
|
*/
|
||||||
SIPAuthLine* buildAuth(const SIPMessage& original) const;
|
MimeAuthLine* buildAuth(const SIPMessage& original) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepare the message for automatic client transaction authentication.
|
* Prepare the message for automatic client transaction authentication.
|
||||||
|
@ -350,13 +317,13 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract routes from Record-Route: headers
|
* Extract routes from Record-Route: headers
|
||||||
* @return A list of SIPHeaderLine representing SIP routes
|
* @return A list of MimeHeaderLine representing SIP routes
|
||||||
*/
|
*/
|
||||||
ObjList* getRoutes() const;
|
ObjList* getRoutes() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add Route: headers to an outgoing message
|
* Add Route: headers to an outgoing message
|
||||||
* @param routes List of SIPHeaderLine representing SIP routes
|
* @param routes List of MimeHeaderLine representing SIP routes
|
||||||
*/
|
*/
|
||||||
void addRoutes(const ObjList* routes);
|
void addRoutes(const ObjList* routes);
|
||||||
|
|
||||||
|
|
|
@ -377,7 +377,7 @@ private:
|
||||||
bool addSdpParams(Message& msg, const MimeBody* body);
|
bool addSdpParams(Message& msg, const MimeBody* body);
|
||||||
bool addRtpParams(Message& msg, const String& natAddr, const MimeBody* body);
|
bool addRtpParams(Message& msg, const String& natAddr, const MimeBody* body);
|
||||||
bool startClientReInvite(Message& msg);
|
bool startClientReInvite(Message& msg);
|
||||||
bool initUnattendedTransfer(Message*& msg, SIPMessage*& sipNotify, const SIPMessage* sipRefer, const SIPHeaderLine* refHdr);
|
bool initUnattendedTransfer(Message*& msg, SIPMessage*& sipNotify, const SIPMessage* sipRefer, const MimeHeaderLine* refHdr);
|
||||||
|
|
||||||
SIPTransaction* m_tr;
|
SIPTransaction* m_tr;
|
||||||
SIPTransaction* m_tr2;
|
SIPTransaction* m_tr2;
|
||||||
|
@ -723,7 +723,7 @@ static void copySipHeaders(Message& msg, const SIPMessage& sip, bool filter = tr
|
||||||
{
|
{
|
||||||
const ObjList* l = sip.header.skipNull();
|
const ObjList* l = sip.header.skipNull();
|
||||||
for (; l; l = l->skipNext()) {
|
for (; l; l = l->skipNext()) {
|
||||||
const SIPHeaderLine* t = static_cast<const SIPHeaderLine*>(l->get());
|
const MimeHeaderLine* t = static_cast<const MimeHeaderLine*>(l->get());
|
||||||
String name(t->name());
|
String name(t->name());
|
||||||
name.toLower();
|
name.toLower();
|
||||||
if (matchAny(name,s_rejectHeaders))
|
if (matchAny(name,s_rejectHeaders))
|
||||||
|
@ -763,7 +763,7 @@ static void copySipHeaders(SIPMessage& sip, const Message& msg, const char* pref
|
||||||
static void copyPrivacy(Message& msg, const SIPMessage& sip)
|
static void copyPrivacy(Message& msg, const SIPMessage& sip)
|
||||||
{
|
{
|
||||||
bool anonip = (sip.getHeaderValue("Anonymity") &= "ipaddr");
|
bool anonip = (sip.getHeaderValue("Anonymity") &= "ipaddr");
|
||||||
const SIPHeaderLine* hl = sip.getHeader("Remote-Party-ID");
|
const MimeHeaderLine* hl = sip.getHeader("Remote-Party-ID");
|
||||||
if (!(anonip || hl))
|
if (!(anonip || hl))
|
||||||
return;
|
return;
|
||||||
const NamedString* p = hl ? hl->getParam("screen") : 0;
|
const NamedString* p = hl ? hl->getParam("screen") : 0;
|
||||||
|
@ -807,7 +807,7 @@ static void copyPrivacy(SIPMessage& sip, const Message& msg)
|
||||||
if (tmp)
|
if (tmp)
|
||||||
tmp = "\"" + tmp + "\" ";
|
tmp = "\"" + tmp + "\" ";
|
||||||
tmp << "<sip:" << caller << "@" << msg.getValue("domain","domain") << ">";
|
tmp << "<sip:" << caller << "@" << msg.getValue("domain","domain") << ">";
|
||||||
SIPHeaderLine* hl = new SIPHeaderLine("Remote-Party-ID",tmp);
|
MimeHeaderLine* hl = new MimeHeaderLine("Remote-Party-ID",tmp);
|
||||||
if (screen)
|
if (screen)
|
||||||
hl->setParam("screen","yes");
|
hl->setParam("screen","yes");
|
||||||
if (privname && privuri)
|
if (privname && privuri)
|
||||||
|
@ -1451,7 +1451,7 @@ void YateSIPEndPoint::regreq(SIPEvent* e, SIPTransaction* t)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const SIPMessage* message = e->getMessage();
|
const SIPMessage* message = e->getMessage();
|
||||||
const SIPHeaderLine* hl = message->getHeader("Contact");
|
const MimeHeaderLine* hl = message->getHeader("Contact");
|
||||||
if (!hl) {
|
if (!hl) {
|
||||||
t->setResponse(400);
|
t->setResponse(400);
|
||||||
return;
|
return;
|
||||||
|
@ -1542,7 +1542,7 @@ void YateSIPEndPoint::regreq(SIPEvent* e, SIPTransaction* t)
|
||||||
tmp = expires;
|
tmp = expires;
|
||||||
SIPMessage* r = new SIPMessage(t->initialMessage(),200);
|
SIPMessage* r = new SIPMessage(t->initialMessage(),200);
|
||||||
r->addHeader("Expires",tmp);
|
r->addHeader("Expires",tmp);
|
||||||
SIPHeaderLine* contact = new SIPHeaderLine("Contact","<" + addr + ">");
|
MimeHeaderLine* contact = new MimeHeaderLine("Contact","<" + addr + ">");
|
||||||
contact->setParam("expires",tmp);
|
contact->setParam("expires",tmp);
|
||||||
r->addHeader(contact);
|
r->addHeader(contact);
|
||||||
if (natChanged) {
|
if (natChanged) {
|
||||||
|
@ -1562,7 +1562,7 @@ void YateSIPEndPoint::regreq(SIPEvent* e, SIPTransaction* t)
|
||||||
|
|
||||||
void YateSIPEndPoint::options(SIPEvent* e, SIPTransaction* t)
|
void YateSIPEndPoint::options(SIPEvent* e, SIPTransaction* t)
|
||||||
{
|
{
|
||||||
const SIPHeaderLine* acpt = e->getMessage()->getHeader("Accept");
|
const MimeHeaderLine* acpt = e->getMessage()->getHeader("Accept");
|
||||||
if (acpt) {
|
if (acpt) {
|
||||||
if (*acpt != "application/sdp") {
|
if (*acpt != "application/sdp") {
|
||||||
t->setResponse(415);
|
t->setResponse(415);
|
||||||
|
@ -1736,7 +1736,7 @@ YateSIPConnection::YateSIPConnection(SIPEvent* ev, SIPTransaction* tr)
|
||||||
m->addParam("called",uri.getUser());
|
m->addParam("called",uri.getUser());
|
||||||
if (m_uri.getDescription())
|
if (m_uri.getDescription())
|
||||||
m->addParam("callername",m_uri.getDescription());
|
m->addParam("callername",m_uri.getDescription());
|
||||||
const SIPHeaderLine* hl = m_tr->initialMessage()->getHeader("Call-Info");
|
const MimeHeaderLine* hl = m_tr->initialMessage()->getHeader("Call-Info");
|
||||||
if (hl) {
|
if (hl) {
|
||||||
const NamedString* type = hl->getParam("purpose");
|
const NamedString* type = hl->getParam("purpose");
|
||||||
if (!type || *type == "info")
|
if (!type || *type == "info")
|
||||||
|
@ -1885,14 +1885,14 @@ YateSIPConnection::YateSIPConnection(Message& msg, const String& uri, const char
|
||||||
if (display) {
|
if (display) {
|
||||||
String desc;
|
String desc;
|
||||||
desc << "\"" << display << "\" ";
|
desc << "\"" << display << "\" ";
|
||||||
SIPHeaderLine* hl = const_cast<SIPHeaderLine*>(m->getHeader("From"));
|
MimeHeaderLine* hl = const_cast<MimeHeaderLine*>(m->getHeader("From"));
|
||||||
if (hl)
|
if (hl)
|
||||||
*hl = desc + *hl;
|
*hl = desc + *hl;
|
||||||
}
|
}
|
||||||
if (msg.getParam("calledname")) {
|
if (msg.getParam("calledname")) {
|
||||||
String desc;
|
String desc;
|
||||||
desc << "\"" << msg.getValue("calledname") << "\" ";
|
desc << "\"" << msg.getValue("calledname") << "\" ";
|
||||||
SIPHeaderLine* hl = const_cast<SIPHeaderLine*>(m->getHeader("To"));
|
MimeHeaderLine* hl = const_cast<MimeHeaderLine*>(m->getHeader("To"));
|
||||||
if (hl)
|
if (hl)
|
||||||
*hl = desc + *hl;
|
*hl = desc + *hl;
|
||||||
}
|
}
|
||||||
|
@ -1909,19 +1909,19 @@ YateSIPConnection::YateSIPConnection(Message& msg, const String& uri, const char
|
||||||
// add some Call-Info headers
|
// add some Call-Info headers
|
||||||
const char* info = msg.getValue("caller_info_uri");
|
const char* info = msg.getValue("caller_info_uri");
|
||||||
if (info) {
|
if (info) {
|
||||||
SIPHeaderLine* hl = new SIPHeaderLine("Call-Info",info);
|
MimeHeaderLine* hl = new MimeHeaderLine("Call-Info",info);
|
||||||
hl->setParam("purpose","info");
|
hl->setParam("purpose","info");
|
||||||
m->addHeader(hl);
|
m->addHeader(hl);
|
||||||
}
|
}
|
||||||
info = msg.getValue("caller_icon_uri");
|
info = msg.getValue("caller_icon_uri");
|
||||||
if (info) {
|
if (info) {
|
||||||
SIPHeaderLine* hl = new SIPHeaderLine("Call-Info",info);
|
MimeHeaderLine* hl = new MimeHeaderLine("Call-Info",info);
|
||||||
hl->setParam("purpose","icon");
|
hl->setParam("purpose","icon");
|
||||||
m->addHeader(hl);
|
m->addHeader(hl);
|
||||||
}
|
}
|
||||||
info = msg.getValue("caller_card_uri");
|
info = msg.getValue("caller_card_uri");
|
||||||
if (info) {
|
if (info) {
|
||||||
SIPHeaderLine* hl = new SIPHeaderLine("Call-Info",info);
|
MimeHeaderLine* hl = new MimeHeaderLine("Call-Info",info);
|
||||||
hl->setParam("purpose","card");
|
hl->setParam("purpose","card");
|
||||||
m->addHeader(hl);
|
m->addHeader(hl);
|
||||||
}
|
}
|
||||||
|
@ -2058,7 +2058,7 @@ void YateSIPConnection::hangup()
|
||||||
tmp << i->getCSeq() << " CANCEL";
|
tmp << i->getCSeq() << " CANCEL";
|
||||||
m->addHeader("CSeq",tmp);
|
m->addHeader("CSeq",tmp);
|
||||||
if (m_reason == "pickup") {
|
if (m_reason == "pickup") {
|
||||||
SIPHeaderLine* hl = new SIPHeaderLine("Reason","SIP");
|
MimeHeaderLine* hl = new MimeHeaderLine("Reason","SIP");
|
||||||
hl->setParam("cause","200");
|
hl->setParam("cause","200");
|
||||||
hl->setParam("text","\"Call completed elsewhere\"");
|
hl->setParam("text","\"Call completed elsewhere\"");
|
||||||
m->addHeader(hl);
|
m->addHeader(hl);
|
||||||
|
@ -2078,7 +2078,7 @@ void YateSIPConnection::hangup()
|
||||||
if (m) {
|
if (m) {
|
||||||
if (m_reason) {
|
if (m_reason) {
|
||||||
// FIXME: add SIP and Q.850 cause codes, set the proper reason
|
// FIXME: add SIP and Q.850 cause codes, set the proper reason
|
||||||
SIPHeaderLine* hl = new SIPHeaderLine("Reason","SIP");
|
MimeHeaderLine* hl = new MimeHeaderLine("Reason","SIP");
|
||||||
hl->setParam("text","\"" + m_reason + "\"");
|
hl->setParam("text","\"" + m_reason + "\"");
|
||||||
m->addHeader(hl);
|
m->addHeader(hl);
|
||||||
}
|
}
|
||||||
|
@ -2108,7 +2108,7 @@ SIPMessage* YateSIPConnection::createDlgMsg(const char* method, const char* uri)
|
||||||
m->addHeader("Call-ID",m_callid);
|
m->addHeader("Call-ID",m_callid);
|
||||||
String tmp;
|
String tmp;
|
||||||
tmp << "<" << m_dialog.localURI << ">";
|
tmp << "<" << m_dialog.localURI << ">";
|
||||||
SIPHeaderLine* hl = new SIPHeaderLine("From",tmp);
|
MimeHeaderLine* hl = new MimeHeaderLine("From",tmp);
|
||||||
tmp = m_dialog.localTag;
|
tmp = m_dialog.localTag;
|
||||||
if (tmp.null() && m_tr)
|
if (tmp.null() && m_tr)
|
||||||
tmp = m_tr->getDialogTag();
|
tmp = m_tr->getDialogTag();
|
||||||
|
@ -2117,7 +2117,7 @@ SIPMessage* YateSIPConnection::createDlgMsg(const char* method, const char* uri)
|
||||||
m->addHeader(hl);
|
m->addHeader(hl);
|
||||||
tmp.clear();
|
tmp.clear();
|
||||||
tmp << "<" << m_dialog.remoteURI << ">";
|
tmp << "<" << m_dialog.remoteURI << ">";
|
||||||
hl = new SIPHeaderLine("To",tmp);
|
hl = new MimeHeaderLine("To",tmp);
|
||||||
tmp = m_dialog.remoteTag;
|
tmp = m_dialog.remoteTag;
|
||||||
if (tmp.null() && m_tr)
|
if (tmp.null() && m_tr)
|
||||||
tmp = m_tr->getDialogTag();
|
tmp = m_tr->getDialogTag();
|
||||||
|
@ -2134,8 +2134,8 @@ bool YateSIPConnection::emitPRACK(const SIPMessage* msg)
|
||||||
return false;
|
return false;
|
||||||
if (!plugin.ep()->engine()->prack())
|
if (!plugin.ep()->engine()->prack())
|
||||||
return true;
|
return true;
|
||||||
const SIPHeaderLine* rs = msg->getHeader("RSeq");
|
const MimeHeaderLine* rs = msg->getHeader("RSeq");
|
||||||
const SIPHeaderLine* cs = msg->getHeader("CSeq");
|
const MimeHeaderLine* cs = msg->getHeader("CSeq");
|
||||||
if (!(rs && cs))
|
if (!(rs && cs))
|
||||||
return true;
|
return true;
|
||||||
int seq = rs->toInteger(0,10);
|
int seq = rs->toInteger(0,10);
|
||||||
|
@ -2148,7 +2148,7 @@ bool YateSIPConnection::emitPRACK(const SIPMessage* msg)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
String tmp;
|
String tmp;
|
||||||
const SIPHeaderLine* co = msg->getHeader("Contact");
|
const MimeHeaderLine* co = msg->getHeader("Contact");
|
||||||
if (co) {
|
if (co) {
|
||||||
tmp = *co;
|
tmp = *co;
|
||||||
Regexp r("^[^<]*<\\([^>]*\\)>.*$");
|
Regexp r("^[^<]*<\\([^>]*\\)>.*$");
|
||||||
|
@ -2616,7 +2616,7 @@ bool YateSIPConnection::process(SIPEvent* ev)
|
||||||
// see if we should detect our external address
|
// see if we should detect our external address
|
||||||
const YateSIPLine* line = plugin.findLine(m_line);
|
const YateSIPLine* line = plugin.findLine(m_line);
|
||||||
if (line && line->localDetect()) {
|
if (line && line->localDetect()) {
|
||||||
SIPHeaderLine* hl = const_cast<SIPHeaderLine*>(msg->getHeader("Via"));
|
MimeHeaderLine* hl = const_cast<MimeHeaderLine*>(msg->getHeader("Via"));
|
||||||
if (hl) {
|
if (hl) {
|
||||||
const NamedString* par = hl->getParam("received");
|
const NamedString* par = hl->getParam("received");
|
||||||
if (par && *par) {
|
if (par && *par) {
|
||||||
|
@ -2922,7 +2922,7 @@ void YateSIPConnection::doBye(SIPTransaction* t)
|
||||||
if (m_authBye && !checkUser(t))
|
if (m_authBye && !checkUser(t))
|
||||||
return;
|
return;
|
||||||
DDebug(this,DebugAll,"YateSIPConnection::doBye(%p) [%p]",t,this);
|
DDebug(this,DebugAll,"YateSIPConnection::doBye(%p) [%p]",t,this);
|
||||||
const SIPHeaderLine* hl = t->initialMessage()->getHeader("Reason");
|
const MimeHeaderLine* hl = t->initialMessage()->getHeader("Reason");
|
||||||
if (hl) {
|
if (hl) {
|
||||||
const NamedString* text = hl->getParam("text");
|
const NamedString* text = hl->getParam("text");
|
||||||
if (text)
|
if (text)
|
||||||
|
@ -3001,7 +3001,7 @@ void YateSIPConnection::doRefer(SIPTransaction* t)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_referring = true;
|
m_referring = true;
|
||||||
const SIPHeaderLine* refHdr = t->initialMessage()->getHeader("Refer-To");
|
const MimeHeaderLine* refHdr = t->initialMessage()->getHeader("Refer-To");
|
||||||
if (!(refHdr && refHdr->length())) {
|
if (!(refHdr && refHdr->length())) {
|
||||||
DDebug(this,DebugAll,"YateSIPConnection::doRefer(%p) [%p]. Empty or missing 'Refer-To' header.",t,this);
|
DDebug(this,DebugAll,"YateSIPConnection::doRefer(%p) [%p]. Empty or missing 'Refer-To' header.",t,this);
|
||||||
t->setResponse(400); // Bad request
|
t->setResponse(400); // Bad request
|
||||||
|
@ -3093,7 +3093,7 @@ bool YateSIPConnection::msgAnswered(Message& msg)
|
||||||
}
|
}
|
||||||
m->setBody(sdp);
|
m->setBody(sdp);
|
||||||
|
|
||||||
const SIPHeaderLine* co = m_tr->initialMessage()->getHeader("Contact");
|
const MimeHeaderLine* co = m_tr->initialMessage()->getHeader("Contact");
|
||||||
if (co) {
|
if (co) {
|
||||||
// INVITE had a Contact: header - time to change remote URI
|
// INVITE had a Contact: header - time to change remote URI
|
||||||
m_uri = *co;
|
m_uri = *co;
|
||||||
|
@ -3422,7 +3422,7 @@ void YateSIPConnection::startPendingUpdate()
|
||||||
// sipRefer: received REFER message, refHdr: 'Refer-To' header
|
// sipRefer: received REFER message, refHdr: 'Refer-To' header
|
||||||
// If return false, msg and sipNotify are 0
|
// If return false, msg and sipNotify are 0
|
||||||
bool YateSIPConnection::initUnattendedTransfer(Message*& msg, SIPMessage*& sipNotify,
|
bool YateSIPConnection::initUnattendedTransfer(Message*& msg, SIPMessage*& sipNotify,
|
||||||
const SIPMessage* sipRefer, const SIPHeaderLine* refHdr)
|
const SIPMessage* sipRefer, const MimeHeaderLine* refHdr)
|
||||||
{
|
{
|
||||||
// call.route
|
// call.route
|
||||||
msg = new Message("call.route");
|
msg = new Message("call.route");
|
||||||
|
@ -3432,7 +3432,7 @@ bool YateSIPConnection::initUnattendedTransfer(Message*& msg, SIPMessage*& sipNo
|
||||||
if (m_user)
|
if (m_user)
|
||||||
msg->addParam("username",m_user);
|
msg->addParam("username",m_user);
|
||||||
|
|
||||||
const SIPHeaderLine* sh = sipRefer->getHeader("To"); // caller
|
const MimeHeaderLine* sh = sipRefer->getHeader("To"); // caller
|
||||||
if (sh) {
|
if (sh) {
|
||||||
URI uriCaller(*sh);
|
URI uriCaller(*sh);
|
||||||
uriCaller.parse();
|
uriCaller.parse();
|
||||||
|
@ -3456,7 +3456,7 @@ bool YateSIPConnection::initUnattendedTransfer(Message*& msg, SIPMessage*& sipNo
|
||||||
msg->addParam("reason","transfer"); // reason
|
msg->addParam("reason","transfer"); // reason
|
||||||
// NOTIFY
|
// NOTIFY
|
||||||
String tmp;
|
String tmp;
|
||||||
const SIPHeaderLine* co = sipRefer->getHeader("Contact");
|
const MimeHeaderLine* co = sipRefer->getHeader("Contact");
|
||||||
if (co) {
|
if (co) {
|
||||||
tmp = *co;
|
tmp = *co;
|
||||||
Regexp r("^[^<]*<\\([^>]*\\)>.*$");
|
Regexp r("^[^<]*<\\([^>]*\\)>.*$");
|
||||||
|
@ -3651,7 +3651,7 @@ void YateSIPLine::detectLocal(const SIPMessage* msg)
|
||||||
return;
|
return;
|
||||||
String laddr = m_localAddr;
|
String laddr = m_localAddr;
|
||||||
int lport = m_localPort;
|
int lport = m_localPort;
|
||||||
SIPHeaderLine* hl = const_cast<SIPHeaderLine*>(msg->getHeader("Via"));
|
MimeHeaderLine* hl = const_cast<MimeHeaderLine*>(msg->getHeader("Via"));
|
||||||
if (hl) {
|
if (hl) {
|
||||||
const NamedString* par = hl->getParam("received");
|
const NamedString* par = hl->getParam("received");
|
||||||
if (par && *par)
|
if (par && *par)
|
||||||
|
|
189
yatemime.h
189
yatemime.h
|
@ -36,6 +36,176 @@
|
||||||
*/
|
*/
|
||||||
namespace TelEngine {
|
namespace TelEngine {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A MIME header line.
|
||||||
|
* The NamedString's value contain the first parameter after the header name
|
||||||
|
* @short MIME header line
|
||||||
|
*/
|
||||||
|
class YATE_API MimeHeaderLine : public NamedString
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
* Builds a MIME header line from a string buffer.
|
||||||
|
* Splits the value into header parameters
|
||||||
|
* @param name The header name
|
||||||
|
* @param value The header value
|
||||||
|
* @param sep Optional parameter separator. If 0, the default ';' will be used
|
||||||
|
*/
|
||||||
|
MimeHeaderLine(const char* name, const String& value, char sep = 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
* Builds this MIME header line from another one
|
||||||
|
* @param original Original header line to build from.
|
||||||
|
* @param newName Optional new header name. If 0, the original name will be used
|
||||||
|
*/
|
||||||
|
MimeHeaderLine(const MimeHeaderLine& original, const char* newName = 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor.
|
||||||
|
*/
|
||||||
|
virtual ~MimeHeaderLine();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RTTI method, get a pointer to a derived class given the class name.
|
||||||
|
* @param name Name of the class we are asking for
|
||||||
|
* @return Pointer to the requested class or NULL if this object doesn't implement it
|
||||||
|
*/
|
||||||
|
virtual void* getObject(const String& name) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Duplicate this MIME header line.
|
||||||
|
* @param newName Optional new header name. If 0, this header's name will be used
|
||||||
|
* @return Copy of this MIME header line
|
||||||
|
*/
|
||||||
|
virtual MimeHeaderLine* clone(const char* newName = 0) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a string line from this MIME header without adding a line separator
|
||||||
|
* @param line Destination string
|
||||||
|
*/
|
||||||
|
virtual void buildLine(String& line) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assignement operator. Set the header's value
|
||||||
|
* @param value The new headr value
|
||||||
|
*/
|
||||||
|
inline MimeHeaderLine& operator=(const char* value)
|
||||||
|
{ NamedString::operator=(value); return *this; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the header's parameters
|
||||||
|
* @return This header's list of parameters
|
||||||
|
*/
|
||||||
|
inline const ObjList& params() const
|
||||||
|
{ return m_params; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the character used as separator in header line
|
||||||
|
* @return This header's separator
|
||||||
|
*/
|
||||||
|
inline char separator() const
|
||||||
|
{ return m_separator; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replace the value of an existing parameter or add a new one
|
||||||
|
* @param name Parameter's name
|
||||||
|
* @param value Parameter's value
|
||||||
|
*/
|
||||||
|
void setParam(const char* name, const char* value = 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a parameter from list
|
||||||
|
* @param name Parameter's name
|
||||||
|
*/
|
||||||
|
void delParam(const char* name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a header parameter
|
||||||
|
* @param name Parameter's name
|
||||||
|
* @return Pointer to the desired parameter or 0 if not found
|
||||||
|
*/
|
||||||
|
const NamedString* getParam(const char* name) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility function, puts quotes around a string.
|
||||||
|
* @param str String to put quotes around.
|
||||||
|
*/
|
||||||
|
static void addQuotes(String& str);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility function, removes quotes around a string.
|
||||||
|
* @param str String to remove quotes.
|
||||||
|
*/
|
||||||
|
static void delQuotes(String& str);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility function, puts quotes around a string.
|
||||||
|
* @param str String to put quotes around.
|
||||||
|
* @return The input string enclosed in quotes.
|
||||||
|
*/
|
||||||
|
static String quote(const String& str);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility function to find a separator not in "quotes" or inside <uri>.
|
||||||
|
* @param str Input string used to find the separator.
|
||||||
|
* @param sep The separator to find.
|
||||||
|
* @param offs Starting offset in input string.
|
||||||
|
* @return The position of the separator in input string or -1 if not found.
|
||||||
|
*/
|
||||||
|
static int findSep(const char* str, char sep, int offs = 0);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ObjList m_params; // Header list of parameters
|
||||||
|
char m_separator; // Parameter separator
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A MIME header line containing authentication data.
|
||||||
|
* @short MIME authentication line
|
||||||
|
*/
|
||||||
|
class YATE_API MimeAuthLine : public MimeHeaderLine
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
* Builds a MIME authentication header line from a string buffer.
|
||||||
|
* Splits the value into header parameters
|
||||||
|
* @param name The header name
|
||||||
|
* @param value The header value
|
||||||
|
*/
|
||||||
|
MimeAuthLine(const char* name, const String& value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
* Builds this MIME authentication header line from another one
|
||||||
|
* @param original Original header line to build from.
|
||||||
|
* @param newName Optional new header name. If 0, the original name will be used
|
||||||
|
*/
|
||||||
|
MimeAuthLine(const MimeAuthLine& original, const char* newName = 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RTTI method, get a pointer to a derived class given the class name.
|
||||||
|
* @param name Name of the class we are asking for
|
||||||
|
* @return Pointer to the requested class or NULL if this object doesn't implement it
|
||||||
|
*/
|
||||||
|
virtual void* getObject(const String& name) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Duplicate this MIME header line.
|
||||||
|
* @param newName Optional new header name. If 0, this header's name will be used
|
||||||
|
* @return Copy of this MIME header line
|
||||||
|
*/
|
||||||
|
virtual MimeHeaderLine* clone(const char* newName = 0) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a string line from this MIME header without adding a line separator
|
||||||
|
* @param line Destination string
|
||||||
|
*/
|
||||||
|
virtual void buildLine(String& line) const;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract base class for holding Multipurpose Internet Mail Extensions data
|
* Abstract base class for holding Multipurpose Internet Mail Extensions data
|
||||||
* @short Abstract MIME data holder
|
* @short Abstract MIME data holder
|
||||||
|
@ -49,7 +219,7 @@ public:
|
||||||
virtual ~MimeBody();
|
virtual ~MimeBody();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RTTI method, get a pointer to a derived class given that class name
|
* RTTI method, get a pointer to a derived class given the class name
|
||||||
* @param name Name of the class we are asking for
|
* @param name Name of the class we are asking for
|
||||||
* @return Pointer to the requested class or NULL if this object doesn't implement it
|
* @return Pointer to the requested class or NULL if this object doesn't implement it
|
||||||
*/
|
*/
|
||||||
|
@ -59,7 +229,7 @@ public:
|
||||||
* Retrive the MIME type of this body
|
* Retrive the MIME type of this body
|
||||||
* @return Name of the MIME type/subtype
|
* @return Name of the MIME type/subtype
|
||||||
*/
|
*/
|
||||||
inline const String& getType() const
|
inline const MimeHeaderLine& getType() const
|
||||||
{ return m_type; }
|
{ return m_type; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -92,7 +262,8 @@ public:
|
||||||
* Method to build a MIME body from a type and data buffer
|
* Method to build a MIME body from a type and data buffer
|
||||||
* @param buf Pointer to buffer of data
|
* @param buf Pointer to buffer of data
|
||||||
* @param len Length of data in buffer
|
* @param len Length of data in buffer
|
||||||
* @param type Name of the MIME type/subtype, must be lower case
|
* @param type Name of the MIME type/subtype, must be lower case.
|
||||||
|
* This is the whole content type line, including the parameters
|
||||||
* @return Newly allocated MIME body or NULL if type is unknown
|
* @return Newly allocated MIME body or NULL if type is unknown
|
||||||
*/
|
*/
|
||||||
static MimeBody* build(const char* buf, int len, const String& type);
|
static MimeBody* build(const char* buf, int len, const String& type);
|
||||||
|
@ -123,7 +294,7 @@ protected:
|
||||||
mutable DataBlock m_body;
|
mutable DataBlock m_body;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
String m_type;
|
MimeHeaderLine m_type; // Content type header line
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -140,9 +311,9 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor from block of data
|
* Constructor from block of data
|
||||||
|
* @param type Name of the MIME type/subtype, should be "application/sdp"
|
||||||
* @param buf Pointer to buffer of data
|
* @param buf Pointer to buffer of data
|
||||||
* @param len Length of data in buffer
|
* @param len Length of data in buffer
|
||||||
* @param type Name of the MIME type/subtype, should be "application/sdp"
|
|
||||||
*/
|
*/
|
||||||
MimeSdpBody(const String& type, const char* buf, int len);
|
MimeSdpBody(const String& type, const char* buf, int len);
|
||||||
|
|
||||||
|
@ -152,7 +323,7 @@ public:
|
||||||
virtual ~MimeSdpBody();
|
virtual ~MimeSdpBody();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RTTI method, get a pointer to a derived class given that class name
|
* RTTI method, get a pointer to a derived class given the class name
|
||||||
* @param name Name of the class we are asking for
|
* @param name Name of the class we are asking for
|
||||||
* @return Pointer to the requested class or NULL if this object doesn't implement it
|
* @return Pointer to the requested class or NULL if this object doesn't implement it
|
||||||
*/
|
*/
|
||||||
|
@ -236,7 +407,7 @@ public:
|
||||||
virtual ~MimeBinaryBody();
|
virtual ~MimeBinaryBody();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RTTI method, get a pointer to a derived class given that class name
|
* RTTI method, get a pointer to a derived class given the class name
|
||||||
* @param name Name of the class we are asking for
|
* @param name Name of the class we are asking for
|
||||||
* @return Pointer to the requested class or NULL if this object doesn't implement it
|
* @return Pointer to the requested class or NULL if this object doesn't implement it
|
||||||
*/
|
*/
|
||||||
|
@ -281,7 +452,7 @@ public:
|
||||||
virtual ~MimeStringBody();
|
virtual ~MimeStringBody();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RTTI method, get a pointer to a derived class given that class name
|
* RTTI method, get a pointer to a derived class given the class name
|
||||||
* @param name Name of the class we are asking for
|
* @param name Name of the class we are asking for
|
||||||
* @return Pointer to the requested class or NULL if this object doesn't implement it
|
* @return Pointer to the requested class or NULL if this object doesn't implement it
|
||||||
*/
|
*/
|
||||||
|
@ -336,7 +507,7 @@ public:
|
||||||
virtual ~MimeLinesBody();
|
virtual ~MimeLinesBody();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RTTI method, get a pointer to a derived class given that class name
|
* RTTI method, get a pointer to a derived class given the class name
|
||||||
* @param name Name of the class we are asking for
|
* @param name Name of the class we are asking for
|
||||||
* @return Pointer to the requested class or NULL if this object doesn't implement it
|
* @return Pointer to the requested class or NULL if this object doesn't implement it
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue