|
|
|
//=============================================================================
|
|
|
|
// File: multipar.cpp
|
|
|
|
// Contents: Definitions for MultiparBodyPart and MultipartMessage
|
|
|
|
// Maintainer: Doug Sauder <dwsauder@fwb.gulf.net>
|
|
|
|
// WWW: http://www.fwb.gulf.net/~dwsauder/mimepp.html
|
|
|
|
//
|
|
|
|
// Copyright (c) 1996, 1997 Douglas W. Sauder
|
|
|
|
// All rights reserved.
|
|
|
|
//
|
|
|
|
// IN NO EVENT SHALL DOUGLAS W. SAUDER BE LIABLE TO ANY PARTY FOR DIRECT,
|
|
|
|
// INDIRECT, SPECIAL, INCIDENTAL, OR CONSETQUENTIAL DAMAGES ARISING OUT OF
|
|
|
|
// THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF DOUGLAS W. SAUDER
|
|
|
|
// HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
//
|
|
|
|
// DOUGLAS W. SAUDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT
|
|
|
|
// NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
|
|
|
// PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
|
|
|
|
// BASIS, AND DOUGLAS W. SAUDER HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
|
|
|
|
// SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
|
|
|
//
|
|
|
|
//=============================================================================
|
|
|
|
|
|
|
|
#include <assert.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include "multipar.h"
|
|
|
|
|
|
|
|
|
|
|
|
MultipartBodyPart::MultipartBodyPart()
|
|
|
|
: mType("Text"),
|
|
|
|
mSubtype("Plain"),
|
|
|
|
mCte("7bit")
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
MultipartBodyPart::~MultipartBodyPart()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const DwString& MultipartBodyPart::TypeStr() const
|
|
|
|
{
|
|
|
|
return mType;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int MultipartBodyPart::Type() const
|
|
|
|
{
|
|
|
|
int type = DwTypeStrToEnum(mType);
|
|
|
|
return type;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MultipartBodyPart::SetTypeStr(const DwString& aStr)
|
|
|
|
{
|
|
|
|
mType = aStr;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MultipartBodyPart::SetType(int aType)
|
|
|
|
{
|
|
|
|
DwTypeEnumToStr(aType, mType);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const DwString& MultipartBodyPart::SubtypeStr() const
|
|
|
|
{
|
|
|
|
return mSubtype;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int MultipartBodyPart::Subtype() const
|
|
|
|
{
|
|
|
|
int subtype = DwSubtypeStrToEnum(mSubtype);
|
|
|
|
return subtype;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MultipartBodyPart::SetSubtypeStr(const DwString& aStr)
|
|
|
|
{
|
|
|
|
mSubtype = aStr;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MultipartBodyPart::SetSubtype(int aSubtype)
|
|
|
|
{
|
|
|
|
DwSubtypeEnumToStr(aSubtype, mSubtype);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const DwString& MultipartBodyPart::ContentTransferEncodingStr() const
|
|
|
|
{
|
|
|
|
return mCte;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int MultipartBodyPart::ContentTransferEncoding() const
|
|
|
|
{
|
|
|
|
int cte = DwCteStrToEnum(mCte);
|
|
|
|
return cte;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MultipartBodyPart::SetContentTransferEncodingStr(const DwString& aStr)
|
|
|
|
{
|
|
|
|
mCte = aStr;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MultipartBodyPart::SetContentTransferEncoding(int aCte)
|
|
|
|
{
|
|
|
|
DwCteEnumToStr(aCte, mCte);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const DwString& MultipartBodyPart::CteStr() const
|
|
|
|
{
|
|
|
|
return mCte;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int MultipartBodyPart::Cte() const
|
|
|
|
{
|
|
|
|
int cte = DwCteStrToEnum(mCte);
|
|
|
|
return cte;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MultipartBodyPart::SetCteStr(const DwString& aStr)
|
|
|
|
{
|
|
|
|
mCte = aStr;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MultipartBodyPart::SetCte(int aCte)
|
|
|
|
{
|
|
|
|
DwCteEnumToStr(aCte, mCte);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const DwString& MultipartBodyPart::ContentDescription() const
|
|
|
|
{
|
|
|
|
return mContentDescription;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MultipartBodyPart::SetContentDescription(const DwString& aStr)
|
|
|
|
{
|
|
|
|
mContentDescription = aStr;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const DwString& MultipartBodyPart::ContentDisposition() const
|
|
|
|
{
|
|
|
|
return mContentDisposition;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MultipartBodyPart::SetContentDisposition(const DwString& aStr)
|
|
|
|
{
|
|
|
|
mContentDisposition = aStr;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const DwString& MultipartBodyPart::Body() const
|
|
|
|
{
|
|
|
|
return mBody;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MultipartBodyPart::SetBody(const DwString& aStr)
|
|
|
|
{
|
|
|
|
mBody = aStr;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
MultipartMessage::MultipartMessage()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
MultipartMessage::MultipartMessage(DwMessage* aMsg)
|
|
|
|
: BasicMessage(aMsg)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
MultipartMessage::~MultipartMessage()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MultipartMessage::SetAutomaticFields()
|
|
|
|
{
|
|
|
|
BasicMessage::SetAutomaticFields();
|
|
|
|
|
|
|
|
// Set the type to 'Multipart' and the subtype to 'Mixed'
|
|
|
|
|
|
|
|
DwMediaType& contentType = mMessage->Headers().ContentType();
|
|
|
|
contentType.SetType(DwMime::kTypeMultipart);
|
|
|
|
contentType.SetSubtype(DwMime::kSubtypeMixed);
|
|
|
|
|
|
|
|
// Create a random printable string and set it as the boundary parameter
|
|
|
|
|
|
|
|
contentType.CreateBoundary(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int MultipartMessage::NumberOfParts() const
|
|
|
|
{
|
|
|
|
int count = 0;
|
|
|
|
DwBodyPart* part = mMessage->Body().FirstBodyPart();
|
|
|
|
while (part) {
|
|
|
|
++count;
|
|
|
|
part = part->Next();
|
|
|
|
}
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MultipartMessage::BodyPart(int aIdx, MultipartBodyPart& aPart)
|
|
|
|
{
|
|
|
|
// Get the DwBodyPart for this index
|
|
|
|
|
|
|
|
DwBodyPart* part = mMessage->Body().FirstBodyPart();
|
|
|
|
for (int curIdx=0; curIdx < aIdx && part; ++curIdx) {
|
|
|
|
part = part->Next();
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the DwBodyPart was found get the header fields and body
|
|
|
|
|
|
|
|
if (part != 0) {
|
|
|
|
DwHeaders& headers = part->Headers();
|
|
|
|
|
|
|
|
// Content-type
|
|
|
|
|
|
|
|
if (headers.HasContentType()) {
|
|
|
|
const DwString& type = headers.ContentType().TypeStr();
|
|
|
|
const DwString& subtype = headers.ContentType().SubtypeStr();
|
|
|
|
aPart.SetTypeStr(type);
|
|
|
|
aPart.SetSubtypeStr(subtype);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// Set to defaults
|
|
|
|
aPart.SetTypeStr("Text");
|
|
|
|
aPart.SetSubtypeStr("Plain");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Content-transfer-encoding
|
|
|
|
|
|
|
|
if (headers.HasContentTransferEncoding()) {
|
|
|
|
const DwString& cte = headers.ContentTransferEncoding().AsString();
|
|
|
|
aPart.SetCteStr(cte);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// Set to default
|
|
|
|
aPart.SetCteStr("7bit");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Content-description
|
|
|
|
|
|
|
|
if (headers.HasContentDescription()) {
|
|
|
|
const DwString& desc = headers.ContentDescription().AsString();
|
|
|
|
aPart.SetContentDescription(desc);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
aPart.SetContentDescription("");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Content-disposition
|
|
|
|
|
|
|
|
if (headers.HasContentDisposition()) {
|
|
|
|
const DwString& disp = headers.ContentDisposition().AsString();
|
|
|
|
aPart.SetContentDisposition(disp);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
aPart.SetContentDisposition("");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Body
|
|
|
|
|
|
|
|
const DwString& body = part->Body().AsString();
|
|
|
|
aPart.SetBody(body);
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the body part was not found, set all MultipartBodyPart attributes
|
|
|
|
// to empty values. This only happens if you don't pay attention to
|
|
|
|
// the value returned from NumberOfParts().
|
|
|
|
else {
|
|
|
|
aPart.SetTypeStr("");
|
|
|
|
aPart.SetSubtypeStr("");
|
|
|
|
aPart.SetCteStr("");
|
|
|
|
aPart.SetContentDescription("");
|
|
|
|
aPart.SetContentDisposition("");
|
|
|
|
aPart.SetBody("");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MultipartMessage::SetBodyPart(int aIdx, const MultipartBodyPart& aPart)
|
|
|
|
{
|
|
|
|
DwBody& body = mMessage->Body();
|
|
|
|
int numParts = NumberOfParts();
|
|
|
|
DwBodyPart* part = 0;
|
|
|
|
// If indexed part exists already, just replace its values
|
|
|
|
if (0 <= aIdx && aIdx < numParts) {
|
|
|
|
part = body.FirstBodyPart();
|
|
|
|
for (int curIdx=0; curIdx < aIdx; ++curIdx) {
|
|
|
|
part = part->Next();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Otherwise, add as many new parts as necessary.
|
|
|
|
else if (numParts <= aIdx) {
|
|
|
|
while (numParts <= aIdx) {
|
|
|
|
part = DwBodyPart::NewBodyPart(mEmptyString, 0);
|
|
|
|
body.AddBodyPart(part);
|
|
|
|
++numParts;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else /* if (aIdx < 0) */ {
|
|
|
|
// error!
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const DwString& type = aPart.TypeStr();
|
|
|
|
const DwString& subtype = aPart.SubtypeStr();
|
|
|
|
const DwString& cte = aPart.CteStr();
|
|
|
|
const DwString& contDesc = aPart.ContentDescription();
|
|
|
|
const DwString& contDisp = aPart.ContentDisposition();
|
|
|
|
const DwString& bodyStr = aPart.Body();
|
|
|
|
|
|
|
|
DwHeaders& headers = part->Headers();
|
|
|
|
if (!type.empty() && !subtype.empty()) {
|
|
|
|
headers.ContentType().SetTypeStr(type);
|
|
|
|
headers.ContentType().SetSubtypeStr(subtype);
|
|
|
|
}
|
|
|
|
if (!cte.empty()) {
|
|
|
|
headers.Cte().FromString(cte);
|
|
|
|
}
|
|
|
|
if (!contDesc.empty()) {
|
|
|
|
headers.ContentDescription().FromString(contDesc);
|
|
|
|
}
|
|
|
|
if (!contDisp.empty()) {
|
|
|
|
headers.ContentDisposition().FromString(contDisp);
|
|
|
|
}
|
|
|
|
part->Body().FromString(bodyStr);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MultipartMessage::AddBodyPart(const MultipartBodyPart& aPart)
|
|
|
|
{
|
|
|
|
DwBodyPart* part = DwBodyPart::NewBodyPart(mEmptyString, 0);
|
|
|
|
|
|
|
|
const DwString& type = aPart.TypeStr();
|
|
|
|
const DwString& subtype = aPart.SubtypeStr();
|
|
|
|
const DwString& cte = aPart.CteStr();
|
|
|
|
const DwString& contDesc = aPart.ContentDescription();
|
|
|
|
const DwString& contDisp = aPart.ContentDisposition();
|
|
|
|
const DwString& bodyStr = aPart.Body();
|
|
|
|
|
|
|
|
DwHeaders& headers = part->Headers();
|
|
|
|
if (!type.empty() && !subtype.empty()) {
|
|
|
|
headers.ContentType().SetTypeStr(type);
|
|
|
|
headers.ContentType().SetSubtypeStr(subtype);
|
|
|
|
}
|
|
|
|
if (!cte.empty()) {
|
|
|
|
headers.Cte().FromString(cte);
|
|
|
|
}
|
|
|
|
if (!contDesc.empty()) {
|
|
|
|
headers.ContentDescription().FromString(contDesc);
|
|
|
|
}
|
|
|
|
if (!contDisp.empty()) {
|
|
|
|
headers.ContentDisposition().FromString(contDisp);
|
|
|
|
}
|
|
|
|
part->Body().FromString(bodyStr);
|
|
|
|
|
|
|
|
mMessage->Body().AddBodyPart(part);
|
|
|
|
}
|