dtmailpr: fix vla warning
[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 libraries 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 <Dt/LocaleXlate.h>
53 #include <locale.h>
54 #include <strings.h>
55 #include "utils/str_utils.h"
56
57
58 DmxMsg::DmxMsg (void)
59 {
60         // initialize everything
61         message = NULL;
62         addlInfo = NULL;
63         numBPs = 0;
64         cachedValues = B_FALSE;
65         isCurrent = B_FALSE;
66         hasAttachments = B_FALSE;
67         isNew = B_FALSE;
68         msgHandle = NULL;
69         msgHeader.header_values = NULL;
70         msgHeader.number_of_names = 0;
71         bodyParts = NULL;
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           free(ret);
301    }
302
303 // Get iconv from and to codeset and do conversion.
304    int converted = 0;
305    if (mime_cs) {
306       from_cs = firstPart->csToConvName(mime_cs);
307 #ifdef DEBUG
308       env.logError(DTM_FALSE, "DEBUG dtmailpr: mime_cs = %s\n", mime_cs);
309 #endif
310    } else {
311       from_cs = firstPart->csToConvName(v3_cs);
312 #ifdef DEBUG
313       env.logError(DTM_FALSE, "DEBUG dtmailpr: v3_cs = %s\n", v3_cs);
314 #endif
315    }
316    to_cs = firstPart->locToConvName();
317
318 #ifdef DEBUG
319    if ( from_cs == NULL )
320    env.logError(DTM_FALSE, "DEBUG dtmailpr: from_cs is NULL\n");
321    else
322    env.logError(DTM_FALSE, "DEBUG dtmailpr: from_cs = %s\n", from_cs);
323
324    if ( to_cs == NULL )
325    env.logError(DTM_FALSE, "DEBUG dtmailpr: to_cs is NULL\n");
326    else
327    env.logError(DTM_FALSE, "DEBUG dtmailpr: to_cs = %s\n", to_cs);
328 #endif
329
330    if ( from_cs && to_cs ) {
331      if ( strcasecmp(from_cs, to_cs) != 0 ) {
332         converted = firstPart->csConvert((char **)&contents, length, 0, from_cs, to_cs);
333 #ifdef DEBUG
334         env.logError(DTM_FALSE, "DEBUG dtmailpr: converted = %d\n", converted);
335 #endif
336      }
337    }
338    if ( mime_cs )
339       free ( mime_cs );
340    if ( from_cs )
341       free( from_cs );
342    if ( to_cs )
343       free ( to_cs );
344  
345 // End of For CHARSET
346
347
348         buf = new char [length + 1];
349         memset (buf, 0, (size_t) length + 1);
350
351         // have to "seek" length bytes into the
352         // contents buffer
353         memmove (buf, contents, (size_t) length);
354         buf [length] = '\0';    // null-terminate
355                                 // that puppy
356
357 // For CHARSET
358     if (converted && contents)
359            free(contents);
360
361         char    *numbuf = new char [10241];
362         memset (numbuf, 0, 1024);
363
364 #ifdef NEVER
365         // Don't want "Message 1:" appearing in print output
366         sprintf (numbuf, "Messsage %s:\n%s\n",
367                 addlInfo, printHeader (MSGHEADER));
368 #endif
369         puts(printHeader(MSGHEADER));
370         puts(buf);
371
372         fflush(stdout);
373
374         // No attachments?  We're done.
375         if (numBPs < 2)
376                 return;
377
378         int     i = 0;
379
380         char    *attbuf = NULL;
381
382         printf ("\n");
383         for (i = 1; i < numBPs ; i++)
384         {
385                 nextpart = bodyParts [i];
386
387                 if (nextpart == NULL)
388                         fprintf (stderr, "Error getting part!\n");
389
390                 length = 0;
391                 type = "";
392                 sunDataDescription = "";
393                 description = "";
394                 name = "";
395                 mode = -1;
396                 
397                 nextpart->getContents(env, NULL, &length, &type,
398                                 &name, &mode, &sunDataDescription);
399                 if (handleError (env, "getContents") == B_TRUE)
400                         exit (1);
401
402                 if (type == NULL)
403                         type = "(unknown)";
404
405                 if (sunDataDescription == NULL)
406                 {
407                         description = "";
408                 } else {
409                         // should add bracket or something
410                         attbuf = new char [strlen (sunDataDescription) +10];
411                         sprintf (attbuf, " (%s)", sunDataDescription);
412                         description = attbuf;
413                 }
414
415                 if (name == NULL)
416                         name = "(name)";
417
418                 printf ("[%d] \"%s\"%s, ", i, name, description);
419                 printf ("%s, %lu bytes\n", type, length);
420
421                 if (attbuf != NULL)
422                         delete [] attbuf;
423
424         }
425
426         delete [] v3_cs;
427         return;
428 }
429
430 void
431 DmxMsg::parse (void)
432 {
433         // store the body parts for later reference
434
435         DtMailEnv                       env;
436         boolean_t               FirstIsText = B_FALSE;
437         DtMail::BodyPart        *part = NULL, *nextpart = NULL;
438         char                    *type = NULL, *attr = NULL;
439
440         int     bc = message->getBodyCount (env);
441         if (handleError (env, "getBodyCount") == B_TRUE)
442                 exit (1);
443
444         part = message->getFirstBodyPart (env);
445         if (handleError (env, "getFirstBodyPart") == B_TRUE)
446                 exit (1);
447
448         part->getContents (env, NULL, NULL, &type, NULL, NULL, NULL);
449         if (handleError (env, "getContents") == B_TRUE)
450                 exit (1);
451
452         bodyParts = new DtMail::BodyPart *[bc];
453         cachedValues = B_TRUE;
454
455         // cache values
456         bodyParts [0] = part;
457         numBPs++;
458
459
460         if (type != NULL)
461         {
462                 attr = DtDtsDataTypeToAttributeValue (type,
463                                                 DtDTS_DA_IS_TEXT,
464                                                 NULL);
465                 if (attr != NULL)
466                 {
467                         FirstIsText = B_TRUE;
468                 }
469                 //free (type);  // it's allocating some data for us
470         } else {
471                 FirstIsText = B_FALSE;
472         }
473
474         // No attachments?  We're done.
475         if (bc < 2)
476                 return;
477
478         int     i;
479
480         for (i = 1; i < bc; i++)
481         {
482                 nextpart = NULL;
483                 nextpart = message->getNextBodyPart (env,
484                                                 part);
485                 if (handleError (env, "getNextBodyPart") == B_TRUE)
486                         exit (1);
487
488                 if (nextpart == NULL)
489                         fprintf (stderr, "Error getting part!\n");
490
491
492                 bodyParts [i] = nextpart;
493                 numBPs++;
494
495                 part = nextpart;
496         }
497 }
498