dthelp: Change to ANSI function definitions
[oweals/cde.git] / cde / programs / dtmail / libDtMail / RFC / RFCFormat.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 /*
24  *+SNOTICE
25  *
26  *
27  *      $TOG: RFCFormat.C /main/11 1998/07/23 18:03:02 mgreess $
28  *
29  *      RESTRICTED CONFIDENTIAL INFORMATION:
30  *      
31  *      The information in this document is subject to special
32  *      restrictions in a confidential disclosure agreement bertween
33  *      HP, IBM, Sun, USL, SCO and Univel.  Do not distribute this
34  *      document outside HP, IBM, Sun, USL, SCO, or Univel wihtout
35  *      Sun's specific written approval.  This documment and all copies
36  *      and derivative works thereof must be returned or destroyed at
37  *      Sun's request.
38  *
39  *      Copyright 1993 Sun Microsystems, Inc.  All rights reserved.
40  *
41  *+ENOTICE
42  */
43
44 #include <ctype.h>
45 #include <EUSCompat.h>
46 #include <DtMail/IO.hh>
47 #include "RFCFormat.hh"
48 #include "str_utils.h"
49
50 #include <time.h>
51
52 RFCFormat::RFCFormat(DtMail::Session * session)
53 {
54     _session = session;
55     _is_write_bcc = DTM_FALSE;
56     _use_cr = DTM_FALSE;
57 }
58
59 RFCFormat::~RFCFormat(void)
60 {
61 }
62
63 void
64 RFCFormat::msgToBuffer(DtMailEnv & error,
65                        DtMail::Message & msg,
66                        DtMailBoolean include_content_length,
67                        DtMailBoolean include_unix_from,
68                        DtMailBoolean,
69                        Buffer & headers,
70                        Buffer & body)
71 {
72     error.clear();
73
74     _use_cr = DTM_TRUE;
75
76     if (include_content_length || include_unix_from) {
77         _use_cr = DTM_FALSE;
78     }
79
80     // We will format the bodies first, then the headers. The
81     // reason we do this is that the result of formatting the body
82     // is required for the headers. The content-type, content-length,
83     // and other content based headers need to be computed before
84     // being written.
85     //
86     char * extra_headers = NULL;
87     formatBodies(error, msg, include_content_length, &extra_headers, body);
88     if (error.isSet()) {
89         return;
90     }
91
92     formatHeaders(error, msg, include_unix_from, extra_headers, headers);
93     free(extra_headers);
94     return;
95 }
96
97 void
98 RFCFormat::writeHeaders(DtMailEnv & error,
99                         DtMail::Message & msg,
100                         DtMailBoolean include_unix_from,
101                         const char * extra_headers,
102                         const char ** suppress_headers,
103                         Buffer & buf)
104 {
105     error.clear();
106
107     // First we copy each header from the message to the
108     // buffer. The headers may need encoding to put them away, so
109     // we will apply RFC1522 if necessary.
110     //
111     DtMailHeaderHandle hnd;
112     DtMail::Envelope * env = msg.getEnvelope(error);
113     if (error.isSet()) {
114         return;
115     }
116
117     char * name = NULL;
118     DtMailValueSeq value;
119
120     hnd = env->getFirstHeader(error, &name, value);
121     if (!hnd || error.isSet()) {
122         return;
123     }
124
125     if (include_unix_from &&
126         (error.isSet() || strcmp(name, "From") != 0)) {
127         // We require a Unix from line, and we don't have one.
128         // we will make one up using the sender, and the current
129         // date.
130         //
131         char *unix_from = new char[100];
132         strcpy(unix_from, "From ");
133         
134         DtMailValueSeq sender;
135         env->getHeader(error, DtMailMessageSender, DTM_TRUE, sender);
136         if (error.isSet()) {
137             // We no longer know who this is really from.
138             //
139             strcat(unix_from, "nobody@nowhere");
140         }
141         else {
142             DtMailAddressSeq * addrSeq = sender[0]->toAddress();
143             
144             strcat(unix_from, (*addrSeq)[0]->dtm_address);
145             delete addrSeq;
146         }
147         error.clear();
148
149         time_t now = time(NULL);
150         char time_format[30];
151         
152         SafeCtime(&now, time_format, sizeof(time_format));
153         
154         strcat(unix_from, " ");
155         strcat(unix_from, time_format);
156         buf.appendData(unix_from, strlen(unix_from));
157         delete [] unix_from;
158     }
159     else {
160         // Put out any header, except Unix From line
161         //
162         if (strcmp(name, "From") == 0) {
163             value.clear();
164             free(name);
165             hnd = env->getNextHeader(error, hnd, &name, value);
166         }
167     }
168
169     for (; // First time is determined above.
170          hnd && !error.isSet();
171          value.clear(), hnd = env->getNextHeader(error, hnd, &name, value)) {
172
173         const char **hdr;
174         for (hdr = suppress_headers; *hdr; hdr++) {
175             if (strcasecmp(name, *hdr) == 0)
176               break;
177         }
178
179         //add _is_write_bcc for fixing aix defect 177096
180         if (*hdr || strcasecmp(name, "bcc") == 0 && !_is_write_bcc ) {
181             free(name);
182             continue; // We will generate these headers.
183         }
184
185         int name_len = strlen(name);
186
187         for (int val = 0; val < value.length(); val++) {
188             //
189             // If the value is null or empty do not emit this field
190             const char *valPtr;
191             for (valPtr = *(value[val]);
192                  *valPtr && (isspace((unsigned char)*valPtr));
193                  valPtr++)
194             {}
195             if (!*valPtr)
196               continue;
197             
198             buf.appendData(name, name_len);
199             buf.appendData(": ", 2);
200             rfc1522cpy(buf, *(value[val]));
201         }
202
203         free(name);
204     }
205     error.clear();
206
207     buf.appendData(extra_headers, strlen(extra_headers));
208
209     // Add new line that terminates the headers.
210     //
211     crlf(buf);
212 }
213
214 void
215 RFCFormat::rfc1522cpy(Buffer & buf, const char * value)
216 {
217     buf.appendData(value, strlen(value));
218     crlf(buf);
219 }
220
221 void
222 RFCFormat::getCharSet(char * charset)
223 {
224         char *mimeCS = NULL;
225
226         mimeCS = _session->targetTagName();
227
228     if (mimeCS) {
229         strcpy(charset, mimeCS);
230         free(mimeCS);
231     } else {
232         strcpy(charset, "us-ascii");   /* default MIME codeset */
233     }
234 }
235
236 void
237 RFCFormat::getCharSet(char * charset, char *special)
238 {
239         char *mimeCS = NULL;
240
241         mimeCS = _session->targetTagName(special);
242
243     if (mimeCS) {
244        strcpy(charset, mimeCS);
245        free(mimeCS);
246     } else {
247         strcpy(charset, "us-ascii");   /* default MIME codeset */
248     }
249 }