Revision: 7472
http://mahogany.svn.sourceforge.net/mahogany/?rev=7472&view=rev
Author: vadz
Date: 2008-05-04 18:15:04 -0700 (Sun, 04 May 2008)
Log Message:
-----------
fix uudecoding and virtual MIME parts which were totally broken in Unicode
build; also fix virtual MIME parts body size determination which was broken
even in ANSI build
Modified Paths:
--------------
trunk/M/include/MimePartVirtual.h
trunk/M/src/classes/MessageView.cpp
trunk/M/src/mail/MessageCC.cpp
trunk/M/src/mail/MimePartVirtual.cpp
trunk/M/src/modules/viewflt/UUDecode.cpp
Modified: trunk/M/include/MimePartVirtual.h
===================================================================
--- trunk/M/include/MimePartVirtual.h 2008-05-04 20:40:22 UTC (rev 7471)
+++ trunk/M/include/MimePartVirtual.h 2008-05-05 01:15:04 UTC (rev 7472)
@@ -31,7 +31,7 @@
/**
Construct a MIME part from the entire part text (body + header).
*/
- MimePartVirtual(const String& msgText);
+ MimePartVirtual(const wxMemoryBuffer& msgText);
/**
Construct a nested MIME part.
@@ -62,7 +62,7 @@
// the entire text of the message, only non empty for the top level part
- String m_msgText;
+ wxMemoryBuffer m_msgText;
// pointer to the start of headers of this part
const char *m_pStart;
Modified: trunk/M/src/classes/MessageView.cpp
===================================================================
--- trunk/M/src/classes/MessageView.cpp 2008-05-04 20:40:22 UTC (rev 7471)
+++ trunk/M/src/classes/MessageView.cpp 2008-05-05 01:15:04 UTC (rev 7472)
@@ -2583,7 +2583,9 @@
pgpInfo = new PGPInfoGoodMsg(this);
{
- MimePartVirtual *mpv = new MimePartVirtual(decryptedData);
+ wxMemoryBuffer buf;
+ buf.AppendData(decryptedData.To8BitData(), decryptedData.length());
+ MimePartVirtual *mpv = new MimePartVirtual(buf);
AddVirtualMimePart(mpv);
ProcessPart(mpv);
}
Modified: trunk/M/src/mail/MessageCC.cpp
===================================================================
--- trunk/M/src/mail/MessageCC.cpp 2008-05-04 20:40:22 UTC (rev 7471)
+++ trunk/M/src/mail/MessageCC.cpp 2008-05-05 01:15:04 UTC (rev 7472)
@@ -869,34 +869,14 @@
BODY **ppBody,
size_t *pHdrLen)
{
- const char *bodycptr = NULL;
- unsigned long headerLen = 0;
-
- // find end of header "\r\n\r\n"
- bool eol = true;
- for ( unsigned long pos = 0; msgText[pos]; pos++ )
- {
- // empty line or end of text?
- if ( msgText[pos] == '\r' && msgText[++pos] == '\n' )
- {
- if ( eol )
- {
- headerLen = pos - 1;
- bodycptr = msgText + pos + 1; // skip eol
- break;
- }
-
- eol = true;
- }
- else
- {
- eol = false;
- }
- }
-
- if ( !headerLen )
+ // find end of header indicated by a blank line
+ const char *bodycptr = strstr(msgText, "\r\n\r\n");
+ if ( !bodycptr )
return false;
+ const unsigned long headerLen = bodycptr - msgText + 2; // include EOL
+ bodycptr += 4; // skip 2 EOLs
+
STRING str;
INIT(&str, mail_string, const_cast<char *>(bodycptr), strlen(bodycptr));
rfc822_parse_msg(ppEnv, ppBody,
Modified: trunk/M/src/mail/MimePartVirtual.cpp
===================================================================
--- trunk/M/src/mail/MimePartVirtual.cpp 2008-05-04 20:40:22 UTC (rev
7471)
+++ trunk/M/src/mail/MimePartVirtual.cpp 2008-05-05 01:15:04 UTC (rev
7472)
@@ -44,17 +44,17 @@
// ----------------------------------------------------------------------------
// ctor for top level part
-MimePartVirtual::MimePartVirtual(const String& msgText)
+MimePartVirtual::MimePartVirtual(const wxMemoryBuffer& msgText)
: m_msgText(msgText)
{
- m_pStart = m_msgText;
+ m_pStart = static_cast<char *>(m_msgText.GetData());
m_env = NULL;
m_lenHeader =
m_lenBody = 0;
- if ( !CclientParseMessage(msgText, &m_env, &m_body, &m_lenHeader) )
+ if ( !CclientParseMessage(m_pStart, &m_env, &m_body, &m_lenHeader) )
{
// no idea what is user supposed to make out of this message...
wxLogError(_("Failed to create a virtual MIME part."));
@@ -62,8 +62,14 @@
return;
}
- m_lenBody = m_msgText.length() - m_lenHeader - lenEOL;
+ m_lenBody = m_msgText.GetDataLen() - m_lenHeader - lenEOL;
+ // c-client can't determine it itself correctly (the "string" we pass to it
+ // can have embedded NULs and we don't pass the real length), so fix it here
+ m_body->size.bytes =
+ m_body->contents.text.size = m_lenBody;
+
+
CreateSubParts();
}
Modified: trunk/M/src/modules/viewflt/UUDecode.cpp
===================================================================
--- trunk/M/src/modules/viewflt/UUDecode.cpp 2008-05-04 20:40:22 UTC (rev
7471)
+++ trunk/M/src/modules/viewflt/UUDecode.cpp 2008-05-05 01:15:04 UTC (rev
7472)
@@ -59,10 +59,10 @@
// all UUencoded data start with a line whose prefix is "begin" and preceded by
// a blank line
-#define UU_BEGIN_PREFIX _T("begin ")
+#define UU_BEGIN_PREFIX "begin "
// UUencoded data ends at a line consisting solely of "end"
-#define UU_END_PREFIX _T("\r\nend\r\n")
+#define UU_END_PREFIX "\r\nend\r\n"
// ============================================================================
// UUDecodeFilter implementation
@@ -89,99 +89,95 @@
// UUDecodeFilter work function
// ----------------------------------------------------------------------------
+namespace
+{
+
// check if c is valid in uuencoded text
-static inline bool IsUUValid(wxChar c)
+inline bool IsUUValid(char c)
{
- return c >= _T(' ') && c <= _T('`');
+ return c >= ' ' && c <= '`';
}
+static const int MAX_UU_LINE_LEN = 45;
+
// "decode" a single character
-#define DEC(c) (((c) - ' ') & 077)
+#define UUdec(c) (((c) - ' ') & 077)
-int UUdecodeLine(const wxChar* input, wxChar* output, const wxChar** endOfLine)
+int UUdecodeLine(const char *input, char *output, const char **endOfLine)
{
- // "input[0] - space" contains the count of characters in this line, check
- // that it is valid
- if ( input[0] <= _T(' ') || input[0] > _T('`') )
- {
- // invalid uu char
+ if ( !IsUUValid(*input) )
return -1;
- }
- wxChar * cv_ptr = output;
- register const wxChar * p = input;
+ const int cv_len = UUdec(*input++);
+ if ( cv_len > MAX_UU_LINE_LEN )
+ return -1;
- const int cv_len = DEC(*p++);
-
// Actually decode the uue data; ensure characters are in range.
- for (int i=0; i<cv_len; i+=3, p+=4)
+ for ( int i = 0; i < cv_len; i += 3, input += 4 )
{
- if ( !IsUUValid(p[0]) ||
- !IsUUValid(p[1]) ||
- !IsUUValid(p[2]) ||
- !IsUUValid(p[3]) )
+ if ( !IsUUValid(input[0]) || !IsUUValid(input[1]) ||
+ !IsUUValid(input[2]) || !IsUUValid(input[3]) )
{
return -1;
}
- *cv_ptr++ = DEC(p[0]) << 2 | DEC(p[1]) >> 4;
- *cv_ptr++ = DEC(p[1]) << 4 | DEC(p[2]) >> 2;
- *cv_ptr++ = DEC(p[2]) << 6 | DEC(p[3]);
+ *output++ = UUdec(input[0]) << 2 | UUdec(input[1]) >> 4;
+ *output++ = UUdec(input[1]) << 4 | UUdec(input[2]) >> 2;
+ *output++ = UUdec(input[2]) << 6 | UUdec(input[3]);
}
- if (*p != _T('\r') && *p != _T('\n') && *p != _T('\0'))
+
+ if ( *input != '\r' && *input != '\n' && *input != '\0' )
return -1;
- //else *p=0;
- *endOfLine = p;
+ *endOfLine = input;
return cv_len;
}
-bool UUdecodeFile(const wxChar* input, String& output, const wxChar**
endOfEncodedStream)
+bool
+UUdecodeFile(const char *input,
+ wxMemoryBuffer& output,
+ const char **endOfEncodedStream)
{
- static const int allocationSize = 10000;
+ static const size_t allocationSize = 10000;
- String decodedFile;
size_t totalAllocatedBytes = 0;
size_t totalDecodedBytes = 0;
int decodedBytesInLine;
- const wxChar* startOfLine = input;
- const wxChar* endOfLine = 0; // init not needed
- wxChar* buffer = new wxChar[45];
+ const char *startOfLine = input;
+ const char *endOfLine = 0; // init not needed
+ char buffer[MAX_UU_LINE_LEN];
while ( (decodedBytesInLine =
UUdecodeLine(startOfLine, buffer, &endOfLine)) > 0 )
{
// We've just decoded a line
totalDecodedBytes += decodedBytesInLine;
- String decodedLine(buffer, decodedBytesInLine);
- if (decodedFile.length() + (size_t)decodedBytesInLine >=
totalAllocatedBytes)
+ if ( output.GetDataLen() + decodedBytesInLine >= totalAllocatedBytes )
{
totalAllocatedBytes += allocationSize;
- decodedFile.Alloc(totalAllocatedBytes);
+ output.GetWriteBuf(totalAllocatedBytes);
}
- decodedFile += decodedLine;
- ASSERT_MSG( decodedFile.Length() == totalDecodedBytes,
- _T("Number of decoded bytes does not match!") );
- ASSERT_MSG( endOfLine[0] == _T('\r'), _T("Line has no '\\r' at the
end!") );
- ASSERT_MSG( endOfLine[1] == _T('\n'), _T("Line has no '\\n' at the
end!") );
+ output.AppendData(buffer, decodedBytesInLine);
+ ASSERT_MSG( endOfLine[0] == '\r', "Line has no '\\r' at the end!" );
+ ASSERT_MSG( endOfLine[1] == '\n', "Line has no '\\n' at the end!" );
+
startOfLine = endOfLine + lenEOL;
}
- delete[] buffer;
- if (decodedBytesInLine < 0)
+ if ( decodedBytesInLine < 0 )
{
wxLogWarning(_("Invalid character in uuencoded text."));
return false;
}
- decodedFile.Shrink();
- output = decodedFile;
*endOfEncodedStream = endOfLine;
+
return true;
}
+} // anonymous namespace
void
@@ -192,8 +188,8 @@
// do we have something looking like UUencoded data?
static const size_t lenBegin = wxStrlen(UU_BEGIN_PREFIX);
- const wxChar *start = text.c_str();
- const wxChar *nextToOutput = start;
+ const char *start = text.c_str();
+ const char *nextToOutput = start;
while ( *start )
{
bool hasBegin = wxStrncmp(start, UU_BEGIN_PREFIX, lenBegin) == 0;
@@ -216,10 +212,10 @@
// 2 or 4 and more characters after the start
default:
// only blank line allowed before
- if ( start[-1] != _T('\n') || start[-2] != _T('\r') )
+ if ( start[-1] != '\n' || start[-2] != '\r' )
hasBegin = false;
if ( start - text.c_str() > 2 &&
- (start[-3] != _T('\n') || start[-4] != _T('\r')) )
+ (start[-3] != '\n' || start[-4] != '\r') )
hasBegin = false;
}
}
@@ -227,7 +223,7 @@
if ( !hasBegin )
{
// try the next line (but only if not already at the end)
- start = wxStrchr(start, _T('\n'));
+ start = wxStrchr(start, '\n');
if ( start )
{
start++; // skip '\n' itself
@@ -244,7 +240,7 @@
}
}
- const wxChar* startBeginLine = start;
+ const char *startBeginLine = start;
start += lenBegin;
// Let's check that the next 4 chars after the 'begin ' are
@@ -252,34 +248,71 @@
//
// NB: 4 digit mode masks are in theory possible but shouldn't be used
// with uuencoded files
- if ( !( start[0] >= _T('0') && start[0] <= _T('7')
- && start[1] >= _T('0') && start[1] <= _T('7')
- && start[2] >= _T('0') && start[2] <= _T('7')
- && start[3] == _T(' ') ) )
+ if ( !( start[0] >= '0' && start[0] <= '7'
+ && start[1] >= '0' && start[1] <= '7'
+ && start[2] >= '0' && start[2] <= '7'
+ && start[3] == ' ' ) )
{
wxLogWarning(_("The BEGIN line is not correctly formed."));
continue;
}
- const wxChar* startName = start+4; // skip mode and space
- const wxChar* endName = startName;
+ const char *startName = start+4; // skip mode and space
+ const char *endName = startName;
// Rest of the line is the name
- while (*endName != _T('\r'))
+ while ( *endName != '\r' )
{
- ++endName;
- ASSERT_MSG( endName < text.c_str()+text.length(),
- _T("'begin' line does not end?") );
+ if ( !*endName++ )
+ {
+ wxLogWarning(_("The BEGIN line is unterminated."));
+ String prolog(nextToOutput);
+ if ( !prolog.empty() )
+ {
+ m_next->Process(prolog, viewer, style);
+ }
+ return; // no more text
+ }
}
- ASSERT_MSG( endName[1] == _T('\n'),
- _T("'begin' line does not end with \"\\r\\n\"?") );
+ ASSERT_MSG( endName[1] == '\n',
+ "'begin' line does not end with \"\\r\\n\"?" );
- String fileName = String(startName, endName);
- const wxChar* start_data = endName + lenEOL;
+ const String fileName(startName, endName);
+ const char *start_data = endName + lenEOL;
- String decodedFile;
- const wxChar* endOfEncodedStream = 0;
- bool ok = UUdecodeFile(start_data, decodedFile, &endOfEncodedStream);
+
+ // buffer with the entire virtual part contents
+ wxMemoryBuffer virtData;
+
+ // start with the header for the uudecoded virtual part
+ String header("Mime-Version: 1.0\r\n"
+ //"Content-Transfer-Encoding: uuencode\r\n"
+ "Content-Disposition: attachment; filename=\"" +
+ fileName + "\"\r\n");
+
+ // get a mimeType from the extention
+ String mimeType;
+ String ext;
+ wxSplitPath(fileName, NULL, NULL, &ext);
+ if ( !ext.empty() )
+ {
+ wxFileType *
+ ft = mApplication->GetMimeManager().GetFileTypeFromExtension(ext);
+ if ( ft )
+ ft->GetMimeType(&mimeType);
+ delete ft;
+ }
+
+ if ( mimeType.empty() )
+ mimeType = "APPLICATION/OCTET-STREAM";
+ header += "Content-Type: " + mimeType;
+ header += "; name=\"" + fileName + "\"\r\n";
+ header += "\r\n"; // blank line separating the header from body
+
+ virtData.AppendData(header.ToAscii(), header.length());
+
+ const char *endOfEncodedStream = 0;
+ bool ok = UUdecodeFile(start_data, virtData, &endOfEncodedStream);
if ( ok )
{
static const size_t lenEnd = wxStrlen(UU_END_PREFIX);
@@ -303,29 +336,8 @@
m_next->Process(prolog, viewer, style);
}
- // now create the header for the uuencoded part
- String header(_T("Mime-Version: 1.0\r\n")
- _T("Content-Disposition: uuencoded\r\n"));
-
- // get a mimeType from the extention
- String mimeType;
- String ext;
- wxSplitPath(fileName, NULL, NULL, &ext);
- if ( !ext.empty() )
- {
- wxFileType *
- ft =
mApplication->GetMimeManager().GetFileTypeFromExtension(ext);
- if ( ft )
- ft->GetMimeType(&mimeType);
- delete ft;
- }
-
- if ( mimeType.empty() )
- mimeType = _T("APPLICATION/OCTET-STREAM");
- header += _T("Content-Type: ") + mimeType + _T("\r\n");
-
- MimePartVirtual *
- mimepart = new MimePartVirtual(header + _T("\r\n") + decodedFile);
+ // create and process the virtual part containing uudecoded contents
+ MimePartVirtual * const mimepart = new MimePartVirtual(virtData);
m_msgView->AddVirtualMimePart(mimepart);
m_msgView->ShowPart(mimepart);
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference
Don't miss this year's exciting event. There's still time to save $100.
Use priority code J8TL2D2.
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone
_______________________________________________
Mahogany-cvsupdates mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mahogany-cvsupdates