summaryrefslogtreecommitdiff
path: root/imap/src/c-client
diff options
context:
space:
mode:
authorEduardo Chappa <chappa@washington.edu>2016-02-01 21:19:43 -0700
committerEduardo Chappa <chappa@washington.edu>2016-02-01 21:19:43 -0700
commit160c65c07175315edddfec7297ad400486a8cabd (patch)
treee2c8ebaa4866366cb3fb88bc0813f5e991931881 /imap/src/c-client
parente8d813ec09607b9466e97155ffd35e27d485ef8a (diff)
downloadalpine-160c65c07175315edddfec7297ad400486a8cabd.tar.xz
* Added support for RFC 2971 - IMAP ID extension.
Diffstat (limited to 'imap/src/c-client')
-rw-r--r--imap/src/c-client/imap4r1.c108
-rw-r--r--imap/src/c-client/mail.c17
-rw-r--r--imap/src/c-client/mail.h18
3 files changed, 139 insertions, 4 deletions
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 <chappa@gmx.com>
+ *
+ */
/* ========================================================================
* 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);