Dear list, the attached patch for imap annotation support within the c-client library might have been submitted before. But I was unable to find it in the mailing list archives and so I wanted to request its current status.
This patch is of interest to all Kolab (http://www.kolab.org) users and presents a problem to the distributions packaging Kolab (SuSE, Debian, Gentoo, OpenPKG etc.). We currently still need to provide patched c-client packages. Since the patch mentioned above is the only c-client patch needed to make Kolab work, I wanted to inquire if there is any chance of including the patch. I am also member of the Kolab development team so if there are specific problems with the patch that we don't know about, I'd be perfectly willing to fix or modify the code. Thank you! Cheers, Gunnar
diff -Naur imap-2006f.orig/src/c-client/imap4r1.c imap-2006f/src/c-client/imap4r1.c --- imap-2006f.orig/src/c-client/imap4r1.c 2007-03-15 23:35:38.000000000 +0100 +++ imap-2006f/src/c-client/imap4r1.c 2007-03-15 23:35:48.000000000 +0100 @@ -135,7 +135,8 @@ #define MULTIAPPEND 13 #define SNLIST 14 #define MULTIAPPENDREDO 15 - +#define QLIST 16 +#define QSTRING 17 /* Append data */ @@ -205,12 +206,15 @@ void imap_gc_body (BODY *body); void imap_capability (MAILSTREAM *stream); long imap_acl_work (MAILSTREAM *stream,char *command,IMAPARG *args[]); +long imap_annotation_work (MAILSTREAM *stream,char *command,IMAPARG *args[]); IMAPPARSEDREPLY *imap_send (MAILSTREAM *stream,char *cmd,IMAPARG *args[]); IMAPPARSEDREPLY *imap_sout (MAILSTREAM *stream,char *tag,char *base,char **s); long imap_soutr (MAILSTREAM *stream,char *string); IMAPPARSEDREPLY *imap_send_astring (MAILSTREAM *stream,char *tag,char **s, SIZEDTEXT *as,long wildok,char *limit); +IMAPPARSEDREPLY *imap_send_qstring (MAILSTREAM *stream,char *tag,char **s, + SIZEDTEXT *as,char *limit); IMAPPARSEDREPLY *imap_send_literal (MAILSTREAM *stream,char *tag,char **s, STRING *st); IMAPPARSEDREPLY *imap_send_spgm (MAILSTREAM *stream,char *tag,char *base, @@ -2748,6 +2752,84 @@ args[0] = &ambx; args[1] = NIL; return imap_acl_work (stream,"GETACL",args); } + +/* IMAP set annotation + * Accepts: mail stream + * annotation struct + * Returns: T on success, NIL on failure + */ + +long imap_setannotation (MAILSTREAM *stream,ANNOTATION *annotation) +{ + IMAPARG *args[4],ambx,apth,aval; + long ret; + + ambx.type = ASTRING; + ambx.text = (void *) annotation->mbox; + args[0] = &ambx; + + apth.type = QSTRING; + apth.text = (void *) annotation->entry; + args[1] = &apth; + + STRINGLIST *st,*l; + ANNOTATION_VALUES *v; + + l = st = mail_newstringlist(); + v = annotation->values; + while(v){ + l->text.size = strlen((char *) (l->text.data = (unsigned char*)cpystr(v->attr))); + l->next = mail_newstringlist(); + l = l->next; + l->text.size = strlen((char *) (l->text.data = (unsigned char*)cpystr(v->value))); + if(v->next){ + l->next = mail_newstringlist(); + l = l->next; + } + v = v->next; + } + + aval.type = QLIST; + aval.text = (void *)st; + args[2] = &aval; + args[3] = NIL; + + ret = imap_annotation_work(stream, "SETANNOTATION",args); + mail_free_stringlist(&st); + return ret; +} + + + +/* IMAP get annotation + * Accepts: mail stream + * mailbox name + * annotation entry list + * annotation attribute list + * Returns: T on success with data returned via callback, NIL on failure + */ + +long imap_getannotation (MAILSTREAM *stream,char *mailbox,STRINGLIST *entries, STRINGLIST *attributes) +{ + IMAPARG *args[4],ambx,apth,aattr; + long ret; + ambx.type = ASTRING; + ambx.text = (void*) mailbox; + args[0] = &ambx; + + + apth.type = QLIST; + apth.text = (void*) entries; + args[1] = &apth; + + aattr.type = QLIST; + aattr.text = (void*) attributes; + args[2] = &aattr; + + args[3] = NIL; + ret = imap_annotation_work(stream, "GETANNOTATION",args); + return ret; +} /* IMAP list rights * Accepts: mail stream @@ -2800,6 +2882,16 @@ else mm_log ("ACL not available on this IMAP server",ERROR); return ret; } + long imap_annotation_work(MAILSTREAM *stream, char *command,IMAPARG *args[]) +{ + long ret = NIL; + IMAPPARSEDREPLY *reply; + if (imap_OK (stream,reply = imap_send (stream,command,args))) + ret = LONGT; + else mm_log (reply->text,ERROR); + return ret; +} + /* IMAP set quota * Accepts: mail stream @@ -2932,6 +3024,11 @@ if (reply = imap_send_astring (stream,tag,&s,&st,NIL,CMDBASE+MAXCOMMAND)) return reply; break; + case QSTRING: /* atom or string, must be literal? */ + st.size = strlen ((char *) (st.data = (unsigned char *) arg->text)); + if (reply = imap_send_qstring (stream,tag,&s,&st,CMDBASE+MAXCOMMAND)) + return reply; + break; case LITERAL: /* literal, as a stringstruct */ if (reply = imap_send_literal (stream,tag,&s,arg->text)) return reply; break; @@ -2948,6 +3045,18 @@ while (list = list->next); *s++ = ')'; /* close list */ break; + case QLIST: /* list of strings */ + list = (STRINGLIST *) arg->text; + c = '('; /* open paren */ + do { /* for each list item */ + *s++ = c; /* write prefix character */ + if (reply = imap_send_qstring (stream,tag,&s,&list->text, + 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)) @@ -3115,6 +3224,32 @@ mail_unlock (stream); /* unlock stream */ return reply; } + +/* IMAP send quoted-string + * Accepts: MAIL stream + * reply tag + * pointer to current position pointer of output bigbuf + * atom-string to output + * maximum to write as atom or qstring + * Returns: error reply or NIL if success + */ + +IMAPPARSEDREPLY *imap_send_qstring (MAILSTREAM *stream,char *tag,char **s, + SIZEDTEXT *as,char *limit) +{ + unsigned long j; + char c; + STRING st; + /* in case needed */ + INIT (&st,mail_string,(void *) as->data,as->size); + /* always write literal if no space */ + if ((*s + as->size) > limit) return imap_send_literal (stream,tag,s,&st); + + *(*s)++ = '"'; /* write open quote */ + for (j = 0; j < as->size; j++) *(*s)++ = as->data[j]; + *(*s)++ = '"'; /* write close quote */ + return NIL; +} /* IMAP send atom-string * Accepts: MAIL stream @@ -4034,6 +4169,50 @@ } } + else if (!strcmp (reply->key,"ANNOTATION") && (s = reply->text)){ + char * mbox; + /* response looks like ANNOTATION "mailbox" "entry" ("attr" "value" ["attr" "value"]) ["entry" ("attr "value" ["attr" "value"] )]*/ + getannotation_t an = (getannotation_t) mail_parameters (NIL,GET_ANNOTATION,NIL); + + mbox = imap_parse_astring (stream, &s, reply,NIL); + + while(*s){ + ANNOTATION * al = mail_newannotation(); + al->mbox = cpystr(mbox); + t = imap_parse_astring (stream, &s, reply,NIL); + al->entry = t; + STRINGLIST *strlist; + if (s){while (*s == ' ')s++;} + + strlist = imap_parse_stringlist(stream, &s,reply); + + ANNOTATION_VALUES *vlIter, *vlBegin; + vlIter = vlBegin = NIL; + if (strlist) { + while(strlist){ + if(vlIter){ + vlIter->next = mail_newannotationvalue(); + vlIter = vlIter->next; + }else{ + vlIter = mail_newannotationvalue(); + vlBegin = vlIter; + } + if ( strlist->text.size ) + vlIter->attr = cpystr (strlist->text.data); + strlist = strlist->next; + if(!strlist) continue; + if ( strlist->text.size ) + vlIter->value = cpystr (strlist->text.data); + strlist = strlist->next; + } + } + al->values = vlBegin; + if (an) + (*an) (stream,al); + mail_free_annotation(&al); + } + fs_give ((void **)&mbox); + } else if (!strcmp (reply->key,"ACL") && (s = reply->text) && (t = imap_parse_astring (stream,&s,reply,NIL))) { getacl_t ar = (getacl_t) mail_parameters (NIL,GET_ACL,NIL); diff -Naur imap-2006f.orig/src/c-client/imap4r1.h imap-2006f/src/c-client/imap4r1.h --- imap-2006f.orig/src/c-client/imap4r1.h 2007-03-15 23:35:38.000000000 +0100 +++ imap-2006f/src/c-client/imap4r1.h 2007-03-15 23:35:48.000000000 +0100 @@ -248,3 +248,5 @@ long imap_setquota (MAILSTREAM *stream,char *qroot,STRINGLIST *limits); long imap_getquota (MAILSTREAM *stream,char *qroot); long imap_getquotaroot (MAILSTREAM *stream,char *mailbox); +long imap_getannotation (MAILSTREAM *stream,char *mailbox,STRINGLIST *entries,STRINGLIST *attributes); +long imap_setannotation (MAILSTREAM *stream,ANNOTATION *annotation); diff -Naur imap-2006f.orig/src/c-client/mail.c imap-2006f/src/c-client/mail.c --- imap-2006f.orig/src/c-client/mail.c 2007-03-15 23:35:38.000000000 +0100 +++ imap-2006f/src/c-client/mail.c 2007-03-15 23:35:48.000000000 +0100 @@ -67,6 +67,7 @@ static newsrcquery_t mailnewsrcquery = NIL; /* ACL results callback */ static getacl_t mailaclresults = NIL; +static getannotation_t mailannotationresults = NIL; /* list rights results callback */ static listrights_t maillistrightsresults = NIL; /* my rights results callback */ @@ -580,6 +581,11 @@ ret = (void *) (debugsensitive ? VOIDT : NIL); break; + case SET_ANNOTATION: + mailannotationresults = (getannotation_t) value; + case GET_ANNOTATION: + ret = (void *) mailannotationresults; + break; case SET_ACL: mailaclresults = (getacl_t) value; case GET_ACL: @@ -5666,7 +5672,15 @@ return (ACLLIST *) memset (fs_get (sizeof (ACLLIST)),0,sizeof (ACLLIST)); } +ANNOTATION *mail_newannotation (void) +{ + return (ANNOTATION *) memset (fs_get (sizeof (ANNOTATION)),0,sizeof(ANNOTATION)); +} +ANNOTATION_VALUES *mail_newannotationvalue (void) +{ + return (ANNOTATION_VALUES *) memset (fs_get (sizeof (ANNOTATION_VALUES)),0,sizeof(ANNOTATION_VALUES)); +} /* Mail instantiate new quotalist * Returns: new quotalist */ @@ -5989,6 +6003,25 @@ } } +static void mail_free_annotation_values(ANNOTATION_VALUES **val) +{ + if (*val) { + if ((*val)->attr) fs_give ((void**) &(*val)->attr); + if ((*val)->value) fs_give ((void**) &(*val)->value); + mail_free_annotation_values (&(*val)->next); + fs_give ((void **) val); + } +} +void mail_free_annotation(ANNOTATION **al) +{ + if (*al) { + if((*al)->mbox) fs_give ((void**) &(*al)->mbox); + if((*al)->entry) fs_give ((void**) &(*al)->entry); + if((*al)->values) + mail_free_annotation_values(&(*al)->values); + fs_give ((void **) al); + } +} /* Mail garbage collect quotalist * Accepts: pointer to quotalist pointer diff -Naur imap-2006f.orig/src/c-client/mail.h imap-2006f/src/c-client/mail.h --- imap-2006f.orig/src/c-client/mail.h 2007-03-15 23:35:38.000000000 +0100 +++ imap-2006f/src/c-client/mail.h 2007-03-15 23:38:25.000000000 +0100 @@ -347,6 +347,8 @@ #define SET_SCANCONTENTS (long) 573 #define GET_MHALLOWINBOX (long) 574 #define SET_MHALLOWINBOX (long) 575 +#define GET_ANNOTATION (long) 576 +#define SET_ANNOTATION (long) 577 /* Driver flags */ @@ -1039,6 +1041,24 @@ ACLLIST *next; }; +/* ANNOTATION Response */ + +#define ANNOTATION_VALUES struct annotation_value_list + +ANNOTATION_VALUES { + char *attr; + char *value; + ANNOTATION_VALUES *next; +}; + +#define ANNOTATION struct annotation + +ANNOTATION { + char *mbox; + char *entry; + ANNOTATION_VALUES * values; +}; + /* Quota resource list */ #define QUOTALIST struct quota_list @@ -1347,6 +1367,7 @@ typedef void (*logouthook_t) (void *data); typedef char *(*sslclientcert_t) (void); typedef char *(*sslclientkey_t) (void); +typedef void (*getannotation_t) (MAILSTREAM *stream,ANNOTATION* annot); /* Globals */ @@ -1763,7 +1784,10 @@ SORTPGM *mail_newsortpgm (void); THREADNODE *mail_newthreadnode (SORTCACHE *sc); ACLLIST *mail_newacllist (void); +ANNOTATION* mail_newannotation(void); +ANNOTATION_VALUES* mail_newannotationvalue(void); QUOTALIST *mail_newquotalist (void); +void mail_free_annotation(ANNOTATION **a); void mail_free_body (BODY **body); void mail_free_body_data (BODY *body); void mail_free_body_parameter (PARAMETER **parameter); diff -Naur imap-2006f.orig/src/mtest/mtest.c imap-2006f/src/mtest/mtest.c --- imap-2006f.orig/src/mtest/mtest.c 2007-03-15 23:35:38.000000000 +0100 +++ imap-2006f/src/mtest/mtest.c 2007-03-15 23:35:48.000000000 +0100 @@ -145,6 +145,8 @@ #endif return NIL; } + +void mm_annotation (MAILSTREAM *stream, ANNOTATION *a); /* MM command loop * Accepts: MAIL stream @@ -195,6 +197,28 @@ mail_setflag (stream,arg,"\\DELETED"); else puts ("?Bad message number"); break; + case 'A': + { + char parms[MAILTMPLEN]; + prompt("Annotation: ",parms); + if (parms) { + mail_parameters(stream,SET_ANNOTATION,mm_annotation); + STRINGLIST *entries = mail_newstringlist(); + STRINGLIST *cur = entries; + cur->text.size = strlen((char *) (cur->text.data = (unsigned char*)cpystr (parms))); + cur->next = NIL; + + STRINGLIST *attributes = mail_newstringlist(); + cur = attributes; + cur->text.size = strlen((char *) (cur->text.data = (unsigned char*)cpystr ("*"))); + cur->next = NIL; + + imap_getannotation(stream,"INBOX",entries,attributes); + mail_free_stringlist(&entries); + mail_free_stringlist(&attributes); + } + } + break; case 'E': /* Expunge command */ mail_expunge (stream); last = 0; @@ -347,7 +371,7 @@ case '?': /* ? command */ puts ("Body, Check, Delete, Expunge, Find, GC, Headers, Literal,"); puts (" MailboxStatus, New Mailbox, Overview, Ping, Quit, Send, Type,"); - puts ("Undelete, Xit, +, -, or <RETURN> for next message"); + puts ("Undelete, Xit,Annotation, +, -, or <RETURN> for next message"); break; default: /* bogus command */ printf ("?Unrecognized command: %s\n",cmd); @@ -595,6 +619,18 @@ /* Interfaces to C-client */ +void mm_annotation (MAILSTREAM *stream, ANNOTATION *a) +{ + if(a){ + fprintf(stderr,"mailbox: %s\nentry: %s\n",a->mbox,a->entry); + ANNOTATION_VALUES * v = a->values; + while(v){ + fprintf(stderr,"attr: %s, value: %s\n",v->attr,v->value); + v = v->next; + } + } +} + void mm_searched (MAILSTREAM *stream,unsigned long number) {
-- ____ http://www.pardus.de _________________ http://gunnarwrobel.de _ E-mail : [EMAIL PROTECTED] Dr. Gunnar Wrobel Tel. : +49 40 432 72335 Hartwig-Hesse Str. 12 Fax : +49 40 432 70855 D-20257 Hamburg ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ >> Mail at ease - Rent a kolab groupware server at [EMAIL PROTECTED] << ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
_______________________________________________ Imap-uw mailing list Imap-uw@u.washington.edu https://mailman1.u.washington.edu/mailman/listinfo/imap-uw