static void content_id(struct rfc2045 *p, struct rfc822t *t) { struct rfc822a *a=rfc822a_alloc(t); int i; if (!a) { rfc2045_enomem(); return; } for (i=0; i<a->naddrs; i++) if (a->addrs[i].tokens) { char *s=rfc822_getaddr(a, i); if (!s) { rfc822a_free(a); rfc2045_enomem(); return; } if (p->content_id) free(p->content_id); p->content_id=s; break; } rfc822a_free(a); }
static void check_sender() { const char *h=hdr("reply-to"); struct rfc822t *t; struct rfc822a *a; if (!h || !*h) h=hdr("from"); if (!h || !*h) exit(0); t=rfc822t_alloc_new(h, NULL, NULL); if (!t || !(a=rfc822a_alloc(t))) { perror("malloc"); exit(EX_TEMPFAIL); } if (a->naddrs <= 0) exit (0); sender=rfc822_getaddr(a, 0); rfc822a_free(a); rfc822t_free(t); if (!sender || !*sender) exit(0); }
static void check_recips() { char *buf; struct rfc822t *t; struct rfc822a *a; struct header *h; if (!recips || !*recips) return; buf=strdup(recips); if (!buf) { perror("strdup"); exit(EX_TEMPFAIL); } for (h=header_list; h; h=h->next) { int i; if (strncasecmp(h->buf, "to:", 3) && strncasecmp(h->buf, "cc:", 3)) continue; t=rfc822t_alloc_new(h->buf+3, NULL, NULL); if (!t || !(a=rfc822a_alloc(t))) { perror("malloc"); exit(EX_TEMPFAIL); } for (i=0; i<a->naddrs; i++) { char *p=rfc822_getaddr(a, i); char *q; strcpy(buf, recips); for (q=buf; (q=strtok(q, ", ")) != 0; q=0) { if (p && strcasecmp(p, q) == 0) { free(p); free(buf); rfc822a_free(a); rfc822t_free(t); return; } } free(p); } rfc822a_free(a); rfc822t_free(t); } free(buf); exit(0); }
static int knownkey(const char *shortname, const char *known_keys) { struct rfc822t *t=rfc822t_alloc_new(shortname, NULL, NULL); struct rfc822a *a; int i; if (!t) return (0); a=rfc822a_alloc(t); if (!a) { rfc822t_free(t); return (0); } for (i=0; i<a->naddrs; i++) { char *p=rfc822_getaddr(a, i); int plen; const char *q; if (!p) continue; if (!*p) { free(p); continue; } plen=strlen(p); for (q=known_keys; *q; ) { if (strncasecmp(q, p, plen) == 0 && q[plen] == '\n') { free(p); rfc822a_free(a); rfc822t_free(t); return (1); } while (*q) if (*q++ == '\n') break; } free(p); } rfc822a_free(a); rfc822t_free(t); return (0); }
char *rfc2045_related_start(const struct rfc2045 *p) { const char *cb=rfc2045_getattr( p->content_type_attr, "start"); struct rfc822t *t; struct rfc822a *a; int i; if (!cb || !*cb) return (0); t=rfc822t_alloc_new(cb, 0, NULL); if (!t) { rfc2045_enomem(); return(0); } a=rfc822a_alloc(t); if (!a) { rfc822t_free(t); rfc2045_enomem(); return (0); } for (i=0; i<a->naddrs; i++) if (a->addrs[i].tokens) { char *s=rfc822_getaddr(a, i); rfc822a_free(a); rfc822t_free(t); if (!s) rfc2045_enomem(); return (s); } rfc822a_free(a); rfc822t_free(t); return (0); }
char *newmsg_alladdrs(FILE *fp) { char *headers=NULL; struct rfc822t *t; struct rfc822a *a; char *p, *q; int l, i; if (fp) { char *header, *value; rewind(fp); /* First, combine all the headers into one header. */ while ((header=maildir_readheader(fp, &value, 1)) != 0) { char *newh; if (strcmp(header, "from") && strcmp(header, "to") && strcmp(header, "cc") && strcmp(header, "bcc")) continue; if (headers) { newh=realloc(headers, strlen(headers) +strlen(value)+2); if (!newh) continue; strcat(newh, ","); headers=newh; } else { newh=malloc(strlen(value)+1); if (!newh) continue; *newh=0; headers=newh; } strcat(headers, value); } } /* Now, parse the header, and extract the addresses */ t=rfc822t_alloc_new(headers ? headers:"", NULL, NULL); a= t ? rfc822a_alloc(t):NULL; l=1; for (i=0; i < (a ? a->naddrs:0); i++) { p=rfc822_getaddr(a, i); if (p) { ++l; l +=strlen(p); free(p); } } p=malloc(l); if (p) *p=0; for (i=0; i < (a ? a->naddrs:0); i++) { q=rfc822_getaddr(a, i); if (q) { if (p) { strcat(strcat(p, q), "\n"); } free(q); } } rfc822a_free(a); rfc822t_free(t); free(headers); return (p); }
static void readforward(FILE *f, int n) { char buf[BUFSIZ]; char *p; struct rfc822t *t; struct rfc822a *a; int i; char *sep; while (fgets(buf, sizeof(buf), f)) { p=strchr(buf, '\n'); if (p) *p=0; p=buf; while (*p && isspace((int)(unsigned char)*p)) ++p; if (strncmp(p, ":include:", 9) == 0) { FILE *g; if (n > 10) { fprintf(stderr, "dotforward: too many :include files.\n"); exit(EX_NOUSER); } p += 9; while (*p && isspace((int)(unsigned char)*p)) ++p; if (!*p) continue; g=fopen(p, "r"); if (!g) { perror(p); exit(EX_NOUSER); } readforward(g, n+1); fclose(g); continue; } if (*p == '|' || *p == '/' || *p == '.') { printf("%s\n", p); continue; } t=rfc822t_alloc_new(p, NULL, NULL); if (!t || !(a=rfc822a_alloc(t))) { perror("malloc"); exit(EX_NOUSER); } for (i=0; i<a->naddrs; i++) { if (a->addrs[i].tokens && a->addrs[i].tokens->token == '"' && a->addrs[i].tokens->next == NULL) a->addrs[i].tokens->token=0; p=rfc822_getaddr(a, i); if (!p) { perror("malloc"); exit(EX_NOUSER); } if (*p == '|' || *p == '/') { printf("%s\n", p); } free(p); } sep=0; for (i=0; i<a->naddrs; i++) { char *q, *r; struct delivered_to *s; char *t; char *orig; p=rfc822_getaddr(a, i); if (!p) { perror("malloc"); exit(EX_NOUSER); } if (*p == '|' || *p == '/' || *p == '.') { free(p); continue; } q=p; if (*q == '\\') ++q; r=strchr(q, '@'); if (!r || config_islocal(r+1, 0)) locallower(q); domainlower(q); t=0; orig=q; if (strchr(q, '@') == 0) { t=malloc(strlen(q)+1+strlen(myaddr)); /* overkill, yeah */ if (!t) { perror("malloc"); exit(EX_NOUSER); } strcat(strcpy(t, q), strchr(myaddr, '@')); q=t; } if (strcmp(myaddr, q) == 0) { exit_code=0; free(p); if (t) free(t); continue; } for (s=delivtolist; s; s=s->next) { if (strcmp(s->addr, q) == 0) break; } if (!s) { if (sep) printf("%s", sep); else printf("!"); sep=", "; printf("%s", orig); } free(p); if (t) free(t); } if (sep) printf("\n"); rfc822a_free(a); rfc822t_free(t); } }
struct imap_refmsg *rfc822_threadmsg(struct imap_refmsgtable *mt, const char *msgidhdr, const char *refhdr, const char *subjheader, const char *dateheader, unsigned long seqnum) { struct rfc822t *t; struct rfc822a *a; struct imap_refmsg *m; char *msgid_s; t=rfc822t_alloc(msgidhdr ? msgidhdr:"", 0); if (!t) return (0); a=rfc822a_alloc(t); if (!a) { rfc822t_free(t); return (0); } msgid_s=a->naddrs > 0 ? rfc822_getaddr(a, 0):strdup(""); rfc822a_free(a); rfc822t_free(t); if (!msgid_s) return (0); t=rfc822t_alloc(refhdr ? refhdr:"", 0); if (!t) { free(msgid_s); return (0); } a=rfc822a_alloc(t); if (!a) { rfc822t_free(t); free(msgid_s); return (0); } m=dorefcreate(mt, msgid_s, a); rfc822a_free(a); rfc822t_free(t); free(msgid_s); if (!m) return (0); if (subjheader && (m->subj=strdup(subjheader)) == 0) return (0); /* Cleanup in rfc822_threadfree() */ m->timestamp=dateheader ? rfc822_parsedt(dateheader):0; m->seqnum=seqnum; return (m); }
static struct imap_refmsg *dorefcreate(struct imap_refmsgtable *mt, const char *newmsgid, struct rfc822a *a) /* a - references header */ { struct imap_refmsg *lastmsg=0, *m; struct imap_refmsg *msg; int n; /* (A) Using the Message-IDs in the message's references, link the corresponding messages together as parent/child. Make the first reference the parent of the second (and the second a child of the first), the second the parent of the third (and the third a child of the second), etc. The following rules govern the creation of these links: If no reference message can be found with a given Message-ID, create a dummy message with this ID. Use this dummy message for all subsequent references to this ID. */ for (n=0; n<a->naddrs; n++) { char *msgid=rfc822_getaddr(a, n); msg=*msgid ? rfc822_threadsearchmsg(mt, msgid ? msgid:""):0; if (!msg) { msg=rfc822_threadallocmsg(mt, msgid ? msgid:""); if (!msg) { if (msgid) free(msgid); return (0); } msg->isdummy=1; } if (msgid) free(msgid); /* If a reference message already has a parent, don't change the existing link. */ if (lastmsg == 0 || msg->parent) { lastmsg=msg; continue; } /* Do not create a parent/child link if creating that link would introduce a loop. For example, before making message A the parent of B, make sure that A is not a descendent of B. */ for (m=lastmsg; m; m=m->parent) if (strcmp(m->msgid, msg->msgid) == 0) break; if (m) { lastmsg=msg; continue; } linkparent(msg, lastmsg); lastmsg=msg; } /* (B) Create a parent/child link between the last reference (or NIL if there are no references) and the current message. If the current message has a parent already, break the current parent/child link before creating the new one. Note that if this message has no references, that it will now have no parent. NOTE: The parent/child links MUST be kept consistent with one another at ALL times. */ msg=*newmsgid ? rfc822_threadsearchmsg(mt, newmsgid):0; /* If a message does not contain a Message-ID header line, or the Message-ID header line does not contain a valid Message ID, then assign a unique Message ID to this message. Implementation note: empty msgid, plus dupe check below, implements that. */ if (msg && msg->isdummy) { msg->isdummy=0; if (msg->parent) breakparent(msg); } else { #if 1 /* ** If two or more messages have the same Message ID, assign ** a unique Message ID to each of the duplicates. ** ** Implementation note: just unlink the existing message from ** it's parents/children. */ if (msg) { while (msg->firstchild) breakparent(msg->firstchild); breakparent(msg); newmsgid=""; /* Create new entry with an empty msgid, if any more ** msgids come, they'll hit the dupe check again. */ } #endif msg=rfc822_threadallocmsg(mt, newmsgid); if (!msg) return (0); } if (lastmsg) { for (m=lastmsg; m; m=m->parent) if (strcmp(m->msgid, msg->msgid) == 0) break; if (!m) linkparent(msg, lastmsg); } return (msg); }