summaryrefslogtreecommitdiffstats
path: root/mimelib/addrlist.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'mimelib/addrlist.cpp')
-rw-r--r--mimelib/addrlist.cpp403
1 files changed, 403 insertions, 0 deletions
diff --git a/mimelib/addrlist.cpp b/mimelib/addrlist.cpp
new file mode 100644
index 000000000..ab444744b
--- /dev/null
+++ b/mimelib/addrlist.cpp
@@ -0,0 +1,403 @@
+//=============================================================================
+// 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;
+ }
+}