http://wiki.kolab.org/index.php/Kolab-major-app-patches Patch description: There is an imap extension for adding "annotations" (eg. metadata) to imap folders in the form of key/value pairs. The key is typically something like /vendor/<vendorname>/<attributename>. Cyrus imapd only supports a few special annotation keys for internal use (such as being able to mark a folder for indexing etc.). The patch extends cyrus imapd to allow any annotation. Impact: The annotation patch is critical to kolab. Without the patch, the clients will not know which folder is for calender, tasks etc. --- imap/annotate.c 2007-02-05 19:41:45.000000000 +0100 +++ imap/annotate.c.oden 2007-05-26 21:12:22.000000000 +0200 @@ -1797,6 +1797,11 @@ { NULL, 0, ANNOTATION_PROXY_T_INVALID, 0, 0, NULL, NULL } }; +const struct annotate_st_entry vendor_entry = + { NULL, ATTRIB_TYPE_STRING, BACKEND_ONLY, + ATTRIB_VALUE_SHARED | ATTRIB_VALUE_PRIV, + ACL_ADMIN, annotation_set_todb, NULL }; + int annotatemore_store(char *mailbox, struct entryattlist *l, struct namespace *namespace, @@ -1809,6 +1814,7 @@ struct attvaluelist *av; struct storedata sdata; const struct annotate_st_entry *entries; + struct annotate_st_entry * working_entry; time_t now = time(0); memset(&sdata, 0, sizeof(struct storedata)); @@ -1830,34 +1836,52 @@ while (e) { int entrycount, attribs; struct annotate_st_entry_list *nentry = NULL; + struct annotate_st_entry *ientry = NULL; /* See if we support this entry */ + working_entry = NULL; for (entrycount = 0; entries[entrycount].name; entrycount++) { if (!strcmp(e->entry, entries[entrycount].name)) { + working_entry = &(entries[entrycount]); break; } } - if (!entries[entrycount].name) { - /* unknown annotation */ - return IMAP_PERMISSION_DENIED; + if (working_entry==NULL) { + /* test for generic vendor annotation */ + if ((strncmp("/vendor/", e->entry, strlen("/vendor/"))==0) && + (strlen(e->entry)>strlen("/vendor/"))) { + working_entry = &(vendor_entry); + } + else { + /* unknown annotation */ + return IMAP_PERMISSION_DENIED; + } } /* Add this entry to our list only if it applies to our particular server type */ - if ((entries[entrycount].proxytype != PROXY_ONLY) + if ((working_entry->proxytype != PROXY_ONLY) || proxy_store_func) { + ientry = xzmalloc(sizeof(struct annotate_st_entry)); + ientry->name = e->entry; + ientry->type = working_entry->type; + ientry->proxytype = working_entry->proxytype; + ientry->attribs = working_entry->attribs; + ientry->acl = working_entry->acl; + ientry->set = working_entry->set; + ientry->rock = working_entry->rock; nentry = xzmalloc(sizeof(struct annotate_st_entry_list)); nentry->next = sdata.entry_list; - nentry->entry = &(entries[entrycount]); + nentry->entry = ientry; nentry->shared.modifiedsince = now; nentry->priv.modifiedsince = now; sdata.entry_list = nentry; } /* See if we are allowed to set the given attributes. */ - attribs = entries[entrycount].attribs; + attribs = working_entry->attribs; av = e->attvalues; while (av) { const char *value; @@ -1867,7 +1891,7 @@ goto cleanup; } value = annotate_canon_value(av->value, - entries[entrycount].type); + working_entry->type); if (!value) { r = IMAP_ANNOTATION_BADVALUE; goto cleanup; @@ -1893,7 +1917,7 @@ goto cleanup; } value = annotate_canon_value(av->value, - entries[entrycount].type); + working_entry->type); if (!value) { r = IMAP_ANNOTATION_BADVALUE; goto cleanup; @@ -1997,6 +2021,12 @@ /* Free the entry list */ while (sdata.entry_list) { struct annotate_st_entry_list *freeme = sdata.entry_list; + if (freeme != NULL){ + struct annotate_st_entry *freeme2 = freeme->entry; + if (freeme2 != NULL) { + free( freeme2 ); + } + } sdata.entry_list = sdata.entry_list->next; free(freeme); }