masqmail

view src/header.c @ 75:257a9e6d1a8e

fixed correct processing of mails with data lines longer 4096 chars Mail messages with lines longer than 4096 chars were already read correctly, i.e. the spool files were correct. This commit fixes the reading of spool files with long lines. The old behavior was that the message body was truncated right before the first line longer 4096 chars. The number comes from MAX_DATALINE.
author meillo@marmaro.de
date Wed, 16 Jun 2010 19:06:34 +0200
parents 26e34ae9a3e3
children 3708b655a371
line source
1 /* MasqMail
2 Copyright (C) 2000 Oliver Kurth
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18 #include "masqmail.h"
20 header_name header_names[] = {
21 {"From", HEAD_FROM,},
22 {"Sender", HEAD_SENDER,},
23 {"To", HEAD_TO,},
24 {"Cc", HEAD_CC,},
25 {"Bcc", HEAD_BCC,},
26 {"Date", HEAD_DATE,},
27 {"Message-Id", HEAD_MESSAGE_ID,},
28 {"Reply-To", HEAD_REPLY_TO,},
29 {"Subject", HEAD_SUBJECT,},
30 {"Return-Path", HEAD_RETURN_PATH,},
31 {"Envelope-To", HEAD_ENVELOPE_TO,},
32 {"Received", HEAD_RECEIVED},
33 };
35 /* this was borrowed from exim and slightly changed */
36 gchar*
37 rec_timestamp()
38 {
39 static gchar buf[64];
40 int len;
42 time_t now = time(NULL);
43 struct tm *t = localtime(&now);
45 int diff_hour, diff_min;
46 struct tm local;
47 struct tm *gmt;
49 memcpy(&local, t, sizeof(struct tm));
50 gmt = gmtime(&now);
51 diff_min = 60 * (local.tm_hour - gmt->tm_hour) + local.tm_min - gmt->tm_min;
52 if (local.tm_year != gmt->tm_year)
53 diff_min += (local.tm_year > gmt->tm_year) ? 1440 : -1440;
54 else if (local.tm_yday != gmt->tm_yday)
55 diff_min += (local.tm_yday > gmt->tm_yday) ? 1440 : -1440;
56 diff_hour = diff_min / 60;
57 diff_min = abs(diff_min - diff_hour * 60);
59 len = strftime(buf, sizeof(buf), "%a, ", &local);
60 g_snprintf(buf + len, sizeof(buf) - len, "%02d ", local.tm_mday);
61 len += strlen(buf + len);
62 len += strftime(buf + len, sizeof(buf) - len, "%b %Y %H:%M:%S", &local);
63 g_snprintf(buf + len, sizeof(buf) - len, " %+03d%02d", diff_hour, diff_min);
65 return buf;
66 }
68 /* finds list of headers matching id
69 if id == HEAD_UNKNOWN and header == NULL finds all unknown headers
70 else finds all headers matching header
71 */
72 GList*
73 find_header(GList * hdr_list, header_id id, gchar * hdr_str)
74 {
75 GList *found_list = NULL;
76 GList *node;
78 if ((id != HEAD_UNKNOWN) || (hdr_str == NULL)) {
79 foreach(hdr_list, node) {
80 header *hdr = (header *) (node->data);
81 if (hdr->id == id)
82 found_list = g_list_append(found_list, hdr);
83 }
84 } else {
85 foreach(hdr_list, node) {
86 header *hdr = (header *) (node->data);
87 gchar buf[64], *q = buf, *p = hdr->header;
89 while (*p != ':' && q < buf + 63 && *p)
90 *(q++) = *(p++);
91 *q = '\0';
93 if (strcasecmp(buf, hdr_str) == 0)
94 found_list = g_list_append(found_list, hdr);
95 }
96 }
97 return found_list;
98 }
100 void
101 header_unfold(header * hdr)
102 {
103 gchar *tmp_hdr = g_malloc(strlen(hdr->header));
104 gchar *p = hdr->header, *q = tmp_hdr;
105 gboolean flag = FALSE;
107 while (*p) {
108 if (*p != '\n')
109 *(q++) = *p;
110 else
111 flag = TRUE;
112 p++;
113 }
114 *(q++) = '\n';
116 if (flag) {
117 gchar *new_hdr;
119 g_free(hdr->header);
120 new_hdr = g_strdup(tmp_hdr);
121 g_free(tmp_hdr);
122 hdr->value = new_hdr + (hdr->value - hdr->header);
123 hdr->header = new_hdr;
124 }
125 }
127 #define MAX_HDR_LEN 72
128 void
129 header_fold(header * hdr)
130 {
131 gint len = strlen(hdr->header);
132 gchar *p, *q;
133 /* size is probably overestimated, but so we are on the safe side */
134 gchar *tmp_hdr = g_malloc(len + 2 * len / MAX_HDR_LEN);
136 p = hdr->header;
137 q = tmp_hdr;
139 if (p[len - 1] == '\n')
140 p[len - 1] = '\0';
142 while (*p) {
143 gint i, l;
144 gchar *pp;
146 /* look forward and find potential break points */
147 i = 0;
148 l = -1;
149 pp = p;
150 while (*pp && (i < MAX_HDR_LEN)) {
151 if ((*pp == ' ') || (*pp == '\t'))
152 l = i;
153 pp++;
154 i++;
155 }
156 if (!*pp)
157 l = pp - p; /* take rest, if EOS found */
159 if (l == -1) {
160 /* no potential break point was found within MAX_HDR_LEN so advance further until the next */
161 while (*pp && *pp != ' ' && *pp != '\t') {
162 pp++;
163 i++;
164 }
165 l = i;
166 }
168 /* copy */
169 i = 0;
170 while (i < l) {
171 *(q++) = *(p++);
172 i++;
173 }
174 *(q++) = '\n';
175 *(q++) = *(p++); /* this is either space, tab or 0 */
176 }
177 {
178 gchar *new_hdr;
180 g_free(hdr->header);
181 new_hdr = g_strdup(tmp_hdr);
182 g_free(tmp_hdr);
183 hdr->value = new_hdr + (hdr->value - hdr->header);
184 hdr->header = new_hdr;
185 }
186 }
188 header*
189 create_header(header_id id, gchar * fmt, ...)
190 {
191 gchar *p;
192 header *hdr;
193 va_list args;
194 va_start(args, fmt);
196 if ((hdr = g_malloc(sizeof(header)))) {
198 hdr->id = id;
199 hdr->header = g_strdup_vprintf(fmt, args);
200 hdr->value = NULL;
202 p = hdr->header;
203 while (*p && *p != ':')
204 p++;
205 if (*p)
206 hdr->value = p + 1;
207 }
209 va_end(args);
210 return hdr;
211 }
213 void
214 destroy_header(header * hdr)
215 {
216 if (hdr) {
217 if (hdr->header)
218 g_free(hdr->header);
219 g_free(hdr);
220 }
221 }
223 header*
224 copy_header(header * hdr)
225 {
226 header *new_hdr = NULL;
228 if (hdr) {
229 if ((new_hdr = g_malloc(sizeof(header)))) {
230 new_hdr->id = hdr->id;
231 new_hdr->header = g_strdup(hdr->header);
232 new_hdr->value = new_hdr->header + (hdr->value - hdr->header);
233 }
234 }
235 return new_hdr;
236 }
238 header*
239 get_header(gchar * line)
240 {
241 gchar *p = line;
242 gchar buf[64], *q = buf;
243 gint i;
244 header *hdr;
246 while (*p && (*p != ':') && (q < buf + 63))
247 *(q++) = *(p++);
248 *q = '\0';
250 if (*p != ':')
251 return NULL;
253 hdr = g_malloc(sizeof(header));
255 hdr->value = NULL;
256 p++;
258 while (*p && (*p == ' ' || *p == '\t'))
259 p++;
260 hdr->value = p;
262 for (i = 0; i < HEAD_NUM_IDS; i++) {
263 if (strcasecmp(header_names[i].header, buf) == 0)
264 break;
265 }
266 hdr->id = (header_id) i;
267 hdr->header = g_strdup(line);
268 hdr->value = hdr->header + (hdr->value - line);
270 DEBUG(4) debugf("header: %d = %s", hdr->id, hdr->header);
272 return hdr;
273 }