Fixed bugs. Allow a multipart body to start with dash-boundary (no CR/LF before). Don't process a body part if a boundary is not found after it.

git-svn-id: http://yate.null.ro/svn/yate/trunk@4793 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
marian 2012-01-04 15:53:45 +00:00
parent f75aceca2a
commit e684fa9f8d
1 changed files with 61 additions and 25 deletions

View File

@ -670,6 +670,31 @@ void MimeMultipartBody::buildBody() const
m_body += boundaryLast;
}
// Skip chars until boundary line ends
// Check for last boundary
static void finalizeBoundary(const char*& buf, int& len, bool& last, const char* boundary)
{
last = (len >= 2 && buf[0] == '-' && buf[1] == '-');
if (last) {
buf += 2;
len -= 2;
// Ignore the rest, we don't need the epilogue
return;
}
// RFC 2046 states the boundary line should be padded with spaces only
// and end with CR/LF. We allow any char until LF
for (; len && *buf != '\n'; buf++, len--)
;
if (len) {
buf++;
len--;
}
if (!len) {
Debug(DebugNote,"Unexpected multipart end for boundary '%s'",boundary + 4);
last = true;
}
}
// Parse a data buffer and append any valid body to this multipart
// Ignore prolog, epilog and invalid bodies
void MimeMultipartBody::parse(const char* buf, int len)
@ -681,9 +706,30 @@ void MimeMultipartBody::parse(const char* buf, int len)
if (!(buf && len > 0 && getBoundary(boundary)))
return;
bool endBody;
// Find first boundary: ignore the data before it
findBoundary(buf,len,boundary.c_str(),boundary.length(),endBody);
bool endBody = false;
bool foundFirst = false;
// RFC 2046: First boundary may be preceded by a preamble
// If there is a preamble, CR/LF MUST be present in boundary
// If there is no preamble CR/LF may not be present, the buffer may start with -
if (buf[0] == '-') {
const char* tmp = boundary.c_str() + 2;
int tmpLen = boundary.length() - 2;
if (tmpLen <= len) {
int i = 0;
for (; i < tmpLen; i++)
if (buf[i] != tmp[i])
break;
if (i == tmpLen) {
foundFirst = true;
buf += tmpLen;
len -= tmpLen;
finalizeBoundary(buf,len,endBody,boundary);
}
}
}
if (!foundFirst)
findBoundary(buf,len,boundary,boundary.length(),endBody);
// Parse for bodies
XDebug(DebugInfo,"Start parsing boundary=%s len=%d [%p]",
@ -772,50 +818,40 @@ int MimeMultipartBody::findBoundary(const char*& buf, int& len,
}
endBody = false;
unsigned int l = len;
int bodyLen = 0;
bool found = false;
while (l) {
while (len) {
// Skip until the first char of boundary
for (; l >= bLen && *buf != boundary[0]; l--, buf++)
for (; len >= (int)bLen && *buf != boundary[0]; len--, buf++)
bodyLen++;
// Current char is the first char of the boundary
// Check if we have enough data for boundary
if (l < bLen) {
bodyLen += l;
buf += l;
l = 0;
if (len < (int)bLen) {
bodyLen += len;
buf += len;
len = 0;
break;
}
// Check boundary
unsigned int n = 0;
for(; n < bLen && *buf == boundary[n]; n++, buf++, l--)
for(; n < bLen && *buf == boundary[n]; n++, buf++, len--)
;
// Not found
if (n < bLen) {
bodyLen += n;
continue;
}
// Check end of data
if (l > 2 && buf[0] == '-' && buf[1] == '-') {
buf += 2;
l -= 2;
endBody = true;
}
// Skip until the end of line or data
for (; l; buf++, l--)
if (*buf == '\n') {
buf++;
l--;
break;
}
found = true;
finalizeBoundary(buf,len,endBody,boundary);
break;
}
len = l;
if (!found)
Debug(DebugNote,"Expected multipart boundary '%s' not found",boundary + 4);
if (!len)
endBody = true;
return bodyLen;
return found ? bodyLen : 0;
}
// Build a boundary string to be used when parsing or building body