static void test1() { struct imap_refmsgtable *mt=rfc822_threadalloc(); char buf[20]; struct imap_refmsg *p; strcpy(buf, "a@b"); p=rfc822_threadallocmsg(mt, buf); strcpy(buf, "c@d"); p=rfc822_threadallocmsg(mt, buf); printf("%s\n", (rfc822_threadsearchmsg(mt, "a@b") ? "found":"not found")); printf("%s\n", (rfc822_threadsearchmsg(mt, "c@d") ? "found":"not found")); printf("%s\n", (rfc822_threadsearchmsg(mt, "e@f") ? "found":"not found")); rfc822_threadfree(mt); }
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); }