//============================================================================= // File: msgid.cpp // Contents: Definitions for DwMsgId // Maintainer: Doug Sauder // 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 #include #include #include #include // UNIX specific includes //#if defined(__unix__) || defined(__unix) #if defined(DW_UNIX) # include # if defined(__SUNPRO_CC) # include # endif // defined(__SUNPRO_CC) #endif // defined (DW_UNIX) #ifdef HAVE_CONFIG_H #include "../config.h" #endif // WIN32 specific includes #if defined(DW_WIN32) # include #endif // defined(DW_WIN32) #include #include #include static void GetHostName(char* buf, int bufLen); static DwUint32 GetPid(); const char* const DwMsgId::sClassName = "DwMsgId"; const char* DwMsgId::sHostName = 0; DwMsgId* (*DwMsgId::sNewMsgId)(const DwString&, DwMessageComponent*) = 0; DwMsgId* DwMsgId::NewMsgId(const DwString& aStr, DwMessageComponent* aParent) { if (sNewMsgId) { return sNewMsgId(aStr, aParent); } else { return new DwMsgId(aStr, aParent); } } DwMsgId::DwMsgId() { mClassId = kCidMsgId; mClassName = sClassName; } DwMsgId::DwMsgId(const DwMsgId& aMsgId) : DwFieldBody(aMsgId), mLocalPart(aMsgId.mLocalPart), mDomain(aMsgId.mDomain) { mClassId = kCidMsgId; mClassName = sClassName; } DwMsgId::DwMsgId(const DwString& aStr, DwMessageComponent* aParent) : DwFieldBody(aStr, aParent) { mClassId = kCidMsgId; mClassName = sClassName; } DwMsgId::~DwMsgId() { } const DwMsgId& DwMsgId::operator = (const DwMsgId& aMsgId) { if (this == &aMsgId) return *this; DwFieldBody::operator = (aMsgId); mLocalPart = aMsgId.mLocalPart; mDomain = aMsgId.mDomain; return *this; } const DwString& DwMsgId::LocalPart() const { return mLocalPart; } void DwMsgId::SetLocalPart(const DwString& aLocalPart) { mLocalPart = aLocalPart; SetModified(); } const DwString& DwMsgId::Domain() const { return mDomain; } void DwMsgId::SetDomain(const DwString& aDomain) { mDomain = aDomain; SetModified(); } void DwMsgId::Parse() { mIsModified = 0; int ch; DwRfc822Tokenizer tokenizer(mString); // Advance to '<' int type = tokenizer.Type(); int found = 0; while (!found && type != eTkNull) { if (type == eTkSpecial && tokenizer.Token()[0] == '<') { found = 1; } ++tokenizer; type = tokenizer.Type(); } // Get the local part found = 0; while (type != eTkNull && !found) { switch (type) { case eTkSpecial: ch = tokenizer.Token()[0]; switch (ch) { case '@': found = 1; break; case '.': mLocalPart += tokenizer.Token(); break; } break; case eTkAtom: case eTkQuotedString: mLocalPart += tokenizer.Token(); break; } ++tokenizer; type = tokenizer.Type(); } // Get the domain found = 0; while (type != eTkNull && !found) { switch (type) { case eTkSpecial: ch = tokenizer.Token()[0]; switch (ch) { case '>': found = 1; break; case '.': mDomain += tokenizer.Token(); break; } break; case eTkAtom: mDomain += tokenizer.Token(); break; case eTkDomainLiteral: mDomain += tokenizer.Token(); break; } ++tokenizer; type = tokenizer.Type(); } } void DwMsgId::Assemble() { if (!mIsModified) return; mString = "<"; mString += mLocalPart; mString += "@"; mString += mDomain; mString += ">"; mIsModified = 0; } DwMessageComponent* DwMsgId::Clone() const { return new DwMsgId(*this); } static char base35chars[] = "0123456789ABCDEFGHIJKLMNPTQRSTUVWXYZ"; void DwMsgId::CreateDefault() { char hostname[80]; hostname[0] = 0; GetHostName(hostname, 80); hostname[79] = 0; char scratch[80]; time_t tt = time(NULL); struct tm tms = *localtime(&tt); int pos = 0; scratch[pos++] = '<'; int n = tms.tm_year; scratch[pos++] = char(n / 10 % 10 + '0'); scratch[pos++] = char(n % 10 + '0'); n = tms.tm_mon + 1; scratch[pos++] = char(n / 10 % 10 + '0'); scratch[pos++] = char(n % 10 + '0'); n = tms.tm_mday; scratch[pos++] = char(n / 10 % 10 + '0'); scratch[pos++] = char(n % 10 + '0'); n = tms.tm_hour; scratch[pos++] = char(n / 10 % 10 + '0'); scratch[pos++] = char(n % 10 + '0'); n = tms.tm_min; scratch[pos++] = char(n / 10 % 10 + '0'); scratch[pos++] = char(n % 10 + '0'); n = tms.tm_sec; scratch[pos++] = char(n / 10 % 10 + '0'); scratch[pos++] = char(n % 10 + '0'); static int counter = 0; scratch[pos++] = base35chars[counter/35%35]; scratch[pos++] = base35chars[counter %35]; ++counter; scratch[pos++] = '.'; DwUint32 pid = GetPid(); scratch[pos++] = char(pid / 10000 % 10 + '0'); scratch[pos++] = char(pid / 1000 % 10 + '0'); scratch[pos++] = char(pid / 100 % 10 + '0'); scratch[pos++] = char(pid / 10 % 10 + '0'); scratch[pos++] = char(pid % 10 + '0'); scratch[pos++] = '@'; char* cp = hostname; while (*cp && pos < 79) { scratch[pos++] = *cp++; } scratch[pos++] = '>'; scratch[pos] = 0; mString = scratch; mIsModified = 0; Parse(); } #if defined (DW_DEBUG_VERSION) void DwMsgId::PrintDebugInfo(std::ostream& aStrm, int /*aDepth*/) const { aStrm << "----------------- Debug info for DwMsgId class -----------------\n"; _PrintDebugInfo(aStrm); } #else void DwMsgId::PrintDebugInfo(std::ostream& , int ) const {} #endif // defined (DW_DEBUG_VERSION) #if defined (DW_DEBUG_VERSION) void DwMsgId::_PrintDebugInfo(std::ostream& aStrm) const { DwFieldBody::_PrintDebugInfo(aStrm); aStrm << "Local part: " << mLocalPart << '\n'; aStrm << "Domain: " << mDomain << '\n'; } #else void DwMsgId::_PrintDebugInfo(std::ostream& ) const {} #endif // defined (DW_DEBUG_VERSION) void DwMsgId::CheckInvariants() const { #if defined (DW_DEBUG_VERSION) DwFieldBody::CheckInvariants(); mLocalPart.CheckInvariants(); mDomain.CheckInvariants(); #endif // defined (DW_DEBUG_VERSION) } //============================================================================ // Platform dependent code follows //============================================================================ //---------------------------------------------------------------------------- // WIN32 //---------------------------------------------------------------------------- #if defined(DW_WIN32) #if defined(WINSOCK) // Winsock version static void GetHostName(char* buf, int bufLen) { WORD wVersionRequested = MAKEWORD(1, 1); WSADATA wsaData; int err = WSAStartup(wVersionRequested, &wsaData); // check winsock version 1.1 if (LOBYTE(wsaData.wVersion) == 1 && HIBYTE(wsaData.wVersion) == 1 && err == 0) { buf[0] = '\0'; if (!gethostname(buf, bufLen)) buf[bufLen-1] = '\0'; } else { // cannot find winsock if (DwMsgId::sHostName) { strcpy(hostname, DwMsgId::sHostName); } else { strcpy(hostname, "noname"); } } WSACleanup(); } #else // !defined(WINSOCK) // Generic version (no Winsock). Requires that DwMsgId::sHostName be set. static void GetHostName(char* buf, int bufLen) { if (DwMsgId::sHostName) { strncpy(buf, DwMsgId::sHostName, bufLen); buf[bufLen-1] = 0; } else { strcpy(buf, "noname"); } } #endif // !defined(WINSOCK) typedef unsigned pid_t; static DwUint32 GetPid() { return GetCurrentProcessId(); } #endif // defined(DW_WIN32) //---------------------------------------------------------------------------- // UNIX //---------------------------------------------------------------------------- #if defined(DW_UNIX) static void GetHostName(char* buf, int bufLen) { buf[0] = '\0'; if (!gethostname(buf, bufLen)) buf[bufLen-1] = '\0'; } static DwUint32 GetPid() { return getpid(); } #endif // defined(DW_UNIX)