From 160c65c07175315edddfec7297ad400486a8cabd Mon Sep 17 00:00:00 2001 From: Eduardo Chappa Date: Mon, 1 Feb 2016 21:19:43 -0700 Subject: * Added support for RFC 2971 - IMAP ID extension. --- imap/src/c-client/imap4r1.c | 108 +++++++++++++++++++++++++++++++++++++++++++- imap/src/c-client/mail.c | 17 ++++++- imap/src/c-client/mail.h | 18 +++++++- 3 files changed, 139 insertions(+), 4 deletions(-) (limited to 'imap/src') diff --git a/imap/src/c-client/imap4r1.c b/imap/src/c-client/imap4r1.c index dbd945ec..de16950d 100644 --- a/imap/src/c-client/imap4r1.c +++ b/imap/src/c-client/imap4r1.c @@ -1,8 +1,13 @@ +/* + * Copyright 2016 Eduardo Chappa + * + * Last Edited: February 1, 2015 Eduardo Chappa + * + */ /* ======================================================================== * Copyright 2008-2011 Mark Crispin * ======================================================================== */ - /* * Program: Interactive Message Access Protocol 4rev1 (IMAP4R1) routines * @@ -74,6 +79,7 @@ typedef struct imap_local { unsigned int byeseen : 1; /* saw a BYE response */ /* got implicit capabilities */ unsigned int gotcapability : 1; + unsigned int setid : 1; /* set id of app */ unsigned int sensitive : 1; /* sensitive data in progress */ unsigned int tlsflag : 1; /* TLS session */ unsigned int tlssslv23 : 1; /* TLS using SSLv23 client method */ @@ -102,6 +108,7 @@ typedef struct imap_local { char *reform; /* reformed sequence */ char tmp[IMAPTMPLEN]; /* temporary buffer */ SEARCHSET *lookahead; /* fetch lookahead */ + IDLIST *id; /* id of stream */ } IMAPLOCAL; @@ -266,6 +273,8 @@ void imap_parse_extension (MAILSTREAM *stream,unsigned char **txtptr, void imap_parse_capabilities (MAILSTREAM *stream,char *t); IMAPPARSEDREPLY *imap_fetch (MAILSTREAM *stream,char *sequence,long flags); char *imap_reform_sequence (MAILSTREAM *stream,char *sequence,long flags); +long imap_setid(MAILSTREAM *stream, IDLIST *idlist); +IDLIST *imap_parse_idlist(char *text); /* Driver dispatch used by MAIL */ @@ -450,6 +459,11 @@ void *imap_parameters (long function,void *value) case GET_IDLETIMEOUT: value = (void *) IDLETIMEOUT; break; + case SET_IDSTREAM: /* set IMAP server ID */ + fatal ("SET_IDSTREAM not permitted"); + case GET_IDSTREAM: /* get IMAP server ID */ + value = (void *) &((IMAPLOCAL *) ((MAILSTREAM *) value)->local)->id; + break; default: value = NIL; /* error case */ break; @@ -980,6 +994,13 @@ MAILSTREAM *imap_open (MAILSTREAM *stream) } strcat (tmp,"}"); + if(LEVELID(stream)){ /* Set ID of app */ + IDLIST *idapp = (IDLIST *) mail_parameters(NIL, GET_IDPARAMS, NIL); + if(idapp && !LOCAL->setid){ + imap_setid(stream, idapp); + LOCAL->setid++; + } + } if (!stream->halfopen) { /* wants to open a mailbox? */ IMAPARG *args[2]; IMAPARG ambx; @@ -1334,6 +1355,7 @@ void imap_close (MAILSTREAM *stream,long options) if (LOCAL->user) fs_give ((void **) &LOCAL->user); if (LOCAL->reply.line) fs_give ((void **) &LOCAL->reply.line); if (LOCAL->reform) fs_give ((void **) &LOCAL->reform); + if (LOCAL->id) mail_free_idlist(&LOCAL->id); /* nuke the local data */ fs_give ((void **) &stream->local); } @@ -2850,7 +2872,86 @@ long imap_setquota (MAILSTREAM *stream,char *qroot,STRINGLIST *limits) else mm_log ("Quota not available on this IMAP server",ERROR); return ret; } - + +IDLIST *imap_parse_idlist (char *text) +{ + IDLIST *ret = NULL; + char *s; + char tmp[MAILTMPLEN]; + + if(text == NULL) return NULL; + for(s = text; *s == ' '; s++); /* move past spaces */ + if(*s == '(') s++; + if(*s++ == '"'){ + char *t; + for(t = s; *t && *t != '"'; t++); + if(*t == '"'){ + ret = fs_get(sizeof(IDLIST)); + *t = '\0'; + ret->name = cpystr(s); + *t = '"'; + for(s = t+1; *s == ' '; s++); /* move past spaces */ + if(*s++ == '"'){ + for(t = s; *t && *t != '"'; t++); + if(*t == '"'){ + *t = '\0'; + ret->value = cpystr(s); + *t++ = '"'; + ret->next = imap_parse_idlist(t); + } + else { + sprintf(tmp,"ID value not found for name %.80s, at %.80s", ret->name, s); + fs_give((void **)&ret->name); + fs_give((void **)&ret); + mm_log (tmp, ERROR); + } + } + else { /* failed!, quit */ + sprintf(tmp,"ID name \"%.80s\" has no value", ret->name); + fs_give((void **)&ret->name); + fs_give((void **)&ret); + mm_log (tmp, ERROR); + } + } + } + return ret; +} + +long imap_setid (MAILSTREAM *stream, IDLIST *idlist) +{ + long ret = NIL; + if (LEVELID (stream)) { /* send "ID (params)" */ + IMAPPARSEDREPLY *reply; + IMAPARG *args[2],aqrt; + IDLIST *list; + char *qroot, *p; + long len = 0L; + + if(idlist == NULL) return ret; + for (list = idlist; list != NULL; list = list->next) + len += strlen(list->name) + strlen(list->value) + 6; + if(len > 0){ + len += 1L; /* in case there is only one field */ + qroot = fs_get(len+1); + memset((void *)&qroot[0], 0, len+1); + p = qroot; + for (list = idlist; list != NULL; list = list->next){ + sprintf(p, " \"%s\" \"%s\"", list->name, list->value); + p += strlen(p); + } + *p = ')'; + qroot[0] = '('; + aqrt.type = ATOM; aqrt.text = (void *) qroot; + args[0] = &aqrt; args[1] = NIL; + if (imap_OK (stream,reply = imap_send (stream,"ID",args))) + ret = LONGT; + else mm_log (reply->text,ERROR); + } else mm_log("Empty or malformed ID list", ERROR); + } + else mm_log ("ID capability not available on this IMAP server",ERROR); + return ret; +} + /* IMAP get quota * Accepts: mail stream * quota root name @@ -4204,6 +4305,9 @@ void imap_parse_unsolicited (MAILSTREAM *stream,IMAPPARSEDREPLY *reply) } fs_give ((void **) &t); /* free root name */ } + else if (!strcmp (reply->key,"ID") && (s = reply->text)){ + if(compare_cstring (s,"NIL")) LOCAL->id = imap_parse_idlist(s); + } else if (!strcmp (reply->key,"QUOTAROOT") && (s = reply->text) && (t = imap_parse_astring (stream,&s,reply,NIL))) { sprintf (LOCAL->tmp,"Bad quota root list for %.80s",(char *) t); diff --git a/imap/src/c-client/mail.c b/imap/src/c-client/mail.c index f3e4bdd2..f989e5d9 100644 --- a/imap/src/c-client/mail.c +++ b/imap/src/c-client/mail.c @@ -34,9 +34,10 @@ char *Panda_copyright = "Copyright 2008-2010 Mark Crispin\n"; char *UW_copyright = "Copyright 1988-2008 University of Washington\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n"; /* c-client global data */ - /* version of this library */ static char *mailcclientversion = CCLIENTVERSION; + /* app identity */ +static IDLIST *idapp = NIL; /* list of mail drivers */ static DRIVER *maildrivers = NIL; /* list of authenticators */ @@ -646,6 +647,10 @@ void *mail_parameters (MAILSTREAM *stream,long function,void *value) case GET_SNARFMAILBOXNAME: if (stream) ret = (void *) stream->snarf.name; break; + case SET_IDPARAMS: /* program id */ + idapp = (IDLIST *) value; + case GET_IDPARAMS: + ret = (void *) idapp; default: if ((r = smtp_parameters (function,value)) != NULL) ret = r; if ((r = env_parameters (function,value)) != NULL) ret = r; @@ -1410,6 +1415,16 @@ MAILHANDLE *mail_makehandle (MAILSTREAM *stream) return handle; } +void mail_free_idlist (IDLIST **idlist) +{ + if (idlist && *idlist){ + if((*idlist)->name) fs_give((void **)&(*idlist)->name); + if((*idlist)->value) fs_give((void **)&(*idlist)->value); + if((*idlist)->next) mail_free_idlist(&(*idlist)->next); + fs_give((void **) idlist); + } +} + /* Mail release handle * Accepts: Mail handle diff --git a/imap/src/c-client/mail.h b/imap/src/c-client/mail.h index 7595bf59..309cf994 100644 --- a/imap/src/c-client/mail.h +++ b/imap/src/c-client/mail.h @@ -144,6 +144,11 @@ #define SET_BLOCKENVINIT (long) 162 #define GET_UCS4WIDTH (long) 163 #define SET_UCS4WIDTH (long) 164 +#define GET_IDPARAMS (long) 165 +#define SET_IDPARAMS (long) 166 +#define GET_IDSTREAM (long) 167 +#define SET_IDSTREAM (long) 168 + /* 2xx: environment */ #define GET_USERNAME (long) 201 #define SET_USERNAME (long) 202 @@ -1081,7 +1086,17 @@ QUOTALIST { unsigned long limit; /* resource limit */ QUOTALIST *next; /* next resource */ }; - + +/* ID List */ + +#define IDLIST struct id_list + +IDLIST { + char *name; /* name of field */ + char *value; /* value of the field */ + IDLIST *next; /* next value in the list */ +}; + /* Mail Access I/O stream */ @@ -1800,6 +1815,7 @@ SORTPGM *mail_newsortpgm (void); THREADNODE *mail_newthreadnode (SORTCACHE *sc); ACLLIST *mail_newacllist (void); QUOTALIST *mail_newquotalist (void); +void mail_free_idlist (IDLIST **idlist); void mail_free_body (BODY **body); void mail_free_body_data (BODY *body); void mail_free_body_parameter (PARAMETER **parameter); -- cgit v1.2.3-70-g09d2