/* Send the completion response and reset the state. */ int io_format_completion_response (mu_stream_t str, struct imap4d_command *command, int rc, const char *format, va_list ap) { int new_state; int status = 0; const char *sc = sc2string (rc); imap4d_sync (); mu_stream_printf (str, "%s %s%s ", command->tag, sc, command->name); mu_stream_vprintf (str, format, ap); mu_stream_write (str, "\n", 1, NULL); /* Reset the state. */ if (rc == RESP_OK) new_state = command->success; else if (command->failure <= state) new_state = command->failure; else new_state = STATE_NONE; if (new_state != STATE_NONE) { if (new_state == STATE_AUTH) set_xscript_level (MU_XSCRIPT_NORMAL); state = new_state; } return status; }
int imap4d_noop (struct imap4d_session *session, struct imap4d_command *command, imap4d_tokbuf_t tok) { if (imap4d_tokbuf_argc (tok) != 2) return io_completion_response (command, RESP_BAD, "Invalid arguments"); imap4d_sync (); return io_completion_response (command, RESP_OK, "Completed"); }
static int imap4d_mainloop (int fd, FILE *infile, FILE *outfile) { imap4d_tokbuf_t tokp; char *text; int debug_mode = isatty (fd); imap4d_child_signal_setup (imap4d_child_signal); util_setio (infile, outfile); if (imap4d_preauth_setup (fd) == 0) { if (debug_mode) { mu_diag_output (MU_DIAG_INFO, _("started in debugging mode")); text = "IMAP4rev1 Debugging mode"; } else text = "IMAP4rev1"; } else { util_flush_output (); return 0; } /* Greetings. */ util_out ((state == STATE_AUTH) ? RESP_PREAUTH : RESP_OK, "%s", text); util_flush_output (); tokp = imap4d_tokbuf_init (); while (1) { imap4d_readline (tokp); /* check for updates */ imap4d_sync (); util_do_command (tokp); imap4d_sync (); util_flush_output (); } return 0; }
/* The code is shared between select and noop */ int imap4d_select_status () { const char *mflags = "\\Answered \\Flagged \\Deleted \\Seen \\Draft"; unsigned long uidvalidity = 0; size_t count = 0, recent = 0, unseen = 0, uidnext = 0; int status = 0; if (state != STATE_SEL) return 0; /* FIXME: this should be something! */ if ((status = util_uidvalidity (mbox, &uidvalidity)) || (status = mu_mailbox_uidnext (mbox, &uidnext)) || (status = mu_mailbox_messages_count (mbox, &count)) || (status = mu_mailbox_messages_recent (mbox, &recent)) || (status = mu_mailbox_message_unseen (mbox, &unseen))) return status; /* This outputs EXISTS and RECENT responses */ imap4d_sync(); io_untagged_response (RESP_OK, "[UIDVALIDITY %lu] UID valididy status", uidvalidity); io_untagged_response (RESP_OK, "[UIDNEXT %lu] Predicted next uid", (unsigned long) uidnext); if (unseen) io_untagged_response (RESP_OK, "[UNSEEN %lu] first unseen message", (unsigned long) unseen); io_untagged_response (RESP_NONE, "FLAGS (%s)", mflags); /* FIXME: - '\*' can be supported if we use the attribute_set userflag() - Answered is still not set in the mailbox code. */ if (!(select_flags & MU_STREAM_WRITE)) io_untagged_response (RESP_OK, "[PERMANENTFLAGS ()] No permanent flags"); else io_untagged_response (RESP_OK, "[PERMANENTFLAGS (%s)] Permanent flags", mflags); return 0; }
/* This code is shared with EXAMINE. */ int imap4d_select0 (struct imap4d_command *command, const char *mboxname, int flags) { int status; char *mailbox_name; /* FIXME: Check state. */ /* Even if a mailbox is selected, a SELECT EXAMINE or LOGOUT command MAY be issued without previously issuing a CLOSE command. The SELECT, EXAMINE, and LOGUT commands implictly close the currently selected mailbox without doing an expunge. */ if (mbox) { imap4d_enter_critical (); mu_mailbox_sync (mbox); mu_mailbox_close (mbox); manlock_unlock (mbox); imap4d_leave_critical (); mu_mailbox_destroy (&mbox); /* Destroy the old uid table. */ imap4d_sync (); } if (strcmp (mboxname, "INBOX") == 0) flags |= MU_STREAM_CREAT; mailbox_name = namespace_getfullpath (mboxname, NULL); if (!mailbox_name) return io_completion_response (command, RESP_NO, "Couldn't open mailbox"); if (flags & MU_STREAM_RDWR) { status = manlock_open_mailbox (&mbox, mailbox_name, 1, flags); } else { status = mu_mailbox_create_default (&mbox, mailbox_name); if (status) mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_create_default", mailbox_name, status); else { status = mu_mailbox_open (mbox, flags); if (status) { mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_open", mailbox_name, status); mu_mailbox_destroy (&mbox); } } } if (status == 0) { select_flags = flags; state = STATE_SEL; imap4d_set_observer (mbox); if ((status = imap4d_select_status ()) == 0) { free (mailbox_name); /* Need to set the state explicitely for select. */ return io_sendf ("%s OK [%s] %s Completed\n", command->tag, ((flags & MU_STREAM_RDWR) == MU_STREAM_RDWR) ? "READ-WRITE" : "READ-ONLY", command->name); } } mu_mailbox_destroy (&mbox); status = io_completion_response (command, RESP_NO, "Could not open %s: %s", mboxname, mu_strerror (status)); free (mailbox_name); return status; }