Initial import of the CDE 2.1.30 sources from the Open Group.
[oweals/cde.git] / cde / programs / dtmail / dtmailpr / message.C
1 /* $TOG: message.C /main/9 1998/07/24 16:08:20 mgreess $
2  *
3  * (c) Copyright 1996 Digital Equipment Corporation.
4  * (c) Copyright 1996 Hewlett-Packard Company.
5  * (c) Copyright 1996 International Business Machines Corp.
6  * (c) Copyright 1994,1996 Sun Microsystems, Inc.
7  * (c) Copyright 1996 Novell, Inc. 
8  * (c) Copyright 1996 FUJITSU LIMITED.
9  * (c) Copyright 1996 Hitachi.
10  */
11
12 /*
13  *+SNOTICE
14  *
15  *      RESTRICTED CONFIDENTIAL INFORMATION:
16  *      
17  *      The information in this document is subject to special
18  *      restrictions in a confidential disclosure agreement between
19  *      HP, IBM, Sun, USL, SCO and Univel.  Do not distribute this
20  *      document outside HP, IBM, Sun, USL, SCO, or Univel without
21  *      Sun's specific written approval.  This document and all copies
22  *      and derivative works thereof must be returned or destroyed at
23  *      Sun's request.
24  *
25  *+ENOTICE
26  */
27
28 #include "dmx.hh"
29 // For CHARSET
30 #include <DtHelp/LocaleXlate.h>
31 #include <locale.h>
32 #if !defined(USL) && !defined(__uxp__)
33 #include <strings.h>
34 #else 
35 #include <EUSCompat.h>
36 #endif 
37 #include "utils/str_utils.h"
38
39
40 DmxMsg::DmxMsg (void)
41 {
42         // initialize everything
43         message = NULL;
44         addlInfo = NULL;
45         numBPs = 0;
46         cachedValues = B_FALSE;
47         isCurrent = B_FALSE;
48         hasAttachments = B_FALSE;
49         isNew = B_FALSE;
50
51         return;
52 }
53
54 void
55 DmxMsg::setHandle (DtMailMessageHandle &h)
56 {
57         msgHandle = h;
58         return;
59 }
60
61 void
62 DmxMsg::setHeader (DtMailHeaderLine &h)
63 {
64         msgHeader = h;
65         return;
66 }
67
68 void
69 DmxMsg::setMessage (DtMail::Message *m)
70 {
71         message = m;
72         return;
73 }
74
75 void
76 DmxMsg::setInfo (char *info)
77 {
78         addlInfo = strdup (info);
79         return;
80 }
81
82 void
83 DmxMsg::getFlags (void)
84 {
85         DtMailEnv       env;
86         DtMailBoolean   flagState;
87
88         memset (&env, '\0', sizeof (DtMailEnv));
89         flagState = DTM_FALSE;
90
91         
92
93
94         flagState = message->flagIsSet (env, DtMailMessageMultipart);
95         if (handleError (env, "msg: multipart?") == B_TRUE)
96                 exit (1);
97
98         if (flagState == DTM_TRUE)
99         {
100                 hasAttachments = B_TRUE;
101         } else {
102                 hasAttachments = B_FALSE;
103         }
104
105         flagState = message->flagIsSet (env, DtMailMessageNew);
106         if (handleError (env, "msg: new?") == B_TRUE)
107                 exit (1);
108         
109         if (flagState == DTM_TRUE)
110         {
111                 isNew = B_TRUE;
112         } else {
113                 isNew = B_FALSE;
114         }
115
116         return;
117 }
118         
119
120         
121
122 char *
123 DmxMsg::printHeader (enum DmxHeaderType htype)
124 {
125         DtMailEnv       env;
126         char            *status, *indicator;
127
128         if (isCurrent == B_TRUE)
129         {
130                 indicator = ">";
131         } else {
132                 indicator = " ";
133         }       
134
135         if (isNew == B_TRUE)
136         {
137                 status = "N";
138         } else {
139                 status = "O"; // how about "unread" ??
140         }
141
142         if (hasAttachments == B_TRUE)
143         {
144                 indicator = "@";
145         }
146
147         // the addlInfo string is any extra info needed by the
148         // viewer, such as a message number
149
150         char *buffer = new char [1024];
151         memset (buffer, 0, 1024);
152
153         switch (htype)
154         {
155                 case MSGLIST:
156                         sprintf (buffer, "%s%s%s %s",
157                                 indicator, status, addlInfo,
158                                 formatHeader (msgHeader, MSGLIST));
159                         break;
160                 case MSGHEADER:
161                         sprintf (buffer, "%s",
162                                 formatHeader (msgHeader, MSGHEADER));
163                         break;
164                 default:
165                         printf ("error in DmxMsg::display\n");
166                         break;
167         }
168
169
170         return buffer;
171 }
172
173
174 void
175 DmxMsg::display (void)
176 {
177         DtMailEnv                       env;
178         boolean_t               FirstIsText = B_FALSE;
179         DtMail::BodyPart        *firstPart = NULL, *nextpart = NULL;
180         char                    *type;
181         char                    *description = NULL;
182         char                    *sunDataDescription = NULL;
183         char                    *name = NULL;
184         void * contents = NULL;
185         unsigned long length = 0;
186         int mode = 0;
187         char *buf = NULL;
188 // For CHARSET
189         char *mime_cs = NULL, *from_cs = NULL, *to_cs = NULL;
190         char *v3_cs = new char [64];
191         
192         if (cachedValues != B_TRUE)
193                 parse ();       // read in body part info
194
195         firstPart = bodyParts [0];
196
197         firstPart->getContents(env,
198                 (const void **) &contents, 
199                 &length,
200                 NULL,   //type
201                 NULL,   //name
202                 NULL,   //mode
203                 NULL);  //description
204
205         if (handleError (env, "getContents") == B_TRUE)
206                 exit (1);
207
208 // For CHARSET
209
210    DtMailValueSeq value;
211    boolean_t err = B_FALSE;
212
213 // Get the bodypart's charset - Try MIME first then V3
214    firstPart->getHeader(env, DtMailMessageContentType, DTM_TRUE, value);
215    if (env.isNotSet()) {
216           mime_cs = firstPart->csFromContentType(value);
217    } else {
218           env.clear();
219           value.clear();
220           firstPart->getHeader(env, DtMailMessageV3charset, DTM_TRUE, value);
221           if (env.isNotSet()) {
222                  strcpy(v3_cs, *(value[0]));
223           } else {
224                  err = B_TRUE;
225                  env.clear();
226                  value.clear();
227           }
228    }
229 // If cannot obtain bodypart's charset header, then maybe this message
230 // has only one bodypart, then in this case the charset header maybe
231 // among the message's envelope (main message headers).
232 // Get the envelope of the message (in order to access the headers)
233    DtMail::Envelope *envelope = NULL;
234    if (err == B_TRUE) {
235           envelope = message->getEnvelope(env);
236           err = B_FALSE;
237 #ifdef DEBUG
238       env.logError(DTM_FALSE, "DEBUG dtmailpr: Looking at main message header\n");
239 #endif
240    }
241    if (envelope != NULL) {
242 //   Check for MIME charset header and then for V3 charset header
243      envelope->getHeader(env, DtMailMessageContentType, DTM_TRUE, value);
244      if (env.isNotSet()) {
245         mime_cs = firstPart->csFromContentType(value);
246      } else {
247             err = B_TRUE;
248             env.clear();
249      }
250      if (mime_cs == NULL || err == B_TRUE) {
251         value.clear();
252         envelope->getHeader(env, DtMailMessageV3charset, DTM_TRUE, value);
253         if (env.isNotSet()) {
254            strcpy(v3_cs, *(value[0]));
255         } else {
256                    err = B_TRUE;
257            env.clear();
258         }
259      }
260    } else {
261 #ifdef DEBUG
262           env.logError(DTM_FALSE, "DEBUG dtmailpr: envelope is null\n");
263 #endif
264           env.clear();
265    }
266
267 // Default codeset in case mime_cs and v3_cs are both null.
268    if ((mime_cs == NULL) && (strlen(v3_cs) == 0)) {
269           char *ret = NULL;
270           firstPart->DtXlateOpToStdLocale(DtLCX_OPER_SETLOCALE,
271                  setlocale(LC_CTYPE, NULL),
272                  NULL,
273                  NULL,
274                  &ret);
275           strcpy(v3_cs, "DEFAULT");
276           strcat(v3_cs, ".");
277           strcat(v3_cs, ret);
278           if (ret)
279                  free(ret);
280    }
281
282 // Get iconv from and to codeset and do conversion.
283    int converted = 0;
284    if (mime_cs) {
285       from_cs = firstPart->csToConvName(mime_cs);
286 #ifdef DEBUG
287       env.logError(DTM_FALSE, "DEBUG dtmailpr: mime_cs = %s\n", mime_cs);
288 #endif
289    } else {
290       from_cs = firstPart->csToConvName(v3_cs);
291 #ifdef DEBUG
292       env.logError(DTM_FALSE, "DEBUG dtmailpr: v3_cs = %s\n", v3_cs);
293 #endif
294    }
295    to_cs = firstPart->locToConvName();
296
297 #ifdef DEBUG
298    if ( from_cs == NULL )
299    env.logError(DTM_FALSE, "DEBUG dtmailpr: from_cs is NULL\n");
300    else
301    env.logError(DTM_FALSE, "DEBUG dtmailpr: from_cs = %s\n", from_cs);
302
303    if ( to_cs == NULL )
304    env.logError(DTM_FALSE, "DEBUG dtmailpr: to_cs is NULL\n");
305    else
306    env.logError(DTM_FALSE, "DEBUG dtmailpr: to_cs = %s\n", to_cs);
307 #endif
308
309    if ( from_cs && to_cs ) {
310      if ( strcasecmp(from_cs, to_cs) != 0 ) {
311         converted = firstPart->csConvert((char **)&contents, length, 0, from_cs, to_cs);
312 #ifdef DEBUG
313         env.logError(DTM_FALSE, "DEBUG dtmailpr: converted = %d\n", converted);
314 #endif
315      }
316    }
317    if ( mime_cs )
318       free ( mime_cs );
319    if ( from_cs )
320       free( from_cs );
321    if ( to_cs )
322       free ( to_cs );
323  
324 // End of For CHARSET
325
326
327         buf = new char [length + 1];
328         memset (buf, 0, (size_t) length + 1);
329
330         // have to "seek" length bytes into the
331         // contents buffer
332         memmove (buf, contents, (size_t) length);
333         buf [length] = '\0';    // null-terminate
334                                 // that puppy
335
336 // For CHARSET
337     if (converted && contents)
338            free(contents);
339
340         char    *numbuf = new char [10241];
341         memset (numbuf, 0, 1024);
342
343 #ifdef NEVER
344         // Don't want "Message 1:" appearing in print output
345         sprintf (numbuf, "Messsage %s:\n%s\n",
346                 addlInfo, printHeader (MSGHEADER));
347 #endif
348         puts(printHeader(MSGHEADER));
349         puts(buf);
350
351         fflush(stdout);
352
353         // No attachments?  We're done.
354         if (numBPs < 2)
355                 return;
356
357         int     i = 0;
358
359         char    *attbuf = NULL;
360
361         printf ("\n");
362         for (i = 1; i < numBPs ; i++)
363         {
364                 nextpart = bodyParts [i];
365
366                 if (nextpart == NULL)
367                         fprintf (stderr, "Error getting part!\n");
368
369                 length = 0;
370                 type = "";
371                 sunDataDescription = "";
372                 description = "";
373                 name = "";
374                 mode = -1;
375                 
376                 nextpart->getContents(env, NULL, &length, &type,
377                                 &name, &mode, &sunDataDescription);
378                 if (handleError (env, "getContents") == B_TRUE)
379                         exit (1);
380
381                 if (type == NULL)
382                         type = "(unknown)";
383
384                 if (sunDataDescription == NULL)
385                 {
386                         description = "";
387                 } else {
388                         // should add bracket or something
389                         attbuf = new char [strlen (sunDataDescription) +10];
390                         sprintf (attbuf, " (%s)", sunDataDescription);
391                         description = attbuf;
392                 }
393
394                 if (name == NULL)
395                         name = "(name)";
396
397                 printf ("[%d] \"%s\"%s, ", i, name, description);
398                 printf ("%s, %d bytes\n", type, length);
399
400                 if (attbuf != NULL)
401                         delete [] attbuf;
402
403         }
404
405         delete [] v3_cs;
406         return;
407 }
408
409 void
410 DmxMsg::parse (void)
411 {
412         // store the body parts for later reference
413
414         DtMailEnv                       env;
415         boolean_t               FirstIsText = B_FALSE;
416         DtMail::BodyPart        *part = NULL, *nextpart = NULL;
417         char                    *type = NULL, *attr = NULL;
418
419         int     bc = message->getBodyCount (env);
420         if (handleError (env, "getBodyCount") == B_TRUE)
421                 exit (1);
422
423         part = message->getFirstBodyPart (env);
424         if (handleError (env, "getFirstBodyPart") == B_TRUE)
425                 exit (1);
426
427         part->getContents (env, NULL, NULL, &type, NULL, NULL, NULL);
428         if (handleError (env, "getContents") == B_TRUE)
429                 exit (1);
430
431         bodyParts = new (DtMail::BodyPart *[bc]);
432         cachedValues = B_TRUE;
433         
434         // cache values
435         bodyParts [0] = part;
436         numBPs++;
437
438
439         if (type != NULL)
440         {
441                 attr = DtDtsDataTypeToAttributeValue (type,
442                                                 DtDTS_DA_IS_TEXT,
443                                                 NULL);
444                 if (attr != NULL)
445                 {
446                         FirstIsText = B_TRUE;
447                 }
448                 //free (type);  // it's allocating some data for us
449         } else {
450                 FirstIsText = B_FALSE;
451         }
452
453         // No attachments?  We're done.
454         if (bc < 2)
455                 return;
456
457         int     i;
458
459         for (i = 1; i < bc; i++)
460         {
461                 nextpart = NULL;
462                 nextpart = message->getNextBodyPart (env,
463                                                 part);
464                 if (handleError (env, "getNextBodyPart") == B_TRUE)
465                         exit (1);
466
467                 if (nextpart == NULL)
468                         fprintf (stderr, "Error getting part!\n");
469
470
471                 bodyParts [i] = nextpart;
472                 numBPs++;
473
474                 part = nextpart;
475         }
476 }
477