1 //=============================================================================
2 // File:       msgid.cpp
3 // Contents:   Definitions for DwMsgId
4 // Maintainer: Doug Sauder <dwsauder@fwb.gulf.net>
5 // WWW:        http://www.fwb.gulf.net/~dwsauder/mimepp.html
6 // $Revision: 1.10.6.1 $
7 // $Date: 2002/12/15 15:59:44 $
8 //
9 // Copyright (c) 1996, 1997 Douglas W. Sauder
10 // All rights reserved.
11 //
12 // IN NO EVENT SHALL DOUGLAS W. SAUDER BE LIABLE TO ANY PARTY FOR DIRECT,
13 // INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
14 // THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF DOUGLAS W. SAUDER
15 // HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16 //
17 // DOUGLAS W. SAUDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT
18 // NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
19 // PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
20 // BASIS, AND DOUGLAS W. SAUDER HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
21 // SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
22 //
23 //=============================================================================
24 
25 #define DW_IMPLEMENTATION
26 
27 #include <mimelib/config.h>
28 #include <mimelib/debug.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <time.h>
32 
33 // UNIX specific includes
34 
35 //#if defined(__unix__) || defined(__unix)
36 #if defined(DW_UNIX)
37 #  include <unistd.h>
38 #  if defined(__SUNPRO_CC)
39 #    include <sysent.h>
40 #  endif // defined(__SUNPRO_CC)
41 #endif // defined (DW_UNIX)
42 
43 #ifdef HAVE_CONFIG_H
44 #include "../config.h"
45 #endif
46 
47 // WIN32 specific includes
48 
49 #if defined(DW_WIN32)
50 #  include <windows.h>
51 #endif // defined(DW_WIN32)
52 
53 #include <mimelib/string.h>
54 #include <mimelib/msgid.h>
55 #include <mimelib/token.h>
56 
57 static void GetHostName(char* buf, int bufLen);
58 static DwUint32 GetPid();
59 
60 
61 const char* const DwMsgId::sClassName = "DwMsgId";
62 const char* DwMsgId::sHostName = 0;
63 
64 
65 DwMsgId* (*DwMsgId::sNewMsgId)(const DwString&, DwMessageComponent*) = 0;
66 
67 
NewMsgId(const DwString & aStr,DwMessageComponent * aParent)68 DwMsgId* DwMsgId::NewMsgId(const DwString& aStr, DwMessageComponent* aParent)
69 {
70     if (sNewMsgId) {
71         return sNewMsgId(aStr, aParent);
72     }
73     else {
74         return new DwMsgId(aStr, aParent);
75     }
76 }
77 
78 
DwMsgId()79 DwMsgId::DwMsgId()
80 {
81     mClassId = kCidMsgId;
82     mClassName = sClassName;
83 }
84 
85 
DwMsgId(const DwMsgId & aMsgId)86 DwMsgId::DwMsgId(const DwMsgId& aMsgId)
87   : DwFieldBody(aMsgId),
88     mLocalPart(aMsgId.mLocalPart),
89     mDomain(aMsgId.mDomain)
90 {
91     mClassId = kCidMsgId;
92     mClassName = sClassName;
93 }
94 
95 
DwMsgId(const DwString & aStr,DwMessageComponent * aParent)96 DwMsgId::DwMsgId(const DwString& aStr, DwMessageComponent* aParent)
97   : DwFieldBody(aStr, aParent)
98 {
99     mClassId = kCidMsgId;
100     mClassName = sClassName;
101 }
102 
103 
~DwMsgId()104 DwMsgId::~DwMsgId()
105 {
106 }
107 
108 
operator =(const DwMsgId & aMsgId)109 const DwMsgId& DwMsgId::operator = (const DwMsgId& aMsgId)
110 {
111     if (this == &aMsgId) return *this;
112     DwFieldBody::operator = (aMsgId);
113     mLocalPart = aMsgId.mLocalPart;
114     mDomain = aMsgId.mDomain;
115     return *this;
116 }
117 
118 
LocalPart() const119 const DwString& DwMsgId::LocalPart() const
120 {
121     return mLocalPart;
122 }
123 
124 
SetLocalPart(const DwString & aLocalPart)125 void DwMsgId::SetLocalPart(const DwString& aLocalPart)
126 {
127     mLocalPart = aLocalPart;
128     SetModified();
129 }
130 
131 
Domain() const132 const DwString& DwMsgId::Domain() const
133 {
134     return mDomain;
135 }
136 
137 
SetDomain(const DwString & aDomain)138 void DwMsgId::SetDomain(const DwString& aDomain)
139 {
140     mDomain = aDomain;
141     SetModified();
142 }
143 
144 
Parse()145 void DwMsgId::Parse()
146 {
147     mIsModified = 0;
148 
149     int ch;
150     DwRfc822Tokenizer tokenizer(mString);
151 
152     // Advance to '<'
153     int type = tokenizer.Type();
154     int found = 0;
155     while (!found && type != eTkNull) {
156         if (type == eTkSpecial && tokenizer.Token()[0] == '<') {
157             found = 1;
158         }
159         ++tokenizer;
160         type = tokenizer.Type();
161     }
162     // Get the local part
163     found = 0;
164     while (type != eTkNull && !found) {
165         switch (type) {
166         case eTkSpecial:
167             ch = tokenizer.Token()[0];
168             switch (ch) {
169             case '@':
170                 found = 1;
171                 break;
172             case '.':
173                 mLocalPart += tokenizer.Token();
174                 break;
175             }
176             break;
177         case eTkAtom:
178         case eTkQuotedString:
179             mLocalPart += tokenizer.Token();
180             break;
181         }
182         ++tokenizer;
183         type = tokenizer.Type();
184     }
185     // Get the domain
186     found = 0;
187     while (type != eTkNull && !found) {
188         switch (type) {
189         case eTkSpecial:
190             ch = tokenizer.Token()[0];
191             switch (ch) {
192             case '>':
193                 found = 1;
194                 break;
195             case '.':
196                 mDomain += tokenizer.Token();
197                 break;
198             }
199             break;
200         case eTkAtom:
201             mDomain += tokenizer.Token();
202             break;
203         case eTkDomainLiteral:
204             mDomain += tokenizer.Token();
205             break;
206         }
207         ++tokenizer;
208         type = tokenizer.Type();
209     }
210 }
211 
212 
Assemble()213 void DwMsgId::Assemble()
214 {
215     if (!mIsModified) return;
216     mString = "<";
217     mString += mLocalPart;
218     mString += "@";
219     mString += mDomain;
220     mString += ">";
221     mIsModified = 0;
222 }
223 
224 
Clone() const225 DwMessageComponent* DwMsgId::Clone() const
226 {
227     return new DwMsgId(*this);
228 }
229 
230 
231 static char base35chars[] = "0123456789ABCDEFGHIJKLMNPQRSTUVWXYZ";
232 
CreateDefault()233 void DwMsgId::CreateDefault()
234 {
235     char hostname[80];
236     hostname[0] = 0;
237     GetHostName(hostname, 80);
238     hostname[79] = 0;
239     char scratch[80];
240     time_t tt = time(NULL);
241     struct tm tms = *localtime(&tt);
242     int pos = 0;
243     scratch[pos++] = '<';
244     int n = tms.tm_year;
245     scratch[pos++] = char(n / 10   % 10 + '0');
246     scratch[pos++] = char(n        % 10 + '0');
247     n = tms.tm_mon + 1;
248     scratch[pos++] = char(n / 10 % 10 + '0');
249     scratch[pos++] = char(n      % 10 + '0');
250     n = tms.tm_mday;
251     scratch[pos++] = char(n / 10 % 10 + '0');
252     scratch[pos++] = char(n      % 10 + '0');
253     n = tms.tm_hour;
254     scratch[pos++] = char(n / 10 % 10 + '0');
255     scratch[pos++] = char(n      % 10 + '0');
256     n = tms.tm_min;
257     scratch[pos++] = char(n / 10 % 10 + '0');
258     scratch[pos++] = char(n      % 10 + '0');
259     n = tms.tm_sec;
260     scratch[pos++] = char(n / 10 % 10 + '0');
261     scratch[pos++] = char(n      % 10 + '0');
262     static int counter = 0;
263     scratch[pos++] = base35chars[counter/35%35];
264     scratch[pos++] = base35chars[counter   %35];
265     ++counter;
266     scratch[pos++] = '.';
267     DwUint32 pid = GetPid();
268     scratch[pos++] = char(pid / 10000 % 10 + '0');
269     scratch[pos++] = char(pid / 1000  % 10 + '0');
270     scratch[pos++] = char(pid / 100   % 10 + '0');
271     scratch[pos++] = char(pid / 10    % 10 + '0');
272     scratch[pos++] = char(pid         % 10 + '0');
273     scratch[pos++] = '@';
274     char* cp = hostname;
275     while (*cp && pos < 79) {
276         scratch[pos++] = *cp++;
277     }
278     scratch[pos++] = '>';
279     scratch[pos] = 0;
280     mString = scratch;
281     mIsModified = 0;
282     Parse();
283 }
284 
285 
PrintDebugInfo(std::ostream & aStrm,int) const286 void DwMsgId::PrintDebugInfo(std::ostream& aStrm, int /*aDepth*/) const
287 {
288 #if defined (DW_DEBUG_VERSION)
289     aStrm <<
290     "----------------- Debug info for DwMsgId class -----------------\n";
291     _PrintDebugInfo(aStrm);
292 #endif // defined (DW_DEBUG_VERSION)
293 }
294 
295 
_PrintDebugInfo(std::ostream & aStrm) const296 void DwMsgId::_PrintDebugInfo(std::ostream& aStrm) const
297 {
298 #if defined (DW_DEBUG_VERSION)
299     DwFieldBody::_PrintDebugInfo(aStrm);
300     aStrm << "Local part:       " << mLocalPart << '\n';
301     aStrm << "Domain:           " << mDomain    << '\n';
302 #endif // defined (DW_DEBUG_VERSION)
303 }
304 
305 
CheckInvariants() const306 void DwMsgId::CheckInvariants() const
307 {
308 #if defined (DW_DEBUG_VERSION)
309     DwFieldBody::CheckInvariants();
310     mLocalPart.CheckInvariants();
311     mDomain.CheckInvariants();
312 #endif // defined (DW_DEBUG_VERSION)
313 }
314 
315 //============================================================================
316 // Platform dependent code follows
317 //============================================================================
318 
319 //----------------------------------------------------------------------------
320 // WIN32
321 //----------------------------------------------------------------------------
322 
323 #if defined(DW_WIN32)
324 #if defined(WINSOCK)
325 
326 // Winsock version
327 
GetHostName(char * buf,int bufLen)328 static void GetHostName(char* buf, int bufLen)
329 {
330     WORD wVersionRequested = MAKEWORD(1, 1);
331     WSADATA wsaData;
332     int err = WSAStartup(wVersionRequested, &wsaData);
333     // check winsock version 1.1
334     if (LOBYTE(wsaData.wVersion) == 1 &&
335         HIBYTE(wsaData.wVersion) == 1 &&
336         err == 0) {
337 	buf[0] = '\0';
338         if (!gethostname(buf, bufLen))
339 	  buf[bufLen-1] = '\0';
340     }
341     else {
342         // cannot find winsock
343         if (DwMsgId::sHostName) {
344             strcpy(hostname, DwMsgId::sHostName);
345         }
346         else {
347             strcpy(hostname, "noname");
348         }
349     }
350     WSACleanup();
351 }
352 
353 #else // !defined(WINSOCK)
354 
355 // Generic version (no Winsock).  Requires that DwMsgId::sHostName be set.
356 
GetHostName(char * buf,int bufLen)357 static void GetHostName(char* buf, int bufLen)
358 {
359     if (DwMsgId::sHostName) {
360         strncpy(buf, DwMsgId::sHostName, bufLen);
361         buf[bufLen-1] = 0;
362     }
363     else {
364         strcpy(buf, "noname");
365     }
366 }
367 
368 #endif // !defined(WINSOCK)
369 
370 typedef unsigned pid_t;
371 
GetPid()372 static DwUint32 GetPid()
373 {
374     return GetCurrentProcessId();
375 }
376 
377 #endif // defined(DW_WIN32)
378 
379 //----------------------------------------------------------------------------
380 // UNIX
381 //----------------------------------------------------------------------------
382 
383 #if defined(DW_UNIX)
384 
GetHostName(char * buf,int bufLen)385 static void GetHostName(char* buf, int bufLen)
386 {
387    buf[0] = '\0';
388    if (!gethostname(buf, bufLen))
389      buf[bufLen-1] = '\0';
390 }
391 
GetPid()392 static DwUint32 GetPid()
393 {
394     return getpid();
395 }
396 
397 #endif // defined(DW_UNIX)
398