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/addrlist.cpp

404 lines
9.3 KiB

//=============================================================================
// File: addrlist.cpp
// Contents: Definitions for DwAddressList
// 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 <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <mimelib/config.h>
#include <mimelib/address.h>
#include <mimelib/addrlist.h>
#include <mimelib/token.h>
#include <mimelib/group.h>
#include <mimelib/mailbox.h>
const char* const DwAddressList::sClassName = "DwAddressList";
DwAddressList* (*DwAddressList::sNewAddressList)(const DwString&,
DwMessageComponent*) = 0;
DwAddressList* DwAddressList::NewAddressList(const DwString& aStr,
DwMessageComponent* aParent)
{
if (sNewAddressList) {
return sNewAddressList(aStr, aParent);
}
else {
return new DwAddressList(aStr, aParent);
}
}
DwAddressList::DwAddressList()
{
mFirstAddress = 0;
mClassId = kCidAddressList;
mClassName = sClassName;
}
DwAddressList::DwAddressList(const DwAddressList& aList)
: DwFieldBody(aList)
{
mFirstAddress = 0;
const DwAddress* addr = aList.mFirstAddress;
if (addr) {
CopyList(addr);
}
mClassId = kCidAddressList;
mClassName = sClassName;
}
DwAddressList::DwAddressList(const DwString& aStr, DwMessageComponent* aParent)
: DwFieldBody(aStr, aParent)
{
mFirstAddress = 0;
mClassId = kCidAddressList;
mClassName = sClassName;
}
DwAddressList::~DwAddressList()
{
if (mFirstAddress) {
DeleteAll();
}
}
const DwAddressList& DwAddressList::operator = (const DwAddressList& aList)
{
if (this == &aList) return *this;
DwFieldBody::operator = (aList);
if (mFirstAddress) {
DeleteAll();
}
const DwAddress* addr = aList.mFirstAddress;
if (addr) {
CopyList(addr);
}
return *this;
}
DwMessageComponent* DwAddressList::Clone() const
{
return new DwAddressList(*this);
}
DwAddress* DwAddressList::FirstAddress() const
{
return mFirstAddress;
}
void DwAddressList::Add(DwAddress* aAddr)
{
aAddr->SetNext(0);
aAddr->SetParent(this);
if (!mFirstAddress) {
mFirstAddress = aAddr;
}
else {
DwAddress* addr = mFirstAddress;
while (addr->Next()) {
addr = (DwAddress*) addr->Next();
}
addr->SetNext(aAddr);
}
SetModified();
}
void DwAddressList::Remove(DwAddress* aAddr)
{
DwAddress* addr = mFirstAddress;
if (addr == aAddr) {
mFirstAddress = (DwAddress*) addr->Next();
aAddr->SetNext(0);
return;
}
while (addr) {
if (addr->Next() == aAddr) {
addr->SetNext(aAddr->Next());
aAddr->SetNext(0);
break;
}
}
SetModified();
}
void DwAddressList::DeleteAll()
{
DwAddress* addr = mFirstAddress;
while (addr) {
DwAddress* nextAddr = (DwAddress*) addr->Next();
delete addr;
addr = nextAddr;
}
mFirstAddress = 0;
}
void DwAddressList::Parse()
{
mIsModified = 0;
if (mFirstAddress) {
DeleteAll();
}
DwAddressListParser parser(mString);
DwAddress* address;
while (1) {
switch (parser.AddrType()) {
case DwAddressListParser::eAddrError:
case DwAddressListParser::eAddrEnd:
goto LOOP_EXIT;
case DwAddressListParser::eAddrMailbox:
address = DwMailbox::NewMailbox(parser.AddrString(), this);
address->Parse();
if (address->IsValid()) {
Add(address);
}
else {
delete address;
}
break;
case DwAddressListParser::eAddrGroup:
address = DwGroup::NewGroup(parser.AddrString(), this);
address->Parse();
if (address->IsValid()) {
Add(address);
}
else {
delete address;
}
break;
case DwAddressListParser::eAddrNull:
break;
}
++parser;
}
LOOP_EXIT:
return;
}
void DwAddressList::Assemble()
{
if (!mIsModified) return;
mString = "";
int count = 0;
DwAddress* addr = mFirstAddress;
while (addr) {
addr->Assemble();
if (addr->IsValid()) {
if (count > 0){
if (IsFolding()) {
mString += "," DW_EOL " ";
}
else {
mString += ", ";
}
}
mString += addr->AsString();
++count;
}
addr = (DwAddress*) addr->Next();
}
mIsModified = 0;
}
void DwAddressList::CopyList(const DwAddress* aFirstAddr)
{
const DwAddress* addr = aFirstAddr;
while (addr) {
DwAddress* newAddr = (DwAddress*) addr->Clone();
Add(newAddr);
addr = (const DwAddress*) addr->Next();
}
}
#if defined (DW_DEBUG_VERSION)
void DwAddressList::PrintDebugInfo(std::ostream& aStrm, int aDepth/*=0*/) const
{
aStrm <<
"-------------- Debug info for DwAddressList class --------------\n";
_PrintDebugInfo(aStrm);
int depth = aDepth - 1;
depth = (depth >= 0) ? depth : 0;
if (aDepth == 0 || depth > 0) {
DwAddress* addr = mFirstAddress;
while (addr) {
addr->PrintDebugInfo(aStrm, depth);
addr = addr->Next();
}
}
}
#else
void DwAddressList::PrintDebugInfo(std::ostream&, int) const {}
#endif // defined (DW_DEBUG_VERSION)
#if defined (DW_DEBUG_VERSION)
void DwAddressList::_PrintDebugInfo(std::ostream& aStrm) const
{
DwFieldBody::_PrintDebugInfo(aStrm);
aStrm << "Address objects: ";
DwAddress* addr = mFirstAddress;
if (addr) {
int count = 0;
while (addr) {
if (count > 0) aStrm << ' ';
aStrm << addr->ObjectId();
addr = addr->Next();
++count;
}
aStrm << '\n';
}
else {
aStrm << "(none)\n";
}
}
#else
void DwAddressList::_PrintDebugInfo(std::ostream&) const {}
#endif // defined (DW_DEBUG_VERSION)
void DwAddressList::CheckInvariants() const
{
#if defined (DW_DEBUG_VERSION)
DwAddress* addr = mFirstAddress;
while (addr) {
addr->CheckInvariants();
assert((DwMessageComponent*) this == addr->Parent());
addr = addr->Next();
}
#endif // defined (DW_DEBUG_VERSION)
}
//-------------------------------------------------------------------------
DwAddressListParser::DwAddressListParser(const DwString& aStr)
: mTokenizer(aStr),
mAddrString(aStr)
{
mAddrType = eAddrError;
ParseNextAddress();
}
DwAddressListParser::~DwAddressListParser()
{
}
int DwAddressListParser::Restart()
{
mTokenizer.Restart();
ParseNextAddress();
return mAddrType;
}
int DwAddressListParser::operator ++ ()
{
ParseNextAddress();
return mAddrType;
}
void DwAddressListParser::ParseNextAddress()
{
mAddrString.SetFirst(mTokenizer);
mAddrType = eAddrEnd;
int type = mTokenizer.Type();
if (type == eTkNull) {
return;
}
enum {
eTopLevel,
eInGroup,
eInRouteAddr
} state;
state = eTopLevel;
// The type will be a mailbox, unless we discover otherwise
mAddrType = eAddrMailbox;
int done = 0;
while (!done) {
if (type == eTkNull) {
mAddrString.ExtendTo(mTokenizer);
break;
}
else if (type == eTkSpecial) {
int ch = mTokenizer.Token()[0];
switch (state) {
case eTopLevel:
switch (ch) {
case ',':
mAddrString.ExtendTo(mTokenizer);
done = 1;
break;
case '<':
state = eInRouteAddr;
break;
case ':':
mAddrType = eAddrGroup;
state = eInGroup;
break;
}
break;
case eInRouteAddr:
switch (ch) {
case '>':
state = eTopLevel;
break;
}
break;
case eInGroup:
switch (ch) {
case ';':
state = eTopLevel;
break;
}
break;
}
}
++mTokenizer;
type = mTokenizer.Type();
}
if (mAddrString.Tokens().length() == 0) {
mAddrType = eAddrNull;
}
}