dtmail: resolve 'deference before null check' errors related to if(!NULL) checks...
[oweals/cde.git] / cde / programs / dtmail / dtmailpr / utils.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 /* $XConsortium: utils.C /main/4 1996/04/21 19:44:10 drk $ */
24
25 /*
26  *+SNOTICE
27  *
28  *      $:$
29  *
30  *      RESTRICTED CONFIDENTIAL INFORMATION:
31  *      
32  *      The information in this document is subject to special
33  *      restrictions in a confidential disclosure agreement between
34  *      HP, IBM, Sun, USL, SCO and Univel.  Do not distribute this
35  *      document outside HP, IBM, Sun, USL, SCO, or Univel without
36  *      Sun's specific written approval.  This document and all copies
37  *      and derivative works thereof must be returned or destroyed at
38  *      Sun's request.
39  *
40  *      Copyright 1994 Sun Microsystems, Inc.  All rights reserved.
41  *
42  *+ENOTICE
43  */
44
45 #include "dmx.hh"
46
47 // fn proto for mailx fn
48 static char * dispname(const char *hdr);
49
50 // error-handling: should do something with minor codes
51
52 boolean_t
53 handleError (DtMailEnv &dterror, char *msg)
54 {
55         if (dterror.isSet () == DTM_TRUE)
56         {
57                 fprintf (stderr, "dtmailpr: (%s) %s\n", 
58                         msg, (const char *)dterror);
59                 dterror.logError (DTM_FALSE, "dtmailpr: (%s) %s\n",
60                         msg, (const char *)dterror);
61
62                 dterror.clear ();
63                 return B_TRUE;
64         }
65
66         dterror.clear ();
67         return B_FALSE;
68 }
69         
70
71 char *
72 errorString (enum DmxHeaders hdr)
73 {
74         switch (hdr)
75         {
76                 case DMXFROM:
77                         return "(unknown)";
78                 case DMXSUBJ:
79                         return "(no subject)";
80                 case DMXCLENGTH:
81                         return "0";
82                 case DMXSTATUS:
83                         return "  ";
84                 case DMXDATE:
85                         return "(unknown date)";
86                 case DMXTO:
87                         return " ";
88                 case DMXNUMHDRS:
89                 default:
90                         return " ";
91         }
92 }
93
94 char *
95 formatHeader (DtMailHeaderLine &info, enum DmxHeaderType htype)
96 {
97         int     i = 0, length = 0;
98         int     buflength = 0;
99         char    *fbuf;
100
101         const char      *header [DMXNUMHDRS];
102
103         for (i = 0; i < DMXNUMHDRS; i++)
104         {
105                 length = info.header_values[i].length ();
106                 if (length == 0)
107                 {
108                         header [i] = errorString ((enum DmxHeaders)i);
109                 } else {
110                         header [i] = *((info.header_values[i])[0]);
111                 }
112         }
113
114         for (i = 0; i < DMXNUMHDRS; i++)
115         {
116                 buflength += strlen (header [i]);
117         }
118
119         fbuf = new char [buflength + 64];
120
121         switch (htype)
122         {
123                 case MSGLIST:
124                         sprintf (fbuf,
125                         "%-18.18s %-16.16s %4d/%-5s %-.25s",
126                                 dispname (header [DMXFROM]),
127                                 header [DMXDATE],
128                                 atoi (header [DMXCLENGTH]) / 40,
129                                 header [DMXCLENGTH],
130                                 header [DMXSUBJ]
131                                 );
132                         break;
133                 case MSGHEADER:
134                         sprintf (fbuf,
135                         "From: %s\nDate: %s\nTo: %s\nSubject: %s\n",
136                                 dispname (header [DMXFROM]),
137                                 header [DMXDATE],
138                                 header [DMXTO],
139                                 header [DMXSUBJ]);
140                         break;
141                 case NUMHDRTYPES:
142                 default:
143                         return "";
144         }
145         return (fbuf); //need to free this after using it
146 }
147
148 // stuff grabbed from mailx...it's ugly, but it looks pretty
149
150 #define NOSTR ((char *) 0)    /* Nill string pointer */
151 #define LINESIZE 5120            /* max readable line width */
152 static char *phrase(char *, int , int );
153
154 /*
155  * Return a pointer to a dynamic copy of the argument.
156  */
157 // changed salloc to malloc
158 char *
159 savestr(char *str)
160 {
161         register char *cp, *cp2, *top;
162
163         for (cp = str; *cp; cp++)
164                 ;
165         top = (char *)malloc((unsigned)(cp-str + 1));
166         if (top == NOSTR)
167                 return(NOSTR);
168         for (cp = str, cp2 = top; *cp; cp++)
169                 *cp2++ = *cp;
170         *cp2 = 0;
171         return(top);
172 }
173
174
175 char *
176 skin(char *name)
177 {
178         return phrase(name, 0, 0);
179 }
180 /*
181  * Return the full name from an RFC-822 header line
182  * or the last two (or one) component of the address.
183  */
184
185 static char *
186 dispname(const char *hdr)
187 // made it a const char * instead of a char *
188 {
189         char *cp, *cp2;
190
191         if (hdr == 0)
192                 return 0;
193         if (((cp = const_cast <char *> (strchr(hdr, '<'))) != 0) && (cp > hdr)) {
194                 *cp = 0;
195                 if ((*hdr == '"') && ((cp = const_cast <char *> (strrchr(++hdr, '"'))) != 0))
196                         *cp = 0;
197                 return (char *)hdr;
198         } else if ((cp = const_cast <char *> (strchr(hdr, '('))) != 0) {
199                 hdr = ++cp;
200                 if ((cp = const_cast <char *> (strchr(hdr, '+'))) != 0)
201                         *cp = 0;
202                 if ((cp = const_cast <char *> (strrchr(hdr, ')'))) != 0)
203                         *cp = 0;
204                 return (char *)hdr;
205         }
206         cp = skin((char *)hdr);
207         if ((cp2 = strrchr(cp, '!')) != 0) {
208                 while (cp2 >= cp && *--cp2 != '!');
209                 cp = ++cp2;
210         }
211         return cp;
212 }
213
214
215 #define equal(a, b)     (strcmp(a,b)==0)/* A nice function to string compare */
216
217 /*
218  * Skin an arpa net address according to the RFC 822 interpretation
219  * of "host-phrase."
220  */
221 // changed salloc to malloc
222 static char *
223 phrase(char *name, int token, int comma)
224 {
225         register char c;
226         register char *cp, *cp2;
227         char *bufend, *nbufp;
228         int gotlt, lastsp, didq;
229         char nbuf[LINESIZE];
230         int nesting;
231
232         if (name == NOSTR)
233                 return(NOSTR);
234         if (strlen(name) >= (unsigned)LINESIZE)
235                 nbufp = (char *)malloc(strlen(name));
236         else
237                 nbufp = nbuf;
238         gotlt = 0;
239         lastsp = 0;
240         bufend = nbufp;
241         for (cp = name, cp2 = bufend; (c = *cp++) != 0;) {
242                 switch (c) {
243                 case '(':
244                         /*
245                                 Start of a comment, ignore it.
246                         */
247                         nesting = 1;
248                         while ((c = *cp) != 0) {
249                                 cp++;
250                                 switch(c) {
251                                 case '\\':
252                                         if (*cp == 0) goto outcm;
253                                         cp++;
254                                         break;
255                                 case '(':
256                                         nesting++;
257                                         break;
258                                 case ')':
259                                         --nesting;
260                                         break;
261                                 }
262                                 if (nesting <= 0) break;
263                         }
264                 outcm:
265                         lastsp = 0;
266                         break;
267                 case '"':
268                         /*
269                                 Start a quoted string.
270                                 Copy it in its entirety.
271                         */
272                         didq = 0;
273                         while ((c = *cp) != 0) {
274                                 cp++;
275                                 switch (c) {
276                                 case '\\':
277                                         if ((c = *cp) == 0) goto outqs;
278                                         cp++;
279                                         break;
280                                 case '"':
281                                         goto outqs;
282                                 }
283                                 if (gotlt == 0 || gotlt == '<') {
284                                         if (lastsp) {
285                                                 lastsp = 0;
286                                                 *cp2++ = ' ';
287                                         }
288                                         if (!didq) {
289                                                 *cp2++ = '"';
290                                                 didq++;
291                                         }
292                                         *cp2++ = c;
293                                 }
294                         }
295                 outqs:
296                         if (didq)
297                                 *cp2++ = '"';
298                         lastsp = 0;
299                         break;
300
301                 case ' ':
302                 case '\t':
303                 case '\n':
304                         if (token && (!comma || c == '\n')) {
305                         done:
306                                 cp[-1] = 0;
307                                 return cp;
308                         }
309                         lastsp = 1;
310                         break;
311
312                 case ',':
313                         *cp2++ = c;
314                         if (gotlt != '<') {
315                                 if (token)
316                                         goto done;
317                                 bufend = cp2 + 1;
318                                 gotlt = 0;
319                         }
320                         break;
321
322                 case '<':
323                         cp2 = bufend;
324                         gotlt = c;
325                         lastsp = 0;
326                         break;
327
328                 case '>':
329                         if (gotlt == '<') {
330                                 gotlt = c;
331                                 break;
332                         }
333
334                         /* FALLTHROUGH . . . */
335
336                 default:
337                         if (gotlt == 0 || gotlt == '<') {
338                                 if (lastsp) {
339                                         lastsp = 0;
340                                         *cp2++ = ' ';
341                                 }
342                                 *cp2++ = c;
343                         }
344                         break;
345                 }
346         }
347         *cp2 = 0;
348         return (token ? --cp : equal(name, nbufp) ? name :
349             nbufp == nbuf ? savestr(nbuf) : nbufp);
350 }
351
352
353