diff options
author | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
---|---|---|
committer | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
commit | 460c52653ab0dcca6f19a4f492ed2c5e4e963ab0 (patch) | |
tree | 67208f7c145782a7e90b123b982ca78d88cc2c87 /mimelib/mailbox.cpp | |
download | tdepim-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.cpp | 481 |
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; +} |