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