diff options
-rw-r--r-- | fetchmail.h | 7 | ||||
-rw-r--r-- | imap.c | 3 | ||||
-rw-r--r-- | sink.c | 3 | ||||
-rw-r--r-- | smtp.c | 4 | ||||
-rw-r--r-- | uid.c | 83 | ||||
-rw-r--r-- | unmime.c | 1 |
6 files changed, 65 insertions, 36 deletions
diff --git a/fetchmail.h b/fetchmail.h index df6563c2..8b4280b3 100644 --- a/fetchmail.h +++ b/fetchmail.h @@ -314,6 +314,7 @@ struct query unsigned int uid; /* UID of user to deliver to */ struct idlist *skipped; /* messages skipped on the mail server */ struct idlist *oldsaved, *newsaved; + struct idlist **oldsavedend; char *lastid; /* last Message-ID seen on this connection */ char *thisid; /* Message-ID of current message */ @@ -515,14 +516,14 @@ void free_str_list(struct idlist **); struct idlist *copy_str_list(struct idlist *idl); void save_str_pair(struct idlist **, const char *, const char *); void free_str_pair_list(struct idlist **); -int delete_str(struct idlist **, int); +int delete_str(struct idlist **, long); int str_in_list(struct idlist **, const char *, const flag); int str_nr_in_list(struct idlist **, const char *); int str_nr_last_in_list(struct idlist **, const char *); void str_set_mark( struct idlist **, const char *, const flag); int count_list( struct idlist **idl ); -char *str_from_nr_list( struct idlist **idl, int number ); -char *str_find(struct idlist **, int); +char *str_from_nr_list( struct idlist **idl, long number ); +char *str_find(struct idlist **, long); char *idpair_find(struct idlist **, const char *); void append_str_list(struct idlist **, struct idlist **); void expunge_uids(struct query *); @@ -57,7 +57,10 @@ static int imap_ok(int sock, char *argbuf) /* interpret untagged status responses */ if (strstr(buf, "* CAPABILITY")) + { strncpy(capabilities, buf + 12, sizeof(capabilities)); + capabilities[sizeof(capabilities)-1] = '\0'; + } else if (strstr(buf, "EXISTS")) { count = atoi(buf+2); @@ -1468,7 +1468,8 @@ va_dcl #endif /* format and ship a warning message line by mail */ { - char buf[MSGBUFSIZE+4]; + /* make huge -- i18n can bulk up error messages a lot */ + char buf[2*MSGBUFSIZE+4]; va_list ap; /* @@ -87,6 +87,7 @@ static void SMTP_auth(int sock, char *username, char *password, char *buf) SockPrintf(sock, "AUTH CRAM-MD5\r\n"); SockRead(sock, smtp_response, sizeof(smtp_response) - 1); strncpy(tmp, smtp_response, sizeof(tmp)); + tmp[sizeof(tmp)-1] == '\0'; if (strncmp(tmp, "334 ", 4)) { /* Server rejects AUTH */ SMTP_auth_error(sock, GT_("Server rejected the AUTH command.\n")); @@ -146,6 +147,7 @@ static void SMTP_auth(int sock, char *username, char *password, char *buf) SockPrintf(sock, "AUTH LOGIN\r\n"); SockRead(sock, smtp_response, sizeof(smtp_response) - 1); strncpy(tmp, smtp_response, sizeof(tmp)); + tmp[sizeof(tmp)-1] == '\0'; if (strncmp(tmp, "334 ", 4)) { /* Server rejects AUTH */ SMTP_auth_error(sock, GT_("Server rejected the AUTH command.\n")); @@ -162,6 +164,7 @@ static void SMTP_auth(int sock, char *username, char *password, char *buf) SockPrintf(sock, "%s\r\n", b64buf); SockRead(sock, smtp_response, sizeof(smtp_response) - 1); strncpy(tmp, smtp_response, sizeof(tmp)); + tmp[sizeof(tmp)-1] == '\0'; p = strchr(tmp, ' '); if (!p) { SMTP_auth_error(sock, GT_("Bad base64 reply from server.\n")); @@ -210,6 +213,7 @@ int SMTP_ehlo(int sock, const char *host, char *name, char *password, int *opt) *opt |= hp->value; if (strncmp(hp->name, "AUTH ", 5) == 0) strncpy(auth_response, smtp_response, sizeof(auth_response)); + auth_response[sizeof(auth_response)-1] == '\0'; } if ((smtp_response[0] == '1' || smtp_response[0] == '2' || smtp_response[0] == '3') && smtp_response[3] == ' ') { if (*opt & ESMTP_AUTH) @@ -23,8 +23,8 @@ /* * 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 + * RFC1725/RFC1939-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 @@ -39,7 +39,7 @@ * 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 + * 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 @@ -63,7 +63,7 @@ * 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! + * Note: some comparisons (those used for DNS address lists) are caseblind! */ /* UIDs associated with un-queried hosts */ @@ -78,8 +78,12 @@ void initialize_saved_lists(struct query *hostlist, const char *idfile) 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; + for (ctl = hostlist; ctl; ctl = ctl->next) { + ctl->skipped = (struct idlist *)NULL; + ctl->oldsaved = (struct idlist *)NULL; + ctl->newsaved = (struct idlist *)NULL; + ctl->oldsavedend = &ctl->oldsaved; + } errno = 0; @@ -91,13 +95,13 @@ void initialize_saved_lists(struct query *hostlist, const char *idfile) * 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, GT_("lstat: %s: %s\n"), idfile, strerror(errno)); - exit(PS_IOERR); + if (lstat(idfile, &statbuf) < 0) { + if (errno == ENOTDIR) + { + report(stderr, GT_("lstat: %s: %s\n"), idfile, strerror(errno)); + exit(PS_IOERR); + } } - } /* let's get stored message UIDs from previous queries */ if ((tmpfp = fopen(idfile, "r")) != (FILE *)NULL) @@ -231,7 +235,11 @@ void initialize_saved_lists(struct query *hostlist, const char *idfile) } #endif /* POP3_ENABLE */ -struct idlist *save_str(struct idlist **idl, const char *str, flag status) +/* return a pointer to the last element of the list to help the quick, + * constant-time addition to the list, NOTE: this function does not dup + * the string, the caller must do that. */ +/*@shared@*/ struct idlist **save_str_quick(/*@shared@*/ struct idlist **idl, + /*@only@*/ char *str, flag status) /* save a number/UID pair on the given UID list */ { struct idlist **end; @@ -242,10 +250,17 @@ struct idlist *save_str(struct idlist **idl, const char *str, flag status) *end = (struct idlist *)xmalloc(sizeof(struct idlist)); (*end)->val.status.mark = status; - (*end)->id = str ? xstrdup(str) : (char *)NULL; + (*end)->id = (unsigned char *)str; (*end)->next = NULL; - return(*end); + return end; +} + +/* return the end list element for direct modification */ +struct idlist *save_str(struct idlist **idl, const char *str, flag st) +{ + return *save_str_quick(idl, str ? xstrdup(str) : NULL, + st); } void free_str_list(struct idlist **idl) @@ -296,14 +311,17 @@ void free_str_pair_list(struct idlist **idl) int str_in_list(struct idlist **idl, const char *str, const flag caseblind) /* is a given ID in the given list? (comparison may be caseblind) */ { - if (*idl == (struct idlist *)NULL || str == (char *) NULL) - return(0); - else if (!caseblind && strcmp(str, (*idl)->id) == 0) - return(1); - else if (caseblind && strcasecmp(str, (*idl)->id) == 0) - return(1); - else - return(str_in_list(&(*idl)->next, str, caseblind)); + struct idlist *walk; + if (caseblind) { + for( walk = *idl; walk; walk = walk->next ) + if( strcasecmp( str, (char *)walk->id) == 0 ) + return 1; + } else { + for( walk = *idl; walk; walk = walk->next ) + if( strcmp( str, (char *)walk->id) == 0 ) + return 1; + } + return 0; } int str_nr_in_list( struct idlist **idl, const char *str ) @@ -352,7 +370,7 @@ int count_list( struct idlist **idl) return 1 + count_list( &(*idl)->next ); } -char *str_from_nr_list(struct idlist **idl, int number) +/*@null@*/ char *str_from_nr_list(struct idlist **idl, long number) /* return the number'th string in idl */ { if( !*idl || number < 0) @@ -362,8 +380,8 @@ char *str_from_nr_list(struct idlist **idl, int number) return str_from_nr_list(&(*idl)->next, number-1); } - -char *str_find(struct idlist **idl, int number) + +char *str_find(struct idlist **idl, long number) /* return the id of the given number in the given list. */ { if (*idl == (struct idlist *) 0) @@ -385,7 +403,7 @@ char *idpair_find(struct idlist **idl, const char *id) return(idpair_find(&(*idl)->next, id)); } -int delete_str(struct idlist **idl, int num) +int delete_str(struct idlist **idl, long num) /* delete given message from given list */ { struct idlist *idp; @@ -487,7 +505,7 @@ void uid_swap_lists(struct query *ctl) void write_saved_lists(struct query *hostlist, const char *idfile) /* perform end-of-run write of seen-messages list */ { - int idcount; + long idcount; FILE *tmpfp; struct query *ctl; struct idlist *idp; @@ -495,10 +513,10 @@ void write_saved_lists(struct query *hostlist, const char *idfile) /* if all lists are empty, nuke the file */ idcount = 0; for (ctl = hostlist; ctl; ctl = ctl->next) { - for (idp = ctl->oldsaved; idp; idp = idp->next) - if (idp->val.status.mark == UID_SEEN - || idp->val.status.mark == UID_DELETED) - idcount++; + for (idp = ctl->oldsaved; idp; idp = idp->next) + if (idp->val.status.mark == UID_SEEN + || idp->val.status.mark == UID_DELETED) + idcount++; } /* either nuke the file or write updated last-seen IDs */ @@ -512,6 +530,7 @@ void write_saved_lists(struct query *hostlist, const char *idfile) { if (outlevel >= O_DEBUG) report(stdout, GT_("Writing fetchids file.\n")); + /* FIXME: do not overwrite the old idfile */ if ((tmpfp = fopen(idfile, "w")) != (FILE *)NULL) { for (ctl = hostlist; ctl; ctl = ctl->next) { for (idp = ctl->oldsaved; idp; idp = idp->next) @@ -468,6 +468,7 @@ int MimeBodyType(unsigned char *hdrs, int WantDecode) the boundary string */ strcpy(MultipartDelimiter, "--"); strncat(MultipartDelimiter, p1, MAX_DELIM_LEN); + MultipartDelimiter[sizeof(MultipartDelimiter)-1] = '\0'; BodyType = (MSG_IS_8BIT | MSG_NEEDS_DECODE); } } |