masqmail

annotate src/header.c @ 381:33b893124c81

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