dd1277c8f15d244dddc08c4dacfcd81bf9401cfc
[mmh] / uip / mhfree.c
1 /*
2 ** mhfree.c -- routines to free the data structures used to
3 **          -- represent MIME messages
4 **
5 ** This code is Copyright (c) 2002, by the authors of nmh.  See the
6 ** COPYRIGHT file in the root directory of the nmh distribution for
7 ** complete copyright information.
8 */
9
10 #include <h/mh.h>
11 #include <errno.h>
12 #include <h/mime.h>
13 #include <h/mhparse.h>
14
15 /* The list of top-level contents to display */
16 CT *cts = NULL;
17
18 /*
19 ** prototypes
20 */
21 void free_content(CT);
22 void free_header(CT);
23 void free_ctinfo(CT);
24 void free_encoding(CT, int);
25 void freects_done(int);
26
27 /*
28 ** static prototypes
29 */
30 static void free_text(CT);
31 static void free_multi(CT);
32 static void free_partial(CT);
33 static void free_external(CT);
34
35
36 /*
37 ** Primary routine to free a MIME content structure
38 */
39
40 void
41 free_content(CT ct)
42 {
43         if (!ct)
44                 return;
45
46         /*
47         ** free all the header fields
48         */
49         free_header(ct);
50
51         if (ct->c_partno)
52                 free(ct->c_partno);
53
54         if (ct->c_vrsn)
55                 free(ct->c_vrsn);
56
57         if (ct->c_ctline)
58                 free(ct->c_ctline);
59
60         free_ctinfo(ct);
61
62         /*
63         ** some of the content types have extra
64         ** parts which need to be freed.
65         */
66         switch (ct->c_type) {
67         case CT_MULTIPART:
68                 free_multi(ct);
69                 break;
70
71         case CT_MESSAGE:
72                 switch (ct->c_subtype) {
73                 case MESSAGE_PARTIAL:
74                         free_partial(ct);
75                         break;
76
77                 case MESSAGE_EXTERNAL:
78                         free_external(ct);
79                         break;
80                 }
81                 break;
82
83         case CT_TEXT:
84                 free_text(ct);
85                 break;
86         }
87
88         if (ct->c_showproc)
89                 free(ct->c_showproc);
90         if (ct->c_termproc)
91                 free(ct->c_termproc);
92         if (ct->c_storeproc)
93                 free(ct->c_storeproc);
94
95         if (ct->c_celine)
96                 free(ct->c_celine);
97
98         /* free structures for content encodings */
99         free_encoding(ct, 1);
100
101         if (ct->c_id)
102                 free(ct->c_id);
103         if (ct->c_descr)
104                 free(ct->c_descr);
105         if (ct->c_dispo)
106                 free(ct->c_dispo);
107
108         if (ct->c_file) {
109                 if (ct->c_unlink)
110                         unlink(ct->c_file);
111                 free(ct->c_file);
112         }
113         if (ct->c_fp)
114                 fclose(ct->c_fp);
115
116         if (ct->c_storage)
117                 free(ct->c_storage);
118         if (ct->c_folder)
119                 free(ct->c_folder);
120
121         free(ct);
122 }
123
124
125 /*
126 ** Free the linked list of header fields
127 ** for this content.
128 */
129
130 void
131 free_header(CT ct)
132 {
133         HF hp1, hp2;
134
135         hp1 = ct->c_first_hf;
136         while (hp1) {
137                 hp2 = hp1->next;
138
139                 free(hp1->name);
140                 free(hp1->value);
141                 free(hp1);
142
143                 hp1 = hp2;
144         }
145
146         ct->c_first_hf = NULL;
147         ct->c_last_hf  = NULL;
148 }
149
150
151 void
152 free_ctinfo(CT ct)
153 {
154         char **ap;
155         CI ci;
156
157         ci = &ct->c_ctinfo;
158         if (ci->ci_type) {
159                 free(ci->ci_type);
160                 ci->ci_type = NULL;
161         }
162         if (ci->ci_subtype) {
163                 free(ci->ci_subtype);
164                 ci->ci_subtype = NULL;
165         }
166         for (ap = ci->ci_attrs; *ap; ap++) {
167                 free(*ap);
168                 *ap = NULL;
169         }
170         if (ci->ci_comment) {
171                 free(ci->ci_comment);
172                 ci->ci_comment = NULL;
173         }
174         if (ci->ci_magic) {
175                 free(ci->ci_magic);
176                 ci->ci_magic = NULL;
177         }
178 }
179
180
181 static void
182 free_text(CT ct)
183 {
184         struct text *t;
185
186         if (!(t = (struct text *) ct->c_ctparams))
187                 return;
188
189         free((char *) t);
190         ct->c_ctparams = NULL;
191 }
192
193
194 static void
195 free_multi(CT ct)
196 {
197         struct multipart *m;
198         struct part *part, *next;
199
200         if (!(m = (struct multipart *) ct->c_ctparams))
201                 return;
202
203         if (m->mp_start)
204                 free(m->mp_start);
205         if (m->mp_stop)
206                 free(m->mp_stop);
207
208         for (part = m->mp_parts; part; part = next) {
209                 next = part->mp_next;
210                 free_content(part->mp_part);
211                 free((char *) part);
212         }
213         m->mp_parts = NULL;
214
215         free((char *) m);
216         ct->c_ctparams = NULL;
217 }
218
219
220 static void
221 free_partial(CT ct)
222 {
223         struct partial *p;
224
225         if (!(p = (struct partial *) ct->c_ctparams))
226                 return;
227
228         if (p->pm_partid)
229                 free(p->pm_partid);
230
231         free((char *) p);
232         ct->c_ctparams = NULL;
233 }
234
235
236 static void
237 free_external(CT ct)
238 {
239         struct exbody *e;
240
241         if (!(e = (struct exbody *) ct->c_ctparams))
242                 return;
243
244         free_content(e->eb_content);
245         if (e->eb_body)
246                 free(e->eb_body);
247
248         free((char *) e);
249         ct->c_ctparams = NULL;
250 }
251
252
253 /*
254 ** Free data structures related to encoding/decoding
255 ** Content-Transfer-Encodings.
256 */
257
258 void
259 free_encoding(CT ct, int toplevel)
260 {
261         CE ce;
262
263         if (!(ce = ct->c_cefile))
264                 return;
265
266         if (ce->ce_fp) {
267                 fclose(ce->ce_fp);
268                 ce->ce_fp = NULL;
269         }
270
271         if (ce->ce_file) {
272                 if (ce->ce_unlink)
273                         unlink(ce->ce_file);
274                 free(ce->ce_file);
275                 ce->ce_file = NULL;
276         }
277
278         if (toplevel) {
279                 free((char *) ce);
280                 ct->c_cefile = NULL;
281         } else {
282                 ct->c_ceopenfnx = NULL;
283         }
284 }
285
286
287 void
288 freects_done(int status)
289 {
290         CT *ctp;
291
292         if ((ctp = cts))
293                 for (; *ctp; ctp++)
294                         free_content(*ctp);
295
296         exit(status);
297 }