Even more spelling fixed
[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 <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         msgHandle = NULL;
73         msgHeader.header_values = NULL;
74         msgHeader.number_of_names = 0;
75         bodyParts = NULL;
76
77         return;
78 }
79
80 void
81 DmxMsg::setHandle (DtMailMessageHandle &h)
82 {
83         msgHandle = h;
84         return;
85 }
86
87 void
88 DmxMsg::setHeader (DtMailHeaderLine &h)
89 {
90         msgHeader = h;
91         return;
92 }
93
94 void
95 DmxMsg::setMessage (DtMail::Message *m)
96 {
97         message = m;
98         return;
99 }
100
101 void
102 DmxMsg::setInfo (char *info)
103 {
104         addlInfo = strdup (info);
105         return;
106 }
107
108 void
109 DmxMsg::getFlags (void)
110 {
111         DtMailEnv       env;
112         DtMailBoolean   flagState;
113
114         memset (&env, '\0', sizeof (DtMailEnv));
115         flagState = DTM_FALSE;
116
117         
118
119
120         flagState = message->flagIsSet (env, DtMailMessageMultipart);
121         if (handleError (env, "msg: multipart?") == B_TRUE)
122                 exit (1);
123
124         if (flagState == DTM_TRUE)
125         {
126                 hasAttachments = B_TRUE;
127         } else {
128                 hasAttachments = B_FALSE;
129         }
130
131         flagState = message->flagIsSet (env, DtMailMessageNew);
132         if (handleError (env, "msg: new?") == B_TRUE)
133                 exit (1);
134         
135         if (flagState == DTM_TRUE)
136         {
137                 isNew = B_TRUE;
138         } else {
139                 isNew = B_FALSE;
140         }
141
142         return;
143 }
144         
145
146         
147
148 char *
149 DmxMsg::printHeader (enum DmxHeaderType htype)
150 {
151         DtMailEnv       env;
152         char            *status, *indicator;
153
154         if (isCurrent == B_TRUE)
155         {
156                 indicator = ">";
157         } else {
158                 indicator = " ";
159         }       
160
161         if (isNew == B_TRUE)
162         {
163                 status = "N";
164         } else {
165                 status = "O"; // how about "unread" ??
166         }
167
168         if (hasAttachments == B_TRUE)
169         {
170                 indicator = "@";
171         }
172
173         // the addlInfo string is any extra info needed by the
174         // viewer, such as a message number
175
176         char *buffer = new char [1024];
177         memset (buffer, 0, 1024);
178
179         switch (htype)
180         {
181                 case MSGLIST:
182                         sprintf (buffer, "%s%s%s %s",
183                                 indicator, status, addlInfo,
184                                 formatHeader (msgHeader, MSGLIST));
185                         break;
186                 case MSGHEADER:
187                         sprintf (buffer, "%s",
188                                 formatHeader (msgHeader, MSGHEADER));
189                         break;
190                 default:
191                         printf ("error in DmxMsg::display\n");
192                         break;
193         }
194
195
196         return buffer;
197 }
198
199
200 void
201 DmxMsg::display (void)
202 {
203         DtMailEnv                       env;
204         boolean_t               FirstIsText = B_FALSE;
205         DtMail::BodyPart        *firstPart = NULL, *nextpart = NULL;
206         char                    *type;
207         char                    *description = NULL;
208         char                    *sunDataDescription = NULL;
209         char                    *name = NULL;
210         void * contents = NULL;
211         unsigned long length = 0;
212         int mode = 0;
213         char *buf = NULL;
214 // For CHARSET
215         char *mime_cs = NULL, *from_cs = NULL, *to_cs = NULL;
216         char *v3_cs = new char [64];
217         
218         if (cachedValues != B_TRUE)
219                 parse ();       // read in body part info
220
221         firstPart = bodyParts [0];
222
223         firstPart->getContents(env,
224                 (const void **) &contents, 
225                 &length,
226                 NULL,   //type
227                 NULL,   //name
228                 NULL,   //mode
229                 NULL);  //description
230
231         if (handleError (env, "getContents") == B_TRUE)
232                 exit (1);
233
234 // For CHARSET
235
236    DtMailValueSeq value;
237    boolean_t err = B_FALSE;
238
239 // Get the bodypart's charset - Try MIME first then V3
240    firstPart->getHeader(env, DtMailMessageContentType, DTM_TRUE, value);
241    if (env.isNotSet()) {
242           mime_cs = firstPart->csFromContentType(value);
243    } else {
244           env.clear();
245           value.clear();
246           firstPart->getHeader(env, DtMailMessageV3charset, DTM_TRUE, value);
247           if (env.isNotSet()) {
248                  strcpy(v3_cs, *(value[0]));
249           } else {
250                  err = B_TRUE;
251                  env.clear();
252                  value.clear();
253           }
254    }
255 // If cannot obtain bodypart's charset header, then maybe this message
256 // has only one bodypart, then in this case the charset header maybe
257 // among the message's envelope (main message headers).
258 // Get the envelope of the message (in order to access the headers)
259    DtMail::Envelope *envelope = NULL;
260    if (err == B_TRUE) {
261           envelope = message->getEnvelope(env);
262           err = B_FALSE;
263 #ifdef DEBUG
264       env.logError(DTM_FALSE, "DEBUG dtmailpr: Looking at main message header\n");
265 #endif
266    }
267    if (envelope != NULL) {
268 //   Check for MIME charset header and then for V3 charset header
269      envelope->getHeader(env, DtMailMessageContentType, DTM_TRUE, value);
270      if (env.isNotSet()) {
271         mime_cs = firstPart->csFromContentType(value);
272      } else {
273             err = B_TRUE;
274             env.clear();
275      }
276      if (mime_cs == NULL || err == B_TRUE) {
277         value.clear();
278         envelope->getHeader(env, DtMailMessageV3charset, DTM_TRUE, value);
279         if (env.isNotSet()) {
280            strcpy(v3_cs, *(value[0]));
281         } else {
282                    err = B_TRUE;
283            env.clear();
284         }
285      }
286    } else {
287 #ifdef DEBUG
288           env.logError(DTM_FALSE, "DEBUG dtmailpr: envelope is null\n");
289 #endif
290           env.clear();
291    }
292
293 // Default codeset in case mime_cs and v3_cs are both null.
294    if ((mime_cs == NULL) && (strlen(v3_cs) == 0)) {
295           char *ret = NULL;
296           firstPart->DtXlateOpToStdLocale(DtLCX_OPER_SETLOCALE,
297                  setlocale(LC_CTYPE, NULL),
298                  NULL,
299                  NULL,
300                  &ret);
301           strcpy(v3_cs, "DEFAULT");
302           strcat(v3_cs, ".");
303           strcat(v3_cs, ret);
304           free(ret);
305    }
306
307 // Get iconv from and to codeset and do conversion.
308    int converted = 0;
309    if (mime_cs) {
310       from_cs = firstPart->csToConvName(mime_cs);
311 #ifdef DEBUG
312       env.logError(DTM_FALSE, "DEBUG dtmailpr: mime_cs = %s\n", mime_cs);
313 #endif
314    } else {
315       from_cs = firstPart->csToConvName(v3_cs);
316 #ifdef DEBUG
317       env.logError(DTM_FALSE, "DEBUG dtmailpr: v3_cs = %s\n", v3_cs);
318 #endif
319    }
320    to_cs = firstPart->locToConvName();
321
322 #ifdef DEBUG
323    if ( from_cs == NULL )
324    env.logError(DTM_FALSE, "DEBUG dtmailpr: from_cs is NULL\n");
325    else
326    env.logError(DTM_FALSE, "DEBUG dtmailpr: from_cs = %s\n", from_cs);
327
328    if ( to_cs == NULL )
329    env.logError(DTM_FALSE, "DEBUG dtmailpr: to_cs is NULL\n");
330    else
331    env.logError(DTM_FALSE, "DEBUG dtmailpr: to_cs = %s\n", to_cs);
332 #endif
333
334    if ( from_cs && to_cs ) {
335      if ( strcasecmp(from_cs, to_cs) != 0 ) {
336         converted = firstPart->csConvert((char **)&contents, length, 0, from_cs, to_cs);
337 #ifdef DEBUG
338         env.logError(DTM_FALSE, "DEBUG dtmailpr: converted = %d\n", converted);
339 #endif
340      }
341    }
342    if ( mime_cs )
343       free ( mime_cs );
344    if ( from_cs )
345       free( from_cs );
346    if ( to_cs )
347       free ( to_cs );
348  
349 // End of For CHARSET
350
351
352         buf = new char [length + 1];
353         memset (buf, 0, (size_t) length + 1);
354
355         // have to "seek" length bytes into the
356         // contents buffer
357         memmove (buf, contents, (size_t) length);
358         buf [length] = '\0';    // null-terminate
359                                 // that puppy
360
361 // For CHARSET
362     if (converted && contents)
363            free(contents);
364
365         char    *numbuf = new char [10241];
366         memset (numbuf, 0, 1024);
367
368 #ifdef NEVER
369         // Don't want "Message 1:" appearing in print output
370         sprintf (numbuf, "Messsage %s:\n%s\n",
371                 addlInfo, printHeader (MSGHEADER));
372 #endif
373         puts(printHeader(MSGHEADER));
374         puts(buf);
375
376         fflush(stdout);
377
378         // No attachments?  We're done.
379         if (numBPs < 2)
380                 return;
381
382         int     i = 0;
383
384         char    *attbuf = NULL;
385
386         printf ("\n");
387         for (i = 1; i < numBPs ; i++)
388         {
389                 nextpart = bodyParts [i];
390
391                 if (nextpart == NULL)
392                         fprintf (stderr, "Error getting part!\n");
393
394                 length = 0;
395                 type = "";
396                 sunDataDescription = "";
397                 description = "";
398                 name = "";
399                 mode = -1;
400                 
401                 nextpart->getContents(env, NULL, &length, &type,
402                                 &name, &mode, &sunDataDescription);
403                 if (handleError (env, "getContents") == B_TRUE)
404                         exit (1);
405
406                 if (type == NULL)
407                         type = "(unknown)";
408
409                 if (sunDataDescription == NULL)
410                 {
411                         description = "";
412                 } else {
413                         // should add bracket or something
414                         attbuf = new char [strlen (sunDataDescription) +10];
415                         sprintf (attbuf, " (%s)", sunDataDescription);
416                         description = attbuf;
417                 }
418
419                 if (name == NULL)
420                         name = "(name)";
421
422                 printf ("[%d] \"%s\"%s, ", i, name, description);
423                 printf ("%s, %lu bytes\n", type, length);
424
425                 if (attbuf != NULL)
426                         delete [] attbuf;
427
428         }
429
430         delete [] v3_cs;
431         return;
432 }
433
434 void
435 DmxMsg::parse (void)
436 {
437         // store the body parts for later reference
438
439         DtMailEnv                       env;
440         boolean_t               FirstIsText = B_FALSE;
441         DtMail::BodyPart        *part = NULL, *nextpart = NULL;
442         char                    *type = NULL, *attr = NULL;
443
444         int     bc = message->getBodyCount (env);
445         if (handleError (env, "getBodyCount") == B_TRUE)
446                 exit (1);
447
448         part = message->getFirstBodyPart (env);
449         if (handleError (env, "getFirstBodyPart") == B_TRUE)
450                 exit (1);
451
452         part->getContents (env, NULL, NULL, &type, NULL, NULL, NULL);
453         if (handleError (env, "getContents") == B_TRUE)
454                 exit (1);
455
456         bodyParts = new (DtMail::BodyPart *[bc]);
457         cachedValues = B_TRUE;
458         
459         // cache values
460         bodyParts [0] = part;
461         numBPs++;
462
463
464         if (type != NULL)
465         {
466                 attr = DtDtsDataTypeToAttributeValue (type,
467                                                 DtDTS_DA_IS_TEXT,
468                                                 NULL);
469                 if (attr != NULL)
470                 {
471                         FirstIsText = B_TRUE;
472                 }
473                 //free (type);  // it's allocating some data for us
474         } else {
475                 FirstIsText = B_FALSE;
476         }
477
478         // No attachments?  We're done.
479         if (bc < 2)
480                 return;
481
482         int     i;
483
484         for (i = 1; i < bc; i++)
485         {
486                 nextpart = NULL;
487                 nextpart = message->getNextBodyPart (env,
488                                                 part);
489                 if (handleError (env, "getNextBodyPart") == B_TRUE)
490                         exit (1);
491
492                 if (nextpart == NULL)
493                         fprintf (stderr, "Error getting part!\n");
494
495
496                 bodyParts [i] = nextpart;
497                 numBPs++;
498
499                 part = nextpart;
500         }
501 }
502