uid.c
上传用户:xxcykj
上传日期:2007-01-04
资源大小:727k
文件大小:13k
- /*
- * uid.c -- UIDL handling for POP3 servers without LAST
- *
- * For license terms, see the file COPYING in this directory.
- */
- #include "config.h"
- #include <sys/stat.h>
- #include <errno.h>
- #include <stdio.h>
- #include <limits.h>
- #if defined(STDC_HEADERS)
- #include <stdlib.h>
- #include <string.h>
- #endif
- #if defined(HAVE_UNISTD_H)
- #include <unistd.h>
- #endif
- #include "fetchmail.h"
- /*
- * Machinery for handling UID lists live here. This is mainly to support
- * RFC1725-conformant POP3 servers without a LAST command, but may also be
- * useful for making the IMAP4 querying logic UID-oriented, if a future
- * revision of IMAP forces me to.
- *
- * These functions are also used by the rest of the code to maintain
- * string lists.
- *
- * Here's the theory:
- *
- * At start of a query, we have a (possibly empty) list of UIDs to be
- * considered seen in `oldsaved'. These are messages that were left in
- * the mailbox and *not deleted* on previous queries (we don't need to
- * remember the UIDs of deleted messages because ... well, they're gone!)
- * This list is initially set up by initialize_saved_list() from the
- * .fetchids file.
- *
- * Early in the query, during the execution of the protocol-specific
- * getrange code, the driver expects that the host's `newsaved' member
- * will be filled with a list of UIDs and message numbers representing
- * the mailbox state. If this list is empty, the server did
- * not respond to the request for a UID listing.
- *
- * Each time a message is fetched, we can check its UID against the
- * `oldsaved' list to see if it is old.
- *
- * Each time a message-id is seen, we mark it with MARK_SEEN.
- *
- * Each time a message is deleted, we mark its id UID_DELETED in the
- * `newsaved' member. When we want to assert that an expunge has been
- * done on the server, we call expunge_uid() to register that all
- * deleted messages are gone by marking them UID_EXPUNGED.
- *
- * At the end of the query, the `newsaved' member becomes the
- * `oldsaved' list. The old `oldsaved' list is freed.
- *
- * At the end of the fetchmail run, seen and non-EXPUNGED members of all
- * current `oldsaved' lists are flushed out to the .fetchids file to
- * be picked up by the next run. If there are no un-expunged
- * messages, the file is deleted.
- *
- * Note: some comparisons (those used for DNS address lists) are caseblind!
- */
- /* UIDs associated with un-queried hosts */
- static struct idlist *scratchlist;
- #ifdef POP3_ENABLE
- void initialize_saved_lists(struct query *hostlist, const char *idfile)
- /* read file of saved IDs and attach to each host */
- {
- struct stat statbuf;
- FILE *tmpfp;
- struct query *ctl;
- /* make sure lists are initially empty */
- for (ctl = hostlist; ctl; ctl = ctl->next)
- ctl->skipped = ctl->oldsaved = ctl->newsaved = (struct idlist *)NULL;
- errno = 0;
- /*
- * Croak if the uidl directory does not exist.
- * This probably means an NFS mount failed and we can't
- * see a uidl file that ought to be there.
- * Question: is this a portable check? It's not clear
- * that all implementations of lstat() will return ENOTDIR
- * rather than plain ENOENT in this case...
- */
- if (lstat(idfile, &statbuf) < 0) {
- if (errno == ENOTDIR)
- {
- report(stderr, "lstat: %s: %sn", idfile, strerror(errno));
- exit(PS_IOERR);
- }
- }
- /* let's get stored message UIDs from previous queries */
- if ((tmpfp = fopen(idfile, "r")) != (FILE *)NULL)
- {
- char buf[POPBUFSIZE+1];
- char *host = NULL; /* pacify -Wall */
- char *user;
- char *id;
- char *atsign; /* temp pointer used in parsing user and host */
- char *delimp1;
- char saveddelim1;
- char *delimp2;
- char saveddelim2 = ' '; /* pacify -Wall */
- while (fgets(buf, POPBUFSIZE, tmpfp) != (char *)NULL)
- {
- /*
- * At this point, we assume the bug has two fields -- a user@host
- * part, and an ID part. Either field may contain spurious @ signs.
- * The previous version of this code presumed one could split at
- * the rightmost '@'. This is not correct, as InterMail puts an
- * '@' in the UIDL.
- */
-
- /* first, skip leading spaces */
- user = buf + strspn(buf, " t");
- /* First, we split the buf into a userhost part and an id part */
- if ((id = strchr(user, '<')) != NULL ) /* set pointer to id */
- {
- for (delimp1 = id; delimp1 >= user; delimp1--)
- if ((*delimp1 != ' ') && (*delimp1 != 't'))
- break;
- delimp1++; /* but what if there is only white space ?!? */
- saveddelim1 = *delimp1; /* save char after token */
- *delimp1 = ' '; /* delimit token with