summaryrefslogtreecommitdiffstats
path: root/mimelib/mailbox.cpp
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commit460c52653ab0dcca6f19a4f492ed2c5e4e963ab0 (patch)
tree67208f7c145782a7e90b123b982ca78d88cc2c87 /mimelib/mailbox.cpp
downloadtdepim-460c52653ab0dcca6f19a4f492ed2c5e4e963ab0.tar.gz
tdepim-460c52653ab0dcca6f19a4f492ed2c5e4e963ab0.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdepim@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'mimelib/mailbox.cpp')
-rw-r--r--mimelib/mailbox.cpp481
1 files changed, 481 insertions, 0 deletions
diff --git a/mimelib/mailbox.cpp b/mimelib/mailbox.cpp
new file mode 100644
index 000000000..b5dc7cc3f
--- /dev/null
+++ b/mimelib/mailbox.cpp
@@ -0,0 +1,481 @@
+//=============================================================================
+// File: mailbox.cpp
+// Contents: Definitions for DwMailbox
+// 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 <iostream>
+#include <mimelib/string.h>
+#include <mimelib/mailbox.h>
+#include <mimelib/token.h>
+
+void RemoveCrAndLf(DwString& aStr);
+
+const char* const DwMailbox::sClassName = "DwMailbox";
+
+
+DwMailbox* (*DwMailbox::sNewMailbox)(const DwString&, DwMessageComponent*) = 0;
+
+
+DwMailbox* DwMailbox::NewMailbox(const DwString& aStr,
+ DwMessageComponent* aParent)
+{
+ if (sNewMailbox) {
+ return sNewMailbox(aStr, aParent);
+ }
+ else {
+ return new DwMailbox(aStr, aParent);
+ }
+}
+
+
+DwMailbox::DwMailbox()
+{
+ mClassId = kCidMailbox;
+ mClassName = sClassName;
+}
+
+
+DwMailbox::DwMailbox(const DwMailbox& aMailbox)
+ : DwAddress(aMailbox),
+ mFullName(aMailbox.mFullName),
+ mRoute(aMailbox.mRoute),
+ mLocalPart(aMailbox.mLocalPart),
+ mDomain(aMailbox.mDomain)
+{
+ mClassId = kCidMailbox;
+ mClassName = sClassName;
+}
+
+
+DwMailbox::DwMailbox(const DwString& aStr, DwMessageComponent* aParent)
+ : DwAddress(aStr, aParent)
+{
+ mClassId = kCidMailbox;
+ mClassName = sClassName;
+}
+
+
+DwMailbox::~DwMailbox()
+{
+}
+
+
+const DwMailbox& DwMailbox::operator = (const DwMailbox& aMailbox)
+{
+ if (this == &aMailbox) return *this;
+ DwAddress::operator = (aMailbox);
+ mFullName = aMailbox.mFullName;
+ mRoute = aMailbox.mRoute;
+ mLocalPart = aMailbox.mLocalPart;
+ mDomain = aMailbox.mDomain;
+ return *this;
+}
+
+
+const DwString& DwMailbox::FullName() const
+{
+ return mFullName;
+}
+
+
+void DwMailbox::SetFullName(const DwString& aFullName)
+{
+ mFullName = aFullName;
+ SetModified();
+}
+
+
+const DwString& DwMailbox::Route() const
+{
+ return mRoute;
+}
+
+
+void DwMailbox::SetRoute(const DwString& aRoute)
+{
+ mRoute = aRoute;
+ SetModified();
+}
+
+
+const DwString& DwMailbox::LocalPart() const
+{
+ return mLocalPart;
+}
+
+
+void DwMailbox::SetLocalPart(const DwString& aLocalPart)
+{
+ mLocalPart = aLocalPart;
+ SetModified();
+}
+
+
+const DwString& DwMailbox::Domain() const
+{
+ return mDomain;
+}
+
+
+void DwMailbox::SetDomain(const DwString& aDomain)
+{
+ mDomain = aDomain;
+ SetModified();
+}
+
+
+// Some mailboxes to test
+//
+// John Doe <john.doe@acme.com>
+// John@acme.com (John Doe)
+// John.Doe@acme.com (John Doe)
+// John.Doe (Jr) @acme.com (John Doe)
+// John <@domain1.com,@domain2.com:jdoe@acme.com>
+// <jdoe@acme>
+// <@node1.[128.129.130.131],@node2.uu.edu:
+// jdoe(John Doe)@node3.[131.130.129.128]> (John Doe)
+//
+void DwMailbox::Parse()
+{
+ mIsModified = 0;
+ DwString emptyString("");
+ DwString space(" ");
+ int isFirstPhraseNull = 1;
+ int isSimpleAddress = 1;
+ DwString firstPhrase(emptyString);
+ DwString lastComment(emptyString);
+ mRoute = emptyString;
+ mLocalPart = emptyString;
+ mDomain = emptyString;
+ mFullName = emptyString;
+ DwRfc822Tokenizer tokenizer(mString);
+ int ch;
+
+ enum {
+ eStart, // start
+ eLtSeen, // less-than-seen
+ eInRoute, // in-route
+ eInAddrSpec, // in-addr-spec
+ eAtSeen, // at-seen
+ eGtSeen // greater-than-seen
+ };
+
+ // Start state -- terminated by '<' or '@'
+
+ int type = tokenizer.Type();
+ int state = eStart;
+ while (state == eStart && type != eTkNull) {
+ switch (type) {
+ case eTkSpecial:
+ ch = tokenizer.Token()[0];
+ switch (ch) {
+ case '@':
+ state = eAtSeen;
+ break;
+ case '<':
+ isSimpleAddress = 0;
+ mLocalPart = emptyString;
+ state = eLtSeen;
+ break;
+ case '.':
+ mLocalPart += tokenizer.Token();
+ break;
+ }
+ break;
+ case eTkAtom:
+ case eTkQuotedString:
+ if (isFirstPhraseNull) {
+ firstPhrase = tokenizer.Token();
+ isFirstPhraseNull = 0;
+ }
+ else {
+ firstPhrase += space;
+ firstPhrase += tokenizer.Token();
+ }
+ mLocalPart += tokenizer.Token();
+ break;
+ case eTkComment:
+ tokenizer.StripDelimiters();
+ lastComment = tokenizer.Token();
+ break;
+ }
+ ++tokenizer;
+ type = tokenizer.Type();
+ }
+
+ // Less-than-seen state -- process only one valid token and transit to
+ // in-route state or in-addr-spec state
+
+ while (state == eLtSeen && type != eTkNull) {
+ switch (type) {
+ case eTkSpecial:
+ ch = tokenizer.Token()[0];
+ switch (ch) {
+ case '@':
+ // '@' immediately following '<' indicates a route
+ mRoute = tokenizer.Token();
+ state = eInRoute;
+ break;
+ }
+ break;
+ case eTkAtom:
+ case eTkQuotedString:
+ mLocalPart = tokenizer.Token();
+ state = eInAddrSpec;
+ break;
+ }
+ ++tokenizer;
+ type = tokenizer.Type();
+ }
+
+ // In-route state -- terminated by ':'
+
+ while (state == eInRoute && type != eTkNull) {
+ switch (type) {
+ case eTkSpecial:
+ ch = tokenizer.Token()[0];
+ switch (ch) {
+ case ':':
+ state = eInAddrSpec;
+ break;
+ case '@':
+ case ',':
+ case '.':
+ mRoute += tokenizer.Token();
+ break;
+ }
+ break;
+ case eTkAtom:
+ mRoute += tokenizer.Token();
+ break;
+ case eTkDomainLiteral:
+ mRoute += tokenizer.Token();
+ break;
+ }
+ ++tokenizer;
+ type = tokenizer.Type();
+ }
+
+ // in-addr-spec state -- terminated by '@'
+
+ while (state == eInAddrSpec && type != eTkNull) {
+ switch (type) {
+ case eTkSpecial:
+ ch = tokenizer.Token()[0];
+ switch (ch) {
+ case '@':
+ state = eAtSeen;
+ break;
+ case '.':
+ mLocalPart += tokenizer.Token();
+ break;
+ }
+ break;
+ case eTkAtom:
+ case eTkQuotedString:
+ mLocalPart += tokenizer.Token();
+ break;
+ }
+ ++tokenizer;
+ type = tokenizer.Type();
+ }
+
+ // at-seen state -- terminated by '>' or end of string
+
+ while (state == eAtSeen && type != eTkNull) {
+ switch (type) {
+ case eTkSpecial:
+ ch = tokenizer.Token()[0];
+ switch (ch) {
+ case '>':
+ state = eGtSeen;
+ break;
+ case '.':
+ mDomain += tokenizer.Token();
+ break;
+ }
+ break;
+ case eTkAtom:
+ mDomain += tokenizer.Token();
+ break;
+ case eTkDomainLiteral:
+ mDomain += tokenizer.Token();
+ break;
+ case eTkComment:
+ tokenizer.StripDelimiters();
+ lastComment = tokenizer.Token();
+ break;
+ }
+ ++tokenizer;
+ type = tokenizer.Type();
+ }
+
+ // greater-than-seen state -- terminated by end of string
+
+ while (state == eGtSeen && type != eTkNull) {
+ switch (type) {
+ case eTkComment:
+ tokenizer.StripDelimiters();
+ lastComment = tokenizer.Token();
+ break;
+ }
+ ++tokenizer;
+ type = tokenizer.Type();
+ }
+
+ // Get full name, if possible
+
+ if (isSimpleAddress) {
+ mFullName = lastComment;
+ }
+ else if (firstPhrase != emptyString) {
+ mFullName = firstPhrase;
+ }
+ else if (lastComment != emptyString) {
+ mFullName = lastComment;
+ }
+
+ // Check validity
+
+ if (mLocalPart.length() > 0) {
+ mIsValid = 1;
+ }
+ else {
+ mIsValid = 0;
+ }
+
+ // Remove CR or LF from local-part or full name
+
+ RemoveCrAndLf(mFullName);
+ RemoveCrAndLf(mLocalPart);
+}
+
+
+void DwMailbox::Assemble()
+{
+ if (!mIsModified) return;
+ mIsValid = 1;
+ if (mLocalPart.length() == 0 || mDomain.length() == 0) {
+ mIsValid = 0;
+ mString = "";
+ return;
+ }
+ mString = "";
+ if (mFullName.length() > 0) {
+ mString += mFullName;
+ mString += " ";
+ }
+ mString += "<";
+ if (mRoute.length() > 0) {
+ mString += mRoute;
+ mString += ":";
+ }
+ mString += mLocalPart;
+ mString += "@";
+ mString += mDomain;
+ mString += ">";
+ mIsModified = 0;
+}
+
+DwMessageComponent* DwMailbox::Clone() const
+{
+ return new DwMailbox(*this);
+}
+
+
+#if defined(DW_DEBUG_VERSION)
+void DwMailbox::PrintDebugInfo(std::ostream& aStrm, int /*aDepth*/) const
+{
+ aStrm <<
+ "---------------- Debug info for DwMailbox class ----------------\n";
+ _PrintDebugInfo(aStrm);
+}
+#else
+void DwMailbox::PrintDebugInfo(std::ostream& , int) const {}
+#endif // defined(DW_DEBUG_VERSION)
+
+
+#if defined(DW_DEBUG_VERSION)
+void DwMailbox::_PrintDebugInfo(std::ostream& aStrm) const
+{
+ DwAddress::_PrintDebugInfo(aStrm);
+ aStrm << "Full Name: " << mFullName << '\n';
+ aStrm << "Route: " << mRoute << '\n';
+ aStrm << "Local Part: " << mLocalPart << '\n';
+ aStrm << "Domain: " << mDomain << '\n';
+}
+#else
+void DwMailbox::_PrintDebugInfo(std::ostream& ) const {}
+#endif // defined(DW_DEBUG_VERSION)
+
+
+void DwMailbox::CheckInvariants() const
+{
+#if defined(DW_DEBUG_VERSION)
+ DwAddress::CheckInvariants();
+ mFullName.CheckInvariants();
+ mRoute.CheckInvariants();
+ mLocalPart.CheckInvariants();
+ mDomain.CheckInvariants();
+#endif // defined(DW_DEBUG_VERSION)
+}
+
+
+void RemoveCrAndLf(DwString& aStr)
+{
+ // Do a quick check to see if at least one CR or LF is present
+
+ size_t n = aStr.find_first_of("\r\n");
+ if (n == DwString::npos)
+ return;
+
+ // At least one CR or LF is present, so copy the string
+
+ const DwString& in = aStr;
+ size_t inLen = in.length();
+ DwString out;
+ out.reserve(inLen);
+ int lastChar = 0;
+ size_t i = 0;
+ while (i < inLen) {
+ int ch = in[i];
+ if (ch == (int) '\r') {
+ out += ' ';
+ }
+ else if (ch == (int) '\n') {
+ if (lastChar != (int) '\r') {
+ out += ' ';
+ }
+ }
+ else {
+ out += (char) ch;
+ }
+ lastChar = ch;
+ ++i;
+ }
+ aStr = out;
+}