Added MIME body constructors from a header line. Adjusted SIP message parser to handle this.

git-svn-id: http://voip.null.ro/svn/yate@1607 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
marian 2008-01-09 11:32:35 +00:00
parent f58f72fa63
commit afded714aa
3 changed files with 156 additions and 28 deletions

View File

@ -302,9 +302,20 @@ YCLASSIMP(MimeBody,GenObject)
MimeBody::MimeBody(const String& type) MimeBody::MimeBody(const String& type)
: m_type("Content-Type",type) : m_type("Content-Type",type)
{ {
m_type.toLower();
DDebug(DebugAll,"MimeBody::MimeBody('%s') [%p]",m_type.c_str(),this); DDebug(DebugAll,"MimeBody::MimeBody('%s') [%p]",m_type.c_str(),this);
} }
// Build from header line
// Make sure the name of the header line is correct
MimeBody::MimeBody(const MimeHeaderLine& type)
: m_type(type,"Content-Type")
{
m_type.toLower();
DDebug(DebugAll,"MimeBody::MimeBody('%s','%s') [%p]",
m_type.name().c_str(),m_type.c_str(),this);
}
MimeBody::~MimeBody() MimeBody::~MimeBody()
{ {
DDebug(DebugAll,"MimeBody::~MimeBody() '%s' [%p]",m_type.c_str(),this); DDebug(DebugAll,"MimeBody::~MimeBody() '%s' [%p]",m_type.c_str(),this);
@ -317,16 +328,19 @@ const DataBlock& MimeBody::getBody() const
return m_body; return m_body;
} }
MimeBody* MimeBody::build(const char* buf, int len, const String& type) // Method to build a MIME body from a type and data buffer
MimeBody* MimeBody::build(const char* buf, int len, const MimeHeaderLine& type)
{ {
DDebug(DebugAll,"MimeBody::build(%p,%d,'%s')",buf,len,type.c_str()); DDebug(DebugAll,"MimeBody::build(%p,%d,'%s')",buf,len,type.c_str());
if ((len <= 0) || !buf) if ((len <= 0) || !buf)
return 0; return 0;
if (type == "application/sdp") String what = type;
what.toLower();
if (what == "application/sdp")
return new MimeSdpBody(type,buf,len); return new MimeSdpBody(type,buf,len);
if (type == "application/dtmf-relay") if (what == "application/dtmf-relay")
return new MimeLinesBody(type,buf,len); return new MimeLinesBody(type,buf,len);
if (type.startsWith("text/") || (type == "application/dtmf")) if (what.startsWith("text/") || (what == "application/dtmf"))
return new MimeStringBody(type,buf,len); return new MimeStringBody(type,buf,len);
return new MimeBinaryBody(type,buf,len); return new MimeBinaryBody(type,buf,len);
} }
@ -408,13 +422,13 @@ MimeSdpBody::MimeSdpBody()
MimeSdpBody::MimeSdpBody(const String& type, const char* buf, int len) MimeSdpBody::MimeSdpBody(const String& type, const char* buf, int len)
: MimeBody(type) : MimeBody(type)
{ {
while (len > 0) { buildLines(buf,len);
String* line = getUnfoldedLine(buf,len); }
int eq = line->find('=');
if (eq > 0) MimeSdpBody::MimeSdpBody(const MimeHeaderLine& type, const char* buf, int len)
m_lines.append(new NamedString(line->substr(0,eq),line->substr(eq+1))); : MimeBody(type)
line->destruct(); {
} buildLines(buf,len);
} }
MimeSdpBody::MimeSdpBody(const MimeSdpBody& original) MimeSdpBody::MimeSdpBody(const MimeSdpBody& original)
@ -480,6 +494,18 @@ const NamedString* MimeSdpBody::getNextLine(const NamedString* line) const
return 0; return 0;
} }
// Build the lines from a data buffer
void MimeSdpBody::buildLines(const char* buf, int len)
{
while (len > 0) {
String* line = getUnfoldedLine(buf,len);
int eq = line->find('=');
if (eq > 0)
m_lines.append(new NamedString(line->substr(0,eq),line->substr(eq+1)));
line->destruct();
}
}
YCLASSIMP(MimeBinaryBody,MimeBody) YCLASSIMP(MimeBinaryBody,MimeBody)
@ -489,6 +515,12 @@ MimeBinaryBody::MimeBinaryBody(const String& type, const char* buf, int len)
m_body.assign((void*)buf,len); m_body.assign((void*)buf,len);
} }
MimeBinaryBody::MimeBinaryBody(const MimeHeaderLine& type, const char* buf, int len)
: MimeBody(type)
{
m_body.assign((void*)buf,len);
}
MimeBinaryBody::MimeBinaryBody(const MimeBinaryBody& original) MimeBinaryBody::MimeBinaryBody(const MimeBinaryBody& original)
: MimeBody(original.getType()) : MimeBody(original.getType())
{ {
@ -518,6 +550,11 @@ MimeStringBody::MimeStringBody(const String& type, const char* buf, int len)
{ {
} }
MimeStringBody::MimeStringBody(const MimeHeaderLine& type, const char* buf, int len)
: MimeBody(type), m_text(buf,len)
{
}
MimeStringBody::MimeStringBody(const MimeStringBody& original) MimeStringBody::MimeStringBody(const MimeStringBody& original)
: MimeBody(original.getType()), m_text(original.m_text) : MimeBody(original.getType()), m_text(original.m_text)
{ {
@ -548,6 +585,13 @@ MimeLinesBody::MimeLinesBody(const String& type, const char* buf, int len)
m_lines.append(getUnfoldedLine(buf,len)); m_lines.append(getUnfoldedLine(buf,len));
} }
MimeLinesBody::MimeLinesBody(const MimeHeaderLine& type, const char* buf, int len)
: MimeBody(type)
{
while (len > 0)
m_lines.append(getUnfoldedLine(buf,len));
}
MimeLinesBody::MimeLinesBody(const MimeLinesBody& original) MimeLinesBody::MimeLinesBody(const MimeLinesBody& original)
: MimeBody(original.getType()) : MimeBody(original.getType())
{ {

View File

@ -383,7 +383,6 @@ bool SIPMessage::parse(const char* buf, int len)
return false; return false;
} }
line->destruct(); line->destruct();
String content;
int clen = -1; int clen = -1;
while (len > 0) { while (len > 0) {
line = MimeBody::getUnfoldedLine(buf,len); line = MimeBody::getUnfoldedLine(buf,len);
@ -416,11 +415,7 @@ bool SIPMessage::parse(const char* buf, int len)
else else
header.append(new MimeHeaderLine(name,*line)); header.append(new MimeHeaderLine(name,*line));
if (content.null() && (name &= "Content-Type")) { if ((clen < 0) && (name &= "Content-Length"))
content = *line;
content.toLower();
}
else if ((clen < 0) && (name &= "Content-Length"))
clen = line->toInteger(-1,10); clen = line->toInteger(-1,10);
else if ((m_cseq < 0) && (name &= "CSeq")) { else if ((m_cseq < 0) && (name &= "CSeq")) {
String seq = *line; String seq = *line;
@ -440,7 +435,23 @@ bool SIPMessage::parse(const char* buf, int len)
len = clen; len = clen;
} }
} }
body = MimeBody::build(buf,len,content); const MimeHeaderLine* cType = getHeader("Content-Type");
if (cType)
body = MimeBody::build(buf,len,*cType);
// Move extra Content- header lines to body
if (body) {
ListIterator iter(header);
for (GenObject* o = 0; (o = iter.get());) {
MimeHeaderLine* line = static_cast<MimeHeaderLine*>(o);
if (!line->startsWith("Content-",false,true) || (*line &= "Content-Length"))
continue;
// Delete Content-Type and move all other lines to body
bool delobj = (line == cType);
header.remove(o,delobj);
if (!delobj)
body->appendHdr(line);
}
}
DDebug(DebugAll,"SIPMessage::parse %d header lines, body %p", DDebug(DebugAll,"SIPMessage::parse %d header lines, body %p",
header.count(),body); header.count(),body);
return true; return true;

View File

@ -207,7 +207,10 @@ public:
}; };
/** /**
* Abstract base class for holding Multipurpose Internet Mail Extensions data * Abstract base class for holding Multipurpose Internet Mail Extensions data.
* Keeps a Content-Type header line with body type and parameters and
* any additional header lines the body may have.
* The body type contains lower case characters.
* @short Abstract MIME data holder * @short Abstract MIME data holder
*/ */
class YATE_API MimeBody : public GenObject class YATE_API MimeBody : public GenObject
@ -232,6 +235,27 @@ public:
inline const MimeHeaderLine& getType() const inline const MimeHeaderLine& getType() const
{ return m_type; } { return m_type; }
/**
* Retrive the additional headers of this MIME body (other then Content-Type)
* @return The list of header lines of this MIME body
*/
inline const ObjList& headers() const
{ return m_headers; }
/**
* Append an additional header line to this body
* @param hdr The header line to append
*/
inline void appendHdr(MimeHeaderLine* hdr)
{ if (hdr) m_headers.append(hdr); }
/**
* Remove an additional header line from this body
* @param hdr The header line to remove
*/
inline void removeHdr(MimeHeaderLine* hdr)
{ if (hdr) m_headers.remove(hdr); }
/** /**
* Retrive the binary encoding of this MIME body * Retrive the binary encoding of this MIME body
* @return Block of binary data * @return Block of binary data
@ -239,7 +263,7 @@ public:
const DataBlock& getBody() const; const DataBlock& getBody() const;
/** /**
* Check if this body is an Session Description Protocol * Check if this body is a Session Description Protocol
* @return True if this body holds a SDP * @return True if this body holds a SDP
*/ */
virtual bool isSDP() const virtual bool isSDP() const
@ -262,11 +286,11 @@ 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 The header line declaring the body's content.
* This is the whole content type line, including the parameters * Usually this is a Content-Type header line
* @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 MimeHeaderLine& type);
/** /**
* Utility method, returns an unfolded line and advances the pointer * Utility method, returns an unfolded line and advances the pointer
@ -278,11 +302,20 @@ public:
protected: protected:
/** /**
* Constructor to be used only by derived classes * Constructor to be used only by derived classes.
* @param type Name of the MIME type/subtype, must be lower case * Converts the MIME type string to lower case
* @param type The value of the Content-Type header line
*/ */
MimeBody(const String& type); MimeBody(const String& type);
/**
* Constructor to be used only by derived classes.
* Builds this body from a header line.
* Converts the MIME type string to lower case
* @param type The content type header line
*/
MimeBody(const MimeHeaderLine& type);
/** /**
* Method that is called internally to build the binary encoded body * Method that is called internally to build the binary encoded body
*/ */
@ -293,6 +326,11 @@ protected:
*/ */
mutable DataBlock m_body; mutable DataBlock m_body;
/**
* Additional body headers (other then Content-Type)
*/
ObjList m_headers;
private: private:
MimeHeaderLine m_type; // Content type header line MimeHeaderLine m_type; // Content type header line
}; };
@ -317,6 +355,14 @@ public:
*/ */
MimeSdpBody(const String& type, const char* buf, int len); MimeSdpBody(const String& type, const char* buf, int len);
/**
* Constructor from block of data
* @param type The content type header line
* @param buf Pointer to buffer of data
* @param len Length of data in buffer
*/
MimeSdpBody(const MimeHeaderLine& type, const char* buf, int len);
/** /**
* Destructor * Destructor
*/ */
@ -383,6 +429,9 @@ protected:
virtual void buildBody() const; virtual void buildBody() const;
private: private:
// Build the lines from a data buffer
void buildLines(const char* buf, int len);
ObjList m_lines; ObjList m_lines;
}; };
@ -395,12 +444,20 @@ class YATE_API MimeBinaryBody : public MimeBody
public: public:
/** /**
* Constructor from block of data * Constructor from block of data
* @param type Name of the specific MIME type/subtype
* @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 specific MIME type/subtype
*/ */
MimeBinaryBody(const String& type, const char* buf, int len); MimeBinaryBody(const String& type, const char* buf, int len);
/**
* Constructor from block of data
* @param type The content type header line
* @param buf Pointer to buffer of data
* @param len Length of data in buffer
*/
MimeBinaryBody(const MimeHeaderLine& type, const char* buf, int len);
/** /**
* Destructor * Destructor
*/ */
@ -440,12 +497,20 @@ class YATE_API MimeStringBody : public MimeBody
public: public:
/** /**
* Constructor from block of data * Constructor from block of data
* @param type Name of the specific MIME type/subtype
* @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 specific MIME type/subtype
*/ */
MimeStringBody(const String& type, const char* buf, int len = -1); MimeStringBody(const String& type, const char* buf, int len = -1);
/**
* Constructor from block of data
* @param type The content type header line
* @param buf Pointer to buffer of data
* @param len Length of data in buffer
*/
MimeStringBody(const MimeHeaderLine& type, const char* buf, int len = -1);
/** /**
* Destructor * Destructor
*/ */
@ -495,12 +560,20 @@ class YATE_API MimeLinesBody : public MimeBody
public: public:
/** /**
* Constructor from block of data * Constructor from block of data
* @param type Name of the specific MIME type/subtype
* @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 specific MIME type/subtype
*/ */
MimeLinesBody(const String& type, const char* buf, int len); MimeLinesBody(const String& type, const char* buf, int len);
/**
* Constructor from block of data
* @param type The content type header line
* @param buf Pointer to buffer of data
* @param len Length of data in buffer
*/
MimeLinesBody(const MimeHeaderLine& type, const char* buf, int len);
/** /**
* Destructor * Destructor
*/ */