1 /* Copyright (C) 2004 Mads Martin Joergensen <mmj at mmj.dk>
2 *
3 * $Id$
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to
7 * deal in the Software without restriction, including without limitation the
8 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9 * sell copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27
28 #include "mlmmj.h"
29 #include "mygetline.h"
30 #include "gethdrline.h"
31 #include "strgen.h"
32 #include "ctrlvalue.h"
33 #include "do_all_the_voodoo_here.h"
34 #include "log_error.h"
35 #include "wrappers.h"
36 #include "memory.h"
37
findit(const char * line,const struct strlist * headers)38 int findit(const char *line, const struct strlist *headers)
39 {
40 int i;
41 size_t len;
42
43 for (i=0;i<headers->count;i++) {
44 len = strlen(headers->strs[i]);
45 if(strncasecmp(line, headers->strs[i], len) == 0)
46 return 1;
47 }
48
49 return 0;
50 }
51
getinfo(const char * line,struct mailhdr * readhdrs)52 void getinfo(const char *line, struct mailhdr *readhdrs)
53 {
54 int i = 0;
55 size_t tokenlen, valuelen;
56
57 while(readhdrs[i].token) {
58 tokenlen = strlen(readhdrs[i].token);
59 if(strncasecmp(line, readhdrs[i].token, tokenlen) == 0) {
60 readhdrs[i].valuecount++;
61 valuelen = strlen(line) - tokenlen;
62 readhdrs[i].values =
63 (char **)myrealloc(readhdrs[i].values,
64 readhdrs[i].valuecount * sizeof(char *));
65 readhdrs[i].values[readhdrs[i].valuecount - 1] =
66 (char *)mymalloc(valuelen + 1);
67 strcpy(readhdrs[i].values[readhdrs[i].valuecount - 1],
68 line+tokenlen);
69 }
70 i++;
71 }
72 }
73
do_all_the_voodoo_here(int infd,int outfd,int hdrfd,int footfd,const struct strlist * delhdrs,struct mailhdr * readhdrs,struct strlist * allhdrs,const char * prefix)74 int do_all_the_voodoo_here(int infd, int outfd, int hdrfd, int footfd,
75 const struct strlist *delhdrs, struct mailhdr *readhdrs,
76 struct strlist *allhdrs, const char *prefix)
77 {
78 char *hdrline, *unfolded, *subject, *unqp;
79 int hdrsadded = 0;
80 int subject_present = 0;
81
82 allhdrs->count = 0;
83 allhdrs->strs = NULL;
84
85 for(;;) {
86 hdrline = gethdrline(infd, &unfolded);
87
88 /* add extra headers before MIME* headers,
89 or after all headers */
90 if(!hdrsadded &&
91 (hdrline == NULL ||
92 strncasecmp(hdrline, "mime", 4) == 0)) {
93 if(hdrfd >= 0) {
94 if(dumpfd2fd(hdrfd, outfd) < 0) {
95 log_error(LOG_ARGS, "Could not "
96 "add extra headers");
97 myfree(hdrline);
98 myfree(unfolded);
99 return -1;
100 }
101 fsync(outfd);
102 }
103 hdrsadded = 1;
104 }
105
106 /* end of headers */
107 if(hdrline == NULL) {
108 /* add Subject if none is present
109 and a prefix is defined */
110 if (prefix && !subject_present) {
111 subject = concatstr(3,"Subject: ",prefix,"\n");
112 writen(outfd, subject, strlen(subject));
113 myfree(subject);
114 subject_present = 1;
115 }
116 /* write LF */
117 if(writen(outfd, "\n", 1) < 0) {
118 myfree(hdrline);
119 myfree(unfolded);
120 log_error(LOG_ARGS, "Error writing hdrs.");
121 return -1;
122 }
123 myfree(hdrline);
124 myfree(unfolded);
125 break;
126 }
127
128 /* Do we want info from hdrs? Get it before it's gone */
129 if(readhdrs)
130 getinfo(hdrline, readhdrs);
131
132 /* Snatch a copy of the header */
133 allhdrs->count++;
134 allhdrs->strs = myrealloc(allhdrs->strs,
135 sizeof(char *) * (allhdrs->count));
136 allhdrs->strs[allhdrs->count-1] = mystrdup(hdrline);
137
138 /* Add Subject: prefix if wanted */
139 if(prefix) {
140 if(strncasecmp(hdrline, "Subject:", 8) == 0) {
141 subject_present = 1;
142 unqp = cleanquotedp(hdrline + 8);
143 if(strstr(hdrline + 8, prefix) == NULL &&
144 strstr(unqp, prefix) == NULL) {
145 subject = concatstr(4,
146 "Subject: ", prefix,
147 hdrline + 8, "\n");
148 writen(outfd, subject,
149 strlen(subject));
150 myfree(subject);
151 myfree(hdrline);
152 myfree(unqp);
153 continue;
154 }
155 myfree(unqp);
156 }
157 }
158
159 /* Should it be stripped? */
160 if(!delhdrs || !findit(hdrline, delhdrs))
161 writen(outfd, unfolded, strlen(unfolded));
162
163 myfree(hdrline);
164 myfree(unfolded);
165 }
166
167 /* Just print the rest of the mail */
168 if(dumpfd2fd(infd, outfd) < 0) {
169 log_error(LOG_ARGS, "Error when dumping rest of mail");
170 return -1;
171 }
172
173 /* No more, let's add the footer if one */
174 if(footfd >= 0)
175 if(dumpfd2fd(footfd, outfd) < 0) {
176 log_error(LOG_ARGS, "Error when adding footer");
177 return -1;
178 }
179
180 fsync(outfd);
181
182 return 0;
183 }
184