void VMIMEMessage::_ReadSinglePartMail (const VMIMEMailHeader *inHeader, VStream &inStream) { xbox_assert(inHeader != NULL); // Read header information. XBOX::VString name, fileName, contentType, contentID; bool isInline, isBase64, isQuotedPrintable; isInline = isBase64 = isQuotedPrintable = false; XBOX::VString string; XBOX::VNameValueCollection params; if (!inHeader->fContentType.IsEmpty()) { contentType = inHeader->fContentType; VHTTPHeader::SplitParameters(inHeader->fContentType, string, params); if (params.Has("name")) { name = params.Get("name"); _UnQuote(&name, '"', '"'); } } if (!inHeader->fContentDisposition.IsEmpty()) { VHTTPHeader::SplitParameters(inHeader->fContentDisposition, string, params); isInline = HTTPTools::EqualASCIIVString(string, "inline"); if (params.Has("filename")) { fileName = params.Get("filename"); _UnQuote(&fileName, '"', '"'); } } if (!inHeader->fContentTransferEncoding.IsEmpty()) { VHTTPHeader::SplitParameters(inHeader->fContentTransferEncoding, string, params); if (!(isBase64 = HTTPTools::EqualASCIIVString(string, "base64"))) isQuotedPrintable = HTTPTools::EqualASCIIVString(string, "quoted-printable"); } // Read body (a single part). Must be bigger than 5 bytes because of the ending "\r\n.\r\n" sequence. XBOX::VError error; VSize size; if ((error = inStream.OpenReading()) != XBOX::VE_OK) XBOX::vThrowError(error); else if ((size = (VSize) inStream.GetSize()) > 5) { uBYTE *buffer; size -= 5; if ((buffer = new uBYTE[size]) == NULL) XBOX::vThrowError(XBOX::VE_MEMORY_FULL); else { XBOX::VMemoryBuffer<> decodedData; XBOX::VPtrStream decodedBody; inStream.GetData(buffer, size); if (isBase64) { XBOX::Base64Coder::Decode(buffer, size, decodedData); decodedBody.SetDataPtr(decodedData.GetDataPtr(), decodedData.GetDataSize()); decodedData.ForgetData(); } else if (isQuotedPrintable) { VMIMEReader::DecodeQuotedPrintable(buffer, size, &decodedData); decodedBody.SetDataPtr(decodedData.GetDataPtr(), decodedData.GetDataSize()); decodedData.ForgetData(); } else decodedBody.SetDataPtr(buffer, size); inStream.CloseReading(); if (fileName.IsEmpty()) _AddTextPart(name, isInline, contentType, contentID, decodedBody); else _AddFilePart(name, fileName, isInline, contentType, contentID, decodedBody); if (isBase64 || isQuotedPrintable) decodedBody.Clear(); else decodedBody.StealData(); // Prevent VPtrStream from freeing buffer. delete[] buffer; } } else inStream.CloseReading(); }
void VMIMEMessage::_ReadMultiPartMail (const XBOX::VStream &inStream) { XBOX::VStream &stream = const_cast<XBOX::VStream&>(inStream); VMIMEReader reader(fBoundary, stream); while (reader.HasNextPart()) { XBOX::VHTTPMessage message; reader.GetNextPart(message); // Parse header of part. XBOX::VHTTPHeader header = message.GetHeaders(); const XBOX::VNameValueCollection &headerList = header.GetHeaderList(); XBOX::VNameValueCollection::ConstIterator it; XBOX::VString name, fileName, contentType, contentID; bool isInline, isBase64, isQuotedPrintable; isInline = isBase64 = isQuotedPrintable = false; for (it = headerList.begin(); it != headerList.end(); it++) { XBOX::VString value; XBOX::VNameValueCollection params; if (HTTPTools::EqualASCIIVString(it->first, "Content-Type", false)) { header.GetHeaderValue(it->first, contentType); VHTTPHeader::SplitParameters(contentType, value, params); if (params.Has("name")) { name = params.Get("name"); _UnQuote(&name, '"', '"'); } } else if (HTTPTools::EqualASCIIVString(it->first, "Content-Disposition", false)) { XBOX::VString disposition; header.GetHeaderValue(it->first, value); VHTTPHeader::SplitParameters(value, disposition, params); isInline = HTTPTools::EqualASCIIVString(disposition, "inline"); if (params.Has("filename")) { fileName = params.Get("filename"); _UnQuote(&fileName, '"', '"'); } } else if (HTTPTools::EqualASCIIVString(it->first, "Content-Transfer-Encoding", false)) { XBOX::VString encoding; header.GetHeaderValue(it->first, value); VHTTPHeader::SplitParameters(value, encoding, params); if (!(isBase64 = HTTPTools::EqualASCIIVString(encoding, "base64"))) isQuotedPrintable = HTTPTools::EqualASCIIVString(encoding, "quoted-printable"); } else if (HTTPTools::EqualASCIIVString(it->first, "Content-ID", false)) { header.GetHeaderValue(it->first, value); VHTTPHeader::SplitParameters(value, contentID, params); _UnQuote(&contentID, '<', '>'); } else { // Ignore unknown fields. } } // Get body of part, decode it if need. XBOX::VMemoryBuffer<> decodedData; XBOX::VPtrStream decodedBody; XBOX::VPtrStream *body = message.GetBodyPtr(); if (isBase64) { XBOX::Base64Coder::Decode(body->GetDataPtr(), body->GetDataSize(), decodedData); decodedBody.SetDataPtr(decodedData.GetDataPtr(), decodedData.GetDataSize()); decodedData.ForgetData(); body = &decodedBody; } else if (isQuotedPrintable) { VMIMEReader::DecodeQuotedPrintable (body->GetDataPtr(), body->GetDataSize(), &decodedData); decodedBody.SetDataPtr(decodedData.GetDataPtr(), decodedData.GetDataSize()); decodedData.ForgetData(); body = &decodedBody; } if (fileName.IsEmpty()) _AddTextPart(name, isInline, contentType, contentID, *body); else _AddFilePart(name, fileName, isInline, contentType, contentID, *body); decodedBody.Clear(); } }