masqmail

view src/header.c @ 375:3f923f97563b

local_hosts now understands glob patterns like `*example.org'.
author markus schnalke <meillo@marmaro.de>
date Sat, 14 Jan 2012 18:14:07 +0100
parents 41958685480d
children 028bc124d744
line source
1 /*
2 ** MasqMail
3 ** Copyright (C) 2000 Oliver Kurth
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19 #include "masqmail.h"
21 header_name header_names[] = {
22 {"From", HEAD_FROM,},
23 {"Sender", HEAD_SENDER,},
24 {"To", HEAD_TO,},
25 {"Cc", HEAD_CC,},
26 {"Bcc", HEAD_BCC,},
27 {"Date", HEAD_DATE,},
28 {"Message-Id", HEAD_MESSAGE_ID,},
29 {"Reply-To", HEAD_REPLY_TO,},
30 {"Subject", HEAD_SUBJECT,},
31 {"Return-Path", HEAD_RETURN_PATH,},
32 {"Envelope-To", HEAD_ENVELOPE_TO,},
33 {"Received", HEAD_RECEIVED},
34 };
36 /* this was borrowed from exim and slightly changed */
37 gchar*
38 rec_timestamp()
39 {
40 static gchar buf[64];
41 int len;
43 time_t now = time(NULL);
44 struct tm *t = localtime(&now);
46 int diff_hour, diff_min;
47 struct tm local;
48 struct tm *gmt;
50 memcpy(&local, t, sizeof(struct tm));
51 gmt = gmtime(&now);
52 diff_min = 60 * (local.tm_hour - gmt->tm_hour) + local.tm_min - gmt->tm_min;
53 if (local.tm_year != gmt->tm_year) {
54 diff_min += (local.tm_year > gmt->tm_year) ? 1440 : -1440;
55 } else if (local.tm_yday != gmt->tm_yday) {
56 diff_min += (local.tm_yday > gmt->tm_yday) ? 1440 : -1440;
57 }
58 diff_hour = diff_min / 60;
59 diff_min = abs(diff_min - diff_hour * 60);
61 len = strftime(buf, sizeof(buf), "%a, ", &local);
62 g_snprintf(buf + len, sizeof(buf) - len, "%02d ", local.tm_mday);
63 len += strlen(buf + len);
64 len += strftime(buf + len, sizeof(buf) - len, "%b %Y %H:%M:%S", &local);
65 g_snprintf(buf + len, sizeof(buf) - len, " %+03d%02d", diff_hour, diff_min);
67 return buf;
68 }
70 /*
71 ** finds list of headers matching id
72 ** if id == HEAD_UNKNOWN and header == NULL finds all unknown headers
73 ** else finds all headers matching header
74 */
75 GList*
76 find_header(GList *hdr_list, header_id id, gchar *hdr_str)
77 {
78 GList *found_list = NULL;
79 GList *node;
81 if ((id != HEAD_UNKNOWN) || !hdr_str) {
82 foreach(hdr_list, node) {
83 header *hdr = (header *) (node->data);
84 if (hdr->id == id) {
85 found_list = g_list_append(found_list, hdr);
86 }
87 }
88 return found_list;
89 }
91 foreach(hdr_list, node) {
92 header *hdr = (header *) (node->data);
93 gchar buf[64], *q = buf, *p = hdr->header;
95 while (*p != ':' && q < buf+sizeof(buf)-1 && *p) {
96 *(q++) = *(p++);
97 }
98 *q = '\0';
100 if (strcasecmp(buf, hdr_str) == 0) {
101 found_list = g_list_append(found_list, hdr);
102 }
103 }
104 return found_list;
105 }
107 void
108 header_unfold(header *hdr)
109 {
110 char *src = hdr->header;
111 char *dest = src;
112 char *p;
114 p = strchr(src, '\n');
115 if (!p || !p[1]) {
116 /* no folded header */
117 return;
118 }
120 while (*src) {
121 if (*src == '\n') {
122 /* ignore */
123 src++;
124 } else {
125 /* copy */
126 *(dest++) = *(src++);
127 }
128 }
129 *(dest++) = '\n';
130 *(dest++) = '\0';
131 }
133 /*
134 ** fold the header at maxlen chars (newline excluded)
135 ** (We exclude the newline because the RFCs deal with it this way)
136 */
137 void
138 header_fold(header *hdr, unsigned int maxlen)
139 {
140 int len = strlen(hdr->header);
141 char *src = hdr->header;
142 char *dest;
143 char *tmp;
144 char *p;
145 int valueoffset;
147 if (len <= maxlen) {
148 /* we don't need to do anything */
149 return;
150 }
152 /* strip trailing whitespace */
153 for (p=src+len-1; *p==' '||*p=='\t'||*p=='\n'; p--) {
154 *p = '\0';
155 len--;
156 printf(" trailing whitespace\n");
157 }
158 printf("stripped len: %d\n", len);
160 /*
161 ** FIXME: would be nice to have a better size calculation
162 ** (the current size + what we insert as break, twice as often as
163 ** we have breaks in the optimal case)
164 */
165 tmp = malloc(len + 2 * (len/maxlen) * strlen("\n\t"));
166 dest = tmp;
168 /* the position in hdr->header where the value part start */
169 valueoffset = hdr->value - hdr->header;
171 while (strlen(src) > maxlen) {
172 int i, l;
173 char *pp;
175 for (pp=src+maxlen; pp>src; pp--) {
176 if (*pp==' ' || *pp=='\t' || *p=='\n') {
177 break;
178 }
179 }
181 if (src == pp) {
182 /* no potential break point was found within
183 maxlen so advance further until the next */
184 for (pp=src+maxlen; *pp; pp++) {
185 if (*pp==' ' || *pp=='\t' || *p=='\n') {
186 break;
187 }
188 }
189 }
190 if (!*pp) {
191 break;
192 }
194 memcpy(dest, src, pp-src);
195 dest += pp-src;
196 *(dest++) = '\n';
197 *(dest++) = '\t';
198 while (*pp == ' ' || *pp == '\t' || *p=='\n') {
199 pp++;
200 }
201 src = pp;
202 }
203 memcpy(dest, src, strlen(src));
204 dest += strlen(src);
206 if (*(dest-1) != '\n') {
207 *dest = '\n';
208 *(dest+1) = '\0';
209 }
211 hdr->header = tmp;
212 hdr->value = hdr->header + valueoffset;
213 }
215 header*
216 create_header(header_id id, gchar *fmt, ...)
217 {
218 gchar *p;
219 header *hdr;
220 va_list args;
221 va_start(args, fmt);
223 /* g_malloc() calls exit on failure */
224 hdr = g_malloc(sizeof(header));
226 hdr->id = id;
227 hdr->header = g_strdup_vprintf(fmt, args);
228 hdr->value = NULL;
230 /*
231 ** value shall point to the first non-whitespace char in the
232 ** value part of the header line (i.e. after the first colon)
233 */
234 p = strchr(hdr->header, ':');
235 if (p) {
236 p++;
237 while (*p == ' ' || *p == '\t' || *p == '\n') {
238 p++;
239 }
240 hdr->value = (*p) ? p : NULL;
241 }
243 DEBUG(3) debugf("create_header(): hdr: `%s'\n", hdr->header);
244 DEBUG(3) debugf("create_header(): val: `%s'\n", hdr->value);
246 va_end(args);
247 return hdr;
248 }
250 void
251 destroy_header(header *hdr)
252 {
253 if (hdr) {
254 if (hdr->header) {
255 g_free(hdr->header);
256 }
257 g_free(hdr);
258 }
259 }
261 header*
262 copy_header(header *hdr)
263 {
264 header *new_hdr = NULL;
266 if (hdr) {
267 new_hdr = g_malloc(sizeof(header));
268 new_hdr->id = hdr->id;
269 new_hdr->header = g_strdup(hdr->header);
270 new_hdr->value = new_hdr->header + (hdr->value - hdr->header);
271 }
272 return new_hdr;
273 }
275 header*
276 get_header(gchar *line)
277 {
278 gchar *p = line;
279 gchar buf[64], *q = buf;
280 gint i;
281 header *hdr;
283 while (*p && (*p != ':') && (q < buf+sizeof(buf)-1)) {
284 *(q++) = *(p++);
285 }
286 *q = '\0';
288 if (*p != ':') {
289 return NULL;
290 }
292 hdr = g_malloc(sizeof(header));
294 hdr->value = NULL;
295 p++;
297 while (*p && (*p == ' ' || *p == '\t')) {
298 p++;
299 }
300 hdr->value = p;
301 /*
302 ** Note: an empty value can also mean that it's only the first part
303 ** of a folded header line
304 */
306 for (i = 0; i < HEAD_NUM_IDS; i++) {
307 if (strcasecmp(header_names[i].header, buf) == 0) {
308 break;
309 }
310 }
311 hdr->id = (header_id) i;
312 hdr->header = g_strdup(line);
313 hdr->value = hdr->header + (hdr->value - line);
315 DEBUG(4) debugf("header: %d = %s[...]", hdr->id, hdr->header);
316 /* Note: This only outputs the first line if the header is folded */
318 return hdr;
319 }