You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdepim/mimelib/disptype.cpp

447 lines
11 KiB

//=============================================================================
// File: disptype.cpp
// Contents: Definitions for DwDispositionType
// 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 CONSEQUENTIAL 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.
//
//=============================================================================
#define DW_IMPLEMENTATION
#include <mimelib/config.h>
#include <mimelib/debug.h>
#include <mimelib/string.h>
#include <mimelib/param.h>
#include <mimelib/disptype.h>
#include <mimelib/token.h>
#include <mimelib/enum.h>
const char* const DwDispositionType::sClassName = "DwDispositionType";
DwDispositionType* (*DwDispositionType::sNewDispositionType)(
const DwString&, DwMessageComponent*) = 0;
DwDispositionType* DwDispositionType::NewDispositionType(
const DwString& aStr, DwMessageComponent* aParent)
{
if (sNewDispositionType) {
return sNewDispositionType(aStr, aParent);
}
else {
return new DwDispositionType(aStr, aParent);
}
}
DwDispositionType::DwDispositionType()
{
mDispositionType = DwMime::kDispTypeNull;
mFirstParameter = 0;
mClassId = kCidDispositionType;
mClassName = sClassName;
}
DwDispositionType::DwDispositionType(const DwDispositionType& aDispType)
: DwFieldBody(aDispType),
mDispositionTypeStr(aDispType.mDispositionTypeStr),
mFilenameStr(aDispType.mFilenameStr)
{
mFirstParameter = 0;
mDispositionType = aDispType.mDispositionType;
if (aDispType.mFirstParameter) {
CopyParameterList(aDispType.mFirstParameter);
}
mClassId = kCidDispositionType;
mClassName = sClassName;
}
DwDispositionType::DwDispositionType(const DwString& aStr,
DwMessageComponent* aParent)
: DwFieldBody(aStr, aParent)
{
mDispositionType = DwMime::kDispTypeNull;
mFirstParameter = 0;
mClassId = kCidDispositionType;
mClassName = sClassName;
}
DwDispositionType::~DwDispositionType()
{
if (mFirstParameter) {
DeleteParameterList();
}
}
const DwDispositionType& DwDispositionType::operator = (
const DwDispositionType& aDispType)
{
if (this == &aDispType) return *this;
mDispositionType = aDispType.mDispositionType;
mDispositionTypeStr = aDispType.mDispositionTypeStr;
mFilenameStr = aDispType.mFilenameStr;
if (mFirstParameter) {
DeleteParameterList();
}
if (aDispType.mFirstParameter) {
CopyParameterList(aDispType.mFirstParameter);
}
if (mParent) {
mParent->SetModified();
}
return *this;
}
int DwDispositionType::DispositionType() const
{
return mDispositionType;
}
void DwDispositionType::SetDispositionType(int aType)
{
mDispositionType = aType;
EnumToStr();
SetModified();
}
const DwString& DwDispositionType::DispositionTypeStr() const
{
return mDispositionTypeStr;
}
void DwDispositionType::SetDispositionTypeStr(const DwString& aStr)
{
mDispositionTypeStr = aStr;
StrToEnum();
SetModified();
}
const DwString& DwDispositionType::Filename() const
{
DwParameter* param = mFirstParameter;
while (param) {
if (DwStrcasecmp(param->Attribute(), "filename") == 0) {
// Filename parameter found. Return its value.
// Implementation note: this member function is const, which
// forbids us from assigning to mFilenameStr. The following
// trick gets around this. (ANSI implementations could use the
// "mutable" declaration).
DwDispositionType* _this = (DwDispositionType*) this;
_this->mFilenameStr = param->Value();
break;
}
param = param->Next();
}
return mFilenameStr;
}
void DwDispositionType::SetFilename(const DwString& aStr)
{
mFilenameStr = aStr;
// Search for filename parameter in parameter list. If found, set its
// value.
DwParameter* param = mFirstParameter;
while (param) {
if (DwStrcasecmp(param->Attribute(), "filename") == 0) {
param->SetValue(mFilenameStr);
return;
}
param = param->Next();
}
// Boundary parameter not found. Add it.
param = DwParameter::NewParameter("", 0);
param->SetAttribute("Filename");
param->SetValue(aStr);
AddParameter(param);
}
DwParameter* DwDispositionType::FirstParameter() const
{
return mFirstParameter;
}
void DwDispositionType::AddParameter(DwParameter* aParam)
{
_AddParameter(aParam);
SetModified();
}
void DwDispositionType::_AddParameter(DwParameter* aParam)
{
if (!mFirstParameter) {
mFirstParameter = aParam;
}
else {
DwParameter* cur = mFirstParameter;
if( cur ) {
DwParameter* next = cur->Next();
while (next) {
cur = next;
next = cur->Next();
}
cur->SetNext(aParam);
}
}
aParam->SetParent(this);
}
void DwDispositionType::Parse()
{
mIsModified = 0;
mDispositionType = DwMime::kDispTypeNull;
mDispositionTypeStr = "";
if (mFirstParameter) {
DeleteParameterList();
}
if (mString.length() == 0) return;
DwRfc1521Tokenizer tokenizer(mString);
int found = 0;
while (!found && tokenizer.Type() != eTkNull) {
if (tokenizer.Type() == eTkToken) {
mDispositionTypeStr = tokenizer.Token();
found = 1;
}
++tokenizer;
}
// Get parameters
DwTokenString tokenStr(mString);
while (1) {
// Get ';'
found = 0;
while (!found && tokenizer.Type() != eTkNull) {
if (tokenizer.Type() == eTkTspecial
&& tokenizer.Token()[0] == ';') {
found = 1;
}
++tokenizer;
}
if (tokenizer.Type() == eTkNull) {
// No more parameters
break;
}
tokenStr.SetFirst(tokenizer);
// Get attribute
DwString attrib;
int attribFound = 0;
while (!attribFound && tokenizer.Type() != eTkNull) {
if (tokenizer.Type() == eTkToken) {
attrib = tokenizer.Token();
attribFound = 1;
}
++tokenizer;
}
// Get '='
found = 0;
while (!found && tokenizer.Type() != eTkNull) {
if (tokenizer.Type() == eTkTspecial
&& tokenizer.Token()[0] == '=') {
found = 1;
}
++tokenizer;
}
// Get value
int valueFound = 0;
while (!valueFound && tokenizer.Type() != eTkNull) {
if (tokenizer.Type() == eTkToken
|| tokenizer.Type() == eTkQuotedString) {
valueFound = 1;
}
++tokenizer;
}
if (attribFound && valueFound) {
tokenStr.ExtendTo(tokenizer);
DwParameter* param =
DwParameter::NewParameter(tokenStr.Tokens(), this);
param->Parse();
_AddParameter(param);
}
}
StrToEnum();
}
void DwDispositionType::Assemble()
{
if (!mIsModified) return;
mString = "";
if (mDispositionTypeStr.length() == 0)
return;
mString += mDispositionTypeStr;
DwParameter* param = FirstParameter();
while (param) {
param->Assemble();
if (IsFolding()) {
mString += ";" DW_EOL " ";
}
else {
mString += "; ";
}
mString += param->AsString();
param = param->Next();
}
mIsModified = 0;
}
DwMessageComponent* DwDispositionType::Clone() const
{
return new DwDispositionType(*this);
}
void DwDispositionType::EnumToStr()
{
switch (mDispositionType) {
case DwMime::kDispTypeInline:
mDispositionTypeStr = "inline";
break;
case DwMime::kDispTypeAttachment:
mDispositionTypeStr = "attachment";
break;
}
}
void DwDispositionType::StrToEnum()
{
switch (mDispositionTypeStr[0]) {
case 'i':
if (DwStrcasecmp(mDispositionTypeStr, "inline") == 0) {
mDispositionType = DwMime::kDispTypeInline;
}
else {
mDispositionType = DwMime::kDispTypeUnknown;
}
break;
case 'a':
if (DwStrcasecmp(mDispositionTypeStr, "attachment") == 0) {
mDispositionType = DwMime::kDispTypeAttachment;
}
else {
mDispositionType = DwMime::kDispTypeUnknown;
}
break;
}
}
void DwDispositionType::DeleteParameterList()
{
DwParameter* param = mFirstParameter;
while (param) {
DwParameter* nextParam = param->Next();
delete param;
param = nextParam;
}
mFirstParameter = 0;
SetModified();
}
void DwDispositionType::CopyParameterList(DwParameter* aFirst)
{
DwParameter* param = aFirst;
while (param) {
DwParameter* newParam = (DwParameter*) param->Clone();
AddParameter(newParam);
param = param->Next();
}
}
#if defined(DW_DEBUG_VERSION)
void DwDispositionType::PrintDebugInfo(std::ostream& aStrm, int aDepth) const
{
aStrm <<
"------------ Debug info for DwDispositionType class ------------\n";
_PrintDebugInfo(aStrm);
int depth = aDepth - 1;
depth = (depth >= 0) ? depth : 0;
if (aDepth == 0 || depth > 0) {
DwParameter* param = mFirstParameter;
while (param) {
param->PrintDebugInfo(aStrm, depth);
param = param->Next();
}
}
}
#else
void DwDispositionType::PrintDebugInfo(std::ostream&, int) const {}
#endif // defined(DW_DEBUG_VERSION)
#if defined(DW_DEBUG_VERSION)
void DwDispositionType::_PrintDebugInfo(std::ostream& aStrm) const
{
DwFieldBody::_PrintDebugInfo(aStrm);
aStrm << "Disposition Type: " << mDispositionTypeStr
<< " (" << mDispositionType << ")\n";
aStrm << "Filename: " << mFilenameStr << "\n";
aStrm << "Parameters: ";
DwParameter* param = mFirstParameter;
if (param) {
int count = 0;
while (param) {
if (count) aStrm << ' ';
aStrm << param->ObjectId();
param = param->Next();
++count;
}
aStrm << '\n';
}
else {
aStrm << "(none)\n";
}
}
#else
void DwDispositionType::_PrintDebugInfo(std::ostream& ) const {}
#endif // defined(DW_DEBUG_VERSION)
void DwDispositionType::CheckInvariants() const
{
#if defined(DW_DEBUG_VERSION)
mDispositionTypeStr.CheckInvariants();
mFilenameStr.CheckInvariants();
DwParameter* param = mFirstParameter;
while (param) {
param->CheckInvariants();
assert((DwMessageComponent*) this == param->Parent());
param = param->Next();
}
#endif // defined(DW_DEBUG_VERSION)
}