/* Proxy SETANNOTATION commands to backend */ int annotate_store_proxy(const char *server, const char *mbox_pat, struct entryattlist *entryatts) { struct backend *be; struct entryattlist *e; struct attvaluelist *av; char mytag[128]; assert(server && mbox_pat && entryatts); be = proxy_findserver(server, &imap_protocol, proxy_userid, &backend_cached, &backend_current, &backend_inbox, imapd_in); if (!be) return IMAP_SERVER_UNAVAILABLE; /* Send command to remote */ proxy_gentag(mytag, sizeof(mytag)); prot_printf(be->out, "%s SETANNOTATION \"%s\" (", mytag, mbox_pat); for (e = entryatts; e; e = e->next) { prot_printf(be->out, "\"%s\" (", e->entry); for (av = e->attvalues; av; av = av->next) { prot_printf(be->out, "\"%s\" ", av->attrib); prot_printmap(be->out, av->value.s, av->value.len); prot_printf(be->out, "%s", av->next ? " " : ""); } prot_printf(be->out, ")"); if (e->next) prot_printf(be->out, " "); } prot_printf(be->out, ")\r\n"); prot_flush(be->out); /* Pipe the results. Note that backend-current may also pipe us other messages. */ pipe_until_tag(be, mytag, 0); return 0; }
static void test_printmap(void) { PROLOG; struct protstream *p; int len; struct buf b = BUF_INITIALIZER; int i; char str[2600]; p = prot_new(_fd, 1); CU_ASSERT_PTR_NOT_NULL_FATAL(p); /* NULL string */ BEGIN; prot_printmap(p, NULL, 0); prot_flush(p); END(str, len); CU_ASSERT_EQUAL(len, 3); CU_ASSERT_STRING_EQUAL(str, "NIL"); /* Zero length string */ BEGIN; prot_printmap(p, "", 0); prot_flush(p); END(str, len); CU_ASSERT_EQUAL(len, 2); CU_ASSERT_STRING_EQUAL(str, "\"\""); /* Boring string */ BEGIN; prot_printmap(p, "Hello", 5); prot_flush(p); END(str, len); CU_ASSERT_EQUAL(len, 7); CU_ASSERT_STRING_EQUAL(str, "\"Hello\""); /* Boring string with short length */ BEGIN; prot_printmap(p, "Hello", 3); prot_flush(p); END(str, len); CU_ASSERT_EQUAL(len, 5); CU_ASSERT_STRING_EQUAL(str, "\"Hel\""); /* String with non-dangerous whitespace */ BEGIN; prot_printmap(p, "Hello World\tagain", 17); prot_flush(p); END(str, len); CU_ASSERT_EQUAL(len, 19); CU_ASSERT_STRING_EQUAL(str, "\"Hello World\tagain\""); /* String with dangerous whitespace */ BEGIN; prot_printmap(p, "Good\rBye\nEarth", 14); prot_flush(p); END(str, len); CU_ASSERT_EQUAL(len, 20); CU_ASSERT_STRING_EQUAL(str, "{14}\r\nGood\rBye\nEarth"); /* String with embedded dquote */ BEGIN; prot_printmap(p, "Quot\"able", 9); prot_flush(p); END(str, len); CU_ASSERT_EQUAL(len, 14); CU_ASSERT_STRING_EQUAL(str, "{9}\r\nQuot\"able"); /* String with embedded percent */ BEGIN; prot_printmap(p, "per%ent", 7); prot_flush(p); END(str, len); CU_ASSERT_EQUAL(len, 12); CU_ASSERT(!strcmp(str, "{7}\r\nper%ent")); /* String with embedded backslash */ BEGIN; prot_printmap(p, "slash\\dot", 9); prot_flush(p); END(str, len); CU_ASSERT_EQUAL(len, 14); CU_ASSERT_STRING_EQUAL(str, "{9}\r\nslash\\dot"); /* String with embedded 8-bit chars */ BEGIN; prot_printmap(p, "Hi I'm \330l\345f", 11); prot_flush(p); END(str, len); CU_ASSERT_EQUAL(len, 17); CU_ASSERT_STRING_EQUAL(str, "{11}\r\nHi I'm \330l\345f"); /* Boring but overly long string */ for (i = 0 ; i<500 ; i++) buf_appendcstr(&b, "blah "); buf_cstring(&b); BEGIN; prot_printmap(p, b.s, b.len); prot_flush(p); END(str, len); CU_ASSERT_EQUAL(len, b.len+8); CU_ASSERT_STRING_EQUAL(str+8, b.s); str[8] = '\0'; CU_ASSERT_STRING_EQUAL(str, "{2500}\r\n"); buf_free(&b); prot_free(p); EPILOG; }