masqmail

annotate src/header.c @ 367:b27f66555ba8

Reformated multiline comments to have leading asterisks on each line Now we use: /* ** comment */ This makes the indent style simpler, too.
author markus schnalke <meillo@marmaro.de>
date Thu, 20 Oct 2011 10:20:59 +0200
parents 41958685480d
children 028bc124d744
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 int i, l;
meillo@303 173 char *pp;
meillo@0 174
meillo@303 175 for (pp=src+maxlen; pp>src; pp--) {
meillo@303 176 if (*pp==' ' || *pp=='\t' || *p=='\n') {
meillo@303 177 break;
meillo@303 178 }
meillo@303 179 }
meillo@303 180
meillo@303 181 if (src == pp) {
meillo@303 182 /* no potential break point was found within
meillo@303 183 maxlen so advance further until the next */
meillo@303 184 for (pp=src+maxlen; *pp; pp++) {
meillo@303 185 if (*pp==' ' || *pp=='\t' || *p=='\n') {
meillo@303 186 break;
meillo@303 187 }
meillo@303 188 }
meillo@303 189 }
meillo@303 190 if (!*pp) {
meillo@303 191 break;
meillo@303 192 }
meillo@0 193
meillo@303 194 memcpy(dest, src, pp-src);
meillo@303 195 dest += pp-src;
meillo@303 196 *(dest++) = '\n';
meillo@303 197 *(dest++) = '\t';
meillo@303 198 while (*pp == ' ' || *pp == '\t' || *p=='\n') {
meillo@303 199 pp++;
meillo@303 200 }
meillo@303 201 src = pp;
meillo@303 202 }
meillo@303 203 memcpy(dest, src, strlen(src));
meillo@303 204 dest += strlen(src);
meillo@303 205
meillo@303 206 if (*(dest-1) != '\n') {
meillo@303 207 *dest = '\n';
meillo@303 208 *(dest+1) = '\0';
meillo@301 209 }
meillo@0 210
meillo@303 211 hdr->header = tmp;
meillo@301 212 hdr->value = hdr->header + valueoffset;
meillo@0 213 }
meillo@0 214
meillo@10 215 header*
meillo@366 216 create_header(header_id id, gchar *fmt, ...)
meillo@0 217 {
meillo@10 218 gchar *p;
meillo@10 219 header *hdr;
meillo@10 220 va_list args;
meillo@10 221 va_start(args, fmt);
meillo@0 222
meillo@301 223 /* g_malloc() calls exit on failure */
meillo@301 224 hdr = g_malloc(sizeof(header));
meillo@0 225
meillo@301 226 hdr->id = id;
meillo@301 227 hdr->header = g_strdup_vprintf(fmt, args);
meillo@301 228 hdr->value = NULL;
meillo@0 229
meillo@367 230 /*
meillo@367 231 ** value shall point to the first non-whitespace char in the
meillo@367 232 ** value part of the header line (i.e. after the first colon)
meillo@367 233 */
meillo@301 234 p = strchr(hdr->header, ':');
meillo@301 235 if (p) {
meillo@301 236 p++;
meillo@301 237 while (*p == ' ' || *p == '\t' || *p == '\n') {
meillo@10 238 p++;
meillo@301 239 }
meillo@301 240 hdr->value = (*p) ? p : NULL;
meillo@10 241 }
meillo@0 242
meillo@301 243 DEBUG(3) debugf("create_header(): hdr: `%s'\n", hdr->header);
meillo@301 244 DEBUG(3) debugf("create_header(): val: `%s'\n", hdr->value);
meillo@301 245
meillo@10 246 va_end(args);
meillo@10 247 return hdr;
meillo@0 248 }
meillo@0 249
meillo@10 250 void
meillo@366 251 destroy_header(header *hdr)
meillo@0 252 {
meillo@10 253 if (hdr) {
meillo@301 254 if (hdr->header) {
meillo@10 255 g_free(hdr->header);
meillo@301 256 }
meillo@10 257 g_free(hdr);
meillo@10 258 }
meillo@0 259 }
meillo@0 260
meillo@10 261 header*
meillo@366 262 copy_header(header *hdr)
meillo@0 263 {
meillo@10 264 header *new_hdr = NULL;
meillo@0 265
meillo@10 266 if (hdr) {
meillo@301 267 new_hdr = g_malloc(sizeof(header));
meillo@301 268 new_hdr->id = hdr->id;
meillo@301 269 new_hdr->header = g_strdup(hdr->header);
meillo@301 270 new_hdr->value = new_hdr->header + (hdr->value - hdr->header);
meillo@10 271 }
meillo@10 272 return new_hdr;
meillo@0 273 }
meillo@0 274
meillo@10 275 header*
meillo@366 276 get_header(gchar *line)
meillo@0 277 {
meillo@10 278 gchar *p = line;
meillo@10 279 gchar buf[64], *q = buf;
meillo@10 280 gint i;
meillo@10 281 header *hdr;
meillo@0 282
meillo@301 283 while (*p && (*p != ':') && (q < buf+sizeof(buf)-1)) {
meillo@10 284 *(q++) = *(p++);
meillo@301 285 }
meillo@15 286 *q = '\0';
meillo@0 287
meillo@301 288 if (*p != ':') {
meillo@10 289 return NULL;
meillo@301 290 }
meillo@0 291
meillo@10 292 hdr = g_malloc(sizeof(header));
meillo@0 293
meillo@10 294 hdr->value = NULL;
meillo@10 295 p++;
meillo@0 296
meillo@301 297 while (*p && (*p == ' ' || *p == '\t')) {
meillo@10 298 p++;
meillo@301 299 }
meillo@10 300 hdr->value = p;
meillo@367 301 /*
meillo@367 302 ** Note: an empty value can also mean that it's only the first part
meillo@367 303 ** of a folded header line
meillo@367 304 */
meillo@0 305
meillo@10 306 for (i = 0; i < HEAD_NUM_IDS; i++) {
meillo@301 307 if (strcasecmp(header_names[i].header, buf) == 0) {
meillo@10 308 break;
meillo@301 309 }
meillo@10 310 }
meillo@10 311 hdr->id = (header_id) i;
meillo@10 312 hdr->header = g_strdup(line);
meillo@10 313 hdr->value = hdr->header + (hdr->value - line);
meillo@10 314
meillo@322 315 DEBUG(4) debugf("header: %d = %s[...]", hdr->id, hdr->header);
meillo@301 316 /* Note: This only outputs the first line if the header is folded */
meillo@10 317
meillo@10 318 return hdr;
meillo@0 319 }