From afded714aa9745f64376b663e3b7370dc4fe8d43 Mon Sep 17 00:00:00 2001 From: marian Date: Wed, 9 Jan 2008 11:32:35 +0000 Subject: [PATCH] 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 --- engine/Mime.cpp | 66 +++++++++++++++++++++++++----- libs/ysip/message.cpp | 25 ++++++++---- yatemime.h | 93 ++++++++++++++++++++++++++++++++++++++----- 3 files changed, 156 insertions(+), 28 deletions(-) diff --git a/engine/Mime.cpp b/engine/Mime.cpp index 5f58e2b0..bb68cdbd 100644 --- a/engine/Mime.cpp +++ b/engine/Mime.cpp @@ -302,9 +302,20 @@ YCLASSIMP(MimeBody,GenObject) MimeBody::MimeBody(const String& type) : m_type("Content-Type",type) { + m_type.toLower(); 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() { DDebug(DebugAll,"MimeBody::~MimeBody() '%s' [%p]",m_type.c_str(),this); @@ -317,16 +328,19 @@ const DataBlock& MimeBody::getBody() const 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()); if ((len <= 0) || !buf) return 0; - if (type == "application/sdp") + String what = type; + what.toLower(); + if (what == "application/sdp") return new MimeSdpBody(type,buf,len); - if (type == "application/dtmf-relay") + if (what == "application/dtmf-relay") 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 MimeBinaryBody(type,buf,len); } @@ -408,13 +422,13 @@ MimeSdpBody::MimeSdpBody() MimeSdpBody::MimeSdpBody(const String& type, const char* buf, int len) : MimeBody(type) { - 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(); - } + buildLines(buf,len); +} + +MimeSdpBody::MimeSdpBody(const MimeHeaderLine& type, const char* buf, int len) + : MimeBody(type) +{ + buildLines(buf,len); } MimeSdpBody::MimeSdpBody(const MimeSdpBody& original) @@ -480,6 +494,18 @@ const NamedString* MimeSdpBody::getNextLine(const NamedString* line) const 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) @@ -489,6 +515,12 @@ MimeBinaryBody::MimeBinaryBody(const String& type, const char* buf, int 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) : 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) : 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)); } +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) : MimeBody(original.getType()) { diff --git a/libs/ysip/message.cpp b/libs/ysip/message.cpp index 35c81e9a..1d2aa804 100644 --- a/libs/ysip/message.cpp +++ b/libs/ysip/message.cpp @@ -383,7 +383,6 @@ bool SIPMessage::parse(const char* buf, int len) return false; } line->destruct(); - String content; int clen = -1; while (len > 0) { line = MimeBody::getUnfoldedLine(buf,len); @@ -416,11 +415,7 @@ bool SIPMessage::parse(const char* buf, int len) else header.append(new MimeHeaderLine(name,*line)); - if (content.null() && (name &= "Content-Type")) { - content = *line; - content.toLower(); - } - else if ((clen < 0) && (name &= "Content-Length")) + if ((clen < 0) && (name &= "Content-Length")) clen = line->toInteger(-1,10); else if ((m_cseq < 0) && (name &= "CSeq")) { String seq = *line; @@ -440,7 +435,23 @@ bool SIPMessage::parse(const char* buf, int len) 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(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", header.count(),body); return true; diff --git a/yatemime.h b/yatemime.h index 543a91c9..7abf85a9 100644 --- a/yatemime.h +++ b/yatemime.h @@ -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 */ class YATE_API MimeBody : public GenObject @@ -232,6 +235,27 @@ public: inline const MimeHeaderLine& getType() const { 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 * @return Block of binary data @@ -239,7 +263,7 @@ public: 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 */ virtual bool isSDP() const @@ -262,11 +286,11 @@ 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. - * This is the whole content type line, including the parameters + * @param type The header line declaring the body's content. + * Usually this is a Content-Type header line * @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 @@ -278,11 +302,20 @@ public: protected: /** - * Constructor to be used only by derived classes - * @param type Name of the MIME type/subtype, must be lower case + * Constructor to be used only by derived classes. + * Converts the MIME type string to lower case + * @param type The value of the Content-Type header line */ 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 */ @@ -293,6 +326,11 @@ protected: */ mutable DataBlock m_body; + /** + * Additional body headers (other then Content-Type) + */ + ObjList m_headers; + private: MimeHeaderLine m_type; // Content type header line }; @@ -317,6 +355,14 @@ public: */ 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 */ @@ -383,6 +429,9 @@ protected: virtual void buildBody() const; private: + // Build the lines from a data buffer + void buildLines(const char* buf, int len); + ObjList m_lines; }; @@ -395,12 +444,20 @@ class YATE_API MimeBinaryBody : public MimeBody public: /** * Constructor from block of data + * @param type Name of the specific MIME type/subtype * @param buf Pointer to buffer of data * @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); + /** + * 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 */ @@ -440,12 +497,20 @@ class YATE_API MimeStringBody : public MimeBody public: /** * Constructor from block of data + * @param type Name of the specific MIME type/subtype * @param buf Pointer to buffer of data * @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); + /** + * 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 */ @@ -495,12 +560,20 @@ class YATE_API MimeLinesBody : public MimeBody public: /** * Constructor from block of data + * @param type Name of the specific MIME type/subtype * @param buf Pointer to buffer of data * @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); + /** + * 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 */