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