Moved header classes and some utilities from SIP to MIME. Updated SIP module and library to reflect the changes.

git-svn-id: http://yate.null.ro/svn/yate/trunk@1599 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
marian 2008-01-08 12:29:12 +00:00
parent e4f067a1eb
commit dabd23216d
9 changed files with 543 additions and 406 deletions

View File

@ -30,10 +30,277 @@ static bool isContinuationBlank(char c)
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)
MimeBody::MimeBody(const String& type)
: m_type(type)
: m_type("Content-Type",type)
{
DDebug(DebugAll,"MimeBody::MimeBody('%s') [%p]",m_type.c_str(),this);
}

View File

@ -192,7 +192,7 @@ SIPTransaction* SIPEngine::addMessage(SIPMessage* message)
if (message->isOutgoing())
message->complete(this);
// 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)
#ifdef SIP_STRICT
return 0;
@ -465,10 +465,10 @@ int SIPEngine::authUser(const SIPMessage* message, String& user, bool proxy, Gen
const ObjList* l = &message->header;
for (; l; l = l->next()) {
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")) {
String usr(t->getParam("username"));
delQuotes(usr);
MimeHeaderLine::delQuotes(usr);
if (usr.null())
continue;
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))
continue;
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
if (nonce.null())
continue;
@ -487,15 +487,15 @@ int SIPEngine::authUser(const SIPMessage* message, String& user, bool proxy, Gen
noUser = false;
XDebug(this,DebugAll,"authUser nonce age is %ld",age);
String res(t->getParam("response"));
delQuotes(res);
MimeHeaderLine::delQuotes(res);
if (res.null())
continue;
String uri(t->getParam("uri"));
delQuotes(uri);
MimeHeaderLine::delQuotes(uri);
if (uri.null())
uri = message->uri;
String realm(t->getParam("realm"));
delQuotes(realm);
MimeHeaderLine::delQuotes(realm);
if (!checkUser(usr,realm,nonce,message->method,uri,res,message,userData))
continue;

View File

@ -30,200 +30,6 @@
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)
: version(original.version), method(original.method), uri(original.uri),
code(original.code), reason(original.reason),
@ -240,13 +46,13 @@ SIPMessage::SIPMessage(const SIPMessage& original)
bool via1 = true;
const ObjList* l = &original.header;
for (; l; l = l->next()) {
const SIPHeaderLine* hl = static_cast<SIPHeaderLine*>(l->get());
const MimeHeaderLine* hl = static_cast<MimeHeaderLine*>(l->get());
if (!hl)
continue;
// CSeq must not be copied, a new one will be built by complete()
if (hl->name() &= "CSeq")
continue;
SIPHeaderLine* nl = hl->clone();
MimeHeaderLine* nl = hl->clone();
// this is a new transaction so let complete() add randomness
if (via1 && (nl->name() &= "Via")) {
via1 = false;
@ -323,19 +129,19 @@ SIPMessage::SIPMessage(const SIPMessage* original, const SIPMessage* answer)
version = original->version;
uri = original->uri;
copyAllHeaders(original,"Via");
SIPHeaderLine* hl = const_cast<SIPHeaderLine*>(getHeader("Via"));
MimeHeaderLine* hl = const_cast<MimeHeaderLine*>(getHeader("Via"));
if (!hl) {
String tmp;
tmp << version << "/" << getParty()->getProtoName();
tmp << " " << getParty()->getLocalAddr() << ":" << getParty()->getLocalPort();
hl = new SIPHeaderLine("Via",tmp);
hl = new MimeHeaderLine("Via",tmp);
header.append(hl);
}
if (answer && (answer->code == 200) && (original->method &= "INVITE")) {
String tmp("z9hG4bK");
tmp << (int)::random();
hl->setParam("branch",tmp);
const SIPHeaderLine* co = answer->getHeader("Contact");
const MimeHeaderLine* co = answer->getHeader("Contact");
if (co) {
uri = *co;
Regexp r("^[^<]*<\\([^>]*\\)>.*$");
@ -397,7 +203,7 @@ void SIPMessage::complete(SIPEngine* engine, const char* user, const char* domai
// only set the dialog tag on ACK
if (isACK()) {
SIPHeaderLine* hl = const_cast<SIPHeaderLine*>(getHeader("To"));
MimeHeaderLine* hl = const_cast<MimeHeaderLine*>(getHeader("To"));
if (dlgTag && hl && !hl->getParam("tag"))
hl->setParam("tag",dlgTag);
return;
@ -406,12 +212,12 @@ void SIPMessage::complete(SIPEngine* engine, const char* user, const char* domai
if (!domain)
domain = getParty()->getLocalAddr();
SIPHeaderLine* hl = const_cast<SIPHeaderLine*>(getHeader("Via"));
MimeHeaderLine* hl = const_cast<MimeHeaderLine*>(getHeader("Via"));
if (!hl) {
String tmp;
tmp << version << "/" << getParty()->getProtoName();
tmp << " " << getParty()->getLocalAddr() << ":" << getParty()->getLocalPort();
hl = new SIPHeaderLine("Via",tmp);
hl = new MimeHeaderLine("Via",tmp);
if (!(isAnswer() || isACK()))
hl->setParam("rport");
header.append(hl);
@ -427,24 +233,24 @@ void SIPMessage::complete(SIPEngine* engine, const char* user, const char* domai
}
if (!isAnswer()) {
hl = const_cast<SIPHeaderLine*>(getHeader("From"));
hl = const_cast<MimeHeaderLine*>(getHeader("From"));
if (!hl) {
String tmp = "<sip:";
if (user)
tmp << user << "@";
tmp << domain << ">";
hl = new SIPHeaderLine("From",tmp);
hl = new MimeHeaderLine("From",tmp);
header.append(hl);
}
if (!hl->getParam("tag"))
hl->setParam("tag",String((int)::random()));
}
hl = const_cast<SIPHeaderLine*>(getHeader("To"));
hl = const_cast<MimeHeaderLine*>(getHeader("To"));
if (!(isAnswer() || hl)) {
String tmp;
tmp << "<" << uri << ">";
hl = new SIPHeaderLine("To",tmp);
hl = new MimeHeaderLine("To",tmp);
header.append(hl);
}
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)
{
const SIPHeaderLine* hl = message ? message->getHeader(name) : 0;
const MimeHeaderLine* hl = message ? message->getHeader(name) : 0;
if (hl) {
header.append(hl->clone(newName));
return true;
@ -514,7 +320,7 @@ int SIPMessage::copyAllHeaders(const SIPMessage* message, const char* name, cons
int c = 0;
const ObjList* l = &message->header;
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)) {
++c;
header.append(hl->clone(newName));
@ -606,9 +412,9 @@ bool SIPMessage::parse(const char* buf, int len)
(name &= "Proxy-Authenticate") ||
(name &= "Authorization") ||
(name &= "Proxy-Authorization"))
header.append(new SIPAuthLine(name,*line));
header.append(new MimeAuthLine(name,*line));
else
header.append(new SIPHeaderLine(name,*line));
header.append(new MimeHeaderLine(name,*line));
if (content.null() && (name &= "Content-Type")) {
content = *line;
@ -650,27 +456,27 @@ SIPMessage* SIPMessage::fromParsing(SIPParty* ep, const char* buf, int len)
return 0;
}
const SIPHeaderLine* SIPMessage::getHeader(const char* name) const
const MimeHeaderLine* SIPMessage::getHeader(const char* name) const
{
if (!(name && *name))
return 0;
const ObjList* l = &header;
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))
return t;
}
return 0;
}
const SIPHeaderLine* SIPMessage::getLastHeader(const char* name) const
const MimeHeaderLine* SIPMessage::getLastHeader(const char* name) const
{
if (!(name && *name))
return 0;
const SIPHeaderLine* res = 0;
const MimeHeaderLine* res = 0;
const ObjList* l = &header;
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))
res = t;
}
@ -683,7 +489,7 @@ void SIPMessage::clearHeaders(const char* name)
return;
ObjList* l = &header;
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))
l->remove();
else
@ -698,7 +504,7 @@ int SIPMessage::countHeaders(const char* name) const
int res = 0;
const ObjList* l = &header;
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))
++res;
}
@ -707,13 +513,13 @@ int SIPMessage::countHeaders(const char* name) 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;
}
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();
}
@ -733,7 +539,7 @@ const String& SIPMessage::getHeaders() const
const ObjList* l = &header;
for (; l; l = l->next()) {
SIPHeaderLine* t = static_cast<SIPHeaderLine*>(l->get());
MimeHeaderLine* t = static_cast<MimeHeaderLine*>(l->get());
if (t) {
t->buildLine(m_string);
m_string << "\r\n";
@ -749,8 +555,8 @@ const DataBlock& SIPMessage::getBuffer() const
m_data.assign((void*)(getHeaders().c_str()),getHeaders().length());
if (body) {
String s;
s << "Content-Type: " << body->getType() << "\r\n";
s << "Content-Length: " << body->getBody().length() << "\r\n\r\n";
body->getType().buildLine(s);
s << "\r\nContent-Length: " << body->getBody().length() << "\r\n\r\n";
m_data += s;
}
else
@ -787,30 +593,30 @@ void SIPMessage::setParty(SIPParty* ep)
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 char* hdr = proxy ? "Proxy-Authenticate" : "WWW-Authenticate";
const ObjList* l = &header;
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")) {
String nonce(t->getParam("nonce"));
delQuotes(nonce);
MimeHeaderLine::delQuotes(nonce);
if (nonce.null())
continue;
String realm(t->getParam("realm"));
delQuotes(realm);
MimeHeaderLine::delQuotes(realm);
int par = uri.find(';');
String msguri = uri.substr(0,par);
String response;
SIPEngine::buildAuth(username,realm,password,nonce,meth,msguri,response);
SIPAuthLine* auth = new SIPAuthLine(proxy ? "Proxy-Authorization" : "Authorization","Digest");
auth->setParam("username",quote(username));
auth->setParam("realm",quote(realm));
auth->setParam("nonce",quote(nonce));
auth->setParam("uri",quote(msguri));
auth->setParam("response",quote(response));
MimeAuthLine* auth = new MimeAuthLine(proxy ? "Proxy-Authorization" : "Authorization","Digest");
auth->setParam("username",MimeHeaderLine::quote(username));
auth->setParam("realm",MimeHeaderLine::quote(realm));
auth->setParam("nonce",MimeHeaderLine::quote(nonce));
auth->setParam("uri",MimeHeaderLine::quote(msguri));
auth->setParam("response",MimeHeaderLine::quote(response));
auth->setParam("algorithm","MD5");
// copy opaque data as-is, only if present
const NamedString* opaque = t->getParam("opaque");
@ -822,7 +628,7 @@ SIPAuthLine* SIPMessage::buildAuth(const String& username, const String& passwor
return 0;
}
SIPAuthLine* SIPMessage::buildAuth(const SIPMessage& original) const
MimeAuthLine* SIPMessage::buildAuth(const SIPMessage& original) const
{
if (original.getAuthUsername().null())
return 0;
@ -835,18 +641,18 @@ ObjList* SIPMessage::getRoutes() const
ObjList* list = 0;
const ObjList* l = &header;
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")) {
int p = 0;
while (p >= 0) {
SIPHeaderLine* line = 0;
int s = findSep(*h,',',p);
MimeHeaderLine* line = 0;
int s = MimeHeaderLine::findSep(*h,',',p);
String tmp;
if (s < 0) {
if (p)
tmp = h->substr(p);
else
line = new SIPHeaderLine(*h,"Route");
line = new MimeHeaderLine(*h,"Route");
p = -1;
}
else {
@ -856,7 +662,7 @@ ObjList* SIPMessage::getRoutes() const
}
tmp.trimBlanks();
if (tmp)
line = new SIPHeaderLine("Route",tmp);
line = new MimeHeaderLine("Route",tmp);
if (!line)
continue;
if (!list)
@ -877,7 +683,7 @@ void SIPMessage::addRoutes(const ObjList* routes)
{
if (isAnswer() || !routes)
return;
SIPHeaderLine* hl = YOBJECT(SIPHeaderLine,routes->get());
MimeHeaderLine* hl = YOBJECT(MimeHeaderLine,routes->get());
if (hl) {
// check if first route is to a RFC 2543 proxy
String tmp = *hl;
@ -886,7 +692,7 @@ void SIPMessage::addRoutes(const ObjList* routes)
tmp = tmp.matchString(1);
if (tmp.find(";lr") < 0) {
// 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
uri = tmp;
routes = routes->next();
@ -897,7 +703,7 @@ void SIPMessage::addRoutes(const ObjList* routes)
// add (remaining) routes
for (; routes; routes = routes->next()) {
const SIPHeaderLine* h = YOBJECT(SIPHeaderLine,routes->get());
const MimeHeaderLine* h = YOBJECT(MimeHeaderLine,routes->get());
if (h)
addHeader(h->clone());
}
@ -949,7 +755,7 @@ SIPDialog::SIPDialog(const SIPMessage& message)
{
Regexp r("<\\([^>]\\+\\)>");
bool local = message.isOutgoing() ^ message.isAnswer();
const SIPHeaderLine* hl = message.getHeader(local ? "From" : "To");
const MimeHeaderLine* hl = message.getHeader(local ? "From" : "To");
localURI = hl;
if (localURI.matches(r))
localURI = localURI.matchString(1);
@ -972,7 +778,7 @@ SIPDialog& SIPDialog::operator=(const SIPMessage& message)
String::operator=(cid);
Regexp r("<\\([^>]\\+\\)>");
bool local = message.isOutgoing() ^ message.isAnswer();
const SIPHeaderLine* hl = message.getHeader(local ? "From" : "To");
const MimeHeaderLine* hl = message.getHeader(local ? "From" : "To");
localURI = hl;
if (localURI.matches(r))
localURI = localURI.matchString(1);

View File

@ -48,7 +48,7 @@ SIPTransaction::SIPTransaction(SIPMessage* message, SIPEngine* engine, bool outg
if (ns)
m_tag = *ns;
const SIPHeaderLine* hl = message->getHeader("Call-ID");
const MimeHeaderLine* hl = message->getHeader("Call-ID");
if (hl)
m_callid = *hl;
@ -83,7 +83,7 @@ SIPTransaction::SIPTransaction(SIPTransaction& original, SIPMessage* answer)
&original,answer,this);
SIPMessage* msg = new SIPMessage(*original.m_firstMessage);
SIPAuthLine* auth = answer->buildAuth(*original.m_firstMessage);
MimeAuthLine* auth = answer->buildAuth(*original.m_firstMessage);
m_firstMessage->setAutoAuth();
msg->complete(m_engine);
msg->addHeader(auth);
@ -370,7 +370,7 @@ void SIPTransaction::requestAuth(const String& realm, const String& domain, bool
if (realm) {
String tmp;
tmp << "Digest realm=\"" << realm << "\"";
SIPHeaderLine* line = new SIPHeaderLine(hdr,tmp,',');
MimeHeaderLine* line = new MimeHeaderLine(hdr,tmp,',');
if (domain)
line->setParam(" domain","\"" + domain + "\"");
m_engine->nonceGet(tmp);

View File

@ -75,68 +75,6 @@ const char* compactForm(const char* 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: */

View File

@ -31,18 +31,6 @@ const char* uncompactForm(const char* header);
// Utility function, returns a compacted header name
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: */

View File

@ -84,39 +84,6 @@ protected:
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.
* 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
* @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
* @param name Name of the header to locate
* @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
@ -286,13 +253,13 @@ public:
* @param value Content of the new header line
*/
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
* @param line Header line to add
*/
inline void addHeader(SIPHeaderLine* line)
inline void addHeader(MimeHeaderLine* line)
{ header.append(line); }
/**
@ -316,7 +283,7 @@ public:
* @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
*/
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;
/**
@ -324,7 +291,7 @@ public:
* @param original Origianl outgoing message
* @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.
@ -350,13 +317,13 @@ public:
/**
* 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;
/**
* 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);

View File

@ -377,7 +377,7 @@ private:
bool addSdpParams(Message& msg, const MimeBody* body);
bool addRtpParams(Message& msg, const String& natAddr, const MimeBody* body);
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_tr2;
@ -723,7 +723,7 @@ static void copySipHeaders(Message& msg, const SIPMessage& sip, bool filter = tr
{
const ObjList* l = sip.header.skipNull();
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());
name.toLower();
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)
{
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))
return;
const NamedString* p = hl ? hl->getParam("screen") : 0;
@ -807,7 +807,7 @@ static void copyPrivacy(SIPMessage& sip, const Message& msg)
if (tmp)
tmp = "\"" + tmp + "\" ";
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)
hl->setParam("screen","yes");
if (privname && privuri)
@ -1451,7 +1451,7 @@ void YateSIPEndPoint::regreq(SIPEvent* e, SIPTransaction* t)
return;
}
const SIPMessage* message = e->getMessage();
const SIPHeaderLine* hl = message->getHeader("Contact");
const MimeHeaderLine* hl = message->getHeader("Contact");
if (!hl) {
t->setResponse(400);
return;
@ -1542,7 +1542,7 @@ void YateSIPEndPoint::regreq(SIPEvent* e, SIPTransaction* t)
tmp = expires;
SIPMessage* r = new SIPMessage(t->initialMessage(),200);
r->addHeader("Expires",tmp);
SIPHeaderLine* contact = new SIPHeaderLine("Contact","<" + addr + ">");
MimeHeaderLine* contact = new MimeHeaderLine("Contact","<" + addr + ">");
contact->setParam("expires",tmp);
r->addHeader(contact);
if (natChanged) {
@ -1562,7 +1562,7 @@ void YateSIPEndPoint::regreq(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 != "application/sdp") {
t->setResponse(415);
@ -1736,7 +1736,7 @@ YateSIPConnection::YateSIPConnection(SIPEvent* ev, SIPTransaction* tr)
m->addParam("called",uri.getUser());
if (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) {
const NamedString* type = hl->getParam("purpose");
if (!type || *type == "info")
@ -1885,14 +1885,14 @@ YateSIPConnection::YateSIPConnection(Message& msg, const String& uri, const char
if (display) {
String desc;
desc << "\"" << display << "\" ";
SIPHeaderLine* hl = const_cast<SIPHeaderLine*>(m->getHeader("From"));
MimeHeaderLine* hl = const_cast<MimeHeaderLine*>(m->getHeader("From"));
if (hl)
*hl = desc + *hl;
}
if (msg.getParam("calledname")) {
String desc;
desc << "\"" << msg.getValue("calledname") << "\" ";
SIPHeaderLine* hl = const_cast<SIPHeaderLine*>(m->getHeader("To"));
MimeHeaderLine* hl = const_cast<MimeHeaderLine*>(m->getHeader("To"));
if (hl)
*hl = desc + *hl;
}
@ -1909,19 +1909,19 @@ YateSIPConnection::YateSIPConnection(Message& msg, const String& uri, const char
// add some Call-Info headers
const char* info = msg.getValue("caller_info_uri");
if (info) {
SIPHeaderLine* hl = new SIPHeaderLine("Call-Info",info);
MimeHeaderLine* hl = new MimeHeaderLine("Call-Info",info);
hl->setParam("purpose","info");
m->addHeader(hl);
}
info = msg.getValue("caller_icon_uri");
if (info) {
SIPHeaderLine* hl = new SIPHeaderLine("Call-Info",info);
MimeHeaderLine* hl = new MimeHeaderLine("Call-Info",info);
hl->setParam("purpose","icon");
m->addHeader(hl);
}
info = msg.getValue("caller_card_uri");
if (info) {
SIPHeaderLine* hl = new SIPHeaderLine("Call-Info",info);
MimeHeaderLine* hl = new MimeHeaderLine("Call-Info",info);
hl->setParam("purpose","card");
m->addHeader(hl);
}
@ -2058,7 +2058,7 @@ void YateSIPConnection::hangup()
tmp << i->getCSeq() << " CANCEL";
m->addHeader("CSeq",tmp);
if (m_reason == "pickup") {
SIPHeaderLine* hl = new SIPHeaderLine("Reason","SIP");
MimeHeaderLine* hl = new MimeHeaderLine("Reason","SIP");
hl->setParam("cause","200");
hl->setParam("text","\"Call completed elsewhere\"");
m->addHeader(hl);
@ -2078,7 +2078,7 @@ void YateSIPConnection::hangup()
if (m) {
if (m_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 + "\"");
m->addHeader(hl);
}
@ -2108,7 +2108,7 @@ SIPMessage* YateSIPConnection::createDlgMsg(const char* method, const char* uri)
m->addHeader("Call-ID",m_callid);
String tmp;
tmp << "<" << m_dialog.localURI << ">";
SIPHeaderLine* hl = new SIPHeaderLine("From",tmp);
MimeHeaderLine* hl = new MimeHeaderLine("From",tmp);
tmp = m_dialog.localTag;
if (tmp.null() && m_tr)
tmp = m_tr->getDialogTag();
@ -2117,7 +2117,7 @@ SIPMessage* YateSIPConnection::createDlgMsg(const char* method, const char* uri)
m->addHeader(hl);
tmp.clear();
tmp << "<" << m_dialog.remoteURI << ">";
hl = new SIPHeaderLine("To",tmp);
hl = new MimeHeaderLine("To",tmp);
tmp = m_dialog.remoteTag;
if (tmp.null() && m_tr)
tmp = m_tr->getDialogTag();
@ -2134,8 +2134,8 @@ bool YateSIPConnection::emitPRACK(const SIPMessage* msg)
return false;
if (!plugin.ep()->engine()->prack())
return true;
const SIPHeaderLine* rs = msg->getHeader("RSeq");
const SIPHeaderLine* cs = msg->getHeader("CSeq");
const MimeHeaderLine* rs = msg->getHeader("RSeq");
const MimeHeaderLine* cs = msg->getHeader("CSeq");
if (!(rs && cs))
return true;
int seq = rs->toInteger(0,10);
@ -2148,7 +2148,7 @@ bool YateSIPConnection::emitPRACK(const SIPMessage* msg)
return false;
}
String tmp;
const SIPHeaderLine* co = msg->getHeader("Contact");
const MimeHeaderLine* co = msg->getHeader("Contact");
if (co) {
tmp = *co;
Regexp r("^[^<]*<\\([^>]*\\)>.*$");
@ -2616,7 +2616,7 @@ bool YateSIPConnection::process(SIPEvent* ev)
// see if we should detect our external address
const YateSIPLine* line = plugin.findLine(m_line);
if (line && line->localDetect()) {
SIPHeaderLine* hl = const_cast<SIPHeaderLine*>(msg->getHeader("Via"));
MimeHeaderLine* hl = const_cast<MimeHeaderLine*>(msg->getHeader("Via"));
if (hl) {
const NamedString* par = hl->getParam("received");
if (par && *par) {
@ -2922,7 +2922,7 @@ void YateSIPConnection::doBye(SIPTransaction* t)
if (m_authBye && !checkUser(t))
return;
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) {
const NamedString* text = hl->getParam("text");
if (text)
@ -3001,7 +3001,7 @@ void YateSIPConnection::doRefer(SIPTransaction* t)
return;
}
m_referring = true;
const SIPHeaderLine* refHdr = t->initialMessage()->getHeader("Refer-To");
const MimeHeaderLine* refHdr = t->initialMessage()->getHeader("Refer-To");
if (!(refHdr && refHdr->length())) {
DDebug(this,DebugAll,"YateSIPConnection::doRefer(%p) [%p]. Empty or missing 'Refer-To' header.",t,this);
t->setResponse(400); // Bad request
@ -3093,7 +3093,7 @@ bool YateSIPConnection::msgAnswered(Message& msg)
}
m->setBody(sdp);
const SIPHeaderLine* co = m_tr->initialMessage()->getHeader("Contact");
const MimeHeaderLine* co = m_tr->initialMessage()->getHeader("Contact");
if (co) {
// INVITE had a Contact: header - time to change remote URI
m_uri = *co;
@ -3422,7 +3422,7 @@ void YateSIPConnection::startPendingUpdate()
// sipRefer: received REFER message, refHdr: 'Refer-To' header
// If return false, msg and sipNotify are 0
bool YateSIPConnection::initUnattendedTransfer(Message*& msg, SIPMessage*& sipNotify,
const SIPMessage* sipRefer, const SIPHeaderLine* refHdr)
const SIPMessage* sipRefer, const MimeHeaderLine* refHdr)
{
// call.route
msg = new Message("call.route");
@ -3432,7 +3432,7 @@ bool YateSIPConnection::initUnattendedTransfer(Message*& msg, SIPMessage*& sipNo
if (m_user)
msg->addParam("username",m_user);
const SIPHeaderLine* sh = sipRefer->getHeader("To"); // caller
const MimeHeaderLine* sh = sipRefer->getHeader("To"); // caller
if (sh) {
URI uriCaller(*sh);
uriCaller.parse();
@ -3456,7 +3456,7 @@ bool YateSIPConnection::initUnattendedTransfer(Message*& msg, SIPMessage*& sipNo
msg->addParam("reason","transfer"); // reason
// NOTIFY
String tmp;
const SIPHeaderLine* co = sipRefer->getHeader("Contact");
const MimeHeaderLine* co = sipRefer->getHeader("Contact");
if (co) {
tmp = *co;
Regexp r("^[^<]*<\\([^>]*\\)>.*$");
@ -3651,7 +3651,7 @@ void YateSIPLine::detectLocal(const SIPMessage* msg)
return;
String laddr = m_localAddr;
int lport = m_localPort;
SIPHeaderLine* hl = const_cast<SIPHeaderLine*>(msg->getHeader("Via"));
MimeHeaderLine* hl = const_cast<MimeHeaderLine*>(msg->getHeader("Via"));
if (hl) {
const NamedString* par = hl->getParam("received");
if (par && *par)

View File

@ -36,6 +36,176 @@
*/
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
* @short Abstract MIME data holder
@ -49,7 +219,7 @@ public:
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
* @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
* @return Name of the MIME type/subtype
*/
inline const String& getType() const
inline const MimeHeaderLine& getType() const
{ return m_type; }
/**
@ -92,7 +262,8 @@ public:
* Method to build a MIME body from a type and data buffer
* @param buf Pointer to buffer of data
* @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
*/
static MimeBody* build(const char* buf, int len, const String& type);
@ -123,7 +294,7 @@ protected:
mutable DataBlock m_body;
private:
String m_type;
MimeHeaderLine m_type; // Content type header line
};
/**
@ -140,9 +311,9 @@ public:
/**
* 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 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);
@ -152,7 +323,7 @@ public:
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
* @return Pointer to the requested class or NULL if this object doesn't implement it
*/
@ -236,7 +407,7 @@ public:
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
* @return Pointer to the requested class or NULL if this object doesn't implement it
*/
@ -281,7 +452,7 @@ public:
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
* @return Pointer to the requested class or NULL if this object doesn't implement it
*/
@ -336,7 +507,7 @@ public:
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
* @return Pointer to the requested class or NULL if this object doesn't implement it
*/