コード例 #1
0
ファイル: imaprefs.c プロジェクト: Stanfan/packages-clib
struct imap_refmsg *rfc822_threadgetroot(struct imap_refmsgtable *mt)
{
	struct imap_refmsg *root, *m;

	if (mt->rootptr)
		return (mt->rootptr);

	root=rfc822_threadallocmsg(mt, "(root)");

	if (!root)	return (0);

	root->parent=root;	/* Temporary */
	root->isdummy=1;

	for (m=mt->firstmsg; m; m=m->next)
		if (!m->parent)
		{
			if (m->isdummy && m->firstchild == 0)
				continue; /* Can happen in reference creation */

			linkparent(m, root);
		}
	root->parent=NULL;
	return (mt->rootptr=root);
}
コード例 #2
0
ファイル: reftest.c プロジェクト: zixia/nospam
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);
}
コード例 #3
0
ファイル: imaprefs.c プロジェクト: Stanfan/packages-clib
int rfc822_threadmergesubj(struct imap_refmsgtable *mt,
			   struct imap_refmsg *root)
{
	struct imap_refmsg *toproot, *p, *q, *nextroot;
	char *str;

	for (toproot=root->firstchild; toproot; toproot=nextroot)
	{
		const char *subj;
		struct imap_subjlookup *subjtop;
		int isrefwd;

		nextroot=toproot->nextsib;

		/*
		** (i) Find the subject of this thread as in step 4.B.i
		** above.
		*/

		p=toproot;
		if (p->isdummy)
			p=p->firstchild;

		subj=p->subj ? p->subj:"";

		/*
		** (ii) If the extracted subject is empty, skip this
		** message.
		*/

		if (*subj == 0)
			continue;

		/*
		** (iii) Lookup the message associated with this extracted
		** subject in the table.
		*/

		if (findsubj(mt, subj, &isrefwd, 0, &subjtop) || subjtop == 0)
			return (-1);

		/*
		** (iv) If the message in the table is the current message,
		** skip it.
		*/

		/* NOTE - ptr comparison IS NOT LEGAL */

		subjtop->msg->flag2=1;
		if (toproot->flag2)
		{
			toproot->flag2=0;
			continue;
		}
		subjtop->msg->flag2=0;

		/*
		** Otherwise, merge the current message with the one in the
		** table using the following rules:
		**
		** If both messages are dummies, append the current
		** message's children to the children of the message in
		** the table (the children of both messages become
		** siblings), and then delete the current message.
		*/

		if (subjtop->msg->isdummy && toproot->isdummy)
		{
			while ((p=toproot->firstchild) != 0)
			{
				breakparent(p);
				linkparent(p, subjtop->msg);
			}
			breakparent(toproot);
			continue;
		}

		/*
		** If the message in the table is a dummy and the current
		** message is not, make the current message a child of
		** the message in the table (a sibling of it's children).
		*/

		if (subjtop->msg->isdummy)
		{
			breakparent(toproot);
			linkparent(toproot, subjtop->msg);
			continue;
		}

		/*
		** If the current message is a reply or forward and the
		** message in the table is not, make the current message
		** a child of the message in the table (a sibling of it's
		** children).
		*/

		if (isrefwd)
		{
			p=subjtop->msg;
			if (p->isdummy)
				p=p->firstchild;

			subj=p->subj ? p->subj:"";

			str=rfc822_coresubj(subj, &isrefwd);

			if (!str)
				return (-1);
			free(str);	/* Don't really care */

			if (!isrefwd)
			{
				breakparent(toproot);
				linkparent(toproot, subjtop->msg);
				continue;
			}
		}

		/*
		** Otherwise, create a new dummy container and make both
		** messages children of the dummy, and replace the
		** message in the table with the dummy message.
		*/

		/* What we do is create a new message, then move the
		** contents of subjtop->msg (including its children)
		** to the new message, then make the new message a child
		** of subjtop->msg, and mark subjtop->msg as a dummy msg.
		*/

		q=rfc822_threadallocmsg(mt, "(dummy)");
		if (!q)
			return (-1);

		q->isdummy=1;

		swapmsgdata(q, subjtop->msg);

		while ((p=subjtop->msg->firstchild) != 0)
		{
			breakparent(p);
			linkparent(p, q);
		}
		linkparent(q, subjtop->msg);

		breakparent(toproot);
		linkparent(toproot, subjtop->msg);
	}
	return (0);
}
コード例 #4
0
ファイル: imaprefs.c プロジェクト: Stanfan/packages-clib
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);
}