| 517 | } |
| 518 | |
| 519 | static struct imap_cmd *issue_imap_cmd(struct imap_store *ctx, |
| 520 | struct imap_cmd_cb *cb, |
| 521 | const char *fmt, va_list ap) |
| 522 | { |
| 523 | struct imap *imap = ctx->imap; |
| 524 | struct imap_cmd *cmd; |
| 525 | int n; |
| 526 | struct strbuf buf = STRBUF_INIT; |
| 527 | |
| 528 | cmd = xmalloc(sizeof(struct imap_cmd)); |
| 529 | cmd->cmd = xstrvfmt(fmt, ap); |
| 530 | cmd->tag = ++imap->nexttag; |
| 531 | |
| 532 | if (cb) |
| 533 | cmd->cb = *cb; |
| 534 | else |
| 535 | memset(&cmd->cb, 0, sizeof(cmd->cb)); |
| 536 | |
| 537 | while (imap->literal_pending) |
| 538 | get_cmd_result(ctx, NULL); |
| 539 | |
| 540 | if (!cmd->cb.data) |
| 541 | strbuf_addf(&buf, "%d %s\r\n", cmd->tag, cmd->cmd); |
| 542 | else |
| 543 | strbuf_addf(&buf, "%d %s{%d%s}\r\n", cmd->tag, cmd->cmd, |
| 544 | cmd->cb.dlen, CAP(LITERALPLUS) ? "+" : ""); |
| 545 | if (buf.len > INT_MAX) |
| 546 | die("imap command overflow!"); |
| 547 | |
| 548 | if (0 < verbosity) { |
| 549 | if (imap->num_in_progress) |
| 550 | printf("(%d in progress) ", imap->num_in_progress); |
| 551 | if (!starts_with(cmd->cmd, "LOGIN")) |
| 552 | printf(">>> %s", buf.buf); |
| 553 | else |
| 554 | printf(">>> %d LOGIN <user> <pass>\n", cmd->tag); |
| 555 | } |
| 556 | if (socket_write(&imap->buf.sock, buf.buf, buf.len) != buf.len) { |
| 557 | free(cmd->cmd); |
| 558 | free(cmd); |
| 559 | if (cb) |
| 560 | free(cb->data); |
| 561 | strbuf_release(&buf); |
| 562 | return NULL; |
| 563 | } |
| 564 | strbuf_release(&buf); |
| 565 | if (cmd->cb.data) { |
| 566 | if (CAP(LITERALPLUS)) { |
| 567 | n = socket_write(&imap->buf.sock, cmd->cb.data, cmd->cb.dlen); |
| 568 | free(cmd->cb.data); |
| 569 | if (n != cmd->cb.dlen || |
| 570 | socket_write(&imap->buf.sock, "\r\n", 2) != 2) { |
| 571 | free(cmd->cmd); |
| 572 | free(cmd); |
| 573 | return NULL; |
| 574 | } |
| 575 | cmd->cb.data = NULL; |
| 576 | } else |
no test coverage detected