X-Git-Url: http://git.madism.org/?p=apps%2Fmadmutt.git;a=blobdiff_plain;f=lib-mx%2Fpop-new.c;h=fcc17df71e859c689d1792a4ebea58ec20458fec;hp=a46cc8212c9f84f8040bae1c2dea13699fb0c8b9;hb=806d13adf4c00b1c71c1c5eaca8431524ce1ec1e;hpb=98f62b5fcbd680fd5214ee85e1635b84322cbdd1 diff --git a/lib-mx/pop-new.c b/lib-mx/pop-new.c index a46cc82..fcc17df 100644 --- a/lib-mx/pop-new.c +++ b/lib-mx/pop-new.c @@ -33,17 +33,16 @@ enum pop_state { POP_CONNECTING, POP_CHECK_CAPA0, POP_STLS, - POP_CHECK_CAPA1, POP_AUTHENTICATE, - POP_CHECK_CAPA2, + POP_CHECK_CAPA1, POP_STAT, POP_READY, }; typedef enum { - CMD_UNKNOWN, /* unknown whether it is available or not */ CMD_NOT_AVAILABLE, CMD_AVAILABLE, + CMD_UNKNOWN, /* unknown whether it is available or not */ } cmd_status; typedef struct pop_data_t { @@ -51,12 +50,10 @@ typedef struct pop_data_t { enum pop_state state; unsigned multiline : 1; - unsigned known_capa : 1; + unsigned capa_done : 1; unsigned use_stls : 2; cmd_status cmd_capa : 2; /* optional command CAPA */ cmd_status cmd_stls : 2; /* optional command STLS */ - cmd_status cmd_uidl : 2; /* optional command UIDL */ - cmd_status cmd_top : 2; /* optional command TOP */ cmd_status cmd_user : 2; /* optional command USER */ ACCOUNT act; @@ -142,39 +139,17 @@ static __fini void pop_shutdown(void) __eol + 1; \ }) -static int pop_read_banner(job_t *w, pop_data_t *pd) +static int pop_parse_capa(job_t *w, pop_data_t *pd, const char *eol) { - const char *eol = POP_CHECK_EOL(w, pd); - const char *p, *q; - - if (m_strncmp(pd->ibuf.data, "+OK", 3)) - return el_job_release(w, EL_ERROR); - - p = memchr(pd->ibuf.data, '<', eol - pd->ibuf.data); - if (p && (q = memchr(p + 1, '>', eol - p - 1))) { - pd->apop_token = p_dupstr(p, q + 1 - p); - } - buffer_consume_upto(&pd->ibuf, eol); - - /* TODO do not check capa again */ - pd->state = POP_CHECK_CAPA0; - buffer_addstr(&pd->obuf, "CAPA\r\n"); - return el_job_setmode(w, EL_WRITING); -} - -static int pop_check_capa(job_t *w, pop_data_t *pd) -{ - const char *p = POP_CHECK_EOL(w, pd); + const char *p = pd->ibuf.data; if (!pd->multiline) { if (m_strncmp(pd->ibuf.data, "+OK", 3)) { - pd->cmd_capa = CMD_NOT_AVAILABLE; - pd->cmd_stls = CMD_NOT_AVAILABLE; - goto end; + buffer_consume_upto(&pd->ibuf, eol); + return 1; } pd->multiline = true; - } else { - p = pd->ibuf.data; + p = eol; } for (;;) { @@ -185,51 +160,84 @@ static int pop_check_capa(job_t *w, pop_data_t *pd) } if (p[0] == '.' && p[1] != '.') { buffer_consume_upto(&pd->ibuf, q); - break; + return 1; } if (m_strcasestart(p, "SASL", &p)) { p = skipspaces(p); pd->auth_mechs = p_dupstr(p, q - p); } else if (m_strcasestart(p, "STLS", NULL)) { pd->cmd_stls = CMD_AVAILABLE; - } else if (m_strcasestart(p, "UIDL", NULL)) { - pd->cmd_uidl = CMD_AVAILABLE; - } else if (m_strcasestart(p, "TOP", NULL)) { - pd->cmd_top = CMD_AVAILABLE; } p = q; } +} + +static int pop_do_connect(job_t *w, pop_data_t *pd) +{ + const char *eol = POP_CHECK_EOL(w, pd); + const char *p, *q; - end: - pd->multiline = false; switch (pd->state) { + case POP_CONNECTING: + if (m_strncmp(pd->ibuf.data, "+OK", 3)) + return el_job_release(w, EL_ERROR); + + p = memchr(pd->ibuf.data, '<', eol - pd->ibuf.data); + if (p && (q = memchr(p + 1, '>', eol - p - 1))) { + pd->apop_token = p_dupstr(p, q + 1 - p); + } + buffer_consume_upto(&pd->ibuf, eol); + if (pd->capa_done) + goto capa0_choice; + pd->state = POP_CHECK_CAPA0; + buffer_addstr(&pd->obuf, "CAPA\r\n"); + return el_job_setmode(w, EL_WRITING); + case POP_CHECK_CAPA0: - if (!pd->act.has_ssl && (pd->cmd_stls || mod_ssl.force_tls)) { - buffer_addstr(&pd->obuf, "STLS\r\n"); - pd->state = POP_STLS; - return el_job_setmode(w, EL_WRITING); + if (!pop_parse_capa(w, pd, eol)) + return 0; + + capa0_choice: + pd->multiline = false; + if (pd->act.has_ssl || (!pd->cmd_stls && !mod_ssl.force_tls)) + goto do_authenticate; + pd->state = POP_STLS; + buffer_addstr(&pd->obuf, "STLS\r\n"); + return el_job_setmode(w, EL_WRITING); + + case POP_STLS: + if (m_strncmp(pd->ibuf.data, "+OK", 3)) { + pd->cmd_stls = CMD_NOT_AVAILABLE; + buffer_consume_upto(&pd->ibuf, eol); + goto do_authenticate; } - /* FALLTHROUGH */ - case POP_CHECK_CAPA1: + do_authenticate: pd->state = POP_AUTHENTICATE; - /* TODO */ - return -1; + return el_job_starttls(w); - case POP_CHECK_CAPA2: + case POP_AUTHENTICATE: + abort(); + pd->state = POP_CHECK_CAPA1; + buffer_addstr(&pd->obuf, "CAPA\r\n"); + return el_job_setmode(w, EL_WRITING); + + case POP_CHECK_CAPA1: + if (!pop_parse_capa(w, pd, eol)) + return 0; + pd->capa_done = true; pd->state = POP_STAT; - return -1; + buffer_addstr(&pd->obuf, "STAT\r\n"); + return el_job_setmode(w, EL_WRITING); + + case POP_STAT: + pd->state = POP_READY; + return el_job_setmode(w, EL_IDLE); default: - return el_job_release(w, EL_ERROR); + abort(); } } -static int (*pop_actions[])(job_t *, pop_data_t *pd) = { - [POP_CONNECTING] = pop_read_banner, - [POP_CHECK_CAPA0] = pop_check_capa, - NULL, -}; - static int pop_setup(job_t *w, void *cfg) { pop_data_t *pd = w->ptr = pop_data_dup(cfg); @@ -244,8 +252,10 @@ static int pop_on_event(job_t *w, el_event evt) case EL_EVT_IN: EL_JOB_CHECK(el_job_read(w, &pd->ibuf)); - EL_JOB_CHECK(pop_actions[pd->state](w, pd)); - /* FALLTHROUGH */ + if (pd->state <= POP_STAT) + return pop_do_connect(w, pd); + abort(); + case EL_EVT_OUT: EL_JOB_CHECK(el_job_write(w, &pd->obuf)); if (pd->obuf.len == 0) @@ -268,7 +278,6 @@ static void pop_finalize(job_t *w, el_status reason) case POP_STLS: case POP_CHECK_CAPA1: case POP_AUTHENTICATE: - case POP_CHECK_CAPA2: case POP_STAT: mutt_error(_("Error connecting to server: %s"), pd->act.host); break;