From 9253a4123e884b7d8d2360239083f3383e9516fe Mon Sep 17 00:00:00 2001 From: "jk7744.park" Date: Tue, 8 Sep 2015 22:07:27 +0900 Subject: [PATCH] tizen 2.3.1 release --- .gitignore | 12 + Makefile.am | 6 +- imap-2007e/c-client/Makefile | 2 +- imap-2007e/c-client/auth_pla.c | 84 ++- imap-2007e/c-client/auth_xoauth2.c | 111 +++ imap-2007e/c-client/auths.c | 1 + imap-2007e/c-client/imap4r1.c | 1408 ++++++++++++++++++++++++------------ imap-2007e/c-client/imap4r1.h | 17 + imap-2007e/c-client/linkage.c | 1 + imap-2007e/c-client/linkage.h | 1 + imap-2007e/c-client/lnx_mail.c | 46 +- imap-2007e/c-client/mail.c | 297 ++++++-- imap-2007e/c-client/mail.h | 28 +- imap-2007e/c-client/osdep.c | 68 +- imap-2007e/c-client/osdepssl.c | 29 +- imap-2007e/c-client/pop3.c | 102 ++- imap-2007e/c-client/rfc822.c | 140 ++-- imap-2007e/c-client/rfc822.h | 2 + imap-2007e/c-client/smtp.c | 99 +-- imap-2007e/c-client/ssl_unix.c | 48 +- imap-2007e/c-client/tcp_unix.c | 79 +- libuw-imap-toolkit.manifest | 5 + packaging/uw-imap-toolkit.spec | 12 +- 23 files changed, 1712 insertions(+), 886 deletions(-) create mode 100755 .gitignore create mode 100755 imap-2007e/c-client/auth_xoauth2.c create mode 100644 libuw-imap-toolkit.manifest diff --git a/.gitignore b/.gitignore new file mode 100755 index 0000000..6c53821 --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +build_log +*.log +*.pyc +usr +opt +*.o +*.os +*.exe +packages +binaries +*.ipk +*~ diff --git a/Makefile.am b/Makefile.am index 063cbb3..db8d2db 100755 --- a/Makefile.am +++ b/Makefile.am @@ -31,6 +31,7 @@ libuw_imap_toolkit_la_CPPFLAGS= -I. \ -D__FEATURE_HEADER_OPTIMIZATION__ \ -D__FEATURE_SEND_OPTMIZATION__ \ -D__FEATURE_XLIST_SUPPORT__ \ + -D__FEATURE_SUPPORT_IMAP_ID__ \ -DCREATEPROTO=unixproto -DEMPTYPROTO=unixproto \ -DMAILSPOOL=\"/var/spool/mail\" \ -DANONYMOUSHOME=\"/var/spool/mail/anonymous\" \ @@ -48,8 +49,9 @@ libuw_imap_toolkit_la_CPPFLAGS= -I. \ -DDATA_PATH=\"/opt/.email/res\" \ -DEXPORT_API="__attribute__((visibility(\"default\")))" -# -DFEATURE_CORE_DEBUG -# -D__NON_BLOCKING_SSL_WRITE__ +#-DFEATURE_CORE_DEBUG +#-D__NON_BLOCKING_SSL_WRITE__ +#-D__FEATURE_METADATA_SUPPORT__ libuw_imap_toolkit_la_LIBADD = -L$(prefix)/lib \ $(SSL_LIBS) diff --git a/imap-2007e/c-client/Makefile b/imap-2007e/c-client/Makefile index 090c8f2..3c043c0 100755 --- a/imap-2007e/c-client/Makefile +++ b/imap-2007e/c-client/Makefile @@ -903,7 +903,7 @@ osdep.o:mail.h misc.h env.h fs.h ftl.h nl.h tcp.h \ gethstid.c getspnam.c \ gr_wait.c gr_wait4.c gr_waitp.c \ kerb_mit.c \ - auth_ext.c auth_gss.c auth_log.c auth_md5.c auth_pla.c \ + auth_ext.c auth_gss.c auth_log.c auth_md5.c auth_pla.c auth_xoauth2.c\ pmatch.c scandir.c setpgrp.c strerror.c truncate.c write.c \ memmove.c memmove2.c memset.c \ tz_bsd.c tz_nul.c tz_sv4.c \ diff --git a/imap-2007e/c-client/auth_pla.c b/imap-2007e/c-client/auth_pla.c index 4813c4c..0327e91 100755 --- a/imap-2007e/c-client/auth_pla.c +++ b/imap-2007e/c-client/auth_pla.c @@ -65,61 +65,67 @@ long auth_plain_client (authchallenge_t challenger,authrespond_t responder, /* get initial (empty) challenge */ if (challenge = (*challenger) (stream,&clen)) { fs_give ((void **) &challenge); - if (clen) { /* abort if challenge non-empty */ - mm_log ("auth_plain_client : Server bug: non-empty initial PLAIN challenge 1",WARN); - (*responder) (stream,NIL,0); - ret = LONGT; /* will get a BAD response back */ - } pwd[0] = NIL; /* prompt user if empty challenge */ mm_login (mb,user,pwd,*trial); - if (!pwd[0]) { /* empty challenge or user requested abort */ - (*responder) (stream,NIL,0); - *trial = 0; /* cancel subsequent attempts */ - ret = LONGT; /* will get a BAD response back */ + if (clen) { + mm_log ("Enter section for handling non-emtpy challenge",WARN); + if ((*responder) (stream,user,strlen (user)) && + (challenge = (*challenger) (stream,&clen))) { + fs_give ((void **) &challenge); + /* send password */ + if ((*responder) (stream,pwd,strlen (pwd))) { + if (challenge = (*challenger) (stream,&clen)) + fs_give ((void **) &challenge); + else { + ++*trial; /* can try again if necessary */ + ret = LONGT; /* check the authentication */ + } + } + } } else { - unsigned long rlen = - strlen (mb->authuser) + strlen (user) + strlen (pwd) + 2; - char *response = (char *) fs_get (rlen); - char *t = response; /* copy authorization id */ + if (!pwd[0]) { /* empty challenge or user requested abort */ + (*responder) (stream,NIL,0); + *trial = 0; /* cancel subsequent attempts */ + ret = LONGT; /* will get a BAD response back */ + } + else { + unsigned long rlen = + strlen (mb->authuser) + strlen (user) + strlen (pwd) + 2; + char *response = (char *) fs_get (rlen); + char *t = response; /* copy authorization id */ - memset(response, 0x00, rlen); + memset(response, 0x00, rlen); - if (mb->authuser[0]) for (u = user; *u; *t++ = *u++); - *t++ = '\0'; /* delimiting NUL */ + if (mb->authuser[0]) for (u = user; *u; *t++ = *u++); + *t++ = '\0'; /* delimiting NUL */ /* copy authentication id */ - for (u = mb->authuser[0] ? mb->authuser : user; *u; *t++ = *u++); - *t++ = '\0'; /* delimiting NUL */ + for (u = mb->authuser[0] ? mb->authuser : user; *u; *t++ = *u++); + *t++ = '\0'; /* delimiting NUL */ /* copy password */ - for (u = pwd; *u; *t++ = *u++); + for (u = pwd; *u; *t++ = *u++); /* send credentials */ - if ((*responder) (stream,response,rlen)) { - if (challenge = (*challenger) (stream,&clen)) - { - fs_give ((void **) &challenge); - } - else { - ++*trial; /* can try again if necessary */ - ret = LONGT; /* check the authentication */ - } + if ((*responder) (stream,response,rlen)) { + if (challenge = (*challenger) (stream,&clen)) { + fs_give ((void **) &challenge); + } + else { + ++*trial; /* can try again if necessary */ + ret = LONGT; /* check the authentication */ + } + } + memset (response,0,rlen); /* erase credentials */ + fs_give ((void **) &response); } - memset (response,0,rlen); /* erase credentials */ - fs_give ((void **) &response); } } - else // [ Written by Kyuho Jo for AOL 2010/02/16 + else { mm_log ("Enter section for handling emtpy challenge",WARN); - if (clen) - { /* abort if challenge non-empty */ - mm_log ("auth_plain_client : Server bug: non-empty initial PLAIN challenge 2",WARN); - (*responder) (stream,NIL,0); - ret = LONGT; /* will get a BAD response back */ - } pwd[0] = NIL; /* prompt user if empty challenge */ mm_login (mb,user,pwd,*trial); @@ -155,7 +161,7 @@ long auth_plain_client (authchallenge_t challenger,authrespond_t responder, fs_give ((void **) &challenge); else { - mm_log ("Second emtpy challege ",WARN); + mm_log ("Second empty challege ",WARN); ++*trial; /* can try again if necessary */ ret = LONGT; /* check the authentication */ } @@ -164,7 +170,7 @@ long auth_plain_client (authchallenge_t challenger,authrespond_t responder, fs_give ((void **) &response); } - } // ] Written by Kyuho Jo for AOL 2010/02/16 + } memset (pwd,0,MAILTMPLEN); /* erase password */ if (!ret) *trial = 65535; /* don't retry if bad protocol */ diff --git a/imap-2007e/c-client/auth_xoauth2.c b/imap-2007e/c-client/auth_xoauth2.c new file mode 100755 index 0000000..ff5f415 --- /dev/null +++ b/imap-2007e/c-client/auth_xoauth2.c @@ -0,0 +1,111 @@ +/* ======================================================================== + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * + * ======================================================================== + */ + +/* + * Program: XOAUTH2 authenticator + * + * Author: Kyuho Jo (kyuho.jo@samsung.com) + * + * Date: 18 May 2013 + */ + +long auth_xoauth2_client (authchallenge_t challenger,authrespond_t responder, + char *service,NETMBX *mb,void *stream, + unsigned long *trial,char *user); +char *auth_xoauth2_server (authresponse_t responder,int argc,char *argv[]); + +AUTHENTICATOR auth_xoauth2 = { + AU_AUTHUSER | AU_HIDE, /* allow authuser, hidden */ + "XOAUTH2", /* authenticator name */ + NIL, /* always valid */ + auth_xoauth2_client, /* client method */ + auth_xoauth2_server, /* server method */ + NIL /* next authenticator */ +}; + +/* Client authenticator + * Accepts: challenger function + * responder function + * SASL service name + * parsed network mailbox structure + * stream argument for functions + * pointer to current trial count + * returned user name + * Returns: T if success, NIL otherwise, number of trials incremented if retry + */ + +#define MAX_RESPONSE_LENGTH 1024 +#define CHAR_SOH 0x01 + +long auth_xoauth2_client (authchallenge_t challenger,authrespond_t responder, + char *service,NETMBX *mb,void *stream, + unsigned long *trial,char *user) +{ + char *u, token[MAILTMPLEN] = { 0, }; + void *challenge; + unsigned long clen; + long ret = NIL; + + if (challenge = (*challenger) (stream,&clen)) { + fs_give ((void **) &challenge); + if (clen) { /* abort if challenge non-empty */ + MM_LOG ("auth_xoauth2_client : non-empty initial XOAUTH2 challenge",WARN); + (*responder) (stream,NIL,0); + ret = LONGT; /* will get a BAD response back */ + } + token[0] = NIL; /* prompt user if empty challenge */ + mm_login (mb, user, token, *trial); + + if (!token[0]) { /* empty challenge or user requested abort */ + (*responder) (stream, NIL, 0); + *trial = 0; /* cancel subsequent attempts */ + ret = LONGT; /* will get a BAD response back */ + } + else { + unsigned long formed_response_length = 0; + char formed_response[MAX_RESPONSE_LENGTH] = { 0, }; + + snprintf(formed_response, MAX_RESPONSE_LENGTH, "user=%s%cauth=Bearer %s%c%c", user, CHAR_SOH, token, CHAR_SOH, CHAR_SOH); + + MM_LOG(formed_response, TCPDEBUG); + + if ((*responder) (stream,formed_response,strlen(formed_response))) { + if (challenge = (*challenger) (stream,&clen)) { + /* print challenge with error code */ + MM_LOG(challenge, ERROR); + /* and send CR */ + (*responder) (stream, "", 0); + fs_give ((void **) &challenge); + ret = LONGT; + } + else { + ++*trial; + ret = LONGT; + } + } + } + memset(token,0,MAILTMPLEN); + } + return ret; +} + +/* Server authenticator + * Accepts: responder function + * argument count + * argument vector + * Returns: authenticated user name or NIL + */ +char *auth_xoauth2_server (authresponse_t responder,int argc,char *argv[]) +{ + char *ret = NIL; + return NIL; +} diff --git a/imap-2007e/c-client/auths.c b/imap-2007e/c-client/auths.c index 3e0e254..5836882 100755 --- a/imap-2007e/c-client/auths.c +++ b/imap-2007e/c-client/auths.c @@ -2,3 +2,4 @@ #include "auth_md5.c" #include "auth_pla.c" #include "auth_log.c" +#include "auth_xoauth2.c" diff --git a/imap-2007e/c-client/imap4r1.c b/imap-2007e/c-client/imap4r1.c index d9ebdc4..f41f22e 100755 --- a/imap-2007e/c-client/imap4r1.c +++ b/imap-2007e/c-client/imap4r1.c @@ -39,6 +39,7 @@ #include "c-client.h" #include "imap4r1.h" + /* Parameters */ #define IMAPLOOKAHEAD 20 /* envelope lookahead */ @@ -134,6 +135,9 @@ typedef struct imap_argument { #define MULTIAPPEND 13 #define SNLIST 14 #define MULTIAPPENDREDO 15 +#define LITERAL_CMD 16 +#define LITERAL_MSG 17 +#define LITERAL_END 18 /* Append data */ @@ -165,6 +169,9 @@ long imap_status (MAILSTREAM *stream,char *mbx,long flags); MAILSTREAM *imap_open (MAILSTREAM *stream); IMAPPARSEDREPLY *imap_rimap (MAILSTREAM *stream,char *service,NETMBX *mb, char *usr,char *tmp); +#ifdef __FEATURE_SUPPORT_IMAP_ID__ +long imap_id (MAILSTREAM *stream); +#endif /* __FEATURE_SUPPORT_IMAP_ID__ */ long imap_anon (MAILSTREAM *stream,char *tmp); long imap_auth (MAILSTREAM *stream,NETMBX *mb,char *tmp,char *usr); long imap_login (MAILSTREAM *stream,NETMBX *mb,char *pwd,char *usr); @@ -199,7 +206,10 @@ long imap_append_referral (char *mailbox,char *tmp,append_t af,void *data, APPENDDATA *map,long options); IMAPPARSEDREPLY *imap_append_single (MAILSTREAM *stream,char *mailbox, char *flags,char *date,STRING *message); - +IMAPPARSEDREPLY *imap_append_single_cmd (MAILSTREAM *stream,char *mailbox, + char *flags,char *date,STRING *message); +IMAPPARSEDREPLY *imap_append_single_msg (MAILSTREAM *stream,STRING *message); +IMAPPARSEDREPLY *imap_append_single_end (MAILSTREAM *stream); void imap_gc (MAILSTREAM *stream,long gcflags); void imap_gc_body (BODY *body); void imap_capability (MAILSTREAM *stream); @@ -212,6 +222,8 @@ IMAPPARSEDREPLY *imap_send_astring (MAILSTREAM *stream,char *tag,char **s, SIZEDTEXT *as,long wildok,char *limit); IMAPPARSEDREPLY *imap_send_literal (MAILSTREAM *stream,char *tag,char **s, STRING *st); +IMAPPARSEDREPLY *imap_send_literal_cmd (MAILSTREAM *stream,char *tag,char **s,STRING *st); +IMAPPARSEDREPLY *imap_send_literal_msg (MAILSTREAM *stream,char *tag,STRING *st); IMAPPARSEDREPLY *imap_send_spgm (MAILSTREAM *stream,char *tag,char *base, char **s,SEARCHPGM *pgm,char *limit); char *imap_send_spgm_trim (char *base,char *s,char *text); @@ -244,9 +256,14 @@ void imap_parse_flags (MAILSTREAM *stream,MESSAGECACHE *elt, unsigned long imap_parse_user_flag (MAILSTREAM *stream,char *flag); unsigned char *imap_parse_astring (MAILSTREAM *stream,unsigned char **txtptr, IMAPPARSEDREPLY *reply,unsigned long *len); +typedef enum { + IMAP_PARSE_STRING_FLAGS_NONE, + IMAP_PARSE_STRING_FLAGS_FOR_NEW_LINE, + IMAP_PARSE_STRING_FLAGS_FOR_DOUBLE_QUOTE, +} imap_parse_string_flags; unsigned char *imap_parse_string (MAILSTREAM *stream,unsigned char **txtptr, IMAPPARSEDREPLY *reply,GETS_DATA *md, - unsigned long *len,long flags); + unsigned long *len,imap_parse_string_flags flags); void imap_parse_body (GETS_DATA *md,char *seg,unsigned char **txtptr, IMAPPARSEDREPLY *reply); void imap_parse_body_structure (MAILSTREAM *stream,BODY *body, @@ -366,7 +383,8 @@ void *imap_parameters (long function,void *value) ((IMAPLOCAL *) ((MAILSTREAM *) value)->local)->cap.threader; break; case SET_FETCHLOOKAHEAD: /* must use pointer from GET_FETCHLOOKAHEAD */ - fatal ("SET_FETCHLOOKAHEAD not permitted"); + MM_FATAL("SET_FETCHLOOKAHEAD not permitted"); + return NIL; case GET_FETCHLOOKAHEAD: value = (void *) &((IMAPLOCAL *) ((MAILSTREAM *) value)->local)->lookahead; break; @@ -445,7 +463,8 @@ void *imap_parameters (long function,void *value) break; case SET_IDLETIMEOUT: - fatal ("SET_IDLETIMEOUT not permitted"); + MM_FATAL("SET_IDLETIMEOUT not permitted"); + return NIL; case GET_IDLETIMEOUT: value = (void *) IDLETIMEOUT; break; @@ -552,7 +571,7 @@ void imap_list_work (MAILSTREAM *stream,char *cmd,char *ref,char *pat, acont.type = ASTRING; acont.text = (void *) contents; imap_send (stream,cmd,args); } - else mm_log ("Scan not valid on this IMAP server",ERROR); + else MM_LOG ("Scan not valid on this IMAP server",ERROR); } else if (LEVELIMAP4 (stream)){/* easy if IMAP4 */ @@ -703,13 +722,15 @@ long imap_manage (MAILSTREAM *stream,char *mailbox,char *command,char *arg2) case 'D': code = REFDELETE; break; case 'R': code = REFRENAME; break; default: - fatal ("impossible referral command"); + MM_FATAL("impossible referral command"); + if (st != stream) mail_close (stream); + return NIL; } if ((code >= 0) && (mailbox = (*ir) (stream,LOCAL->referral,code))) ret = imap_manage (NIL,mailbox,command,(*command == 'R') ? (mailbox + strlen (mailbox) + 1) : NIL); } - mm_log (reply->text,ret ? NIL : ERROR); + MM_LOG (reply->text,ret ? NIL : ERROR); /* toss out temporary stream */ if (st != stream) mail_close (stream); } @@ -813,7 +834,7 @@ MAILSTREAM *imap_open (MAILSTREAM *stream) sprintf (tmp,"Reusing connection to %s",net_host (LOCAL->netstream)); if (LOCAL->user) sprintf (tmp + strlen (tmp),"/user=\"%s\"", LOCAL->user); - if (!stream->silent) mm_log (tmp,(long) NIL); + if (!stream->silent) MM_LOG (tmp,(long) NIL); /* unselect if now want halfopen */ if (stream->halfopen) imap_send (stream,"UNSELECT",NIL); } @@ -879,7 +900,7 @@ MAILSTREAM *imap_open (MAILSTREAM *stream) /* make sure greeting is good */ if (!reply || strcmp (reply->tag,"*") || (strcmp (reply->key,"OK") && strcmp (reply->key,"PREAUTH"))) { - if (reply) mm_log (reply->text,ERROR); + if (reply) MM_LOG (reply->text,ERROR); return NIL; /* lost during greeting */ } @@ -905,7 +926,7 @@ MAILSTREAM *imap_open (MAILSTREAM *stream) if (LOCAL->netstream) imap_capability (stream); } else if (mb.tlsflag) { /* user specified /tls but can't do it */ - mm_log ("Unable to negotiate TLS with this server",ERROR); + MM_LOG ("Unable to negotiate TLS with this server",ERROR); return NIL; } if (LOCAL->netstream) { /* still in the land of the living? */ @@ -916,10 +937,20 @@ MAILSTREAM *imap_open (MAILSTREAM *stream) net_host (LOCAL->netstream),NETMAXHOST-1); mb.host[NETMAXHOST-1] = '\0'; } + + +#ifdef __FEATURE_SUPPORT_IMAP_ID__ + /* Process for IMAP ID */ + if (LOCAL->cap.id) { + MM_LOG ("This server requires IMAP ID", NIL); + imap_id(stream); + } +#endif /* __FEATURE_SUPPORT_IMAP_ID__ */ + /* need new capabilities after login */ LOCAL->gotcapability = NIL; if (!(stream->anonymous ? imap_anon (stream,tmp) : - (LOCAL->cap.auth ? imap_auth (stream,&mb,tmp,usr) : + ((LOCAL->cap.auth && (mb.auth_method > AUTH_METHOD_NONE))? imap_auth (stream,&mb,tmp,usr) : imap_login (stream,&mb,tmp,usr)))) { /* failed, is there a referral? */ if (ir && LOCAL->referral && @@ -990,7 +1021,7 @@ MAILSTREAM *imap_open (MAILSTREAM *stream) "EXAMINE": "SELECT",args))) { strcat (tmp,mb.mailbox);/* mailbox name */ if (!stream->nmsgs && !stream->silent) - mm_log ("Mailbox is empty",(long) NIL); + MM_LOG ("Mailbox is empty",(long) NIL); /* note if an INBOX or not */ stream->inbox = !compare_cstring (mb.mailbox,"INBOX"); } @@ -1002,7 +1033,7 @@ MAILSTREAM *imap_open (MAILSTREAM *stream) return imap_open (stream); } else { - mm_log (reply->text,ERROR); + MM_LOG (reply->text,ERROR); if (imap_closeonerror) return NIL; stream->halfopen = T; /* let him keep it half-open */ } @@ -1062,6 +1093,41 @@ IMAPPARSEDREPLY *imap_rimap (MAILSTREAM *stream,char *service,NETMBX *mb, } return NIL; } + +#ifdef __FEATURE_SUPPORT_IMAP_ID__ +long imap_id (MAILSTREAM *stream) +{ + IMAPPARSEDREPLY *reply; + int ret = NIL; + char *imap_id_tag_string = NULL; + IMAPARG *args[2]; + IMAPARG id_tag; + + if(stream == NULL) + return ret; + + mm_imap_id (&imap_id_tag_string); + + if(imap_id_tag_string != NULL) { + if(stream->debug) + mm_dlog(imap_id_tag_string); + + id_tag.type = ASTRING; + id_tag.text = (void *) imap_id_tag_string; + args[0] = &id_tag; args[1] = NIL; + /* send "ID tag" */ + if (imap_OK (stream,reply = imap_send (stream,"ID",args))) + ret = LONGT; /* success */ + else { + MM_LOG ("ID failed",ERROR); + } + free(imap_id_tag_string); + } + + return ret; +} +#endif /* __FEATURE_SUPPORT_IMAP_ID__ */ + /* IMAP log in as anonymous * Accepts: stream to authenticate @@ -1081,7 +1147,7 @@ long imap_anon (MAILSTREAM *stream,char *tmp) /* build command */ sprintf (tmp,"%s AUTHENTICATE ANONYMOUS",tag); if (!imap_soutr (stream,tmp)) { - mm_log (broken,ERROR); + MM_LOG (broken,ERROR); return NIL; } if (imap_challenge (stream,&i)) imap_response (stream,s,strlen (s)); @@ -1105,7 +1171,7 @@ long imap_anon (MAILSTREAM *stream,char *tmp) } /* success if reply OK */ if (imap_OK (stream,reply)) return T; - mm_log (reply->text,ERROR); + MM_LOG (reply->text,ERROR); return NIL; } @@ -1127,10 +1193,17 @@ long imap_auth (MAILSTREAM *stream,NETMBX *mb,char *tmp,char *usr) IMAPPARSEDREPLY *reply; for (ua = LOCAL->cap.auth, LOCAL->saslcancel = NIL; LOCAL->netstream && ua && (at = mail_lookup_auth (find_rightmost_bit (&ua) + 1));) { + + if (mb->auth_method != AUTH_METHOD_XOAUTH2 && strstr(at->name, auth_xoauth2.name) ) { + sprintf (tmp,"auth_method is not AUTH_METHOD_XOAUTH2. So skipped XOAUTH authenticator."); + MM_LOG (tmp,NIL); + continue; + } + if (lsterr) { /* previous authenticator failed? */ sprintf (tmp,"Retrying using %s authentication after %.80s", at->name,lsterr); - mm_log (tmp,NIL); + MM_LOG (tmp,NIL); fs_give ((void **) &lsterr); } trial = 0; /* initial trial count */ @@ -1138,7 +1211,7 @@ long imap_auth (MAILSTREAM *stream,NETMBX *mb,char *tmp,char *usr) do { /* gensym a new tag */ if (lsterr) { /* previous attempt with this one failed? */ sprintf (tmp,"Retrying %s authentication after %.80s",at->name,lsterr); - mm_log (tmp,WARN); + MM_LOG (tmp,WARN); fs_give ((void **) &lsterr); } LOCAL->saslcancel = NIL; @@ -1161,7 +1234,7 @@ long imap_auth (MAILSTREAM *stream,NETMBX *mb,char *tmp,char *usr) /* good if SASL ok and success response */ if (ok && imap_OK (stream,reply)) return T; if (!trial) { /* if main program requested cancellation */ - mm_log ("IMAP Authentication cancelled",ERROR); + MM_LOG ("IMAP Authentication cancelled",ERROR); return NIL; } /* no error if protocol-initiated cancel */ @@ -1174,7 +1247,7 @@ long imap_auth (MAILSTREAM *stream,NETMBX *mb,char *tmp,char *usr) if (lsterr) { /* previous authenticator failed? */ if (!LOCAL->saslcancel) { /* don't do this if a cancel */ sprintf (tmp,"Can not authenticate to IMAP server: %.80s",lsterr); - mm_log (tmp,ERROR); + MM_LOG (tmp,ERROR); } fs_give ((void **) &lsterr); } @@ -1197,12 +1270,12 @@ long imap_login (MAILSTREAM *stream,NETMBX *mb,char *pwd,char *usr) IMAPARG ausr,apwd; long ret = NIL; if (stream->secure) /* never do LOGIN if want security */ - mm_log ("Can't do secure authentication with this server",ERROR); + MM_LOG ("Can't do secure authentication with this server",ERROR); /* never do LOGIN if server disabled it */ else if (LOCAL->cap.logindisabled) - mm_log ("Server disables LOGIN, no recognized SASL authenticator",ERROR); + MM_LOG ("Server disables LOGIN, no recognized SASL authenticator",ERROR); else if (mb->authuser[0]) /* never do LOGIN with /authuser */ - mm_log ("Can't do /authuser with this server",ERROR); + MM_LOG ("Can't do /authuser with this server",ERROR); else { /* OK to try login */ ausr.type = apwd.type = ASTRING; ausr.text = (void *) usr; @@ -1217,14 +1290,18 @@ long imap_login (MAILSTREAM *stream,NETMBX *mb,char *pwd,char *usr) if (imap_OK (stream,reply = imap_send (stream,"LOGIN",args))) ret = LONGT; /* success */ else { - mm_log (reply->text,WARN); + MM_LOG (reply->text,WARN); + if (reply->text && strstr(reply->text, "AUTHENTICATIONFAILED")) { + MM_LOG ("Can not authenticate",ERROR); + break; + } if (!LOCAL->referral && (trial == imap_maxlogintrials)) - mm_log ("Too many login failures",ERROR); + MM_LOG ("Too many login failures",ERROR); } LOCAL->sensitive = NIL; /* unhide */ } /* user refused to give password */ - else mm_log ("Login aborted",ERROR); + else MM_LOG ("Login aborted",ERROR); } while (!ret && pwd[0] && (trial < imap_maxlogintrials) && LOCAL->netstream && !LOCAL->byeseen && !LOCAL->referral); } @@ -1255,7 +1332,7 @@ void *imap_challenge (void *s,unsigned long *len) strlen (reply->text),len))) { sprintf (tmp,"IMAP SERVER BUG (invalid challenge): %.80s", (char *) reply->text); - mm_log (tmp,ERROR); + MM_LOG (tmp,ERROR); } return ret; } @@ -1309,7 +1386,7 @@ void imap_close (MAILSTREAM *stream,long options) imap_send (stream,LEVELIMAP4 (stream) ? "CLOSE" : "EXPUNGE",NIL); if (LOCAL->netstream && !imap_OK (stream,reply = imap_send (stream,"LOGOUT",NIL))) - mm_log (reply->text,WARN); + MM_LOG (reply->text,WARN); } /* close NET connection if still open */ if (LOCAL->netstream) net_close (LOCAL->netstream); @@ -1354,7 +1431,7 @@ void imap_fast (MAILSTREAM *stream,char *sequence,long flags) #else IMAPPARSEDREPLY *reply = imap_fetch (stream,sequence,flags & FT_UID); #endif - if (!imap_OK (stream,reply)) mm_log (reply->text,ERROR); + if (!imap_OK (stream,reply)) MM_LOG (reply->text,ERROR); } @@ -1375,7 +1452,7 @@ void imap_flags (MAILSTREAM *stream,char *sequence,long flags) aatt.type = ATOM; aatt.text = (void *) "FLAGS"; args[0] = &aseq; args[1] = &aatt; args[2] = NIL; if (!imap_OK (stream,reply = imap_send (stream,cmd,args))) - mm_log (reply->text,ERROR); + MM_LOG (reply->text,ERROR); } /* IMAP fetch overview @@ -1484,7 +1561,7 @@ ENVELOPE *imap_structure (MAILSTREAM *stream,unsigned long msgno,BODY **body, if (!imap_OK (stream,reply = imap_fetch (stream,seq,FT_NEEDENV + (body ? FT_NEEDBODY : NIL) + (flags & (FT_UID + FT_NOHDRS))))) - mm_log (reply->text,ERROR); + MM_LOG (reply->text,ERROR); /* now hunt for this UID */ for (i = 1; i <= stream->nmsgs; i++) if ((elt = mail_elt (stream,i))->private.uid == msgno) { @@ -1611,9 +1688,9 @@ ENVELOPE *imap_structure (MAILSTREAM *stream,unsigned long msgno,BODY **body, if (imap_OK (stream,reply = imap_send (stream,"FETCH",args))) /* doesn't have body capabilities */ LOCAL->cap.imap2bis = NIL; - else mm_log (reply->text,ERROR); + else MM_LOG (reply->text,ERROR); } - else mm_log (reply->text,ERROR); + else MM_LOG (reply->text,ERROR); } } } @@ -1825,7 +1902,7 @@ long imap_msgdata (MAILSTREAM *stream,unsigned long msgno,char *section, if (noextend) { sprintf (tmp,"[NOTIMAP4REV1] IMAP%s server can't do extended body fetch", noextend); - mm_log (tmp,ERROR); + MM_LOG (tmp,ERROR); return NIL; /* can't do anything close either */ } if (nopartial) { @@ -1843,7 +1920,7 @@ long imap_msgdata (MAILSTREAM *stream,unsigned long msgno,char *section, if ((t = nopeek) || (t = nononpeek)) { /* get most recent \Seen setting */ if (!imap_OK (stream,reply = imap_send (stream,cmd,auxargs))) - mm_log (reply->text,WARN); + MM_LOG (reply->text,WARN); /* note current setting of \Seen flag */ if (!(i = mail_elt (stream,msgno)->seen)) { sprintf (tmp,nopeek ? /* only babble if \Seen not set */ @@ -1853,7 +1930,7 @@ long imap_msgdata (MAILSTREAM *stream,unsigned long msgno,char *section, } /* send the fetch command */ if (!imap_OK (stream,reply = imap_send (stream,cmd,args))) { - mm_log (reply->text,ERROR); + MM_LOG (reply->text,ERROR); return NIL; /* failure */ } /* send command if need to reset \Seen */ @@ -1862,11 +1939,11 @@ long imap_msgdata (MAILSTREAM *stream,unsigned long msgno,char *section, ((nononpeek && !mail_elt (stream,msgno)->seen) && (aflg.text = "+FLAGS \\Seen"))) && !imap_OK (stream,reply = imap_send (stream,"STORE",auxargs))) - mm_log (reply->text,WARN); + MM_LOG (reply->text,WARN); } /* simple case if traditional behavior */ else if (!imap_OK (stream,reply = imap_send (stream,cmd,args))) { - mm_log (reply->text,ERROR); + MM_LOG (reply->text,ERROR); return NIL; /* failure */ } /* simulate BODY[1] return for RFC 1064/1176 */ @@ -1919,7 +1996,7 @@ unsigned long imap_uid (MAILSTREAM *stream,unsigned long msgno) } /* send "FETCH msgno UID" */ if (!imap_OK (stream,reply = imap_send (stream,"FETCH",args))) - mm_log (reply->text,ERROR); + MM_LOG (reply->text,ERROR); } return elt->private.uid; /* return our UID now */ } @@ -1955,7 +2032,7 @@ unsigned long imap_msgno (MAILSTREAM *stream,unsigned long uid) sprintf (seq,"%lu",uid); /* send "UID FETCH uid UID" */ if (!imap_OK (stream,reply = imap_send (stream,"UID FETCH",args))) - mm_log (reply->text,ERROR); + MM_LOG (reply->text,ERROR); if (LOCAL->lastuid.uid) { /* got any results from FETCH? */ if ((LOCAL->lastuid.uid == uid) && /* what, me paranoid? */ @@ -1996,7 +2073,7 @@ void imap_flag (MAILSTREAM *stream,char *sequence,char *flag,long flags) args[0] = &aseq; args[1] = &ascm; args[2] = &aflg; args[3] = NIL; /* send "STORE sequence +Flags flag" */ if (!imap_OK (stream,reply = imap_send (stream,cmd,args))) - mm_log (reply->text,ERROR); + MM_LOG (reply->text,ERROR); } /* IMAP search for messages @@ -2044,7 +2121,8 @@ long imap_search (MAILSTREAM *stream,char *charset,SEARCHPGM *pgm,long flags) pgm->reply_to || pgm->in_reply_to || pgm->message_id || pgm->newsgroups || pgm->followup_to || pgm->references)) { if (!mail_search_default (stream,NIL,pgm,flags | SE_NOSERVER)) - fatal ("impossible mail_search_default() failure"); + MM_FATAL("impossible mail_search_default() failure"); + return NIL; } else { /* do server-based SEARCH */ @@ -2089,7 +2167,7 @@ long imap_search (MAILSTREAM *stream,char *charset,SEARCHPGM *pgm,long flags) return NIL; } else if (!imap_OK (stream,reply)) { - mm_log (reply->text,ERROR); + MM_LOG (reply->text,ERROR); return NIL; } } @@ -2121,11 +2199,11 @@ long imap_search (MAILSTREAM *stream,char *charset,SEARCHPGM *pgm,long flags) } if (LOCAL->tmp[0]) { /* anything to pre-fetch? */ /* pre-fetch envelopes for the first imap_prefetch number of messages */ - if (!imap_OK (stream,reply = - imap_fetch (stream,s = cpystr (LOCAL->tmp),FT_NEEDENV + + if (!imap_OK (stream, reply = + imap_fetch (stream,s = cpystr (LOCAL->tmp),FT_NEEDENV + ((flags & SE_NOHDRS) ? FT_NOHDRS : NIL) + ((flags & SE_NEEDBODY) ? FT_NEEDBODY : NIL)))) - mm_log (reply->text,ERROR); + MM_LOG (reply->text,ERROR); fs_give ((void **) &s); /* flush copy of sequence */ } } @@ -2204,7 +2282,7 @@ unsigned long *imap_sort (MAILSTREAM *stream,char *charset,SEARCHPGM *spg, ret = LOCAL->sortdata; LOCAL->sortdata = NIL; /* mail program is responsible for flushing */ } - else mm_log (reply->text,ERROR); + else MM_LOG (reply->text,ERROR); } /* not much can do if short caching */ @@ -2366,7 +2444,7 @@ THREADNODE *imap_thread_work (MAILSTREAM *stream,char *type,char *charset, ret = LOCAL->threaddata; LOCAL->threaddata = NIL; /* mail program is responsible for flushing */ } - else mm_log (reply->text,ERROR); + else MM_LOG (reply->text,ERROR); return ret; } @@ -2390,7 +2468,7 @@ void imap_check (MAILSTREAM *stream) { /* send "CHECK" */ IMAPPARSEDREPLY *reply = imap_send (stream,"CHECK",NIL); - mm_log (reply->text,imap_OK (stream,reply) ? (long) NIL : ERROR); + MM_LOG (reply->text,imap_OK (stream,reply) ? (long) NIL : ERROR); } /* IMAP expunge mailbox @@ -2412,7 +2490,7 @@ long imap_expunge (MAILSTREAM *stream,char *sequence,long options) args[0] = &aseq; args[1] = NIL; ret = imap_OK (stream,reply = imap_send (stream,"UID EXPUNGE",args)); } - else mm_log ("[NOTUIDPLUS] Can't do UID EXPUNGE with this server",ERROR); + else MM_LOG ("[NOTUIDPLUS] Can't do UID EXPUNGE with this server",ERROR); } /* otherwise try to make into UID EXPUNGE */ else if (mail_sequence (stream,sequence)) { @@ -2432,7 +2510,7 @@ long imap_expunge (MAILSTREAM *stream,char *sequence,long options) s += strlen (s); /* point at end of string */ } if ((s - t) > (IMAPTMPLEN - 50)) { - mm_log ("Excessively complex sequence",ERROR); + MM_LOG ("Excessively complex sequence",ERROR); fs_give ((void **) &s); //Prevent fix 10/05/2010 [santosh.br] return NIL; } @@ -2444,7 +2522,7 @@ long imap_expunge (MAILSTREAM *stream,char *sequence,long options) } /* ordinary EXPUNGE */ else ret = imap_OK (stream,reply = imap_send (stream,"EXPUNGE",NIL)); - if (reply) mm_log (reply->text,ret ? (long) NIL : ERROR); + if (reply) MM_LOG (reply->text,ret ? (long) NIL : ERROR); return ret; } @@ -2486,7 +2564,7 @@ long imap_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long flags) (s = (*ir) (stream,LOCAL->referral,REFCOPY))) ret = (*pc) (stream,sequence,s,flags | (stream->debug ? CP_DEBUG : NIL)); /* otherwise issue error message */ - else mm_log (reply->text,ERROR); + else MM_LOG (reply->text,ERROR); return ret; } @@ -2500,57 +2578,85 @@ long imap_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long flags) long imap_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data) { - MAILSTREAM *st = stream; - IMAPARG *args[3],ambx,amap; - IMAPPARSEDREPLY *reply = NIL; - APPENDDATA map; - char tmp[MAILTMPLEN]; - long debug = stream ? stream->debug : NIL; - long ret = NIL; - imapreferral_t ir = - (imapreferral_t) mail_parameters (stream,GET_IMAPREFERRAL,NIL); - /* mailbox must be good */ - if (mail_valid_net (mailbox,&imapdriver,NIL,tmp)) { - /* create a stream if given one no good */ - if ((stream && LOCAL && LOCAL->netstream) || - (stream = mail_open (NIL,mailbox,OP_HALFOPEN|OP_SILENT | - (debug ? OP_DEBUG : NIL)))) { - /* note mailbox in case APPENDUID */ - LOCAL->appendmailbox = mailbox; - /* use multi-append? */ - if (LEVELMULTIAPPEND (stream)) { - ambx.type = ASTRING; ambx.text = (void *) tmp; - amap.type = MULTIAPPEND; amap.text = (void *) ↦ - map.af = af; map.data = data; - args[0] = &ambx; args[1] = &amap; args[2] = NIL; + MAILSTREAM *st = stream; + IMAPARG *args[3],ambx,amap; + IMAPPARSEDREPLY *reply = NIL; + APPENDDATA map; + char tmp[MAILTMPLEN]; + long debug = stream ? stream->debug : NIL; + long ret = NIL; + imapreferral_t ir = (imapreferral_t) mail_parameters (stream,GET_IMAPREFERRAL,NIL); + + /* mailbox must be good */ + if (mail_valid_net (mailbox,&imapdriver,NIL,tmp)) { + /* create a stream if given one no good */ + if ((stream && LOCAL && LOCAL->netstream) || (stream = mail_open (NIL,mailbox,OP_HALFOPEN|OP_SILENT | (debug ? OP_DEBUG : NIL)))) { + /* note mailbox in case APPENDUID */ + LOCAL->appendmailbox = mailbox; + + /* use multi-append? */ + if (LEVELMULTIAPPEND (stream)) { + ambx.type = ASTRING; + ambx.text = (void *) tmp; + amap.type = MULTIAPPEND; + amap.text = (void *) ↦ + map.af = af; + map.data = data; + args[0] = &ambx; + args[1] = &amap; + args[2] = NIL; + /* success if OK */ - ret = imap_OK (stream,reply = imap_send (stream,"APPEND",args)); - LOCAL->appendmailbox = NIL; - } - /* do succession of single appends */ - else while ((*af) (stream,data,&map.flags,&map.date,&map.message) && - map.message && - (ret = imap_OK (stream,reply = - imap_append_single (stream,tmp,map.flags, - map.date,map.message)))); - LOCAL->appendmailbox = NIL; - /* don't do referrals if success or no reply */ - if (ret || !reply) mailbox = NIL; - /* otherwise generate referral */ - else if (!(mailbox = (ir && LOCAL->referral) ? - (*ir) (stream,LOCAL->referral,REFAPPEND) : NIL)) - mm_log (reply->text,ERROR); - /* close temporary stream */ - if (st != stream) stream = mail_close (stream); - if (mailbox) /* chase referral if any */ - ret = imap_append_referral (mailbox,tmp,af,data,map.flags,map.date, - map.message,&map,debug); - } - else mm_log ("Can't access server for append",ERROR); - } - return ret; /* return */ + ret = imap_OK (stream,reply = imap_send (stream,"APPEND",args)); + LOCAL->appendmailbox = NIL; + } + + /* do succession of single appends */ + else { + int type = 0; + if ((type = (*af) (stream,data,&map.flags,&map.date,&map.message))) { + + if (type == 1) { + reply = imap_append_single (stream,tmp,map.flags,map.date,map.message); + ret = imap_OK (stream,reply); + } else if (type == 2) { + reply = imap_append_single_cmd (stream,tmp,map.flags,map.date,map.message); + if (strncmp (reply->tag,"+", 1) == 0) { + ret = 1; + } else + ret = 0; + } else if (type == 3) { + reply = imap_append_single_msg (stream,map.message); + if (reply == NIL) ret = 1; + else ret = imap_OK (stream,reply); + } else if (type == 4) { + reply = imap_append_single_end (stream); + ret = imap_OK (stream,reply); + } + } + } + LOCAL->appendmailbox = NIL; + + /* don't do referrals if success or no reply */ + if (ret || !reply) mailbox = NIL; + + /* otherwise generate referral */ + else if (!(mailbox = (ir && LOCAL->referral) ? (*ir) (stream,LOCAL->referral,REFAPPEND) : NIL)) + MM_LOG (reply->text,ERROR); + + /* close temporary stream */ + if (st != stream) stream = mail_close (stream); + + if (mailbox) /* chase referral if any */ + ret = imap_append_referral (mailbox,tmp,af,data,map.flags,map.date,map.message,&map,debug); + } + else + MM_LOG ("Can't access server for append",ERROR); + } + + return ret; /* return */ } - + /* IMAP mail append message referral retry * Accepts: destination mailbox * temporary buffer @@ -2578,7 +2684,7 @@ long imap_append_referral (char *mailbox,char *tmp,append_t af,void *data, if (!(stream = mail_open (NIL,mailbox,OP_HALFOPEN|OP_SILENT | (options ? OP_DEBUG : NIL)))) { sprintf (tmp,"Can't access referral server: %.80s",mailbox); - mm_log (tmp,ERROR); + MM_LOG (tmp,ERROR); return NIL; } /* got referral server, use multi-append? */ @@ -2602,7 +2708,7 @@ long imap_append_referral (char *mailbox,char *tmp,append_t af,void *data, /* generate error if no nested referral */ if (!(mailbox = (ir && LOCAL->referral) ? (*ir) (stream,LOCAL->referral,REFAPPEND) : NIL)) - mm_log (reply->text,ERROR); + MM_LOG (reply->text,ERROR); mail_close (stream); /* close previous referral stream */ } return NIL; /* bogus mailbox */ @@ -2620,43 +2726,141 @@ long imap_append_referral (char *mailbox,char *tmp,append_t af,void *data, IMAPPARSEDREPLY *imap_append_single (MAILSTREAM *stream,char *mailbox, char *flags,char *date,STRING *message) { - MESSAGECACHE elt; - IMAPARG *args[5],ambx,aflg,adat,amsg; - IMAPPARSEDREPLY *reply; - char tmp[MAILTMPLEN]; - int i; - ambx.type = ASTRING; ambx.text = (void *) mailbox; - args[i = 0] = &ambx; - if (flags) { - aflg.type = FLAGS; aflg.text = (void *) flags; - args[++i] = &aflg; - } - if (date) { /* ensure date in INTERNALDATE format */ - if (!mail_parse_date (&elt,date)) { - /* flush previous reply */ - if (LOCAL->reply.line) fs_give ((void **) &LOCAL->reply.line); - /* build new fake reply */ - LOCAL->reply.tag = LOCAL->reply.line = cpystr ("*"); - LOCAL->reply.key = "BAD"; - LOCAL->reply.text = "Bad date in append"; - return &LOCAL->reply; - } - adat.type = ASTRING; - adat.text = (void *) (date = mail_date (tmp,&elt)); - args[++i] = &adat; - } - amsg.type = LITERAL; amsg.text = (void *) message; - args[++i] = &amsg; - args[++i] = NIL; - /* easy if IMAP4[rev1] */ - if (LEVELIMAP4 (stream)) reply = imap_send (stream,"APPEND",args); - else { /* try the IMAP2bis way */ - args[1] = &amsg; args[2] = NIL; - reply = imap_send (stream,"APPEND",args); - } - return reply; + MESSAGECACHE elt; + IMAPARG *args[5],ambx,aflg,adat,amsg; + IMAPPARSEDREPLY *reply; + char tmp[MAILTMPLEN]; + int i; + ambx.type = ASTRING; ambx.text = (void *) mailbox; + args[i = 0] = &ambx; + + if (flags) { + aflg.type = FLAGS; aflg.text = (void *) flags; + args[++i] = &aflg; + } + + if (date) { /* ensure date in INTERNALDATE format */ + if (!mail_parse_date (&elt,date)) { + /* flush previous reply */ + if (LOCAL->reply.line) fs_give ((void **) &LOCAL->reply.line); + /* build new fake reply */ + LOCAL->reply.tag = LOCAL->reply.line = cpystr ("*"); + LOCAL->reply.key = "BAD"; + LOCAL->reply.text = "Bad date in append"; + return &LOCAL->reply; + } + adat.type = ASTRING; + adat.text = (void *) (date = mail_date (tmp,&elt)); + args[++i] = &adat; + } + + amsg.type = LITERAL; amsg.text = (void *) message; + args[++i] = &amsg; + args[++i] = NIL; + + /* easy if IMAP4[rev1] */ + if (LEVELIMAP4 (stream)) reply = imap_send (stream,"APPEND",args); + else { /* try the IMAP2bis way */ + args[1] = &amsg; args[2] = NIL; + reply = imap_send (stream,"APPEND",args); + } + + return reply; } - + +IMAPPARSEDREPLY *imap_append_single_cmd (MAILSTREAM *stream,char *mailbox, + char *flags,char *date,STRING *message) +{ + MESSAGECACHE elt; + IMAPARG *args[5],ambx,aflg,adat,amsg; + IMAPPARSEDREPLY *reply; + char tmp[MAILTMPLEN]; + int i; + ambx.type = ASTRING; ambx.text = (void *) mailbox; + args[i = 0] = &ambx; + + if (flags) { + aflg.type = FLAGS; aflg.text = (void *) flags; + args[++i] = &aflg; + } + + if (date) { /* ensure date in INTERNALDATE format */ + if (!mail_parse_date (&elt,date)) { + /* flush previous reply */ + if (LOCAL->reply.line) fs_give ((void **) &LOCAL->reply.line); + /* build new fake reply */ + LOCAL->reply.tag = LOCAL->reply.line = cpystr ("*"); + LOCAL->reply.key = "BAD"; + LOCAL->reply.text = "Bad date in append"; + return &LOCAL->reply; + } + adat.type = ASTRING; + adat.text = (void *) (date = mail_date (tmp,&elt)); + args[++i] = &adat; + } + + amsg.type = LITERAL_CMD; amsg.text = (void *) message; + args[++i] = &amsg; + args[++i] = NIL; + + /* easy if IMAP4[rev1] */ + if (LEVELIMAP4 (stream)) reply = imap_send (stream,"APPEND",args); + else { /* try the IMAP2bis way */ + args[1] = &amsg; args[2] = NIL; + reply = imap_send (stream,"APPEND",args); + } + + return reply; +} + +IMAPPARSEDREPLY *imap_append_single_msg (MAILSTREAM *stream,STRING *message) +{ + MESSAGECACHE elt; + IMAPARG *args[5],ambx,aflg,adat,amsg; + IMAPPARSEDREPLY *reply; + char tmp[MAILTMPLEN]; + int i=0; + + amsg.type = LITERAL_MSG; amsg.text = (void *) message; + args[i] = &amsg; + args[++i] = NIL; + + /* easy if IMAP4[rev1] */ + if (LEVELIMAP4 (stream)) { + reply = imap_send (stream,"APPEND",args); + } + else { /* try the IMAP2bis way */ + args[1] = &amsg; args[2] = NIL; + reply = imap_send (stream,"APPEND",args); + } + + return reply; +} + +IMAPPARSEDREPLY *imap_append_single_end (MAILSTREAM *stream) +{ + MESSAGECACHE elt; + IMAPARG *args[5],ambx,aflg,adat,amsg; + IMAPPARSEDREPLY *reply; + char tmp[MAILTMPLEN]; + int i=0; + + amsg.type = LITERAL_END; amsg.text = NULL; + args[i] = &amsg; + args[++i] = NIL; + + /* easy if IMAP4[rev1] */ + if (LEVELIMAP4 (stream)) { + reply = imap_send (stream,"APPEND",args); + } + else { /* try the IMAP2bis way */ + args[1] = &amsg; args[2] = NIL; + reply = imap_send (stream,"APPEND",args); + } + + return reply; +} + /* IMAP garbage collect stream * Accepts: Mail stream * garbage collection flags @@ -2834,9 +3038,9 @@ long imap_acl_work (MAILSTREAM *stream,char *command,IMAPARG *args[]) IMAPPARSEDREPLY *reply; if (imap_OK (stream,reply = imap_send (stream,command,args))) ret = LONGT; - else mm_log (reply->text,ERROR); + else MM_LOG (reply->text,ERROR); } - else mm_log ("ACL not available on this IMAP server",ERROR); + else MM_LOG ("ACL not available on this IMAP server",ERROR); return ret; } @@ -2858,9 +3062,9 @@ long imap_setquota (MAILSTREAM *stream,char *qroot,STRINGLIST *limits) args[0] = &aqrt; args[1] = &alim; args[2] = NIL; if (imap_OK (stream,reply = imap_send (stream,"SETQUOTA",args))) ret = LONGT; - else mm_log (reply->text,ERROR); + else MM_LOG (reply->text,ERROR); } - else mm_log ("Quota not available on this IMAP server",ERROR); + else MM_LOG ("Quota not available on this IMAP server",ERROR); return ret; } @@ -2880,9 +3084,9 @@ long imap_getquota (MAILSTREAM *stream,char *qroot) args[0] = &aqrt; args[1] = NIL; if (imap_OK (stream,reply = imap_send (stream,"GETQUOTA",args))) ret = LONGT; - else mm_log (reply->text,ERROR); + else MM_LOG (reply->text,ERROR); } - else mm_log ("Quota not available on this IMAP server",ERROR); + else MM_LOG ("Quota not available on this IMAP server",ERROR); return ret; } @@ -2903,11 +3107,78 @@ long imap_getquotaroot (MAILSTREAM *stream,char *mailbox) args[0] = &ambx; args[1] = NIL; if (imap_OK (stream,reply = imap_send (stream,"GETQUOTAROOT",args))) ret = LONGT; - else mm_log (reply->text,ERROR); + else MM_LOG (reply->text,ERROR); } - else mm_log ("Quota not available on this IMAP server",ERROR); + else MM_LOG ("Quota not available on this IMAP server",ERROR); return ret; } + +#ifdef __FEATURE_METADATA_SUPPORT__ +/* RFC5464 : IMAP METADATA Extension */ +char *imap_getmetadata (MAILSTREAM *stream, char *mailbox, char *entry) +{ + char *ret = NIL; + + if (LEVELMETADATA (stream)) { + IMAPPARSEDREPLY *reply = NULL; + IMAPARG *args[3] = { NIL, }; + IMAPARG arg_mailbox, arg_entry; + + arg_mailbox.type = ASTRING; + arg_mailbox.text = (void *) mailbox; + + arg_entry.type = ASTRING; + arg_entry.text = (void *) entry; + + args[0] = &arg_mailbox; + args[1] = &arg_entry; + args[2] = NIL; + + if (imap_OK (stream,reply = imap_send (stream, "GETMETADATA", args))) + ret = LONGT; + else + MM_LOG (reply->text, ERROR); + } + else + MM_LOG ("METADATA not available on this IMAP server", ERROR); + + return ret; +} + +long imap_setmetadata (MAILSTREAM *stream, char *mailbox, char *entry, char *value) +{ + long ret = NIL; + + if (LEVELMETADATA (stream)) { + IMAPPARSEDREPLY *reply = NULL; + IMAPARG *args[4] = { NIL, }; + IMAPARG arg_mailbox, arg_entry, arg_value; + + arg_mailbox.type = ASTRING; + arg_mailbox.text = (void *) mailbox; + + arg_entry.type = ASTRING; + arg_entry.text = (void *) entry; + + arg_value.type = ASTRING; + arg_value.text = (void *) value; + + args[0] = &arg_mailbox; + args[1] = &arg_entry; + args[2] = &arg_value; + args[3] = NIL; + + if (imap_OK (stream,reply = imap_send (stream, "SETMETADATA", args))) + ret = LONGT; + else + MM_LOG (reply->text, ERROR); + } + else + MM_LOG ("SETMETADATA not available on this IMAP server", ERROR); + + return ret; +} +#endif /* __FEATURE_METADATA_SUPPORT__ */ /* Internal routines */ @@ -2918,243 +3189,300 @@ long imap_getquotaroot (MAILSTREAM *stream,char *mailbox) * argument list * Returns: parsed reply */ - +static g_append_cmd_tag[10] = {0,}; #define CMDBASE LOCAL->tmp /* command base */ IMAPPARSEDREPLY *imap_send (MAILSTREAM *stream,char *cmd,IMAPARG *args[]) { - IMAPPARSEDREPLY *reply; - IMAPARG *arg,**arglst; - SORTPGM *spg; - STRINGLIST *list; - SIZEDTEXT st; - APPENDDATA *map; - sendcommand_t sc = (sendcommand_t) mail_parameters (NIL,GET_SENDCOMMAND,NIL); - size_t i; - void *a; - char c,*s,*t,tag[10]; - stream->unhealthy = NIL; /* make stream healthy again */ - /* gensym a new tag */ - sprintf (tag,"%08lx",0xffffffff & (stream->gensym++)); - if (!LOCAL->netstream) /* make sure have a session */ - return imap_fake (stream,tag,"[CLOSED] IMAP connection lost"); - mail_lock (stream); /* lock up the stream */ - if (sc) /* tell client sending a command */ - (*sc) (stream,cmd,((compare_cstring (cmd,"FETCH") && - compare_cstring (cmd,"STORE") && - compare_cstring (cmd,"SEARCH")) ? - NIL : SC_EXPUNGEDEFERRED)); - /* ignore referral from previous command */ - if (LOCAL->referral) fs_give ((void **) &LOCAL->referral); - sprintf (CMDBASE,"%s %s",tag,cmd); - s = CMDBASE + strlen (CMDBASE); - if (arglst = args) while (arg = *arglst++) { - *s++ = ' '; /* delimit argument with space */ - switch (arg->type) { - case ATOM: /* atom */ - for (t = (char *) arg->text; *t; *s++ = *t++); - break; - case NUMBER: /* number */ - sprintf (s,"%lu",(unsigned long) arg->text); - s += strlen (s); - break; - case FLAGS: /* flag list as a single string */ - if (*(t = (char *) arg->text) != '(') { - *s++ = '('; /* wrap parens around string */ - while (*t) *s++ = *t++; - *s++ = ')'; /* wrap parens around string */ - } - else while (*t) *s++ = *t++; - break; - case ASTRING: /* atom or string, must be literal? */ - st.size = strlen ((char *) (st.data = (unsigned char *) arg->text)); - if (reply = imap_send_astring (stream,tag,&s,&st,NIL,CMDBASE+MAXCOMMAND)) - return reply; - break; - case LITERAL: /* literal, as a stringstruct */ - if (reply = imap_send_literal (stream,tag,&s,arg->text)) return reply; - break; - - case LIST: /* list of strings */ - list = (STRINGLIST *) arg->text; - c = '('; /* open paren */ - do { /* for each list item */ - *s++ = c; /* write prefix character */ - if (reply = imap_send_astring (stream,tag,&s,&list->text,NIL, - CMDBASE+MAXCOMMAND)) return reply; - c = ' '; /* prefix character for subsequent strings */ - } - while (list = list->next); - *s++ = ')'; /* close list */ - break; - case SEARCHPROGRAM: /* search program */ - if (reply = imap_send_spgm (stream,tag,CMDBASE,&s,arg->text, - CMDBASE+MAXCOMMAND)) - return reply; - break; - case SORTPROGRAM: /* search program */ - c = '('; /* open paren */ - for (spg = (SORTPGM *) arg->text; spg; spg = spg->next) { - *s++ = c; /* write prefix */ - if (spg->reverse) for (t = "REVERSE "; *t; *s++ = *t++); - switch (spg->function) { - case SORTDATE: - for (t = "DATE"; *t; *s++ = *t++); - break; - case SORTARRIVAL: - for (t = "ARRIVAL"; *t; *s++ = *t++); - break; - case SORTFROM: - for (t = "FROM"; *t; *s++ = *t++); - break; - case SORTSUBJECT: - for (t = "SUBJECT"; *t; *s++ = *t++); - break; - case SORTTO: - for (t = "TO"; *t; *s++ = *t++); - break; - case SORTCC: - for (t = "CC"; *t; *s++ = *t++); - break; - case SORTSIZE: - for (t = "SIZE"; *t; *s++ = *t++); - break; - default: - fatal ("Unknown sort program function in imap_send()!"); - } - c = ' '; /* prefix character for subsequent items */ - } - *s++ = ')'; /* close list */ - break; - - case BODYTEXT: /* body section */ - for (t = "BODY["; *t; *s++ = *t++); - for (t = (char *) arg->text; *t; *s++ = *t++); - break; - case BODYPEEK: /* body section */ - for (t = "BODY.PEEK["; *t; *s++ = *t++); - for (t = (char *) arg->text; *t; *s++ = *t++); - break; - case BODYCLOSE: /* close bracket and possible length */ - s[-1] = ']'; /* no leading space */ - for (t = (char *) arg->text; *t; *s++ = *t++); - break; - case SEQUENCE: /* sequence */ - if ((i = strlen (t = (char *) arg->text)) <= (size_t) MAXCOMMAND) - while (*t) *s++ = *t++; /* easy case */ - else { - mail_unlock (stream); /* unlock stream */ - a = arg->text; /* save original sequence pointer */ - arg->type = ATOM; /* make recursive call be faster */ - do { /* break up into multiple commands */ - if (i <= MAXCOMMAND) {/* final part? */ - reply = imap_send (stream,cmd,args); - i = 0; /* and mark as done */ - } - else { /* still needs to be split further */ - if (!(t = strchr (t + MAXCOMMAND - 30,',')) || - ((t - (char *) arg->text) > MAXCOMMAND)) - fatal ("impossible over-long sequence"); - *t = '\0'; /* tie off sequence at point of split*/ - /* recurse to do this part */ - reply = imap_send (stream,cmd,args); - *t++ = ','; /* restore the comma in case something cares */ - /* punt if error */ - if (!imap_OK (stream,reply)) break; - /* calculate size of remaining sequence */ - i -= (t - (char *) arg->text); - /* point to new remaining sequence */ - arg->text = (void *) t; - } - } while (i); - arg->type = SEQUENCE; /* restore in case something cares */ - arg->text = a; - return reply; /* return result */ - } - break; - case LISTMAILBOX: /* astring with wildcards */ - st.size = strlen ((char *) (st.data = (unsigned char *) arg->text)); - if (reply = imap_send_astring (stream,tag,&s,&st,T,CMDBASE+MAXCOMMAND)) - return reply; - break; - - case MULTIAPPEND: /* append multiple messages */ + IMAPPARSEDREPLY *reply; + IMAPARG *arg,**arglst; + SORTPGM *spg; + STRINGLIST *list; + SIZEDTEXT st; + APPENDDATA *map; + sendcommand_t sc = (sendcommand_t) mail_parameters (NIL,GET_SENDCOMMAND,NIL); + size_t i; + void *a; + char c,*s,*t,tag[10]; + int af_type = 0; + stream->unhealthy = NIL; /* make stream healthy again */ + + /* gensym a new tag */ + sprintf (tag,"%08lx",0xffffffff & (stream->gensym++)); + + if (!LOCAL->netstream) /* make sure have a session */ + return imap_fake (stream,tag,"[CLOSED] IMAP connection lost"); + + mail_lock (stream); /* lock up the stream */ + + if (sc) /* tell client sending a command */ + (*sc) (stream,cmd,((compare_cstring (cmd,"FETCH") && compare_cstring (cmd,"STORE") && + compare_cstring (cmd,"SEARCH")) ? NIL : SC_EXPUNGEDEFERRED)); + + /* ignore referral from previous command */ + if (LOCAL->referral) fs_give ((void **) &LOCAL->referral); + + sprintf (CMDBASE,"%s %s",tag,cmd); + s = CMDBASE + strlen (CMDBASE); + + if (arglst = args) + while (arg = *arglst++) { + *s++ = ' '; /* delimit argument with space */ + switch (arg->type) { + + case ATOM: /* atom */ + for (t = (char *) arg->text; *t; *s++ = *t++); + break; + + case NUMBER: /* number */ + sprintf (s,"%lu",(unsigned long) arg->text); + s += strlen (s); + break; + + case FLAGS: /* flag list as a single string */ + if (*(t = (char *) arg->text) != '(') { + *s++ = '('; /* wrap parens around string */ + while (*t) *s++ = *t++; + *s++ = ')'; /* wrap parens around string */ + } else + while (*t) *s++ = *t++; + break; + + case ASTRING: /* atom or string, must be literal? */ + st.size = strlen ((char *) (st.data = (unsigned char *) arg->text)); + if (reply = imap_send_astring (stream,tag,&s,&st,NIL,CMDBASE+MAXCOMMAND)) + return reply; + break; + + case LITERAL: /* literal, as a stringstruct */ + if (reply = imap_send_literal (stream,tag,&s,arg->text)) + return reply; + break; + + case LITERAL_CMD: + snprintf(g_append_cmd_tag, sizeof(g_append_cmd_tag), "%s", tag); + if (reply = imap_send_literal_cmd (stream,tag,&s,arg->text)) + return reply; + break; + + case LITERAL_MSG: + if (g_append_cmd_tag && strlen(g_append_cmd_tag) > 0) { + snprintf(tag, sizeof(tag), "%s", g_append_cmd_tag); + } + reply = imap_send_literal_msg (stream,tag,arg->text); + return reply; + + case LITERAL_END: + if (g_append_cmd_tag && strlen(g_append_cmd_tag) > 0) { + snprintf(tag, sizeof(tag), "%s", g_append_cmd_tag); + memset(g_append_cmd_tag, 0, sizeof(g_append_cmd_tag)); + } + s = CMDBASE; + break; + + case LIST: /* list of strings */ + list = (STRINGLIST *) arg->text; + c = '('; /* open paren */ + do { /* for each list item */ + *s++ = c; /* write prefix character */ + if (reply = imap_send_astring (stream,tag,&s,&list->text,NIL,CMDBASE+MAXCOMMAND)) + return reply; + c = ' '; /* prefix character for subsequent strings */ + } while (list = list->next); + + *s++ = ')'; /* close list */ + break; + + case SEARCHPROGRAM: /* search program */ + if (reply = imap_send_spgm (stream,tag,CMDBASE,&s,arg->text,CMDBASE+MAXCOMMAND)) + return reply; + break; + + case SORTPROGRAM: /* search program */ + c = '('; /* open paren */ + for (spg = (SORTPGM *) arg->text; spg; spg = spg->next) { + *s++ = c; /* write prefix */ + if (spg->reverse) + for (t = "REVERSE "; *t; *s++ = *t++); + + switch (spg->function) { + case SORTDATE: + for (t = "DATE"; *t; *s++ = *t++); + break; + + case SORTARRIVAL: + for (t = "ARRIVAL"; *t; *s++ = *t++); + break; + + case SORTFROM: + for (t = "FROM"; *t; *s++ = *t++); + break; + + case SORTSUBJECT: + for (t = "SUBJECT"; *t; *s++ = *t++); + break; + + case SORTTO: + for (t = "TO"; *t; *s++ = *t++); + break; + + case SORTCC: + for (t = "CC"; *t; *s++ = *t++); + break; + + case SORTSIZE: + for (t = "SIZE"; *t; *s++ = *t++); + break; + + default: + MM_LOG ("Unknown sort program function in imap_send()!", ERROR); + mail_unlock (stream); /* unlock stream */ + return imap_fake (stream,tag,"imap_send unknown sort program function error"); + } + + c = ' '; /* prefix character for subsequent items */ + } + *s++ = ')'; /* close list */ + break; + + case BODYTEXT: /* body section */ + for (t = "BODY["; *t; *s++ = *t++); + for (t = (char *) arg->text; *t; *s++ = *t++); + break; + + case BODYPEEK: /* body section */ + for (t = "BODY.PEEK["; *t; *s++ = *t++); + for (t = (char *) arg->text; *t; *s++ = *t++); + break; + + case BODYCLOSE: /* close bracket and possible length */ + s[-1] = ']'; /* no leading space */ + for (t = (char *) arg->text; *t; *s++ = *t++); + break; + + case SEQUENCE: /* sequence */ + if ((i = strlen (t = (char *) arg->text)) <= (size_t) MAXCOMMAND) + while (*t) *s++ = *t++; /* easy case */ + else { + mail_unlock (stream); /* unlock stream */ + a = arg->text; /* save original sequence pointer */ + arg->type = ATOM; /* make recursive call be faster */ + + do { /* break up into multiple commands */ + if (i <= MAXCOMMAND) {/* final part? */ + reply = imap_send (stream,cmd,args); + i = 0; /* and mark as done */ + } else { /* still needs to be split further */ + if (!(t = strchr (t + MAXCOMMAND - 30,',')) || ((t - (char *) arg->text) > MAXCOMMAND)) { + MM_LOG ("impossible over-long sequence", ERROR); + reply = imap_fake (stream,tag,"impossible over-long sequence error"); + break; + } + *t = '\0'; /* tie off sequence at point of split*/ + /* recurse to do this part */ + reply = imap_send (stream,cmd,args); + *t++ = ','; /* restore the comma in case something cares */ + /* punt if error */ + if (!imap_OK (stream,reply)) break; + /* calculate size of remaining sequence */ + i -= (t - (char *) arg->text); + /* point to new remaining sequence */ + arg->text = (void *) t; + } + } while (i); + + arg->type = SEQUENCE; /* restore in case something cares */ + arg->text = a; + return reply; /* return result */ + } + break; + + case LISTMAILBOX: /* astring with wildcards */ + st.size = strlen ((char *) (st.data = (unsigned char *) arg->text)); + if (reply = imap_send_astring (stream,tag,&s,&st,T,CMDBASE+MAXCOMMAND)) + return reply; + break; + + case MULTIAPPEND: /* append multiple messages */ /* get package pointer */ - map = (APPENDDATA *) arg->text; - if (!(*map->af) (stream,map->data,&map->flags,&map->date,&map->message)|| - !map->message) { - STRING es; - INIT (&es,mail_string,"",0); - return (reply = imap_send_literal (stream,tag,&s,&es)) ? - reply : imap_fake (stream,tag,"Server zero-length literal error"); - } - case MULTIAPPENDREDO: /* redo multiappend */ + map = (APPENDDATA *) arg->text; + if (!(*map->af) (stream,map->data,&map->flags,&map->date,&map->message)||!map->message) { + STRING es; + INIT (&es,mail_string,"",0); + return (reply = imap_send_literal (stream,tag,&s,&es)) ? reply : imap_fake (stream,tag,"Server zero-length literal error"); + } + + case MULTIAPPENDREDO: /* redo multiappend */ /* get package pointer */ - map = (APPENDDATA *) arg->text; - do { /* make sure date valid if given */ - char datetmp[MAILTMPLEN]; - MESSAGECACHE elt; - STRING es; - if (!map->date || mail_parse_date (&elt,map->date)) { - if (t = map->flags) { /* flags given? */ - if (*t != '(') { - *s++ = '('; /* wrap parens around string */ - while (*t) *s++ = *t++; - *s++ = ')'; /* wrap parens around string */ - } - else while (*t) *s++ = *t++; - *s++ = ' '; /* delimit with space */ - } - if (map->date) { /* date given? */ - st.size = strlen ((char *) (st.data = (unsigned char *) - mail_date (datetmp,&elt))); - if (reply = imap_send_astring (stream,tag,&s,&st,NIL, - CMDBASE+MAXCOMMAND)) return reply; - *s++ = ' '; /* delimit with space */ - } - if (reply = imap_send_literal (stream,tag,&s,map->message)) - return reply; - /* get next message */ - if ((*map->af) (stream,map->data,&map->flags,&map->date, - &map->message)) { - /* have a message, delete next in command */ - if (map->message) *s++ = ' '; - continue; /* loop back for next message */ - } - } - /* bad date or need to abort */ - INIT (&es,mail_string,"",0); - return (reply = imap_send_literal (stream,tag,&s,&es)) ? - reply : imap_fake (stream,tag,"Server zero-length literal error"); - break; /* exit the loop */ - } while (map->message); - break; - - case SNLIST: /* list of string/number pairs */ - list = (STRINGLIST *) arg->text; - c = '('; /* open paren */ - do { /* for each list item */ - *s++ = c; /* write prefix character */ - if (list) { /* sigh, QUOTA has bizarre syntax! */ - for (t = (char *) list->text.data; *t; *s++ = *t++); - sprintf (s," %lu",list->text.size); - s += strlen (s); - c = ' '; /* prefix character for subsequent strings */ - } - } - while (list = list->next); - *s++ = ')'; /* close list */ - break; - default: - fatal ("Unknown argument type in imap_send()!"); - } - } - /* send the command */ - reply = imap_sout (stream,tag,CMDBASE,&s); - mail_unlock (stream); /* unlock stream */ - return reply; + map = (APPENDDATA *) arg->text; + do { /* make sure date valid if given */ + char datetmp[MAILTMPLEN]; + MESSAGECACHE elt; + STRING es; + if (!map->date || mail_parse_date (&elt,map->date)) { + if (t = map->flags) { /* flags given? */ + if (*t != '(') { + *s++ = '('; /* wrap parens around string */ + while (*t) *s++ = *t++; + *s++ = ')'; /* wrap parens around string */ + } + else while (*t) *s++ = *t++; + *s++ = ' '; /* delimit with space */ + } + + if (map->date) { /* date given? */ + st.size = strlen ((char *) (st.data = (unsigned char *)mail_date (datetmp,&elt))); + if (reply = imap_send_astring (stream,tag,&s,&st,NIL,CMDBASE+MAXCOMMAND)) return reply; + *s++ = ' '; /* delimit with space */ + } + + if (reply = imap_send_literal (stream,tag,&s,map->message)) + return reply; + + /* get next message */ + if ((*map->af) (stream,map->data,&map->flags,&map->date,&map->message)) { + /* have a message, delete next in command */ + if (map->message) *s++ = ' '; + continue; /* loop back for next message */ + } + } + + /* bad date or need to abort */ + INIT (&es,mail_string,"",0); + return (reply = imap_send_literal (stream,tag,&s,&es)) ? reply : imap_fake (stream,tag,"Server zero-length literal error"); + break; /* exit the loop */ + } while (map->message); + break; + + case SNLIST: /* list of string/number pairs */ + list = (STRINGLIST *) arg->text; + c = '('; /* open paren */ + do { /* for each list item */ + *s++ = c; /* write prefix character */ + if (list) { /* sigh, QUOTA has bizarre syntax! */ + for (t = (char *) list->text.data; *t; *s++ = *t++); + sprintf (s," %lu",list->text.size); + s += strlen (s); + c = ' '; /* prefix character for subsequent strings */ + } + } while (list = list->next); + + *s++ = ')'; /* close list */ + break; + + default: + MM_LOG ("Unknown argument type in imap_send()!", ERROR); + mail_unlock (stream); /* unlock stream */ + return imap_fake (stream,tag,"[CLOSED] IMAP connection broken (data)"); + } + } + + /* send the command */ + reply = imap_sout (stream,tag,CMDBASE,&s); + mail_unlock (stream); /* unlock stream */ + return reply; } - + /* IMAP send atom-string * Accepts: MAIL stream * reply tag @@ -3214,44 +3542,104 @@ IMAPPARSEDREPLY *imap_send_astring (MAILSTREAM *stream,char *tag,char **s, IMAPPARSEDREPLY *imap_send_literal (MAILSTREAM *stream,char *tag,char **s, STRING *st) { - IMAPPARSEDREPLY *reply; - unsigned long i = SIZE (st); - unsigned long j; - sprintf (*s,"{%lu}",i); /* write literal count */ - *s += strlen (*s); /* size of literal count */ - /* send the command */ - reply = imap_sout (stream,tag,CMDBASE,s); - if (strcmp (reply->tag,"+")) {/* prompt for more data? */ - mail_unlock (stream); /* no, give up */ - return reply; - } - while (i) { /* dump the text */ - if (st->cursize) { /* if text to do in this chunk */ - /* RFC 3501 technically forbids NULs in literals. Normally, the - * delivering MTA would take care of MIME converting the message text - * so that it is NUL-free. If it doesn't, then we have the choice of - * either violating IMAP by sending NULs, corrupting the data, or going - * to lots of work to do MIME conversion in the IMAP server. - * - * No current stringstruct driver objects to having its buffer patched. - * If this ever changes, it will be necessary to change this kludge. - */ - /* patch NULs to C1 control */ - for (j = 0; j < st->cursize; ++j) - if (!st->curpos[j]) st->curpos[j] = 0x80; - if (!net_sout (LOCAL->netstream,st->curpos,st->cursize)) { - mail_unlock (stream); - return imap_fake (stream,tag,"[CLOSED] IMAP connection broken (data)"); - } - i -= st->cursize; /* note that we wrote out this much */ - st->curpos += (st->cursize - 1); - st->cursize = 0; - } - (*st->dtb->next) (st); /* advance to next buffer's worth */ - } - return NIL; /* success */ + IMAPPARSEDREPLY *reply; + unsigned long i = SIZE (st); + unsigned long j; + + sprintf (*s,"{%lu}",i); /* write literal count */ + *s += strlen (*s); /* size of literal count */ + /* send the command */ + reply = imap_sout (stream,tag,CMDBASE,s); + + mm_notify (stream,reply->tag,WARN); + if (strncmp (reply->tag,"+", 1)) {/* prompt for more data? */ + mail_unlock (stream); /* no, give up */ + return reply; + } + + while (i) { /* dump the text */ + if (st->cursize) { /* if text to do in this chunk */ + /* RFC 3501 technically forbids NULs in literals. Normally, the + * delivering MTA would take care of MIME converting the message text + * so that it is NUL-free. If it doesn't, then we have the choice of + * either violating IMAP by sending NULs, corrupting the data, or going + * to lots of work to do MIME conversion in the IMAP server. + * + * No current stringstruct driver objects to having its buffer patched. + * If this ever changes, it will be necessary to change this kludge. + */ + /* patch NULs to C1 control */ + for (j = 0; j < st->cursize; ++j) + if (!st->curpos[j]) st->curpos[j] = 0x80; + + if (!net_sout (LOCAL->netstream,st->curpos,st->cursize)) { + mail_unlock (stream); + return imap_fake (stream,tag,"[CLOSED] IMAP connection broken (data)"); + } + i -= st->cursize; /* note that we wrote out this much */ + st->curpos += (st->cursize - 1); + st->cursize = 0; + } + (*st->dtb->next) (st); /* advance to next buffer's worth */ + } + + return NIL; /* success */ } - + +IMAPPARSEDREPLY *imap_send_literal_cmd (MAILSTREAM *stream,char *tag,char **s,STRING *st) +{ + IMAPPARSEDREPLY *reply; + + sprintf (*s,"{%s}",st->chunk); /* write literal count */ + *s += strlen (*s); /* size of literal count */ + + /* send the command */ + reply = imap_sout (stream,tag,CMDBASE,s); + + if (strncmp (reply->tag,"+", 1) == 0) {/* prompt for more data? */ + mail_unlock (stream); /* no, give up */ + return reply; + } + + return NIL; /* success */ +} + +IMAPPARSEDREPLY *imap_send_literal_msg (MAILSTREAM *stream,char *tag,STRING *st) +{ + IMAPPARSEDREPLY *reply; + unsigned long i = SIZE (st); + unsigned long j; + + while (i) { /* dump the text */ + if (st->cursize) { /* if text to do in this chunk */ + /* RFC 3501 technically forbids NULs in literals. Normally, the + * delivering MTA would take care of MIME converting the message text + * so that it is NUL-free. If it doesn't, then we have the choice of + * either violating IMAP by sending NULs, corrupting the data, or going + * to lots of work to do MIME conversion in the IMAP server. + * + * No current stringstruct driver objects to having its buffer patched. + * If this ever changes, it will be necessary to change this kludge. + */ + /* patch NULs to C1 control */ + for (j = 0; j < st->cursize; ++j) + if (!st->curpos[j]) st->curpos[j] = 0x80; + + if (!net_sout (LOCAL->netstream,st->curpos,st->cursize)) { + mail_unlock (stream); + return imap_fake (stream,tag,"[CLOSED] IMAP connection broken (data)"); + } + i -= st->cursize; /* note that we wrote out this much */ + st->curpos += (st->cursize - 1); + st->cursize = 0; + } + (*st->dtb->next) (st); /* advance to next buffer's worth */ + } + + mail_unlock (stream); /* no, give up */ + return NIL; /* success */ +} + /* IMAP send search program * Accepts: MAIL stream * reply tag @@ -3689,6 +4077,8 @@ IMAPPARSEDREPLY *imap_fake (MAILSTREAM *stream,char *tag,char *text) long imap_OK (MAILSTREAM *stream,IMAPPARSEDREPLY *reply) { long ret = NIL; + if (reply == NULL) return ret; + /* OK - operation succeeded */ if (!strcmp (reply->key,"OK")) { imap_parse_response (stream,reply->text,NIL,NIL); @@ -3705,7 +4095,7 @@ long imap_OK (MAILSTREAM *stream,IMAPPARSEDREPLY *reply) /* bad protocol received */ else sprintf (LOCAL->tmp,"Unexpected IMAP response: %.80s %.80s", (char *) reply->key,(char *) reply->text); - mm_log (LOCAL->tmp,ERROR); /* either way, this is not good */ + MM_LOG (LOCAL->tmp,ERROR); /* either way, this is not good */ } return ret; } @@ -3772,7 +4162,7 @@ void imap_parse_unsolicited (MAILSTREAM *stream,IMAPPARSEDREPLY *reply) /* canonicalize property, parse it */ if (!strcmp (ucase (prop),"FLAGS")) imap_parse_flags (stream,elt,&t); else if (!strcmp (prop,"INTERNALDATE") && - (s = imap_parse_string (stream,&t,reply,NIL,NIL,LONGT))) { + (s = imap_parse_string (stream,&t,reply,NIL,NIL,IMAP_PARSE_STRING_FLAGS_FOR_NEW_LINE))) { if (!mail_parse_date (elt,s)) { sprintf (LOCAL->tmp,"Bogus date: %.80s",(char *) s); mm_notify (stream,LOCAL->tmp,WARN); @@ -3863,7 +4253,7 @@ void imap_parse_unsolicited (MAILSTREAM *stream,IMAPPARSEDREPLY *reply) imap_parse_string (stream,&t,reply, ((md.what[0] && (md.what[0] != 'H')) || md.first || md.last) ? &md : NIL, - &text.size,NIL); + &text.size,IMAP_PARSE_STRING_FLAGS_NONE); /* all done if partial */ if (md.first || md.last) mail_free_stringlist (&stl); /* otherwise register it in the cache */ @@ -3884,7 +4274,7 @@ void imap_parse_unsolicited (MAILSTREAM *stream,IMAPPARSEDREPLY *reply) if (!prop[6]) { /* cache full message */ md.what = ""; text.data = (unsigned char *) - imap_parse_string (stream,&t,reply,&md,&text.size,NIL); + imap_parse_string (stream,&t,reply,&md,&text.size,IMAP_PARSE_STRING_FLAGS_NONE); imap_cache (stream,msgno,md.what,NIL,&text); } else if (!strcmp (prop+7,"SIZE")) @@ -3892,14 +4282,14 @@ void imap_parse_unsolicited (MAILSTREAM *stream,IMAPPARSEDREPLY *reply) /* legacy properties */ else if (!strcmp (prop+7,"HEADER")) { text.data = (unsigned char *) - imap_parse_string (stream,&t,reply,NIL,&text.size,NIL); + imap_parse_string (stream,&t,reply,NIL,&text.size,IMAP_PARSE_STRING_FLAGS_NONE); imap_cache (stream,msgno,"HEADER",NIL,&text); e = stream->scache ? &stream->env : &elt->private.msg.env; } else if (!strcmp (prop+7,"TEXT")) { md.what = "TEXT"; text.data = (unsigned char *) - imap_parse_string (stream,&t,reply,&md,&text.size,NIL); + imap_parse_string (stream,&t,reply,&md,&text.size,IMAP_PARSE_STRING_FLAGS_NONE); imap_cache (stream,msgno,md.what,NIL,&text); } else { @@ -4097,7 +4487,6 @@ void imap_parse_unsolicited (MAILSTREAM *stream,IMAPPARSEDREPLY *reply) else if (!compare_cstring (t,"\\Starred")) i |= LATT_XLIST_FLAGGED; /* Gmail */ else if (!compare_cstring (t,"\\Flagged")) i |= LATT_XLIST_FLAGGED; /* RFC 6154 */ else if (!compare_cstring (t,"\\Trash")) i |= LATT_XLIST_TRASH; /* RFC 6154 and Gmail */ - /* ignore extension flags */ } while (t = strtok_r (NIL," ",&r)); switch (*++s) { /* process delimiter */ @@ -4206,7 +4595,7 @@ void imap_parse_unsolicited (MAILSTREAM *stream,IMAPPARSEDREPLY *reply) fs_give ((void **) &id); /* free identifier */ } else { - sprintf (LOCAL->tmp,"Missing LISTRIGHTS identifer for %.80s",(char *) t); + sprintf (LOCAL->tmp,"Missing LISTRIGHTS identifier for %.80s",(char *) t); mm_notify (stream,LOCAL->tmp,WARN); stream->unhealthy = T; } @@ -4301,6 +4690,16 @@ void imap_parse_unsolicited (MAILSTREAM *stream,IMAPPARSEDREPLY *reply) } fs_give ((void **) &t); } +#ifdef __FEATURE_METADATA_SUPPORT__ + else if (!strcmp (reply->key,"METADATA")) { + /* Example : + * C: a GETMETADATA "" /shared/comment + * S: * METADATA "" (/shared/comment "Shared comment") + * S: a OK GETMETADATA complete + */ + t = imap_parse_astring (stream,&s,reply,NIL); + } +#endif /* __FEATURE_METADATA_SUPPORT__ */ else if (!strcmp (reply->key,"OK") || !strcmp (reply->key,"PREAUTH")) imap_parse_response (stream,reply->text,NIL,T); @@ -4321,6 +4720,11 @@ void imap_parse_unsolicited (MAILSTREAM *stream,IMAPPARSEDREPLY *reply) else t = reply->text; mm_list (stream,NIL,t,NIL); } +#ifdef __FEATURE_SUPPORT_IMAP_ID__ + else if (!strcmp (reply->key,"ID")) { + imap_parse_id (stream,reply->text); + } +#endif /* __FEATURE_SUPPORT_IMAP_ID__ */ else { sprintf (LOCAL->tmp,"Unexpected untagged message: %.80s", (char *) reply->key); @@ -4387,7 +4791,7 @@ void imap_parse_response (MAILSTREAM *stream,char *text,long errflg,long ntfy) } else if (!compare_cstring (t,"CAPABILITY")) - imap_parse_capabilities (stream,s); + imap_parse_capabilities (stream,s); else if ((j = LEVELUIDPLUS (stream) && LOCAL->appendmailbox) && !compare_cstring (t,"COPYUID") && (cu = (copyuid_t) mail_parameters (NIL,GET_COPYUID,NIL)) && @@ -4458,7 +4862,7 @@ NAMESPACE *imap_parse_namespace (MAILSTREAM *stream,unsigned char **txtptr, if (!ret) ret = nam; /* if first time note first namespace */ /* if previous link new block to it */ if (prev) prev->next = nam; - nam->name = imap_parse_string (stream,txtptr,reply,NIL,NIL,NIL); + nam->name = imap_parse_string (stream,txtptr,reply,NIL,NIL,IMAP_PARSE_STRING_FLAGS_NONE); /* ignore whitespace */ while (**txtptr == ' ') ++*txtptr; switch (**txtptr) { /* parse delimiter */ @@ -4483,7 +4887,7 @@ NAMESPACE *imap_parse_namespace (MAILSTREAM *stream,unsigned char **txtptr, while (**txtptr == ' '){/* append new parameter to tail */ if (nam->param) par = par->next = mail_newbody_parameter (); else nam->param = par = mail_newbody_parameter (); - if (!(par->attribute = imap_parse_string (stream,txtptr,reply,NIL, + if (!(par->attribute = imap_parse_string (stream,txtptr,reply,IMAP_PARSE_STRING_FLAGS_NONE, NIL,NIL))) { mm_notify (stream,"Missing namespace extension attribute",WARN); stream->unhealthy = T; @@ -4496,7 +4900,7 @@ NAMESPACE *imap_parse_namespace (MAILSTREAM *stream,unsigned char **txtptr, ++*txtptr; /* yes */ do { /* parse each value */ if (!(par->value = imap_parse_string (stream,txtptr,reply,NIL, - NIL,LONGT))) { + NIL,IMAP_PARSE_STRING_FLAGS_FOR_NEW_LINE))) { sprintf (LOCAL->tmp, "Missing value for namespace attribute %.80s",att); mm_notify (stream,LOCAL->tmp,WARN); @@ -4653,8 +5057,8 @@ void imap_parse_envelope (MAILSTREAM *stream,ENVELOPE **env, switch (c) { /* dispatch on first character */ case '(': /* if envelope S-expression */ *env = mail_newenvelope (); /* parse the new envelope */ - (*env)->date = imap_parse_string (stream,txtptr,reply,NIL,NIL,LONGT); - (*env)->subject = imap_parse_string (stream,txtptr,reply,NIL,NIL,LONGT); + (*env)->date = imap_parse_string (stream,txtptr,reply,NIL,NIL,IMAP_PARSE_STRING_FLAGS_FOR_NEW_LINE); + (*env)->subject = imap_parse_string (stream,txtptr,reply,NIL,NIL,IMAP_PARSE_STRING_FLAGS_FOR_NEW_LINE); (*env)->from = imap_parse_adrlist (stream,txtptr,reply); (*env)->sender = imap_parse_adrlist (stream,txtptr,reply); (*env)->reply_to = imap_parse_adrlist (stream,txtptr,reply); @@ -4662,8 +5066,8 @@ void imap_parse_envelope (MAILSTREAM *stream,ENVELOPE **env, (*env)->cc = imap_parse_adrlist (stream,txtptr,reply); (*env)->bcc = imap_parse_adrlist (stream,txtptr,reply); (*env)->in_reply_to = imap_parse_string (stream,txtptr,reply,NIL,NIL, - LONGT); - (*env)->message_id = imap_parse_string (stream,txtptr,reply,NIL,NIL,LONGT); + IMAP_PARSE_STRING_FLAGS_FOR_NEW_LINE); + (*env)->message_id = imap_parse_string (stream,txtptr,reply,NIL,NIL,IMAP_PARSE_STRING_FLAGS_FOR_NEW_LINE); if (oenv) { /* need to merge old envelope? */ (*env)->newsgroups = oenv->newsgroups; oenv->newsgroups = NIL; @@ -4760,10 +5164,10 @@ ADDRESS *imap_parse_address (MAILSTREAM *stream,unsigned char **txtptr, ++*txtptr; /* skip past open paren */ if (adr) prev = adr; /* note previous if any */ adr = mail_newaddr (); /* instantiate address and parse its fields */ - adr->personal = imap_parse_string (stream,txtptr,reply,NIL,NIL,LONGT); - adr->adl = imap_parse_string (stream,txtptr,reply,NIL,NIL,LONGT); - adr->mailbox = imap_parse_string (stream,txtptr,reply,NIL,NIL,LONGT); - adr->host = imap_parse_string (stream,txtptr,reply,NIL,NIL,LONGT); + adr->personal = imap_parse_string (stream,txtptr,reply,NIL,NIL,IMAP_PARSE_STRING_FLAGS_FOR_DOUBLE_QUOTE); + adr->adl = imap_parse_string (stream,txtptr,reply,NIL,NIL,IMAP_PARSE_STRING_FLAGS_FOR_NEW_LINE); + adr->mailbox = imap_parse_string (stream,txtptr,reply,NIL,NIL,IMAP_PARSE_STRING_FLAGS_FOR_NEW_LINE); + adr->host = imap_parse_string (stream,txtptr,reply,NIL,NIL,IMAP_PARSE_STRING_FLAGS_FOR_NEW_LINE); if (**txtptr != ')') { /* handle trailing paren */ sprintf (LOCAL->tmp,"Junk at end of address: %.80s",(char *) *txtptr); mm_notify (stream,LOCAL->tmp,WARN); @@ -4923,7 +5327,7 @@ unsigned char *imap_parse_astring (MAILSTREAM *stream,unsigned char **txtptr, switch (c) { case '"': /* quoted string? */ case '{': /* literal? */ - ret = imap_parse_string (stream,txtptr,reply,NIL,len,NIL); + ret = imap_parse_string (stream,txtptr,reply,NIL,len,IMAP_PARSE_STRING_FLAGS_NONE); break; default: /* must be atom */ for (c = *(s = *txtptr); /* find end of atom */ @@ -4953,7 +5357,7 @@ unsigned char *imap_parse_astring (MAILSTREAM *stream,unsigned char **txtptr, * parsed reply * mailgets data * returned string length - * filter newline flag + * filter newline/double quote handling flag * Returns: string * * Updates text pointer @@ -4961,7 +5365,7 @@ unsigned char *imap_parse_astring (MAILSTREAM *stream,unsigned char **txtptr, unsigned char *imap_parse_string (MAILSTREAM *stream,unsigned char **txtptr, IMAPPARSEDREPLY *reply,GETS_DATA *md, - unsigned long *len,long flags) + unsigned long *len,imap_parse_string_flags flags) { char *st; char *string = NIL; @@ -4980,25 +5384,48 @@ unsigned char *imap_parse_string (MAILSTREAM *stream,unsigned char **txtptr, /* search for end of string */ for (c = **txtptr; c != '"'; ++i,c = *++*txtptr) { /* backslash quotes next character */ - if (c == '\\') c = *++*txtptr; + if (c == '\\') { + if (flags == IMAP_PARSE_STRING_FLAGS_FOR_DOUBLE_QUOTE) { + if (*((*txtptr)+1) == '"') { + i++; + c = *++*txtptr; + } + } + else { + c = *++*txtptr; + } + } /* CHAR8 not permitted in quoted string */ if (!bogon && (bogon = (c & 0x80))) { - sprintf (LOCAL->tmp,"Invalid CHAR in quoted string: %x", - (unsigned int) c); - mm_notify (stream,LOCAL->tmp,WARN); - stream->unhealthy = T; + sprintf (LOCAL->tmp,"Invalid CHAR in quoted string: %x", + (unsigned int) c); + mm_notify (stream,LOCAL->tmp,WARN); + stream->unhealthy = T; } else if (!c) { /* NUL not permitted either */ - mm_notify (stream,"Unterminated quoted string",WARN); - stream->unhealthy = T; - if (len) *len = 0; /* punt, since may be at end of string */ - return NIL; + mm_notify (stream,"Unterminated quoted string",WARN); + stream->unhealthy = T; + if (len) *len = 0; /* punt, since may be at end of string */ + return NIL; } } + ++*txtptr; /* bump past delimiter */ - string = (char *) fs_get ((size_t) i + 1); + string = (char *) fs_get ((size_t) i + 3); for (j = 0; j < i; j++) { /* copy the string */ - if (*st == '\\') ++st; /* quoted character */ + + if (*st == '\\') /* quoted character */ { + if (flags == IMAP_PARSE_STRING_FLAGS_FOR_DOUBLE_QUOTE) { + if (*(st + 1) == '"') { + string[j++] = *st++; + } + else + ++st; + } + else + ++st; /* quoted character */ + } + string[j] = *st++; } string[j] = '\0'; /* tie off string */ @@ -5061,7 +5488,7 @@ unsigned char *imap_parse_string (MAILSTREAM *stream,unsigned char **txtptr, else net_getbuffer (LOCAL->netstream,i,string); } fs_give ((void **) &reply->line); - if (flags && string) /* need to filter newlines? */ + if (flags == IMAP_PARSE_STRING_FLAGS_FOR_NEW_LINE && string) /* need to filter newlines? */ for (st = string; st = strpbrk (st,"\015\012\011"); *st++ = ' '); /* get new reply text line */ if (!(reply->line = net_getline (LOCAL->netstream))) @@ -5119,7 +5546,8 @@ long imap_cache (MAILSTREAM *stream,unsigned long msgno,char *seg, imap_parse_header (stream,&stream->env,text,stl); } /* regular caching */ - else imap_parse_header (stream,&elt->private.msg.env,text,stl); + else + imap_parse_header (stream,&elt->private.msg.env,text,stl); } } /* top level text */ @@ -5212,29 +5640,31 @@ void imap_parse_body_structure (MAILSTREAM *stream,BODY *body, /* parse it */ imap_parse_body_structure (stream,&part->body,txtptr,reply); } while (**txtptr == '(');/* for each body part */ - if (body->subtype = imap_parse_string(stream,txtptr,reply,NIL,NIL,LONGT)) + if (body->subtype = imap_parse_string(stream,txtptr,reply,NIL,NIL,IMAP_PARSE_STRING_FLAGS_FOR_NEW_LINE)) ucase (body->subtype); else { mm_notify (stream,"Missing multipart subtype",WARN); stream->unhealthy = T; body->subtype = cpystr (rfc822_default_subtype (body->type)); } - if (**txtptr == ' ') /* multipart parameters */ + if (**txtptr == ' ' && *((*txtptr)+ 1) != ')') { /* multipart parameters */ body->parameter = imap_parse_body_parameter (stream,txtptr,reply); - if (**txtptr == ' ') { /* disposition */ + } + if (**txtptr == ' ' && *((*txtptr)+ 1) != ')') { /* disposition */ imap_parse_disposition (stream,body,txtptr,reply); if (LOCAL->cap.extlevel < BODYEXTDSP) LOCAL->cap.extlevel = BODYEXTDSP; } - if (**txtptr == ' ') { /* language */ + if (**txtptr == ' ' && *((*txtptr)+ 1) != ')') { /* language */ body->language = imap_parse_language (stream,txtptr,reply); if (LOCAL->cap.extlevel < BODYEXTLANG) LOCAL->cap.extlevel = BODYEXTLANG; } - if (**txtptr == ' ') { /* location */ - body->location = imap_parse_string (stream,txtptr,reply,NIL,NIL,LONGT); + if (**txtptr == ' ' && *((*txtptr)+ 1) != ')') { /* location */ + body->location = imap_parse_string (stream,txtptr,reply,NIL,NIL,IMAP_PARSE_STRING_FLAGS_FOR_NEW_LINE); if (LOCAL->cap.extlevel < BODYEXTLOC) LOCAL->cap.extlevel = BODYEXTLOC; } - while (**txtptr == ' ') imap_parse_extension (stream,txtptr,reply); + while (**txtptr == ' ' && *((*txtptr)+ 1) != ')') imap_parse_extension (stream,txtptr,reply); + while ((c = **txtptr) == ' ') ++*(txtptr); if (**txtptr != ')') { /* validate ending */ sprintf (LOCAL->tmp,"Junk at end of multipart body: %.80s", (char *) *txtptr); @@ -5252,7 +5682,7 @@ void imap_parse_body_structure (MAILSTREAM *stream,BODY *body, body->type = TYPEOTHER; /* assume unknown type */ body->encoding = ENCOTHER;/* and unknown encoding */ /* parse type */ - if (s = imap_parse_string (stream,txtptr,reply,NIL,NIL,LONGT)) { + if (s = imap_parse_string (stream,txtptr,reply,NIL,NIL,IMAP_PARSE_STRING_FLAGS_FOR_NEW_LINE)) { ucase (s); /* application always gets uppercase form */ for (i = 0; /* look in existing table */ (i <= TYPEMAX) && body_types[i] && strcmp (s,body_types[i]); i++); @@ -5262,7 +5692,7 @@ void imap_parse_body_structure (MAILSTREAM *stream,BODY *body, else body_types[i]=s; /* assign empty slot */ } } - if (body->subtype = imap_parse_string(stream,txtptr,reply,NIL,NIL,LONGT)) + if (body->subtype = imap_parse_string(stream,txtptr,reply,NIL,NIL,IMAP_PARSE_STRING_FLAGS_FOR_NEW_LINE)) ucase (body->subtype); /* parse subtype */ else { mm_notify (stream,"Missing body subtype",WARN); @@ -5270,10 +5700,10 @@ void imap_parse_body_structure (MAILSTREAM *stream,BODY *body, body->subtype = cpystr (rfc822_default_subtype (body->type)); } body->parameter = imap_parse_body_parameter (stream,txtptr,reply); - body->id = imap_parse_string (stream,txtptr,reply,NIL,NIL,LONGT); + body->id = imap_parse_string (stream,txtptr,reply,NIL,NIL,IMAP_PARSE_STRING_FLAGS_FOR_NEW_LINE); body->description = imap_parse_string (stream,txtptr,reply,NIL,NIL, - LONGT); - if (s = imap_parse_string (stream,txtptr,reply,NIL,NIL,LONGT)) { + IMAP_PARSE_STRING_FLAGS_FOR_NEW_LINE); + if (s = imap_parse_string (stream,txtptr,reply,NIL,NIL,IMAP_PARSE_STRING_FLAGS_FOR_NEW_LINE)) { ucase (s); /* application always gets uppercase form */ for (i = 0; /* search for body encoding */ (i <= ENCMAX) && body_encodings[i] && strcmp(s,body_encodings[i]); @@ -5313,21 +5743,21 @@ void imap_parse_body_structure (MAILSTREAM *stream,BODY *body, break; } - if (**txtptr == ' ') { /* extension data - md5 */ - body->md5 = imap_parse_string (stream,txtptr,reply,NIL,NIL,LONGT); + if (**txtptr == ' ' && *(*txtptr + 1) != ')') { /* extension data - md5 */ + body->md5 = imap_parse_string (stream,txtptr,reply,NIL,NIL,IMAP_PARSE_STRING_FLAGS_FOR_NEW_LINE); if (LOCAL->cap.extlevel < BODYEXTMD5) LOCAL->cap.extlevel = BODYEXTMD5; } - if (**txtptr == ' ') { /* disposition */ + if (**txtptr == ' ' && *(*txtptr + 1) != ')') { /* disposition */ imap_parse_disposition (stream,body,txtptr,reply); if (LOCAL->cap.extlevel < BODYEXTDSP) LOCAL->cap.extlevel = BODYEXTDSP; } - if (**txtptr == ' ') { /* language */ + if (**txtptr == ' ' && *(*txtptr + 1) != ')') { /* language */ body->language = imap_parse_language (stream,txtptr,reply); if (LOCAL->cap.extlevel < BODYEXTLANG) LOCAL->cap.extlevel = BODYEXTLANG; } - if (**txtptr == ' ') { /* location */ - body->location = imap_parse_string (stream,txtptr,reply,NIL,NIL,LONGT); + if (**txtptr == ' ' && *(*txtptr + 1) != ')') { /* location */ + body->location = imap_parse_string (stream,txtptr,reply,NIL,NIL,IMAP_PARSE_STRING_FLAGS_FOR_NEW_LINE); if (LOCAL->cap.extlevel < BODYEXTLOC) LOCAL->cap.extlevel = BODYEXTLOC; } while (**txtptr == ' ') imap_parse_extension (stream,txtptr,reply); @@ -5376,16 +5806,21 @@ PARAMETER *imap_parse_body_parameter (MAILSTREAM *stream, if (ret) par = par->next = mail_newbody_parameter (); else ret = par = mail_newbody_parameter (); if(!(par->attribute=imap_parse_string (stream,txtptr,reply,NIL,NIL, - LONGT))) { + IMAP_PARSE_STRING_FLAGS_FOR_NEW_LINE))) { mm_notify (stream,"Missing parameter attribute",WARN); stream->unhealthy = T; par->attribute = cpystr ("UNKNOWN"); } - if (!(par->value = imap_parse_string (stream,txtptr,reply,NIL,NIL,LONGT))){ + if (!(par->value = imap_parse_string (stream,txtptr,reply,NIL,NIL,IMAP_PARSE_STRING_FLAGS_FOR_NEW_LINE))){ sprintf (LOCAL->tmp,"Missing value for parameter %.80s",par->attribute); mm_notify (stream,LOCAL->tmp,WARN); - stream->unhealthy = T; - par->value = cpystr ("UNKNOWN"); + if (strcmp(par->attribute, "boundary") == 0) { + par->value = cpystr ("NIL"); + } + else { + stream->unhealthy = T; + par->value = cpystr ("UNKNOWN"); + } } switch (c = **txtptr) { /* see what comes after */ case ' ': /* flush whitespace */ @@ -5428,7 +5863,7 @@ void imap_parse_disposition (MAILSTREAM *stream,BODY *body, case '(': ++*txtptr; /* skip open paren */ body->disposition.type = imap_parse_string (stream,txtptr,reply,NIL,NIL, - LONGT); + IMAP_PARSE_STRING_FLAGS_FOR_NEW_LINE); body->disposition.parameter = imap_parse_body_parameter (stream,txtptr,reply); if (**txtptr != ')') { /* validate ending */ @@ -5470,7 +5905,7 @@ STRINGLIST *imap_parse_language (MAILSTREAM *stream,unsigned char **txtptr, STRINGLIST *ret = NIL; /* language is a list */ if (*++*txtptr == '(') ret = imap_parse_stringlist (stream,txtptr,reply); - else if (s = imap_parse_string (stream,txtptr,reply,NIL,&i,LONGT)) { + else if (s = imap_parse_string (stream,txtptr,reply,NIL,&i,IMAP_PARSE_STRING_FLAGS_FOR_NEW_LINE)) { (ret = mail_newstringlist ())->text.data = (unsigned char *) s; ret->text.size = i; } @@ -5635,6 +6070,9 @@ void imap_parse_capabilities (MAILSTREAM *stream,char *t) #ifdef __FEATURE_XLIST_SUPPORT__ else if (!compare_cstring (t,"XLIST")) LOCAL->cap.xlist = T; #endif /* __FEATURE_XLIST_SUPPORT__ */ +#ifdef __FEATURE_METADATA_SUPPORT__ + else if (!compare_cstring (t,"METADATA") || !compare_cstring (t,"METADATA-SERVER")) LOCAL->cap.metadata = T; +#endif /* __FEATURE_METADATA_SUPPORT__ */ /* ignore other capabilities */ } /* disable LOGIN if PLAIN also advertised */ @@ -5643,6 +6081,16 @@ void imap_parse_capabilities (MAILSTREAM *stream,char *t) (i = mail_lookup_auth_name ("LOGIN",NIL)) && (--i < MAXAUTHENTICATORS)) LOCAL->cap.auth &= ~(1 << i); } + +/* IMAP parse id + * Accepts: MAIL stream + * reply + */ + +void imap_parse_id (MAILSTREAM *stream,char *t) +{ + /* If ID information from host is needed, add parser here */ +} /* IMAP load cache * Accepts: MAIL stream @@ -5767,8 +6215,10 @@ char *imap_reform_sequence (MAILSTREAM *stream,char *sequence,long flags) char *imap_host (MAILSTREAM *stream) { - if (stream->dtb != &imapdriver) - fatal ("imap_host called on non-IMAP stream!"); + if (stream->dtb != &imapdriver) { + MM_FATAL("imap_host called on non-IMAP stream!"); + return NULL; + } /* return host name on stream if open */ return (LOCAL && LOCAL->netstream) ? net_host (LOCAL->netstream) : ".NO-IMAP-CONNECTION."; @@ -5782,7 +6232,9 @@ char *imap_host (MAILSTREAM *stream) IMAPCAP *imap_cap (MAILSTREAM *stream) { - if (stream->dtb != &imapdriver) - fatal ("imap_cap called on non-IMAP stream!"); + if (stream->dtb != &imapdriver) { + MM_FATAL("imap_cap called on non-IMAP stream!"); + return NULL; + } return &LOCAL->cap; /* return capability structure */ } diff --git a/imap-2007e/c-client/imap4r1.h b/imap-2007e/c-client/imap4r1.h index 3f94c68..e8f5ffe 100755 --- a/imap-2007e/c-client/imap4r1.h +++ b/imap-2007e/c-client/imap4r1.h @@ -93,6 +93,9 @@ typedef struct imap_cap { #ifdef __FEATURE_XLIST_SUPPORT__ unsigned int xlist : 1; #endif /* __FEATURE_XLIST_SUPPORT__ */ +#ifdef __FEATURE_METADATA_SUPPORT__ + unsigned int metadata : 1; +#endif /* __FEATURE_METADATA_SUPPORT__ */ } IMAPCAP; /* IMAP4rev1 level or better */ @@ -249,6 +252,14 @@ typedef struct imap_cap { /* Has WITHIN extension */ #define LEVELWITHIN(stream) imap_cap (stream)->within + + +#ifdef __FEATURE_METADATA_SUPPORT__ +/* Has METADATA extension */ + +#define LEVELMETADATA(stream) imap_cap (stream)->metadata +#endif /* __FEATURE_METADATA_SUPPORT__ */ + /* Body structure extension levels */ @@ -282,3 +293,9 @@ long imap_myrights (MAILSTREAM *stream,char *mailbox); long imap_setquota (MAILSTREAM *stream,char *qroot,STRINGLIST *limits); long imap_getquota (MAILSTREAM *stream,char *qroot); long imap_getquotaroot (MAILSTREAM *stream,char *mailbox); + +#ifdef __FEATURE_METADATA_SUPPORT__ +/* RFC5464 - METADATA extension */ +char *imap_getmetadata (MAILSTREAM *stream, char *mailbox, char *entry); +long imap_setmetadata (MAILSTREAM *stream, char *mailbox, char *entry, char *value); +#endif /* __FEATURE_METADATA_SUPPORT__ */ diff --git a/imap-2007e/c-client/linkage.c b/imap-2007e/c-client/linkage.c index 66fb599..9de09a7 100755 --- a/imap-2007e/c-client/linkage.c +++ b/imap-2007e/c-client/linkage.c @@ -17,6 +17,7 @@ auth_link (&auth_md5); /* link in the md5 authenticator */ auth_link (&auth_pla); /* link in the pla authenticator */ auth_link (&auth_log); /* link in the log authenticator */ + auth_link (&auth_xoauth2); /* link in the xoauth2 authenticator */ mail_versioncheck (CCLIENTVERSION); ssl_onceonlyinit (); mail_parameters (NIL,SET_DISABLEPLAINTEXT,(void *) 2); diff --git a/imap-2007e/c-client/linkage.h b/imap-2007e/c-client/linkage.h index e7ed506..7fe61dd 100755 --- a/imap-2007e/c-client/linkage.h +++ b/imap-2007e/c-client/linkage.h @@ -17,3 +17,4 @@ extern AUTHENTICATOR auth_ext; extern AUTHENTICATOR auth_md5; extern AUTHENTICATOR auth_pla; extern AUTHENTICATOR auth_log; +extern AUTHENTICATOR auth_xoauth2; diff --git a/imap-2007e/c-client/lnx_mail.c b/imap-2007e/c-client/lnx_mail.c index 6ed835b..15ce4e1 100755 --- a/imap-2007e/c-client/lnx_mail.c +++ b/imap-2007e/c-client/lnx_mail.c @@ -22,7 +22,6 @@ #include "mail.c" -//#include "em-core-utils.h" #include #include #include @@ -43,14 +42,15 @@ #include "tcp_unix.h" +#define RETRY_COUNT_LIMITATION 3 -long -tcp_getdata_lnx(TCPSTREAM* stream) +long tcp_getdata_lnx(TCPSTREAM* stream) { struct timeval tmout; fd_set readfds; int nread, sret, sockid, maxfd; - int max_timeout = 0; + int retry_count = 0; + long ttmo_read = (long) mail_parameters (NIL, GET_READTIMEOUT, NIL); sockid = stream->tcpsi; maxfd = sockid + 1; @@ -59,8 +59,8 @@ tcp_getdata_lnx(TCPSTREAM* stream) while (stream->ictr < 1) { - tmout.tv_usec = 0;//1000*10; - tmout.tv_sec = 1; + tmout.tv_usec = 0; + tmout.tv_sec = ttmo_read ? ttmo_read : 5; FD_ZERO(&readfds); FD_SET(sockid, &readfds); @@ -72,27 +72,25 @@ tcp_getdata_lnx(TCPSTREAM* stream) return false; } else if (!sret) { - if (max_timeout >= 50) { - IMAP_DEBUG_EXCEPTION("max select timeout %d", max_timeout); - - //em_core_set_network_error(EMF_ERROR_NO_RESPONSE); + if (retry_count >= RETRY_COUNT_LIMITATION) { + IMAP_DEBUG_EXCEPTION("retry_count exceeded limitation", retry_count); return false; } - IMAP_DEBUG_EXCEPTION("%d select timeout", max_timeout); + IMAP_DEBUG_EXCEPTION("retry_count [%d]", retry_count); - ++max_timeout; + ++retry_count; continue; } if ((nread = read(sockid, stream->ibuf, BUFLEN)) < 0) { - IMAP_DEBUG_EXCEPTION("\t socket read failed...\n"); + IMAP_DEBUG_EXCEPTION("socket read failed..."); tcp_abort(stream); return false; } if (!nread) { - IMAP_DEBUG_EXCEPTION("\t socket read no data...\n"); + IMAP_DEBUG_EXCEPTION("socket read empty data..."); tcp_abort(stream); return false; } @@ -154,31 +152,11 @@ char *tcp_getline_lnx (void *vstream) } #endif - -int try_auth = 0; unsigned int mail_lookup_auth_name (char *mechanism,long flags) { int i; AUTHENTICATOR *auth; - if(!try_auth) return 0; - - for (i = 1, auth = mailauthenticators; auth; i++, auth = auth->next) - if (auth->client && !(flags & ~auth->flags) && - !compare_cstring (auth->name,mechanism)) - return i; - return 0; -} - -// 22-Mar-2010 added -int try_auth_smtp = 0; -unsigned int mail_lookup_auth_name_smtp (char *mechanism,long flags) -{ - int i; - AUTHENTICATOR *auth; - - if(!try_auth_smtp) return 0; - for (i = 1, auth = mailauthenticators; auth; i++, auth = auth->next) if (auth->client && !(flags & ~auth->flags) && !compare_cstring (auth->name,mechanism)) diff --git a/imap-2007e/c-client/mail.c b/imap-2007e/c-client/mail.c index a4ffc43..5b2b737 100755 --- a/imap-2007e/c-client/mail.c +++ b/imap-2007e/c-client/mail.c @@ -217,7 +217,7 @@ void *mm_cache (MAILSTREAM *stream,unsigned long msgno,long op) stream->sc[i] = NIL; break; default: - fatal ("Bad mm_cache op"); + MM_FATAL("Bad mm_cache op"); break; } return ret; @@ -328,24 +328,28 @@ void *mail_parameters (MAILSTREAM *stream,long function,void *value) AUTHENTICATOR *a; switch ((int) function) { case SET_INBOXPATH: - fatal ("SET_INBOXPATH not permitted"); + MM_FATAL ("SET_INBOXPATH not permitted"); + return NULL; case GET_INBOXPATH: if ((stream || (stream = mail_open (NIL,"INBOX",OP_PROTOTYPE))) && stream->dtb) ret = (*stream->dtb->parameters) (function,value); break; case SET_THREADERS: - fatal ("SET_THREADERS not permitted"); + MM_FATAL ("SET_THREADERS not permitted"); + return NULL; case GET_THREADERS: /* use stream dtb instead of global */ ret = (stream && stream->dtb) ? /* KLUDGE ALERT: note stream passed as value */ (*stream->dtb->parameters) (function,stream) : (void *) &mailthreadlist; break; case SET_NAMESPACE: - fatal ("SET_NAMESPACE not permitted"); - break; + MM_FATAL ("SET_NAMESPACE not permitted"); + return NULL; case SET_NEWSRC: /* too late on open stream */ - if (stream && stream->dtb && (stream != ((*stream->dtb->open) (NIL)))) - fatal ("SET_NEWSRC not permitted"); + if (stream && stream->dtb && (stream != ((*stream->dtb->open) (NIL)))) { + MM_FATAL ("SET_NEWSRC not permitted"); + return NULL; + } else ret = env_parameters (function,value); break; case GET_NAMESPACE: @@ -356,24 +360,31 @@ void *mail_parameters (MAILSTREAM *stream,long function,void *value) env_parameters (function,value); break; case ENABLE_DEBUG: - fatal ("ENABLE_DEBUG not permitted"); + MM_FATAL ("ENABLE_DEBUG not permitted"); + return NULL; case DISABLE_DEBUG: - fatal ("DISABLE_DEBUG not permitted"); + MM_FATAL ("DISABLE_DEBUG not permitted"); + return NULL; case SET_DIRFMTTEST: - fatal ("SET_DIRFMTTEST not permitted"); + MM_FATAL ("SET_DIRFMTTEST not permitted"); + return NULL; case GET_DIRFMTTEST: if (!(stream && stream->dtb && - (ret = (*stream->dtb->parameters) (function,NIL)))) - fatal ("GET_DIRFMTTEST not permitted"); + (ret = (*stream->dtb->parameters) (function,NIL)))) { + MM_FATAL ("GET_DIRFMTTEST not permitted"); + return NULL; + } break; case SET_DRIVERS: - fatal ("SET_DRIVERS not permitted"); + MM_FATAL ("SET_DRIVERS not permitted"); + return NULL; case GET_DRIVERS: /* always return global */ ret = (void *) maildrivers; break; case SET_DRIVER: - fatal ("SET_DRIVER not permitted"); + MM_FATAL ("SET_DRIVER not permitted"); + return NULL; case GET_DRIVER: for (d = maildrivers; d && compare_cstring (d->name,(char *) value); d = d->next); @@ -636,7 +647,10 @@ void *mail_parameters (MAILSTREAM *stream,long function,void *value) if (stream->snarf.name) fs_give ((void **) &stream->snarf.name); stream->snarf.name = cpystr ((char *) value); } - else fatal ("SET_SNARFMAILBOXNAME with no stream"); + else { + MM_FATAL ("SET_SNARFMAILBOXNAME with no stream"); + return NULL; + } case GET_SNARFMAILBOXNAME: if (stream) ret = (void *) stream->snarf.name; break; @@ -806,9 +820,14 @@ long mail_valid_net_parse_work (char *name,NETMBX *mb,char *service) else if (!compare_cstring (s,"loser")) mb->loser = T; else if (!compare_cstring (s,"tls") && !mb->notlsflag) mb->tlsflag = T; - //APOP Authentication - shasikala.p@siso.com else if (!compare_cstring (s,"apop")) mb->apop = T; + else if (!compare_cstring (s,"force_tls_v1_0")) + mb->force_tls_v1_0 = T; + else if (!compare_cstring (s,"needauth")) + mb->auth_method = AUTH_METHOD_DEFAULT; + else if (!compare_cstring (s,"xoauth2")) + mb->auth_method = AUTH_METHOD_XOAUTH2; else if (!compare_cstring (s,"tls-sslv23") && !mb->notlsflag) mb->tlssslv23 = mb->tlsflag = T; else if (!compare_cstring (s,"notls") && !mb->tlsflag) @@ -1260,7 +1279,10 @@ MAILSTREAM *mail_open (MAILSTREAM *stream,char *name,long options) d = mail_valid (NIL,name,(options & OP_SILENT) ? (char *) NIL : "open mailbox"); } - return d ? mail_open_work (d,stream,name,options) : stream; + if(d) + return mail_open_work (d,stream,name,options); + + return stream; } /* Mail open worker routine @@ -1276,16 +1298,17 @@ MAILSTREAM *mail_open_work (DRIVER *d,MAILSTREAM *stream,char *name, { int i; char tmp[MAILTMPLEN]; + char *local_mailbox_name = NULL; NETMBX mb; if (options & OP_PROTOTYPE) return (*d->open) (NIL); /* name is copied here in case the caller does a re-open using * stream->mailbox or stream->original_mailbox as the argument. */ - name = cpystr (name); /* make copy of name */ + local_mailbox_name = cpystr (name); /* make copy of name */ if (stream) { /* recycling requested? */ if ((stream->dtb == d) && (d->flags & DR_RECYCLE) && ((d->flags & DR_HALFOPEN) || !(options & OP_HALFOPEN)) && - mail_usable_network_stream (stream,name)) { + mail_usable_network_stream (stream,local_mailbox_name)) { /* yes, checkpoint if needed */ if (d->flags & DR_XPOINT) mail_check (stream); mail_free_cache (stream); /* clean up stream */ @@ -1308,7 +1331,7 @@ MAILSTREAM *mail_open_work (DRIVER *d,MAILSTREAM *stream,char *name, } /* check if driver does not support halfopen */ else if ((options & OP_HALFOPEN) && !(d->flags & DR_HALFOPEN)) { - fs_give ((void **) &name); + fs_give ((void **) &local_mailbox_name); return NIL; } @@ -1318,7 +1341,7 @@ MAILSTREAM *mail_open_work (DRIVER *d,MAILSTREAM *stream,char *name, sizeof (MAILSTREAM)),(long) 0,CH_INIT); stream->dtb = d; /* set dispatch */ /* set mailbox name */ - stream->mailbox = cpystr (stream->original_mailbox = name); + stream->mailbox = cpystr (stream->original_mailbox = local_mailbox_name); /* initialize stream flags */ stream->inbox = stream->lock = NIL; stream->debug = (options & OP_DEBUG) ? T : NIL; @@ -1350,9 +1373,15 @@ MAILSTREAM *mail_open_work (DRIVER *d,MAILSTREAM *stream,char *name, MAILSTREAM *mail_close_full (MAILSTREAM *stream,long options) { int i; + char tmp[MAILTMPLEN] = { 0, }; if (stream) { /* make sure argument given */ - /* do the driver's close action */ - if (stream->dtb) (*stream->dtb->close) (stream,options); + if(stream->unhealthy) { + snprintf (tmp, MAILTMPLEN, "Checking 'unhealthy' flag of MAILSTEAM.. [%d]", stream->unhealthy); + MM_LOG (tmp,(long)WARN); + return NIL; + } + /* do the driver's close action */ + if (stream->dtb && stream->dtb->close) (*stream->dtb->close) (stream,options); stream->dtb = NIL; /* resign driver */ if (stream->mailbox) fs_give ((void **) &stream->mailbox); if (stream->original_mailbox) @@ -1428,7 +1457,8 @@ MESSAGECACHE *mail_elt (MAILSTREAM *stream,unsigned long msgno) char tmp[MAILTMPLEN]; sprintf (tmp,"Bad msgno %lu in mail_elt, nmsgs = %lu, mbx=%.80s", msgno,stream->nmsgs,stream->mailbox ? stream->mailbox : "???"); - fatal (tmp); + MM_FATAL (tmp); + return NULL; } return (MESSAGECACHE *) (*mailcache) (stream,msgno,CH_MAKEELT); } @@ -2071,7 +2101,10 @@ long mail_partial_text (MAILSTREAM *stream,unsigned long msgno,char *section, BODY *b; char tmp[MAILTMPLEN]; unsigned long i; - if (!mailgets) fatal ("mail_partial_text() called without a mailgets!"); + if (!mailgets) { + MM_FATAL ("mail_partial_text() called without a mailgets!"); + return NIL; + } if (section && (strlen (section) > (MAILTMPLEN - 20))) return NIL; if (flags & FT_UID) { /* UID form of call */ if (msgno = mail_msgno (stream,msgno)) flags &= ~FT_UID; @@ -2142,7 +2175,10 @@ long mail_partial_body (MAILSTREAM *stream,unsigned long msgno,char *section, unsigned long i; if (!(section && *section)) /* top-level text wanted? */ return mail_partial_text (stream,msgno,NIL,first,last,flags); - if (!mailgets) fatal ("mail_partial_body() called without a mailgets!"); + if (!mailgets) { + MM_FATAL ("mail_partial_body() called without a mailgets!"); + return NIL; + } if (flags & FT_UID) { /* UID form of call */ if (msgno = mail_msgno (stream,msgno)) flags &= ~FT_UID; else return NIL; /* must get UID/msgno map first */ @@ -2590,9 +2626,9 @@ long mail_copy_full (MAILSTREAM *stream,char *sequence,char *mailbox, /* Append data package to use for old single-message mail_append() interface */ typedef struct mail_append_package { - char *flags; /* initial flags */ - char *date; /* message internal date */ - STRING *message; /* stringstruct of message */ + char *flags; /* initial flags */ + char *date; /* message internal date */ + STRING *message; /* stringstruct of message */ } APPENDPACKAGE; @@ -2616,6 +2652,39 @@ static long mail_append_single (MAILSTREAM *stream,void *data,char **flags, return LONGT; /* always return success */ } +static long mail_append_single_command (MAILSTREAM *stream,void *data,char **flags, + char **date,STRING **message) +{ + APPENDPACKAGE *ap = (APPENDPACKAGE *) data; + *flags = ap->flags; /* get desired data from the package */ + *date = ap->date; + *message = ap->message; + ap->message = NIL; /* so next callback puts a stop to it */ + return 2; /* always return success */ +} + +static long mail_append_single_message (MAILSTREAM *stream,void *data,char **flags, + char **date,STRING **message) +{ + APPENDPACKAGE *ap = (APPENDPACKAGE *) data; + *flags = ap->flags; /* get desired data from the package */ + *date = ap->date; + *message = ap->message; + ap->message = NIL; /* so next callback puts a stop to it */ + return 3; /* always return success */ +} + +static long mail_append_single_end (MAILSTREAM *stream,void *data,char **flags, + char **date,STRING **message) +{ + APPENDPACKAGE *ap = (APPENDPACKAGE *) data; + *flags = ap->flags; /* get desired data from the package */ + *date = ap->date; + *message = ap->message; + ap->message = NIL; /* so next callback puts a stop to it */ + return 4; /* always return success */ +} + /* Mail append message string * Accepts: mail stream @@ -2635,7 +2704,34 @@ long mail_append_full (MAILSTREAM *stream,char *mailbox,char *flags,char *date, ap.message = message; return mail_append_multiple (stream,mailbox,mail_append_single,(void *) &ap); } - + +long mail_append_command (MAILSTREAM *stream,char *mailbox,char *flags,char *date, STRING *message) +{ + APPENDPACKAGE ap; + ap.flags = flags; /* load append package */ + ap.date = date; + ap.message = message; + return mail_append_multiple (stream,mailbox,mail_append_single_command,(void *) &ap); +} + +long mail_append_message (MAILSTREAM *stream,char *mailbox,STRING *message) +{ + APPENDPACKAGE ap; + ap.flags = NULL; + ap.date = NULL; + ap.message = message; + return mail_append_multiple (stream,mailbox,mail_append_single_message,(void *) &ap); +} + +long mail_append_end (MAILSTREAM *stream,char *mailbox) +{ + APPENDPACKAGE ap; + ap.flags = NULL; + ap.date = NULL; + ap.message = NULL; + return mail_append_multiple (stream,mailbox,mail_append_single_end,(void *) &ap); +} + /* Mail append message(s) * Accepts: mail stream * destination mailbox @@ -2644,52 +2740,53 @@ long mail_append_full (MAILSTREAM *stream,char *mailbox,char *flags,char *date, * Returns: T on success, NIL on failure */ -long mail_append_multiple (MAILSTREAM *stream,char *mailbox,append_t af, - void *data) +long mail_append_multiple (MAILSTREAM *stream,char *mailbox,append_t af,void *data) { - char *s,tmp[MAILTMPLEN]; - DRIVER *d = NIL; - long ret = NIL; - /* never allow names with newlines */ - if (strpbrk (mailbox,"\015\012")) - MM_LOG ("Can't append to mailbox with such a name",ERROR); - else if (strlen (mailbox) >= - (NETMAXHOST+(NETMAXUSER*2)+NETMAXMBX+NETMAXSRV+50)) { - sprintf (tmp,"Can't append %.80s: %s",mailbox,(*mailbox == '{') ? - "invalid remote specification" : "no such mailbox"); - MM_LOG (tmp,ERROR); - } - /* special driver hack? */ - else if (!strncmp (lcase (strcpy (tmp,mailbox)),"#driver.",8)) { - /* yes, tie off name at likely delimiter */ - if (!(s = strpbrk (tmp+8,"/\\:"))) { - sprintf (tmp,"Can't append to mailbox %.80s: bad driver syntax",mailbox); - MM_LOG (tmp,ERROR); - return NIL; - } - *s++ = '\0'; /* tie off at delimiter */ - if (!(d = (DRIVER *) mail_parameters (NIL,GET_DRIVER,tmp+8))) { - sprintf (tmp,"Can't append to mailbox %.80s: unknown driver",mailbox); - MM_LOG (tmp,ERROR); - } - else ret = SAFE_APPEND (d,stream,mailbox + (s - tmp),af,data); - } - else if (d = mail_valid (stream,mailbox,NIL)) - ret = SAFE_APPEND (d,stream,mailbox,af,data); - /* No driver, try for TRYCREATE if no stream. Note that we use the - * createProto here, not the appendProto, since the dummy driver already - * took care of the appendProto case. Otherwise, if appendProto is set to - * NIL, we won't get a TRYCREATE. - */ - else if (!stream && (stream = default_proto (NIL)) && stream->dtb && - SAFE_APPEND (stream->dtb,stream,mailbox,af,data)) - /* timing race? */ - MM_NOTIFY (stream,"Append validity confusion",WARN); - /* generate error message */ - else mail_valid (stream,mailbox,"append to mailbox"); - return ret; + char *s,tmp[MAILTMPLEN]; + DRIVER *d = NIL; + long ret = NIL; + + /* never allow names with newlines */ + if (strpbrk (mailbox,"\015\012")) + MM_LOG ("Can't append to mailbox with such a name",ERROR); + else if (strlen (mailbox) >= (NETMAXHOST+(NETMAXUSER*2)+NETMAXMBX+NETMAXSRV+50)) { + sprintf (tmp,"Can't append %.80s: %s",mailbox,(*mailbox == '{') ? "invalid remote specification" : "no such mailbox"); + MM_LOG (tmp,ERROR); + } + /* special driver hack? */ + else if (!strncmp (lcase (strcpy (tmp,mailbox)),"#driver.",8)) { + /* yes, tie off name at likely delimiter */ + if (!(s = strpbrk (tmp+8,"/\\:"))) { + sprintf (tmp,"Can't append to mailbox %.80s: bad driver syntax",mailbox); + MM_LOG (tmp,ERROR); + return NIL; + } + *s++ = '\0'; /* tie off at delimiter */ + + if (!(d = (DRIVER *) mail_parameters (NIL,GET_DRIVER,tmp+8))) { + sprintf (tmp,"Can't append to mailbox %.80s: unknown driver",mailbox); + MM_LOG (tmp,ERROR); + } else + ret = SAFE_APPEND (d,stream,mailbox + (s - tmp),af,data); + } + else if (d = mail_valid (stream,mailbox,NIL)) + ret = SAFE_APPEND (d,stream,mailbox,af,data); + /* No driver, try for TRYCREATE if no stream. Note that we use the + * createProto here, not the appendProto, since the dummy driver already + * took care of the appendProto case. Otherwise, if appendProto is set to + * NIL, we won't get a TRYCREATE. + */ + else if (!stream && (stream = default_proto (NIL)) && stream->dtb && SAFE_APPEND (stream->dtb,stream,mailbox,af,data)) + /* timing race? */ + MM_NOTIFY (stream,"Append validity confusion",WARN); + /* generate error message */ + + else + mail_valid (stream,mailbox,"append to mailbox"); + + return ret; } - + /* Mail garbage collect stream * Accepts: mail stream * garbage collection flags @@ -3262,7 +3359,7 @@ void mail_lock (MAILSTREAM *stream) char tmp[MAILTMPLEN]; sprintf (tmp,"Lock when already locked, mbx=%.80s", stream->mailbox ? stream->mailbox : "???"); - fatal (tmp); + MM_FATAL (tmp); } else stream->lock = T; /* lock stream */ } @@ -3274,7 +3371,7 @@ void mail_lock (MAILSTREAM *stream) void mail_unlock (MAILSTREAM *stream) { - if (!stream->lock) fatal ("Unlock when not locked"); + if (!stream->lock) MM_FATAL ("Unlock when not locked"); else stream->lock = NIL; /* unlock stream */ } @@ -4005,7 +4102,8 @@ char *mail_search_gets (readfn_t f,void *stream,unsigned long size, sprintf (tmp,"Search botch, mbx = %.80s, %s = %lu[%.80s]", md->stream->mailbox, (md->flags & FT_UID) ? "UID" : "msg",md->msgno,md->what); - fatal (tmp); + MM_FATAL (tmp); + return NIL; } /* initially no match for search */ md->stream->private.search.result = NIL; @@ -4076,6 +4174,10 @@ SEARCHPGM *mail_criteria (char *criteria) else if (!strcmp (criterion+1,"ROM")) f = mail_criteria_string (&pgm->from,&r); break; + case 'H': /* possible HEADER */ + if (!strcmp (criterion+1,"EADER")) + f = mail_criteria_header_string (&pgm->header, &r); + break; case 'K': /* possible KEYWORD */ if (!strcmp (criterion+1,"EYWORD")) f = mail_criteria_string (&pgm->keyword,&r); @@ -4157,6 +4259,25 @@ int mail_criteria_date (unsigned short *date,char **r) * Returns: shortdate */ +int mail_criteria_header_string(SEARCHHEADER **hdr, char **r) +{ + unsigned long line_n, text_n; + char e,*d,*end = " ",*c = strtok_r (NIL,"",r); + char *line, *text; + if (!c) return NIL; + + if (line = strtok_r (c,end,r)) line_n = strlen (line); + else return NIL; + + if (text = strtok_r (NIL,end,r)) text_n = strlen (text); + else return NIL; + + while (*hdr) hdr = &(*hdr)->next; + *hdr = mail_newsearchheader(line, text); + + return T; +} + unsigned short mail_shortdate (unsigned int year,unsigned int month, unsigned int day) { @@ -4555,7 +4676,8 @@ SORTCACHE **mail_sort_loadcache (MAILSTREAM *stream,SORTPGM *pgm) } break; default: - fatal ("Unknown sort function"); + MM_FATAL ("Unknown sort function"); + return NIL; } } return sc; @@ -4882,7 +5004,10 @@ THREADNODE *mail_thread_orderedsubject (MAILSTREAM *stream,char *charset, tc = (THREADNODE **) fs_get (i * sizeof (THREADNODE *)); /* load threadnode cache */ for (j = 0, cur = thr; cur; cur = cur->branch) tc[j++] = cur; - if (i != j) fatal ("Threadnode cache confusion"); + if (i != j) { + MM_FATAL ("Threadnode cache confusion"); + return NIL; + } qsort ((void *) tc,i,sizeof (THREADNODE *),mail_thread_compare_date); for (j = 0, --i; j < i; j++) tc[j]->branch = tc[j+1]; tc[j]->branch = NIL; /* end of root */ @@ -6226,6 +6351,9 @@ NETSTREAM *net_open (NETMBX *mb,NETDRIVER *dv,unsigned long port, NETSTREAM *stream = NIL; char tmp[MAILTMPLEN]; unsigned long flags = mb->novalidate ? NET_NOVALIDATECERT : 0; + + flags |= (mb->force_tls_v1_0) ? NET_FORCE_LOWER_TLS_VERSION : 0; + if (strlen (mb->host) >= NETMAXHOST) { sprintf (tmp,"Invalid host name: %.80s",mb->host); MM_LOG (tmp,ERROR); @@ -6339,6 +6467,7 @@ long net_getbuffer (void *st,unsigned long size,char *buffer) long net_soutr (NETSTREAM *stream,char *string) { + if (!stream) return NIL; return (*stream->dtb->soutr) (stream->stream,string); } @@ -6352,6 +6481,7 @@ long net_soutr (NETSTREAM *stream,char *string) long net_sout (NETSTREAM *stream,char *string,unsigned long size) { + if (!stream) return NIL; return (*stream->dtb->sout) (stream->stream,string,size); } @@ -6361,6 +6491,7 @@ long net_sout (NETSTREAM *stream,char *string,unsigned long size) void net_close (NETSTREAM *stream) { + if (!stream) return; if (stream->stream) (*stream->dtb->close) (stream->stream); fs_give ((void **) &stream); } @@ -6373,6 +6504,8 @@ void net_close (NETSTREAM *stream) char *net_host (NETSTREAM *stream) { + if(stream == NULL || stream->stream == NULL) + return ""; return (*stream->dtb->host) (stream->stream); } @@ -6384,6 +6517,8 @@ char *net_host (NETSTREAM *stream) char *net_remotehost (NETSTREAM *stream) { + if(stream == NULL || stream->stream == NULL) + return ""; return (*stream->dtb->remotehost) (stream->stream); } @@ -6394,6 +6529,8 @@ char *net_remotehost (NETSTREAM *stream) unsigned long net_port (NETSTREAM *stream) { + if(stream == NULL || stream->stream == NULL) + return 0; return (*stream->dtb->port) (stream->stream); } @@ -6405,5 +6542,7 @@ unsigned long net_port (NETSTREAM *stream) char *net_localhost (NETSTREAM *stream) { + if(stream == NULL || stream->stream == NULL) + return ""; return (*stream->dtb->localhost) (stream->stream); } diff --git a/imap-2007e/c-client/mail.h b/imap-2007e/c-client/mail.h index 138b162..10489b0 100755 --- a/imap-2007e/c-client/mail.h +++ b/imap-2007e/c-client/mail.h @@ -413,6 +413,8 @@ #define OP_NOKOD (long) 0x800 /* suppress kiss-of-death */ #define OP_SNIFF (long) 0x1000 /* metadata only open */ /* reserved for application use */ + +#define OP_FORCE_LOWER_TLS_VERSION 0x2000 /* force lower TLS version */ #define OP_RESERVED (unsigned long) 0xff000000 @@ -428,6 +430,8 @@ #define NET_TLSCLIENT ((unsigned long) 0x10000000) /* try SSL mode */ #define NET_TRYSSL ((unsigned long) 0x8000000) + /* force lower TLS version */ +#define NET_FORCE_LOWER_TLS_VERSION ((unsigned long) 0x4000000) /* Close options */ @@ -587,6 +591,9 @@ #endif /* __FEATURE_XLIST_SUPPORT__ */ +#define AUTH_METHOD_NONE 0 +#define AUTH_METHOD_DEFAULT 1 +#define AUTH_METHOD_XOAUTH2 2 /* Sort functions */ @@ -678,7 +685,9 @@ typedef struct net_mailbox { unsigned int norsh : 1; /* don't use rsh/ssh */ unsigned int loser : 1; /* server is a loser */ unsigned int tlssslv23 : 1; /* force SSLv23 client method over TLS */ - unsigned int apop; /*APOP Authentication - shasikala.p@siso.com*/ + unsigned int apop; /*APOP Authentication */ + unsigned int force_tls_v1_0 : 1; /* force TLS v1.0 */ + unsigned int auth_method; /* Authentication method */ } NETMBX; /* Item in an address list */ @@ -1612,7 +1621,15 @@ DRIVER { #define MM_FLAGS mm_flags #define MM_NOTIFY mm_notify #define MM_STATUS mm_status -#define MM_LOG mm_log +/* #define MM_LOG mm_log */ +#define MM_LOG(str, errflg) \ + do {\ + char *path_log = g_strdup_printf("%s (%d)> %s", __FUNCTION__, __LINE__, str);\ + mm_log(path_log, errflg);\ + g_free(path_log);\ + path_log = NULL;\ + } while(0) + #define MM_CRITICAL mm_critical #define MM_NOCRITICAL mm_nocritical #define MM_DISKERROR mm_diskerror @@ -1637,6 +1654,9 @@ void mm_nocritical (MAILSTREAM *stream); long mm_diskerror (MAILSTREAM *stream,long errcode,long serious); void mm_fatal (char *string); void *mm_cache (MAILSTREAM *stream,unsigned long msgno,long op); +#ifdef __FEATURE_IMAP_ID_SUPPORT__ +void mm_imap_id (char **id_string); +#endif /* __FEATURE_IMAP_ID_SUPPORT__ */ extern STRINGDRIVER mail_string; void mail_versioncheck (char *version); @@ -1715,6 +1735,9 @@ long mail_copy_full (MAILSTREAM *stream,char *sequence,char *mailbox, long options); long mail_append_full (MAILSTREAM *stream,char *mailbox,char *flags,char *date, STRING *message); +long mail_append_command (MAILSTREAM *stream,char *mailbox,char *flags,char *date, STRING *message); +long mail_append_message (MAILSTREAM *stream,char *mailbox,STRING *message); +long mail_append_end (MAILSTREAM *stream,char *mailbox); long mail_append_multiple (MAILSTREAM *stream,char *mailbox,append_t af, void *data); void mail_gc (MAILSTREAM *stream,long gcflags); @@ -1755,6 +1778,7 @@ char *mail_search_gets (readfn_t f,void *stream,unsigned long size, SEARCHPGM *mail_criteria (char *criteria); int mail_criteria_date (unsigned short *date,char **r); int mail_criteria_string (STRINGLIST **s,char **r); +int mail_criteria_header_string (SEARCHHEADER **hdr, char **r); unsigned short mail_shortdate (unsigned int year,unsigned int month, unsigned int day); SEARCHSET *mail_parse_set (char *s,char **ret); diff --git a/imap-2007e/c-client/osdep.c b/imap-2007e/c-client/osdep.c index 61a5972..c38742b 100755 --- a/imap-2007e/c-client/osdep.c +++ b/imap-2007e/c-client/osdep.c @@ -257,6 +257,7 @@ void ssl_onceonlyinit (void) mail_parameters (NIL,SET_SSLDRIVER,(void *) &ssldriver); mail_parameters (NIL,SET_SSLSTART,(void *) ssl_start); SSL_library_init (); /* add all algorithms */ + SSL_load_error_strings(); } } @@ -327,11 +328,12 @@ static SSLSTREAM *ssl_start (TCPSTREAM *tstream,char *host,unsigned long flags) /* pass to error callback */ else if (sf) (*sf) (host,reason,flags); else { /* no error callback, build error message */ - sprintf (tmp,"TLS/SSL failure for %.80s: %.512s",host,reason); - mm_log (tmp,ERROR); + sprintf (tmp,"TLS/SSL failure for %.80s: %.512s",host,reason); + mm_log (tmp,ERROR); } break; } + free (reason); /* OpenSSL error buf */ } return stream; } @@ -347,7 +349,7 @@ static SSLSTREAM *ssl_start (TCPSTREAM *tstream,char *host,unsigned long flags) static char *ssl_last_error = NIL; static char *ssl_last_host = NIL; -/* #define __NON_BLOCKING_SSL_WRITE__ */ +#define __NON_BLOCKING_SSL_WRITE__ #ifdef __NON_BLOCKING_SSL_WRITE__ /* g.shyamakshi@samsung.com @@ -399,9 +401,26 @@ static char *ssl_start_work (SSLSTREAM *stream,char *host,unsigned long flags) ssl_last_host = host; if (!(stream->context = SSL_CTX_new ((flags & NET_TLSCLIENT) ? TLSv1_client_method () : - SSLv23_client_method ()))) - return "SSL context failed"; - SSL_CTX_set_options (stream->context,0); + SSLv23_client_method ()))) { + /* bio to memory buf */ + BIO *bio = BIO_new (BIO_s_mem ()); + ERR_print_errors (bio); + char *buf = NULL; + size_t len = BIO_get_mem_data (bio, &buf); + char *ret = (char *) calloc (1, 1 + len + 40); + if (ret) { + memcpy (ret, buf , len); + } + sprintf (ret+len, ": SSL context failed [0x%x] ", flags & NET_TLSCLIENT); + BIO_free (bio); + return ret; +// return "SSL context failed"; + } + if (flags & NET_FORCE_LOWER_TLS_VERSION) + SSL_CTX_set_options(stream->context, SSL_OP_NO_SSLv2|SSL_OP_NO_TLSv1_1|SSL_OP_NO_TLSv1_2); + else + SSL_CTX_set_options (stream->context,0); + /* disable certificate validation? */ if (flags & NET_NOVALIDATECERT) SSL_CTX_set_verify (stream->context,SSL_VERIFY_NONE,NIL); @@ -418,7 +437,7 @@ static char *ssl_start_work (SSLSTREAM *stream,char *host,unsigned long flags) X509_free (cert); } BIO_free (bio); - if (!cert) return "SSL client certificate failed"; + if (!cert) return strdup("SSL client certificate failed"); /* want to supply private key? */ if ((t = (sck ? (*sck) () : s)) && (tl = strlen (t))) { EVP_PKEY *key; @@ -435,23 +454,33 @@ static char *ssl_start_work (SSLSTREAM *stream,char *host,unsigned long flags) /* create connection */ if (!(stream->con = (SSL *) SSL_new (stream->context))) - return "SSL connection failed"; + return strdup("SSL connection failed"); bio = BIO_new_socket (stream->tcpstream->tcpsi,BIO_NOCLOSE); SSL_set_bio (stream->con,bio,bio); SSL_set_connect_state (stream->con); if (SSL_in_init (stream->con)) SSL_total_renegotiations (stream->con); /* now negotiate SSL */ if (SSL_write (stream->con,"",0) < 0) - return ssl_last_error ? ssl_last_error : "SSL negotiation failed"; + return strdup(ssl_last_error ? ssl_last_error : "SSL negotiation failed"); /* need to validate host names? */ - if (!(flags & NET_NOVALIDATECERT) && - (err = ssl_validate_cert (cert = SSL_get_peer_certificate (stream->con), - host))) { - /* application callback */ - if (scq) return (*scq) (err,host,cert ? cert->name : "???") ? NIL : ""; - /* error message to return via mm_log() */ - sprintf (tmp,"*%.128s: %.255s",err,cert ? cert->name : "???"); - return ssl_last_error = cpystr (tmp); + if (!(flags & NET_NOVALIDATECERT)) { + cert = SSL_get_peer_certificate (stream->con); + if (err = ssl_validate_cert (cert, host)) { + /* application callback */ + if (scq) { + long err = (*scq) (err,host,cert ? cert->name : "???"); + if (cert) + X509_free (cert); + return (err? NIL : strdup("")); + } + /* error message to return via mm_log() */ + sprintf (tmp,"*%.128s: %.255s",err,cert ? cert->name : "???"); + if (cert) + X509_free (cert); + return strdup(ssl_last_error = cpystr (tmp)); + } + if (cert) + X509_free (cert); } return NIL; } @@ -933,7 +962,10 @@ static long ssl_abort (SSLSTREAM *stream) char *ssl_host (SSLSTREAM *stream) { - return tcp_host (stream->tcpstream); + if(stream == NULL || stream->tcpstream == NULL) + return ""; + + return tcp_host (stream->tcpstream); } diff --git a/imap-2007e/c-client/osdepssl.c b/imap-2007e/c-client/osdepssl.c index 3bfdff3..79884a2 100755 --- a/imap-2007e/c-client/osdepssl.c +++ b/imap-2007e/c-client/osdepssl.c @@ -115,6 +115,7 @@ void ssl_onceonlyinit (void) mail_parameters (NIL,SET_SSLDRIVER,(void *) &ssldriver); mail_parameters (NIL,SET_SSLSTART,(void *) ssl_start); SSL_library_init (); /* add all algorithms */ + SSL_load_error_strings(); } } @@ -185,8 +186,9 @@ static SSLSTREAM *ssl_start (TCPSTREAM *tstream,char *host,unsigned long flags) /* pass to error callback */ else if (sf) (*sf) (host,reason,flags); else { /* no error callback, build error message */ - sprintf (tmp,"TLS/SSL failure for %.80s: %.512s",host,reason); - mm_log (tmp,ERROR); + sprintf (tmp,"TLS/SSL failure for %.80s: %.512s",host,reason); + mm_log (tmp,ERROR); + free (reason); /* OpenSSL error buf */ } break; } @@ -221,9 +223,26 @@ static char *ssl_start_work (SSLSTREAM *stream,char *host,unsigned long flags) ssl_last_host = host; if (!(stream->context = SSL_CTX_new ((flags & NET_TLSCLIENT) ? TLSv1_client_method () : - SSLv23_client_method ()))) - return "SSL context failed"; - SSL_CTX_set_options (stream->context,0); + SSLv23_client_method ()))) { + /* bio to memory buf */ + BIO *bio = BIO_new (BIO_s_mem ()); + ERR_print_errors (bio); + char *buf = NULL; + size_t len = BIO_get_mem_data (bio, &buf); + char *ret = (char *) calloc (1, 1 + len + 40); + if (ret) { + memcpy (ret, buf , len); + } + sprintf (ret+len, ": SSL context failed [0x%x] ", flags & NET_TLSCLIENT); + BIO_free (bio); + return ret; +// return "SSL context failed"; + } + if (flags & NET_FORCE_LOWER_TLS_VERSION) + SSL_CTX_set_options(stream->context, SSL_OP_NO_SSLv2|SSL_OP_NO_TLSv1_1|SSL_OP_NO_TLSv1_2); + else + SSL_CTX_set_options (stream->context,0); + /* disable certificate validation? */ if (flags & NET_NOVALIDATECERT) SSL_CTX_set_verify (stream->context,SSL_VERIFY_NONE,NIL); diff --git a/imap-2007e/c-client/pop3.c b/imap-2007e/c-client/pop3.c index e7fb8f2..0cdc65e 100755 --- a/imap-2007e/c-client/pop3.c +++ b/imap-2007e/c-client/pop3.c @@ -249,7 +249,7 @@ void pop3_scan (MAILSTREAM *stream,char *ref,char *pat,char *contents) if ((ref && *ref) ? /* have a reference */ (pop3_valid (ref) && pmatch ("INBOX",pat)) : (mail_valid_net (pat,&pop3driver,NIL,tmp) && pmatch ("INBOX",tmp))) - mm_log ("Scan not valid for POP3 mailboxes",ERROR); + MM_LOG ("Scan not valid for POP3 mailboxes",ERROR); } @@ -413,12 +413,12 @@ MAILSTREAM *pop3_open (MAILSTREAM *stream) if (stream->local) fatal ("pop3 recycle stream"); /* /anonymous not supported */ if (mb.anoflag || stream->anonymous) { - mm_log ("Anonymous POP3 login not available",ERROR); + MM_LOG ("Anonymous POP3 login not available",ERROR); return NIL; } /* /readonly not supported either */ if (mb.readonlyflag || stream->rdonly) { - mm_log ("Read-only POP3 access not available",ERROR); + MM_LOG ("Read-only POP3 access not available",ERROR); return NIL; } /* copy other switches */ @@ -435,44 +435,44 @@ MAILSTREAM *pop3_open (MAILSTREAM *stream) (NETDRIVER *) mail_parameters (NIL,GET_SSLDRIVER,NIL), "*pop3s",pop3_sslport ? pop3_sslport : POP3SSLPORT)) && pop3_reply (stream)) { - mm_log (LOCAL->reply,NIL); /* give greeting */ + MM_LOG (LOCAL->reply,NIL); /* give greeting */ #if 1 //APOP - shasikala.p@siso.com strcpy(tmp_str, LOCAL->reply); - mm_log(tmp_str, NIL); + MM_LOG(tmp_str, NIL); timestamp = strchr(tmp_str, '<'); sprintf(temp, "Pop3_open - mb->apop - %d", mb.apop); - mm_log(temp, NIL); + MM_LOG(temp, NIL); if(timestamp && mb.apop != 0) apop = 1; else { - mm_log("server doesnt support apop", NIL); + MM_LOG("server doesnt support apop", NIL); if(mb.apop == 1) - mm_log("Uncheck apop", NIL); + MM_LOG("Uncheck apop", NIL); apop = 0; } if(apop) { - mm_log(timestamp, NIL); + MM_LOG(timestamp, NIL); mm_login(&mb, usr, tmp, 0); - mm_log(usr, NIL); - mm_log(tmp, NIL); + MM_LOG(usr, NIL); + MM_LOG(tmp, NIL); timestamp = strcat(timestamp, tmp); - mm_log(timestamp, NIL); + MM_LOG(timestamp, NIL); memset(tmp, 0, MAILTMPLEN); md5_init (&ctx); md5_update (&ctx,(unsigned char *) timestamp,strlen (timestamp)); md5_final (digest,&ctx); - mm_log(digest, NIL); + MM_LOG(digest, NIL); for (i = 0, s = tmp ; i < MD5DIGLEN; i++) { *s++ = hex[(j = digest[i]) >> 4]; *s++ = hex[j & 0xf]; } *s = '\0'; - mm_log(tmp, NIL); + MM_LOG(tmp, NIL); } #endif @@ -515,7 +515,7 @@ MAILSTREAM *pop3_open (MAILSTREAM *stream) /* flush final dot */ if (s) fs_give ((void **) &s); else { /* lost connection */ - mm_log ("POP3 connection broken while itemizing messages",ERROR); + MM_LOG ("POP3 connection broken while itemizing messages",ERROR); pop3_close (stream,NIL); return NIL; } @@ -523,15 +523,15 @@ MAILSTREAM *pop3_open (MAILSTREAM *stream) stream->silent = silent; /* notify main program */ mail_exists (stream,stream->nmsgs); /* notify if empty */ - if (!(stream->nmsgs || stream->silent)) mm_log ("Mailbox is empty",WARN); + if (!(stream->nmsgs || stream->silent)) MM_LOG ("Mailbox is empty",WARN); } else { /* error in STAT */ - mm_log (LOCAL->reply,ERROR); + MM_LOG (LOCAL->reply,ERROR); pop3_close (stream,NIL); /* too bad */ } } else { /* connection failed */ - if (LOCAL->reply) mm_log (LOCAL->reply,ERROR); + if (LOCAL->reply) MM_LOG (LOCAL->reply,ERROR); pop3_close (stream,NIL); /* failed, clean up */ } return LOCAL ? stream : NIL; /* if stream is alive, return to caller */ @@ -622,17 +622,15 @@ long pop3_auth (MAILSTREAM *stream,NETMBX *mb,char *pwd,char *usr, int apop) long ret = NIL; long flags = (stream->secure ? AU_SECURE : NIL) | (mb->authuser[0] ? AU_AUTHUSER : NIL); - mm_log("in pop3_auth1", NIL); - if(apop) - { + MM_LOG("in pop3_auth1", NIL); + if(apop) { apop = 0; - mm_log("apop set", NIL); + MM_LOG("apop set", NIL); char* tmp = (char *)malloc(strlen(usr)+strlen(pwd) +1); sprintf (tmp,"%s %s",usr,pwd); - mm_log(tmp, NIL); - if(pop3_send(stream, "APOP", tmp)) - { - mm_log("successfully logged in using APOP", NIL); + MM_LOG(tmp, NIL); + if(pop3_send(stream, "APOP", tmp)) { + MM_LOG("successfully logged in using APOP", NIL); pop3_capa (stream,flags); return LONGT; } @@ -657,7 +655,7 @@ long pop3_auth (MAILSTREAM *stream,NETMBX *mb,char *pwd,char *usr, int apop) pop3_capa (stream,flags); /* get capabilities now that TLS in effect */ } else if (mb->tlsflag) { /* user specified /tls but can't do it */ - mm_log ("Unable to negotiate TLS with this server",ERROR); + MM_LOG ("Unable to negotiate TLS with this server",ERROR); return NIL; } /* get authenticators from capabilities */ @@ -690,20 +688,20 @@ long pop3_auth (MAILSTREAM *stream,NETMBX *mb,char *pwd,char *usr, int apop) mb->host[NETMAXHOST-1] = '\0'; } for (t = NIL, LOCAL->saslcancel = NIL; !ret && LOCAL->netstream && auths && - (at = mail_lookup_auth (find_rightmost_bit (&auths)+1)); ) { + (at = mail_lookup_auth (find_rightmost_bit (&auths)+1)); ) { if (t) { /* previous authenticator failed? */ - sprintf (pwd,"Retrying using %.80s authentication after %.80s", - at->name,t); - mm_log (pwd,NIL); - fs_give ((void **) &t); + sprintf (pwd,"Retrying using %.80s authentication after %.80s", + at->name,t); + MM_LOG (pwd,NIL); + fs_give ((void **) &t); } trial = 0; /* initial trial count */ do { - if (t) { - sprintf (pwd,"Retrying %s authentication after %.80s",at->name,t); - mm_log (pwd,WARN); - fs_give ((void **) &t); - } + if (t) { + sprintf (pwd,"Retrying %s authentication after %.80s",at->name,t); + MM_LOG (pwd,WARN); + fs_give ((void **) &t); + } LOCAL->saslcancel = NIL; if (pop3_send (stream,"AUTH",at->name)) { /* hide client authentication responses */ @@ -712,7 +710,7 @@ long pop3_auth (MAILSTREAM *stream,NETMBX *mb,char *pwd,char *usr, int apop) &trial,usr) && LOCAL->response) { if (*LOCAL->response == '+') ret = LONGT; /* if main program requested cancellation */ - else if (!trial) mm_log ("POP3 Authentication cancelled",ERROR); + else if (!trial) MM_LOG ("POP3 Authentication cancelled",ERROR); } LOCAL->sensitive=NIL; /* unhide */ } @@ -723,18 +721,18 @@ long pop3_auth (MAILSTREAM *stream,NETMBX *mb,char *pwd,char *usr, int apop) } if (t) { /* previous authenticator failed? */ if (!LOCAL->saslcancel) { /* don't do this if a cancel */ - sprintf (pwd,"Can not authenticate to POP3 server: %.80s",t); - mm_log (pwd,ERROR); + sprintf (pwd,"Can not authenticate to POP3 server: %.80s",t); + MM_LOG (pwd,ERROR); } fs_give ((void **) &t); } } else if (stream->secure) - mm_log ("Can't do secure authentication with this server",ERROR); + MM_LOG ("Can't do secure authentication with this server",ERROR); else if (mb->authuser[0]) - mm_log ("Can't do /authuser with this server",ERROR); - else if (!LOCAL->cap.user) mm_log ("Can't login to this server",ERROR); + MM_LOG ("Can't do /authuser with this server",ERROR); + else if (!LOCAL->cap.user) MM_LOG ("Can't login to this server",ERROR); else { /* traditional login */ trial = 0; /* initial trial count */ do { @@ -747,13 +745,13 @@ long pop3_auth (MAILSTREAM *stream,NETMBX *mb,char *pwd,char *usr, int apop) LOCAL->sensitive=NIL; /* unhide */ } if (!ret) { /* failure */ - mm_log (LOCAL->reply,WARN); + MM_LOG (LOCAL->reply,WARN); if (trial == pop3_maxlogintrials) - mm_log ("Too many login failures",ERROR); + MM_LOG ("Too many login failures",ERROR); } } /* user refused to give password */ - else mm_log ("Login aborted",ERROR); + else MM_LOG ("Login aborted",ERROR); } while (!ret && pwd[0] && (trial < pop3_maxlogintrials) && LOCAL->netstream); } @@ -779,7 +777,7 @@ void *pop3_challenge (void *s,unsigned long *len) !(ret = rfc822_base64 ((unsigned char *) LOCAL->reply, strlen (LOCAL->reply),len))) { sprintf (tmp,"POP3 SERVER BUG (invalid challenge): %.80s",LOCAL->reply); - mm_log (tmp,ERROR); + MM_LOG (tmp,ERROR); } return ret; } @@ -1007,7 +1005,7 @@ long pop3_ping (MAILSTREAM *stream) void pop3_check (MAILSTREAM *stream) { - if (pop3_ping (stream)) mm_log ("Check completed",NIL); + if (pop3_ping (stream)) MM_LOG ("Check completed",NIL); } @@ -1047,9 +1045,9 @@ long pop3_expunge (MAILSTREAM *stream,char *sequence,long options) if (!stream->silent) { /* only if not silent */ if (n) { /* did we expunge anything? */ sprintf (tmp,"Expunged %lu messages",n); - mm_log (tmp,(long) NIL); + MM_LOG (tmp,(long) NIL); } - else mm_log ("No messages deleted, so no update needed",(long) NIL); + else MM_LOG ("No messages deleted, so no update needed",(long) NIL); } } return ret; @@ -1068,7 +1066,7 @@ long pop3_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options) mailproxycopy_t pc = (mailproxycopy_t) mail_parameters (stream,GET_MAILPROXYCOPY,NIL); if (pc) return (*pc) (stream,sequence,mailbox,options); - mm_log ("Copy not valid for POP3",ERROR); + MM_LOG ("Copy not valid for POP3",ERROR); return NIL; } @@ -1083,7 +1081,7 @@ long pop3_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options) long pop3_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data) { - mm_log ("Append not valid for POP3",ERROR); + MM_LOG ("Append not valid for POP3",ERROR); return NIL; } diff --git a/imap-2007e/c-client/rfc822.c b/imap-2007e/c-client/rfc822.c index 07a724a..1e6193e 100755 --- a/imap-2007e/c-client/rfc822.c +++ b/imap-2007e/c-client/rfc822.c @@ -198,7 +198,7 @@ void rfc822_parse_msg_full (ENVELOPE **en,BODY **bdy,char *s,unsigned long i, if (!env->date && !strcmp (tmp+1,"ATE")) env->date = cpystr (d); break; case 'F': /* possible From: */ - if (!strcmp (tmp+1,"ROM")) rfc822_parse_adrlist (&env->from,d,host); + if (!strcmp (tmp+1,"ROM")) rfc822_parse_adrlist (&env->from,d,host); else if (!strcmp (tmp+1,"OLLOWUP-TO")) { t = env->followup_to = (char *) fs_get (1 + strlen (d)); while (c = *d++) if (c != ' ') *t++ = c; @@ -738,6 +738,13 @@ void rfc822_parse_adrlist (ADDRESS **lst,char *string,char *host) last = adr; /* new tail address */ if (string) { /* analyze what follows */ rfc822_skipws (&string); + + /* Recovery from failure on parsing */ + if ( string != NULL) { + while (*string != ',' && *string != '\0') + string++; + } + switch (c = *(unsigned char *) string) { case ',': /* comma? */ ++string; /* then another address follows */ @@ -900,7 +907,7 @@ ADDRESS *rfc822_parse_mailbox (char **string,char *defaulthost) /* phrase is a personal name */ if (adr->personal) fs_give ((void **) &adr->personal); *end = '\0'; /* tie off phrase */ - adr->personal = rfc822_cpy (s); + adr->personal = rfc822_cpy_for_personal (s); } /* call external phraseparser if phrase only */ else if (pp && rfc822_phraseonly (end) && @@ -985,9 +992,11 @@ ADDRESS *rfc822_parse_routeaddr (char *string,char **ret,char *defaulthost) if (!**ret) *ret = NIL; /* wipe pointer if at end of string */ return adr; /* return the address */ } - sprintf (tmp,"Unterminated mailbox: %.80s@%.80s",adr->mailbox, - *adr->host == '@' ? "" : adr->host); - MM_LOG (tmp,PARSE); + if (adr) { + sprintf (tmp,"Unterminated mailbox: %.80s@%.80s", (adr->mailbox == NULL) ? "" : adr->mailbox, + (adr->host == NULL || *adr->host == '@') ? "" : adr->host); + MM_LOG (tmp,PARSE); + } adr->next = mail_newaddr (); adr->next->mailbox = cpystr ("MISSING_MAILBOX_TERMINATOR"); adr->next->host = cpystr (errhst); @@ -1062,7 +1071,7 @@ ADDRESS *rfc822_parse_addrspec (char *string,char **ret,char *defaulthost) if (end && !(adr->personal && *adr->personal)) { while (*end == ' ') ++end; /* see if we can find a person name here */ if ((*end == '(') && (s = rfc822_skip_comment (&end,LONGT)) && strlen (s)) - adr->personal = rfc822_cpy (s); + adr->personal = rfc822_cpy_for_personal (s); rfc822_skipws (&end); /* skip any other WS in the normal way */ } /* set return to end pointer */ @@ -1165,56 +1174,56 @@ char *rfc822_parse_word (char *s,const char *delimiters) str = ++st; /* always skip past ESC */ switch (*st) { /* special hack for RFC 1468 (ISO-2022-JP) */ case I2C_MULTI: /* multi byte sequence */ - switch (*++st) { - case I2CS_94x94_JIS_OLD:/* old JIS (1978) */ - case I2CS_94x94_JIS_NEW:/* new JIS (1983) */ - str = ++st; /* skip past the shift to JIS */ - while (st = strchr (st,I2C_ESC)) - if ((*++st == I2C_G0_94) && ((st[1] == I2CS_94_ASCII) || - (st[1] == I2CS_94_JIS_ROMAN) || - (st[1] == I2CS_94_JIS_BUGROM))) { - str = st += 2; /* skip past the shift back to ASCII */ - break; - } + switch (*++st) { + case I2CS_94x94_JIS_OLD:/* old JIS (1978) */ + case I2CS_94x94_JIS_NEW:/* new JIS (1983) */ + str = ++st; /* skip past the shift to JIS */ + while (st = strchr (st,I2C_ESC)) + if ((*++st == I2C_G0_94) && ((st[1] == I2CS_94_ASCII) || + (st[1] == I2CS_94_JIS_ROMAN) || + (st[1] == I2CS_94_JIS_BUGROM))) { + str = st += 2; /* skip past the shift back to ASCII */ + break; + } /* eats entire text if no shift back */ - if (!st || !*st) return str + strlen (str); - } - break; - case I2C_G0_94: /* single byte sequence */ - switch (st[1]) { - case I2CS_94_ASCII: /* shift to ASCII */ - case I2CS_94_JIS_ROMAN: /* shift to JIS-Roman */ - case I2CS_94_JIS_BUGROM:/* old buggy definition of JIS-Roman */ - str = st + 2; /* skip past the shift */ - break; - } + if (!st || !*st) return str + strlen (str); + } + break; + case I2C_G0_94: /* single byte sequence */ + switch (st[1]) { + case I2CS_94_ASCII: /* shift to ASCII */ + case I2CS_94_JIS_ROMAN: /* shift to JIS-Roman */ + case I2CS_94_JIS_BUGROM:/* old buggy definition of JIS-Roman */ + str = st + 2; /* skip past the shift */ + break; + } } } else switch (*st) { /* dispatch based on delimiter */ - case '"': /* quoted string */ + case '"': /* quoted string */ /* look for close quote */ - while (*++st != '"') switch (*st) { - case '\0': /* unbalanced quoted string */ - return NIL; /* sick sick sick */ - case '\\': /* quoted character */ - if (!*++st) return NIL; /* skip the next character */ - default: /* ordinary character */ - break; /* no special action */ - } - str = ++st; /* continue parse */ - break; - case '\\': /* quoted character */ + while (*++st != '"') switch (*st) { + case '\0': /* unbalanced quoted string */ + return NIL; /* sick sick sick */ + case '\\': /* quoted character */ + if (!*++st) return NIL; /* skip the next character */ + default: /* ordinary character */ + break; /* no special action */ + } + str = ++st; /* continue parse */ + break; + case '\\': /* quoted character */ /* This is wrong; a quoted-pair can not be part of a word. However, * domain-literal is parsed as a word and quoted-pairs can be used * *there*. Either way, it's pretty pathological. */ - if (st[1]) { /* not on NUL though... */ - str = st + 2; /* skip quoted character and go on */ - break; - } - default: /* found a word delimiter */ - return (st == s) ? NIL : st; + if (st[1]) { /* not on NUL though... */ + str = st + 2; /* skip quoted character and go on */ + break; + } + default: /* found a word delimiter */ + return (st == s) ? NIL : st; } } } @@ -1230,6 +1239,14 @@ char *rfc822_cpy (char *src) return rfc822_quote (cpystr (src)); } +char *rfc822_cpy_for_personal (char *src) +{ + /* copy and unquote */ + return rfc822_quote (cpystr (src)); + /* Calling rfc822_quote should be replaced with below line. */ + /* return rfc822quote_for_personal (cpystr (src)); */ +} + /* Unquote an RFC 2822 format string * Accepts: string @@ -1253,6 +1270,27 @@ char *rfc822_quote (char *src) return ret; /* return our string */ } +char *rfc822_quote_for_personal (char *src) +{ + char *ret = src; + if (strpbrk (src,"\\\"")) { /* any quoting in string? */ + char *dst = ret; + while (*src) { /* copy string */ + if (*src == '\\') { + if (*(src + 1) == '\"') + *dst++ = *src++; /* copy character */ + else + src++;/* skip over single quote, copy next always */ + } + else if (*src == '\"') + src++; /* skip double quote entirely */ + *dst++ = *src++; /* copy character */ + } + *dst = '\0'; /* tie off string */ + } + return ret; /* return our string */ +} + /* Copy address list * Accepts: address list @@ -1548,7 +1586,7 @@ long rfc822_output_address_list (RFC822BUFFER *buf,ADDRESS *adr,long pretty, rspecials) : LONGT) && rfc822_output_string (buf," <") && rfc822_output_address (buf,adr) && - rfc822_output_string (buf,">"))) return NIL; + rfc822_output_string (buf,">"))) return NIL; } else if (!rfc822_output_address (buf,adr)) return NIL; if (adr->next && adr->next->mailbox && @@ -1720,6 +1758,7 @@ void rfc822_encode_body_7bit (ENVELOPE *env,BODY *body) PARAMETER **param; if (body) switch (body->type) { case TYPEMULTIPART: /* multi-part */ + MM_LOG ("rfc822_encode_body_7bit-MULTIPART",PARSE); for (param = &body->parameter; *param && strcmp ((*param)->attribute,"BOUNDARY"); param = &(*param)->next); @@ -1737,6 +1776,7 @@ void rfc822_encode_body_7bit (ENVELOPE *env,BODY *body) while (part = part->next); /* until done */ break; case TYPEMESSAGE: /* encapsulated message */ + MM_LOG ("rfc822_encode_body_7bit-MESSAGE",PARSE); switch (body->encoding) { case ENC7BIT: break; @@ -1754,19 +1794,25 @@ void rfc822_encode_body_7bit (ENVELOPE *env,BODY *body) switch (body->encoding) { case ENC8BIT: /* encode 8BIT into QUOTED-PRINTABLE */ /* remember old 8-bit contents */ + MM_LOG ("rfc822_encode_body_7bit-encode-ENC8BIT",PARSE); f = (void *) body->contents.text.data; + MM_LOG ("rfc822_8bit-begin",PARSE); body->contents.text.data = rfc822_8bit (body->contents.text.data, body->contents.text.size,&body->contents.text.size); + MM_LOG ("rfc822_8bit-end",PARSE); body->encoding = ENCQUOTEDPRINTABLE; fs_give (&f); /* flush old binary contents */ break; case ENCBINARY: /* encode binary into BASE64 */ /* remember old binary contents */ + MM_LOG ("rfc822_encode_body_7bit-encode-ENCBINARY",PARSE); f = (void *) body->contents.text.data; + MM_LOG ("rfc822_binary-begin",PARSE); body->contents.text.data = rfc822_binary ((void *) body->contents.text.data, body->contents.text.size,&body->contents.text.size); + MM_LOG ("rfc822_binary-end",PARSE); body->encoding = ENCBASE64; fs_give (&f); /* flush old binary contents */ default: /* otherwise OK */ diff --git a/imap-2007e/c-client/rfc822.h b/imap-2007e/c-client/rfc822.h index 0621732..95d1761 100755 --- a/imap-2007e/c-client/rfc822.h +++ b/imap-2007e/c-client/rfc822.h @@ -76,7 +76,9 @@ char *rfc822_parse_domain (char *string,char **end); char *rfc822_parse_phrase (char *string); char *rfc822_parse_word (char *string,const char *delimiters); char *rfc822_cpy (char *src); +char *rfc822_cpy_for_personal (char *src); char *rfc822_quote (char *src); +char *rfc822_quote_for_personal (char *src); ADDRESS *rfc822_cpy_adr (ADDRESS *adr); void rfc822_skipws (char **s); char *rfc822_skip_comment (char **s,long trim); diff --git a/imap-2007e/c-client/smtp.c b/imap-2007e/c-client/smtp.c index 023464a..47cc970 100755 --- a/imap-2007e/c-client/smtp.c +++ b/imap-2007e/c-client/smtp.c @@ -150,14 +150,14 @@ SENDSTREAM *smtp_open_full (NETDRIVER *dv,char **hostlist,char *service, char *s,tmp[MAILTMPLEN]; NETSTREAM *netstream; NETMBX mb; - if (!(hostlist && *hostlist)) mm_log ("Missing SMTP service host",ERROR); + if (!(hostlist && *hostlist)) MM_LOG ("Missing SMTP service host",ERROR); /* maximum domain name is 64 characters */ else do if (strlen (*hostlist) < SMTPMAXDOMAIN) { sprintf (tmp,"{%.1000s}",*hostlist); if (!mail_valid_net_parse_work (tmp,&mb,service ? service : "smtp") || mb.anoflag || mb.readonlyflag) { sprintf (tmp,"Invalid host specifier: %.80s",*hostlist); - mm_log (tmp,ERROR); + MM_LOG (tmp,ERROR); } else { /* light tryssl flag if requested */ mb.trysslflag = (options & SOP_TRYSSL) ? T : NIL; @@ -190,14 +190,14 @@ SENDSTREAM *smtp_open_full (NETDRIVER *dv,char **hostlist,char *service, while ((reply < 100) || (stream->reply[3] == '-')); if (reply != SMTPGREET){/* get SMTP greeting */ sprintf (tmp,"SMTP greeting failure: %.80s",stream->reply); - mm_log (tmp,ERROR); + MM_LOG (tmp,ERROR); stream = smtp_close (stream); } /* try EHLO first, then HELO */ else if (((reply = smtp_ehlo (stream,s,&mb)) != SMTPOK) && ((reply = smtp_send (stream,"HELO",s)) != SMTPOK)) { sprintf (tmp,"SMTP hello failure: %.80s",stream->reply); - mm_log (tmp,ERROR); + MM_LOG (tmp,ERROR); stream = smtp_close (stream); } else { @@ -217,7 +217,7 @@ SENDSTREAM *smtp_open_full (NETDRIVER *dv,char **hostlist,char *service, /* TLS negotiation failed after STARTTLS */ sprintf (tmp,"Unable to negotiate TLS with this server: %.80s", mb.host); - mm_log (tmp,ERROR); + MM_LOG (tmp,ERROR); /* close without doing QUIT */ if (stream->netstream) net_close (stream->netstream); stream->netstream = NIL; @@ -227,14 +227,14 @@ SENDSTREAM *smtp_open_full (NETDRIVER *dv,char **hostlist,char *service, else if ((reply = smtp_ehlo (stream,s,&mb)) != SMTPOK) { sprintf (tmp,"SMTP EHLO failure after STARTTLS: %.80s", stream->reply); - mm_log (tmp,ERROR); + MM_LOG (tmp,ERROR); stream = smtp_close (stream); } else ESMTP.ok = T; /* TLS OK and EHLO successful */ } else if (mb.tlsflag) {/* user specified /tls but can't do it */ sprintf (tmp,"TLS unavailable with this server: %.80s",mb.host); - mm_log (tmp,ERROR); + MM_LOG (tmp,ERROR); stream = smtp_close (stream); } @@ -249,11 +249,13 @@ SENDSTREAM *smtp_open_full (NETDRIVER *dv,char **hostlist,char *service, NETMAXHOST-1); mb.host[NETMAXHOST-1] = '\0'; } - if (!smtp_auth (stream,&mb,tmp)) stream = smtp_close (stream); + if(mb.auth_method > 0) { + if (!smtp_auth (stream,&mb,tmp)) stream = smtp_close (stream); + } } else { /* no available authenticators? */ sprintf (tmp,"%sSMTP authentication not available: %.80s", mb.secflag ? "Secure " : "",mb.host); - mm_log (tmp,ERROR); + MM_LOG (tmp,ERROR); stream = smtp_close (stream); } } @@ -294,9 +296,18 @@ long smtp_auth (SENDSTREAM *stream,NETMBX *mb,char *tmp) for (auths = ESMTP.auth, stream->saslcancel = NIL; !ret && stream->netstream && auths && (at = mail_lookup_auth (find_rightmost_bit (&auths) + 1)); ) { + + if (mb->auth_method != AUTH_METHOD_XOAUTH2 && strstr(at->name, auth_xoauth2.name) ) { + sprintf (tmp,"auth_method is not AUTH_METHOD_XOAUTH2. So skipped XOAUTH authenticator."); + MM_LOG (tmp,NIL); + continue; + } + + sprintf (tmp,"Trying using %s authentication. ", at->name); + MM_LOG (tmp,NIL); if (lsterr) { /* previous authenticator failed? */ sprintf (tmp,"Retrying using %s authentication after %.80s", at->name,lsterr); - mm_log (tmp,NIL); + MM_LOG (tmp,NIL); fs_give ((void **) &lsterr); } trial = 0; /* initial trial count */ @@ -304,7 +315,7 @@ long smtp_auth (SENDSTREAM *stream,NETMBX *mb,char *tmp) if (stream->netstream) do { if (lsterr) { sprintf (tmp,"Retrying %s authentication after %.80s",at->name,lsterr); - mm_log (tmp,WARN); + MM_LOG (tmp,WARN); fs_give ((void **) &lsterr); } stream->saslcancel = NIL; @@ -318,56 +329,10 @@ long smtp_auth (SENDSTREAM *stream,NETMBX *mb,char *tmp) ret = LONGT; } /* if main program requested cancellation */ - else if (!trial) mm_log ("SMTP Authentication cancelled",ERROR); + else if (!trial) MM_LOG ("SMTP Authentication cancelled",ERROR); } stream->sensitive = NIL;/* unhide */ } -#if 1 // for smtp.web.de - else if (!strcmp(at->name, "PLAIN")) { - char* user = usr; - char pwd[MAILTMPLEN]; - - pwd[0] = NIL; - mm_login(mb, user, pwd, trial); - - unsigned long rlen = strlen(mb->authuser) + strlen(user) + strlen(pwd) + 2; - char* response = (char*) fs_get(rlen); - char* t = response; - char* u; - - if (mb->authuser[0]) - for (u =user; *u; *t++ = *u++); - - *t++ = '\0'; - - for (u = (mb->authuser[0] ? mb->authuser : user); *u; *t++ = *u++); - - *t++ = '\0'; - - for (u = pwd; *u; *t++ = *u++); - - unsigned long i, j; - - for (t = (char*) rfc822_binary(response, rlen, &i), u = t, j = 0; j < i; j++) { - if (t[j] > ' ') *u++ = t[j]; - } - - *u = '\0'; - - i = smtp_send(stream, "AUTH PLAIN", t); - - fs_give((void**)&t); - - memset(response, 0, rlen); - fs_give((void**)&response); - - if (i == SMTPAUTHED) { - ESMTP.auth = NIL; - ret = LONGT; - } - else if (!trial) mm_log("SMTP Authentication cancelled", ERROR); - } -#endif /* remember response if error and no cancel */ if (!ret && trial) lsterr = cpystr (stream->reply); } while (!ret && stream->netstream && trial && @@ -376,7 +341,7 @@ long smtp_auth (SENDSTREAM *stream,NETMBX *mb,char *tmp) if (lsterr) { /* previous authenticator failed? */ if (!stream->saslcancel) { /* don't do this if a cancel */ sprintf (tmp,"Can not authenticate to SMTP server: %.80s",lsterr); - mm_log (tmp,ERROR); + MM_LOG (tmp,ERROR); } fs_give ((void **) &lsterr); } @@ -397,7 +362,7 @@ void *smtp_challenge (void *s,unsigned long *len) // for smtp.mail.yahoo.co.kr if (!strcmp(stream->reply+4, "ok, go on")) { sprintf (tmp,"smtp_challenge : Server bug: non-empty initial PLAIN challenge 3: %.80s",stream->reply+4); - mm_log (tmp,WARN); + MM_LOG (tmp,WARN); *len = 0; // MUST BE return cpystr("ok, go on"); @@ -413,7 +378,7 @@ void *smtp_challenge (void *s,unsigned long *len) !(ret = rfc822_base64 ((unsigned char *) stream->reply + 4, strlen (stream->reply + 4),len))) { sprintf (tmp,"SMTP SERVER BUG (invalid challenge): %.80s",stream->reply+4); - mm_log (tmp,ERROR); + MM_LOG (tmp,ERROR); } return ret; } @@ -768,9 +733,8 @@ long smtp_ehlo (SENDSTREAM *stream,char *host,NETMBX *mb) ESMTP.atrn.ok = T; } else if (!compare_cstring (s,"AUTH")) - //do if ((j = mail_lookup_auth_name (t,flags)) && - do if ((j = mail_lookup_auth_name_smtp (t,flags)) && // 22-Mar-2010 Fix for SMTP Authorization issue - avoid race condition. change from mail_lookup_auth_name to mail_lookup_auth_name_smtp - (--j < MAXAUTHENTICATORS)) ESMTP.auth |= (1 << j); + do if ((j = mail_lookup_auth_name (t,flags)) && + (--j < MAXAUTHENTICATORS)) ESMTP.auth |= (1 << j); while ((t = strtok_r (NIL," ",&r)) && *t); } /* EHLO options which do not take arguments */ @@ -795,17 +759,12 @@ long smtp_ehlo (SENDSTREAM *stream,char *host,NETMBX *mb) } while ((i < 100) || (stream->reply[3] == '-')); /* disable LOGIN if PLAIN also advertised */ - // 22-Mar-2010 change from mail_lookup_auth_name to mail_lookup_auth_name_smtp /* if ((j = mail_lookup_auth_name ("PLAIN",NIL)) && (--j < MAXAUTHENTICATORS) && (ESMTP.auth & (1 << j)) && (j = mail_lookup_auth_name ("LOGIN",NIL)) && (--j < MAXAUTHENTICATORS)) ESMTP.auth &= ~(1 << j); - */ - if ((j = mail_lookup_auth_name_smtp ("PLAIN",NIL)) && (--j < MAXAUTHENTICATORS) && - (ESMTP.auth & (1 << j)) && - (j = mail_lookup_auth_name_smtp ("LOGIN",NIL)) && (--j < MAXAUTHENTICATORS)) - ESMTP.auth &= ~(1 << j); + */ return i; /* return the response code */ } diff --git a/imap-2007e/c-client/ssl_unix.c b/imap-2007e/c-client/ssl_unix.c index 3bfdff3..84b392f 100755 --- a/imap-2007e/c-client/ssl_unix.c +++ b/imap-2007e/c-client/ssl_unix.c @@ -115,6 +115,7 @@ void ssl_onceonlyinit (void) mail_parameters (NIL,SET_SSLDRIVER,(void *) &ssldriver); mail_parameters (NIL,SET_SSLSTART,(void *) ssl_start); SSL_library_init (); /* add all algorithms */ + SSL_load_error_strings(); } } @@ -173,7 +174,7 @@ static SSLSTREAM *ssl_start (TCPSTREAM *tstream,char *host,unsigned long flags) if (sf) (*sf) (host,reason,flags); else { /* no error callback, build error message */ sprintf (tmp,"Certificate failure for %.80s: %.512s",host,reason); - mm_log (tmp,ERROR); + MM_LOG (tmp,ERROR); } case '\0': /* user answered no to certificate callback */ if (flags & NET_TRYSSL) /* return dummy stream to stop tryssl */ @@ -185,8 +186,9 @@ static SSLSTREAM *ssl_start (TCPSTREAM *tstream,char *host,unsigned long flags) /* pass to error callback */ else if (sf) (*sf) (host,reason,flags); else { /* no error callback, build error message */ - sprintf (tmp,"TLS/SSL failure for %.80s: %.512s",host,reason); - mm_log (tmp,ERROR); + sprintf (tmp,"TLS/SSL failure for %.80s: %.512s",host,reason); + MM_LOG (tmp,ERROR); + free (reason); /* OpenSSL error buf */ } break; } @@ -221,9 +223,25 @@ static char *ssl_start_work (SSLSTREAM *stream,char *host,unsigned long flags) ssl_last_host = host; if (!(stream->context = SSL_CTX_new ((flags & NET_TLSCLIENT) ? TLSv1_client_method () : - SSLv23_client_method ()))) - return "SSL context failed"; - SSL_CTX_set_options (stream->context,0); + SSLv23_client_method ()))) { + /* bio to memory buf */ + BIO *bio = BIO_new (BIO_s_mem ()); + ERR_print_errors (bio); + char *buf = NULL; + size_t len = BIO_get_mem_data (bio, &buf); + char *ret = (char *) calloc (1, 1 + len + 40); + if (ret) { + memcpy (ret, buf , len); + } + sprintf (ret+len, ": SSL context failed [0x%x] ", flags & NET_TLSCLIENT); + BIO_free (bio); + return ret; +// return "SSL context failed"; + } + if (flags & NET_FORCE_LOWER_TLS_VERSION) + SSL_CTX_set_options(stream->context, SSL_OP_NO_SSLv2|SSL_OP_NO_TLSv1_1|SSL_OP_NO_TLSv1_2); + else + SSL_CTX_set_options (stream->context,0); /* disable certificate validation? */ if (flags & NET_NOVALIDATECERT) SSL_CTX_set_verify (stream->context,SSL_VERIFY_NONE,NIL); @@ -271,7 +289,7 @@ static char *ssl_start_work (SSLSTREAM *stream,char *host,unsigned long flags) host))) { /* application callback */ if (scq) return (*scq) (err,host,cert ? cert->name : "???") ? NIL : ""; - /* error message to return via mm_log() */ + /* error message to return via MM_LOG() */ sprintf (tmp,"*%.128s: %.255s",err,cert ? cert->name : "???"); return ssl_last_error = cpystr (tmp); } @@ -294,7 +312,7 @@ static int ssl_open_verify (int ok,X509_STORE_CTX *ctx) (X509_STORE_CTX_get_error (ctx)); X509_NAME_oneline (X509_get_subject_name (X509_STORE_CTX_get_current_cert (ctx)),cert,255); - if (!scq) { /* mm_log() error message if no callback */ + if (!scq) { /* MM_LOG() error message if no callback */ sprintf (tmp,"*%.128s: %.255s",err,cert); ssl_last_error = cpystr (tmp); } @@ -489,7 +507,7 @@ long ssl_getdata (SSLSTREAM *stream) int ti = ttmo_read ? now + ttmo_read : 0; if (SSL_pending (stream->con)) i = 1; else { - if (tcpdebug) mm_log ("Reading SSL data",TCPDEBUG); + if (tcpdebug) MM_LOG ("Reading SSL data",TCPDEBUG); tmo.tv_usec = 0; FD_ZERO (&fds); /* initialize selection vector */ FD_ZERO (&efds); /* handle errors too */ @@ -515,17 +533,17 @@ long ssl_getdata (SSLSTREAM *stream) if (i) sprintf (s = tmp,"SSL data read I/O error %d SSL error %d", errno,SSL_get_error (stream->con,i)); else s = "SSL data read end of file"; - mm_log (s,TCPDEBUG); + MM_LOG (s,TCPDEBUG); } return ssl_abort (stream); } stream->iptr = stream->ibuf;/* point at TCP buffer */ stream->ictr = i; /* set new byte count */ - if (tcpdebug) mm_log ("Successfully read SSL data",TCPDEBUG); + if (tcpdebug) MM_LOG ("Successfully read SSL data",TCPDEBUG); } /* timeout, punt unless told not to */ else if (!tmoh || !(*tmoh) (now - t,now - tl)) { - if (tcpdebug) mm_log ("SSL data read timeout",TCPDEBUG); + if (tcpdebug) MM_LOG ("SSL data read timeout",TCPDEBUG); return ssl_abort (stream); } } @@ -558,7 +576,7 @@ long ssl_sout (SSLSTREAM *stream,char *string,unsigned long size) blocknotify_t bn = (blocknotify_t) mail_parameters (NIL,GET_BLOCKNOTIFY,NIL); if (!stream->con) return NIL; (*bn) (BLOCK_TCPWRITE,NIL); - if (tcpdebug) mm_log ("Writing to SSL",TCPDEBUG); + if (tcpdebug) MM_LOG ("Writing to SSL",TCPDEBUG); /* until request satisfied */ for (i = 0; size > 0; string += i,size -= i) /* write as much as we can */ @@ -567,11 +585,11 @@ long ssl_sout (SSLSTREAM *stream,char *string,unsigned long size) char tmp[MAILTMPLEN]; sprintf (tmp,"SSL data write I/O error %d SSL error %d", errno,SSL_get_error (stream->con,i)); - mm_log (tmp,TCPDEBUG); + MM_LOG (tmp,TCPDEBUG); } return ssl_abort (stream);/* write failed */ } - if (tcpdebug) mm_log ("successfully wrote to TCP",TCPDEBUG); + if (tcpdebug) MM_LOG ("successfully wrote to TCP",TCPDEBUG); (*bn) (BLOCK_NONE,NIL); return LONGT; /* all done */ } diff --git a/imap-2007e/c-client/tcp_unix.c b/imap-2007e/c-client/tcp_unix.c index 7129092..288e085 100755 --- a/imap-2007e/c-client/tcp_unix.c +++ b/imap-2007e/c-client/tcp_unix.c @@ -150,7 +150,7 @@ void *tcp_parameters (long function,void *value) TCPSTREAM *tcp_open (char *host,char *service,unsigned long port) { - mm_log("tcp_open - begin", NIL); + MM_LOG("tcp_open - begin", NIL); TCPSTREAM *stream = NIL; int family; int sock = -1; @@ -177,7 +177,7 @@ TCPSTREAM *tcp_open (char *host,char *service,unsigned long port) if (adr = ip_stringtoaddr (tmp,&adrlen,&family)) { (*bn) (BLOCK_TCPOPEN,NIL); /* get an open socket for this system */ - mm_log("tcp_open - Before calling tcp_socket_open", NIL); + MM_LOG("tcp_open - Before calling tcp_socket_open", NIL); sock = tcp_socket_open (family,adr,adrlen,port,tmp,ctrp,hostname = host); (*bn) (BLOCK_NONE,NIL); fs_give ((void **) &adr); @@ -187,7 +187,7 @@ TCPSTREAM *tcp_open (char *host,char *service,unsigned long port) else { /* lookup host name */ if (tcpdebug) { sprintf (tmp,"DNS resolution %.80s",host); - mm_log (tmp,TCPDEBUG); + MM_LOG (tmp,TCPDEBUG); } (*bn) (BLOCK_DNSLOOKUP,NIL);/* quell alarms */ data = (*bn) (BLOCK_SENSITIVE,NIL); @@ -196,15 +196,16 @@ TCPSTREAM *tcp_open (char *host,char *service,unsigned long port) (*bn) (BLOCK_NONSENSITIVE,data); (*bn) (BLOCK_NONE,NIL); if (s) { /* DNS resolution won? */ - if (tcpdebug) mm_log ("DNS resolution done",TCPDEBUG); + if (tcpdebug) MM_LOG ("DNS resolution done",TCPDEBUG); + int retry_all_addr = 0; /* if you want to try all ip addresses, set it */ do { (*bn) (BLOCK_TCPOPEN,NIL); if (((sock = tcp_socket_open (family,s,adrlen,port,tmp,ctrp, hostname)) < 0) && (s = ip_nametoaddr (NIL,&adrlen,&family,&hostname,&next)) && - !silent) mm_log (tmp,WARN); + !silent) MM_LOG (tmp,WARN); (*bn) (BLOCK_NONE,NIL); - } while ((sock < 0) && s);/* repeat until success or no more addreses */ + } while ((sock < 0) && s && retry_all_addr);/* repeat until success or no more addreses */ } } if (sock >= 0) { /* won */ @@ -217,9 +218,9 @@ TCPSTREAM *tcp_open (char *host,char *service,unsigned long port) if (stream->ictr = ctr) *(stream->iptr = stream->ibuf) = tmp[0]; /* copy official host name */ stream->host = cpystr (hostname); - if (tcpdebug) mm_log ("Stream open and ready for read",TCPDEBUG); + if (tcpdebug) MM_LOG ("Stream open and ready for read",TCPDEBUG); } - else if (!silent) mm_log (tmp,ERROR); + else if (!silent) MM_LOG (tmp,ERROR); return stream; /* return success */ } @@ -237,7 +238,7 @@ TCPSTREAM *tcp_open (char *host,char *service,unsigned long port) int tcp_socket_open (int family,void *adr,size_t adrlen,unsigned short port, char *tmp,int *ctr,char *hst) { - mm_log("tcp_socket_open - begin", NIL); + MM_LOG("tcp_socket_open - begin", NIL); int i,ti,sock,flgs; size_t len; time_t now; @@ -250,9 +251,9 @@ int tcp_socket_open (int family,void *adr,size_t adrlen,unsigned short port, /* fetid Solaris */ void *data = (*bn) (BLOCK_SENSITIVE,NIL); sprintf (tmp,"Trying IP address [%s]",ip_sockaddrtostring (sadr)); - mm_log (tmp,NIL); + MM_LOG (tmp,NIL); /* make a socket */ - mm_log("tcp_socket_open - make a socket", NIL); + MM_LOG("tcp_socket_open - make a socket", NIL); if ((sock = socket (sadr->sa_family,SOCK_STREAM,pt ? pt->p_proto : 0)) < 0) { sprintf (tmp,"Unable to create TCP socket: %s",strerror (errno)); (*bn) (BLOCK_NONSENSITIVE,data); @@ -288,14 +289,14 @@ int tcp_socket_open (int family,void *adr,size_t adrlen,unsigned short port, } snprintf (debug_meesage, DEBUG_MESSAGE_LENGTH, "tcp_socket_open - socket id [%d]", sock); - mm_log(debug_meesage, NIL); + MM_LOG(debug_meesage, NIL); if ((sock >= 0) && ctr) { /* want open timeout? */ now = time (0); /* open timeout */ ti = ttmo_open ? now + ttmo_open : 0; snprintf (debug_meesage, DEBUG_MESSAGE_LENGTH, "ti [%d]", ti); - mm_log(debug_meesage, NIL); + MM_LOG(debug_meesage, NIL); tmo.tv_usec = 0; FD_ZERO (&rfds); /* initialize selection vector */ @@ -306,9 +307,9 @@ int tcp_socket_open (int family,void *adr,size_t adrlen,unsigned short port, FD_SET (sock,&efds); do { /* block under timeout */ tmo.tv_sec = ti ? ti - now : 0; - mm_log("tcp_socket_open - Before calling select", NIL); + MM_LOG("tcp_socket_open - Before calling select", NIL); i = select (sock+1,&rfds,&wfds,&efds,ti ? &tmo : NIL); - mm_log("tcp_socket_open - After calling select", NIL); + MM_LOG("tcp_socket_open - After calling select", NIL); now = time (0); /* fake timeout if interrupt & time expired */ if ((i < 0) && (errno == EINTR) && ti && (ti <= now)) i = 0; } while ((i < 0) && (errno == EINTR)); @@ -321,7 +322,7 @@ int tcp_socket_open (int family,void *adr,size_t adrlen,unsigned short port, } if (i <= 0) { /* timeout or error? */ snprintf (debug_meesage, DEBUG_MESSAGE_LENGTH, "timed out or error. i [%d]", i); - mm_log(debug_meesage, NIL); + MM_LOG(debug_meesage, NIL); i = i ? errno : ETIMEDOUT;/* determine error code */ close (sock); /* flush socket */ sock = -1; @@ -381,7 +382,7 @@ TCPSTREAM *tcp_aopen (NETMBX *mb,char *service,char *usrbuf) if (adr = ip_stringtoaddr (host,&len,&i)) fs_give ((void **) &adr); else { sprintf (tmp,"Bad format domain-literal: %.80s",host); - mm_log (tmp,ERROR); + MM_LOG (tmp,ERROR); return NIL; } } @@ -395,7 +396,7 @@ TCPSTREAM *tcp_aopen (NETMBX *mb,char *service,char *usrbuf) if (tcpdebug) { char msg[MAILTMPLEN]; sprintf (msg,"Trying %.100s",tmp); - mm_log (msg,TCPDEBUG); + MM_LOG (msg,TCPDEBUG); } /* parse command into argv */ for (i = 1,path = argv[0] = strtok_r (tmp," ",&r); @@ -460,7 +461,7 @@ TCPSTREAM *tcp_aopen (NETMBX *mb,char *service,char *usrbuf) if (i <= 0) { /* timeout or error? */ sprintf (tmp,i ? "error in %s to IMAP server" : "%s to IMAP server timed out",(*service == '*') ? "ssh" : "rsh"); - mm_log (tmp,WARN); + MM_LOG (tmp,WARN); tcp_close (stream); /* punt stream */ stream = NIL; } @@ -552,7 +553,10 @@ long tcp_getbuffer (TCPSTREAM *stream,unsigned long size,char *s) { unsigned long n; /* make sure socket still alive */ - if (stream->tcpsi < 0) return NIL; + if (stream->tcpsi < 0) { + MM_LOG ("tcpsi < 0",TCPDEBUG); + return NIL; + } /* can transfer bytes from buffer? */ if (n = min (size,stream->ictr)) { memcpy (s,stream->iptr,n); /* yes, slurp as much as we can from it */ @@ -572,7 +576,7 @@ long tcp_getbuffer (TCPSTREAM *stream,unsigned long size,char *s) time_t tl = time (0); time_t now = tl; time_t ti = ttmo_read ? now + ttmo_read : 0; - if (tcpdebug) mm_log ("Reading TCP buffer",TCPDEBUG); + if (tcpdebug) MM_LOG ("Reading TCP buffer",TCPDEBUG); tmo.tv_usec = 0; FD_ZERO (&fds); /* initialize selection vector */ FD_ZERO (&efds); /* handle errors too */ @@ -591,21 +595,20 @@ long tcp_getbuffer (TCPSTREAM *stream,unsigned long size,char *s) while (((i = read (stream->tcpsi,s,(int) min (maxposint,size))) < 0) && (errno == EINTR)); if (i <= 0) { /* error seen? */ - if (tcpdebug) { char tmp[MAILTMPLEN]; if (i) sprintf (s = tmp,"TCP buffer read I/O error %d",errno); else s = "TCP buffer read end of file"; - mm_log (s,TCPDEBUG); - } + MM_LOG (s,TCPDEBUG); + return tcp_abort (stream); } s += i; /* success, point at new place to write */ size -= i; /* reduce byte count */ - if (tcpdebug) mm_log ("Successfully read TCP buffer",TCPDEBUG); + if (tcpdebug) MM_LOG ("Successfully read TCP buffer",TCPDEBUG); } /* timeout, punt unless told not to */ else if (!tmoh || !(*tmoh) (now - t,now - tl)) { - if (tcpdebug) mm_log ("TCP buffer read timeout",TCPDEBUG); + MM_LOG ("TCP buffer read timeout",TCPDEBUG); return tcp_abort (stream); } } @@ -633,7 +636,7 @@ long tcp_getdata (TCPSTREAM *stream) time_t tl = time (0); /* start of request */ time_t now = tl; time_t ti = ttmo_read ? now + ttmo_read : 0; - if (tcpdebug) mm_log ("Reading TCP data",TCPDEBUG); + if (tcpdebug) MM_LOG ("Reading TCP data",TCPDEBUG); tmo.tv_usec = 0; FD_ZERO (&fds); /* initialize selection vector */ FD_ZERO (&efds); /* handle errors too */ @@ -655,17 +658,17 @@ long tcp_getdata (TCPSTREAM *stream) char *s,tmp[MAILTMPLEN]; if (i) sprintf (s = tmp,"TCP data read I/O error %d",errno); else s = "TCP data read end of file"; - mm_log (s,TCPDEBUG); + MM_LOG (s,TCPDEBUG); } return tcp_abort (stream); } stream->ictr = i; /* success, set new count and pointer */ stream->iptr = stream->ibuf; - if (tcpdebug) mm_log ("Successfully read TCP data",TCPDEBUG); + if (tcpdebug) MM_LOG ("Successfully read TCP data",TCPDEBUG); } /* timeout, punt unless told not to */ else if (!tmoh || !(*tmoh) (now - t,now - tl)) { - if (tcpdebug) mm_log ("TCP data read timeout",TCPDEBUG); + if (tcpdebug) MM_LOG ("TCP data read timeout",TCPDEBUG); return tcp_abort (stream);/* error or timeout no-continue */ } } @@ -705,7 +708,7 @@ long tcp_sout (TCPSTREAM *stream,char *string,unsigned long size) time_t tl = time (0); /* start of request */ time_t now = tl; time_t ti = ttmo_write ? now + ttmo_write : 0; - if (tcpdebug) mm_log ("Writing to TCP",TCPDEBUG); + if (tcpdebug) MM_LOG ("Writing to TCP",TCPDEBUG); tmo.tv_usec = 0; FD_ZERO (&fds); /* initialize selection vector */ FD_ZERO (&efds); /* handle errors too */ @@ -726,17 +729,17 @@ long tcp_sout (TCPSTREAM *stream,char *string,unsigned long size) if (tcpdebug) { char tmp[MAILTMPLEN]; sprintf (tmp,"TCP write I/O error %d",errno); - mm_log (tmp,TCPDEBUG); + MM_LOG (tmp,TCPDEBUG); } return tcp_abort (stream); } string += i; /* how much we sent */ size -= i; /* count this size */ - if (tcpdebug) mm_log ("successfully wrote to TCP",TCPDEBUG); + if (tcpdebug) MM_LOG ("successfully wrote to TCP",TCPDEBUG); } /* timeout, punt unless told not to */ else if (!tmoh || !(*tmoh) (now - t,now - tl)) { - if (tcpdebug) mm_log ("TCP write timeout",TCPDEBUG); + if (tcpdebug) MM_LOG ("TCP write timeout",TCPDEBUG); return tcp_abort (stream); } } @@ -969,13 +972,13 @@ char *tcp_canonical (char *name) data = (*bn) (BLOCK_SENSITIVE,NIL); if (tcpdebug) { sprintf (host,"DNS canonicalization %.80s",name); - mm_log (host,TCPDEBUG); + MM_LOG (host,TCPDEBUG); } /* get canonical name */ if (!ip_nametoaddr (name,NIL,NIL,&ret,NIL)) ret = name; (*bn) (BLOCK_NONSENSITIVE,data); (*bn) (BLOCK_NONE,NIL); /* alarms OK now */ - if (tcpdebug) mm_log ("DNS canonicalization done",TCPDEBUG); + if (tcpdebug) MM_LOG ("DNS canonicalization done",TCPDEBUG); return ret; } @@ -994,7 +997,7 @@ char *tcp_name (struct sockaddr *sadr,long flag) void *data; if (tcpdebug) { sprintf (tmp,"Reverse DNS resolution %s",adr); - mm_log (tmp,TCPDEBUG); + MM_LOG (tmp,TCPDEBUG); } (*bn) (BLOCK_DNSLOOKUP,NIL);/* quell alarms */ data = (*bn) (BLOCK_SENSITIVE,NIL); @@ -1006,7 +1009,7 @@ char *tcp_name (struct sockaddr *sadr,long flag) } (*bn) (BLOCK_NONSENSITIVE,data); (*bn) (BLOCK_NONE,NIL); /* alarms OK now */ - if (tcpdebug) mm_log ("Reverse DNS resolution done",TCPDEBUG); + if (tcpdebug) MM_LOG ("Reverse DNS resolution done",TCPDEBUG); } return cpystr (ret); } diff --git a/libuw-imap-toolkit.manifest b/libuw-imap-toolkit.manifest new file mode 100644 index 0000000..75b0fa5 --- /dev/null +++ b/libuw-imap-toolkit.manifest @@ -0,0 +1,5 @@ + + + + + diff --git a/packaging/uw-imap-toolkit.spec b/packaging/uw-imap-toolkit.spec index 71fbbea..8067e66 100644 --- a/packaging/uw-imap-toolkit.spec +++ b/packaging/uw-imap-toolkit.spec @@ -1,14 +1,11 @@ -#sbs-git:slp/pkgs/u/uw-imap-toolkit uw-imap-toolkit 0.1.1 a675e5c581b6726dcb93c63d826d6827bf29d671 %define _optdir /opt %define _appdir %{_optdir}/apps - - Name: uw-imap-toolkit Summary: IMAP-2007e developed by University of Washington -Version: 0.1.1 +Version: 0.1.35 Release: 0 Group: TO_BE/FILLED_IN -License: TO BE FILLED IN +License: Apache-2.0 Source0: %{name}-%{version}.tar.gz Requires(post): /sbin/ldconfig Requires(postun): /sbin/ldconfig @@ -51,6 +48,8 @@ make %{?jobs:-j%jobs} rm -rf %{buildroot} %make_install +mkdir -p %{buildroot}/usr/share/license/%{name} +cp imap-2007e/LICENSE.txt %{buildroot}/usr/share/license/%{name}/LICENSE %post -n libuw-imap-toolkit -p /sbin/ldconfig @@ -59,9 +58,10 @@ rm -rf %{buildroot} %files -n libuw-imap-toolkit +%manifest libuw-imap-toolkit.manifest %defattr(-,root,root,-) %{_libdir}/libuw-imap-toolkit.so.* - +/usr/share/license/%{name}/LICENSE %files -n libuw-imap-toolkit-devel %defattr(-,root,root,-) -- 2.7.4