diff options
-rw-r--r-- | imap/Makefile.am | 4 | ||||
-rw-r--r-- | imap/auth_anon.c | 24 | ||||
-rw-r--r-- | pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */* Amlogic Audio FIFO controllers
Required properties:
- compatible: 'amlogic,axg-toddr' or
'amlogic,axg-toddr' or
'amlogic,g12a-frddr' or
'amlogic,g12a-toddr' or
'amlogic,sm1-frddr' or
'amlogic,sm1-toddr'
- reg: physical base address of the controller and length of memory
mapped region.
- interrupts: interrupt specifier for the fifo.
- clocks: phandle to the fifo peripheral clock provided by the audio
clock controller.
- resets: list of reset phandle, one for each entry reset-names.
- reset-names: should contain the following:
* "arb" : memory ARB line (required)
* "rst" : dedicated device reset line (optional)
- #sound-dai-cells: must be 0.
- amlogic,fifo-depth: The size of the controller's fifo in bytes. This
is useful for determining certain configuration such
as the flush threshold of the fifo
Example of FRDDR A on the A113 SoC:
frddr_a: audio-controller@1c0 {
compatible = "amlogic,axg-frddr";
reg = <0x0 0x1c0 0x0 0x1c>;
#sound-dai-cells = <0>;
interrupts = <GIC_SPI 88 IRQ_TYPE_EDGE_RISING>;
clocks = <&clkc_audio AUD_CLKID_FRDDR_A>;
resets = <&arb AXG_ARB_FRDDR_A>;
fifo-depth = <512>;
};
{ dprint (1, (debugfile, "Invalid response from server.\n")); goto bail; } - strfcpy (buf, "ZHVtbXkK\r\n", sizeof (buf)); /* base64 ("dummy") */ - - mutt_socket_write (idata->conn, buf); + mutt_socket_write (idata->conn, "ZHVtbXkK\r\n"); /* base64 ("dummy") */ - if (mutt_socket_readln (buf, sizeof (buf), idata->conn) < 0) + do + rc = imap_cmd_resp (idata); + while (rc == IMAP_CMD_CONTINUE); + + if (rc != IMAP_CMD_DONE) { dprint (1, (debugfile, "Error receiving server response.\n")); goto bail; } - if (imap_code (buf)) + if (imap_code (idata->buf)) return IMAP_AUTH_SUCCESS; bail: diff --git a/imap/auth_cram.c b/imap/auth_cram.c index 9736ee36..00e0f0d9 100644 --- a/imap/auth_cram.c +++ b/imap/auth_cram.c @@ -36,6 +36,7 @@ imap_auth_res_t imap_auth_cram_md5 (IMAP_DATA* idata) char ibuf[LONG_STRING], obuf[LONG_STRING]; unsigned char hmac_response[MD5_DIGEST_LEN]; int len; + int rc; if (!mutt_bit_isset (idata->capabilities, ACRAM_MD5)) return IMAP_AUTH_UNAVAIL; @@ -56,19 +57,17 @@ imap_auth_res_t imap_auth_cram_md5 (IMAP_DATA* idata) * primary host name of the server. The syntax of the unencoded form must * correspond to that of an RFC 822 'msg-id' [RFC822] as described in [POP3]. */ - if (mutt_socket_readln (ibuf, sizeof (ibuf), idata->conn) < 0) - { - dprint (1, (debugfile, "Error receiving server response.\n")); - goto bail; - } - - if (ibuf[0] != '+') + do + rc = imap_cmd_resp (idata); + while (rc == IMAP_CMD_CONTINUE); + + if (rc != IMAP_CMD_RESPOND) { dprint (1, (debugfile, "Invalid response from server: %s\n", ibuf)); goto bail; } - if ((len = mutt_from_base64 (obuf, ibuf + 2)) == -1) + if ((len = mutt_from_base64 (obuf, idata->buf + 2)) == -1) { dprint (1, (debugfile, "Error decoding base64 response.\n")); goto bail; @@ -103,13 +102,17 @@ imap_auth_res_t imap_auth_cram_md5 (IMAP_DATA* idata) strcpy (ibuf + strlen (ibuf), "\r\n"); mutt_socket_write (idata->conn, ibuf); - if (mutt_socket_readln (ibuf, LONG_STRING, idata->conn) < 0) + do + rc = imap_cmd_resp (idata); + while (rc == IMAP_CMD_CONTINUE); + + if (rc != IMAP_CMD_DONE) { dprint (1, (debugfile, "Error receiving server response.\n")); goto bail; } - if (imap_code (ibuf)) + if (imap_code (idata->buf)) return IMAP_AUTH_SUCCESS; bail: diff --git a/imap/auth_gss.c b/imap/auth_gss.c index 96f79b56..bf59c019 100644 --- a/imap/auth_gss.c +++ b/imap/auth_gss.c @@ -54,6 +54,7 @@ imap_auth_res_t imap_auth_gss (IMAP_DATA* idata) OM_uint32 maj_stat, min_stat; char buf1[GSS_BUFSIZE], buf2[GSS_BUFSIZE], server_conf_flags; unsigned long buf_size; + int rc; if (!mutt_bit_isset (idata->capabilities, AGSSAPI)) return IMAP_AUTH_UNAVAIL; @@ -88,14 +89,11 @@ imap_auth_res_t imap_auth_gss (IMAP_DATA* idata) imap_cmd_start (idata, "AUTHENTICATE GSSAPI"); /* expect a null continuation response ("+") */ - if (mutt_socket_readln (buf1, sizeof (buf1), idata->conn) < 0) - { - dprint (1, (debugfile, "Error receiving server response.\n")); - gss_release_name (&min_stat, &target_name); - goto bail; - } + do + rc = imap_cmd_resp (idata); + while (rc == IMAP_CMD_CONTINUE); - if (buf1[0] != '+') + if (rc != IMAP_CMD_RESPOND) { dprint (2, (debugfile, "Invalid response from server: %s\n", buf1)); gss_release_name (&min_stat, &target_name); @@ -128,7 +126,9 @@ imap_auth_res_t imap_auth_gss (IMAP_DATA* idata) gss_release_name (&min_stat, &target_name); /* end authentication attempt */ mutt_socket_write (idata->conn, "*\r\n"); - mutt_socket_readln (buf1, sizeof (buf1), idata->conn); + do + rc = imap_cmd_resp (idata); + while (rc == IMAP_CMD_CONTINUE); goto bail; } @@ -141,14 +141,18 @@ imap_auth_res_t imap_auth_gss (IMAP_DATA* idata) if (maj_stat == GSS_S_CONTINUE_NEEDED) { - if (mutt_socket_readln (buf1, sizeof (buf1), idata->conn) < 0) + do + rc = imap_cmd_resp (idata); + while (rc == IMAP_CMD_CONTINUE); + + if (rc != IMAP_CMD_RESPOND) { dprint (1, (debugfile, "Error receiving server response.\n")); gss_release_name (&min_stat, &target_name); goto bail; } - request_buf.length = mutt_from_base64 (buf2, buf1 + 2); + request_buf.length = mutt_from_base64 (buf2, idata->buf + 2); request_buf.value = buf2; sec_token = &request_buf; } @@ -158,12 +162,16 @@ imap_auth_res_t imap_auth_gss (IMAP_DATA* idata) gss_release_name (&min_stat, &target_name); /* get security flags and buffer size */ - if (mutt_socket_readln (buf1, sizeof (buf1), idata->conn) < 0) + do + rc = imap_cmd_resp (idata); + while (rc == IMAP_CMD_CONTINUE); + + if (rc != IMAP_CMD_RESPOND) { dprint (1, (debugfile, "Error receiving server response.\n")); goto bail; } - request_buf.length = mutt_from_base64 (buf2, buf1 + 2); + request_buf.length = mutt_from_base64 (buf2, idata->buf + 2); request_buf.value = buf2; maj_stat = gss_unwrap (&min_stat, context, &request_buf, &send_token, @@ -221,13 +229,16 @@ imap_auth_res_t imap_auth_gss (IMAP_DATA* idata) mutt_socket_write (idata->conn, buf1); /* Joy of victory or agony of defeat? */ - if (mutt_socket_readln (buf1, GSS_BUFSIZE, idata->conn) < 0) + do + rc = imap_cmd_resp (idata); + while (rc == IMAP_CMD_CONTINUE); + if (rc != IMAP_CMD_DONE) { dprint (1, (debugfile, "Error receiving server response.\n")); mutt_socket_write(idata->conn, "*\r\n"); goto bail; } - if (imap_code (buf1)) + if (imap_code (idata->buf)) { /* flush the security context */ dprint (2, (debugfile, "Releasing GSS credentials\n")); diff --git a/imap/auth_login.c b/imap/auth_login.c index 757c3538..731f14f3 100644 --- a/imap/auth_login.c +++ b/imap/auth_login.c @@ -26,7 +26,7 @@ imap_auth_res_t imap_auth_login (IMAP_DATA* idata) { char q_user[SHORT_STRING], q_pass[SHORT_STRING]; - char buf[LONG_STRING]; + char buf[STRING]; int rc; if (mutt_account_getuser (&idata->conn->account)) @@ -49,8 +49,7 @@ imap_auth_res_t imap_auth_login (IMAP_DATA* idata) #endif snprintf (buf, sizeof (buf), "LOGIN %s %s", q_user, q_pass); - rc = imap_exec (buf, sizeof (buf), idata, buf, - IMAP_CMD_FAIL_OK | IMAP_CMD_PASS); + rc = imap_exec (idata, buf, IMAP_CMD_FAIL_OK | IMAP_CMD_PASS); if (!rc) return IMAP_AUTH_SUCCESS; diff --git a/imap/auth_sasl.c b/imap/auth_sasl.c index 946500ec..5e01331b 100644 --- a/imap/auth_sasl.c +++ b/imap/auth_sasl.c @@ -31,7 +31,7 @@ imap_auth_res_t imap_auth_sasl (IMAP_DATA* idata) { sasl_conn_t* saslconn; sasl_interact_t* interaction = NULL; - int rc; + int rc, irc; char buf[LONG_STRING]; const char* mech; char* pc; @@ -92,27 +92,27 @@ imap_auth_res_t imap_auth_sasl (IMAP_DATA* idata) snprintf (buf, sizeof (buf), "AUTHENTICATE %s", mech); imap_cmd_start (idata, buf); + irc = IMAP_CMD_CONTINUE; /* looping protocol */ while (rc == SASL_CONTINUE) { - if (mutt_socket_readln (buf, sizeof (buf), idata->conn) < 0) + do + irc = imap_cmd_resp (idata); + while (irc == IMAP_CMD_CONTINUE); + + if (irc == IMAP_CMD_FAIL) goto bail; - if (!mutt_strncmp (buf, "+ ", 2)) + if (irc == IMAP_CMD_RESPOND) { - if (sasl_decode64 (buf+2, strlen (buf+2), buf, &len) != SASL_OK) + if (sasl_decode64 (idata->buf+2, strlen (idata->buf+2), buf, &len) != + SASL_OK) { dprint (1, (debugfile, "imap_auth_sasl: error base64-decoding server response.\n")); goto bail; } } - else if ((buf[0] == '*')) - { - if (imap_handle_untagged (idata, buf)) - goto bail; - else continue; - } if (!client_start) do @@ -146,14 +146,14 @@ imap_auth_res_t imap_auth_sasl (IMAP_DATA* idata) } } - while (mutt_strncmp (buf, idata->seq, SEQLEN)) - if (mutt_socket_readln (buf, sizeof (buf), idata->conn) < 0) - goto bail; + while (irc != IMAP_CMD_DONE) + if ((irc = imap_cmd_resp (idata)) != IMAP_CMD_CONTINUE) + break; if (rc != SASL_OK) goto bail; - if (imap_code (buf)) + if (imap_code (idata->buf)) { mutt_sasl_setup_conn (idata->conn, saslconn); return IMAP_AUTH_SUCCESS; diff --git a/imap/browse.c b/imap/browse.c index c63487ee..1571a705 100644 --- a/imap/browse.c +++ b/imap/browse.c @@ -36,10 +36,11 @@ static int browse_get_namespace (IMAP_DATA *idata, char *nsbuf, int nsblen, static int browse_verify_namespace (IMAP_DATA* idata, IMAP_NAMESPACE_INFO* nsi, int nns); +/* imap_browse: IMAP hook into the folder browser, fills out browser_state, + * given a current folder to browse */ int imap_browse (char* path, struct browser_state* state) { - CONNECTION *conn; - IMAP_DATA *idata; + IMAP_DATA* idata; char buf[LONG_STRING]; char nsbuf[LONG_STRING]; char mbox[LONG_STRING]; @@ -67,7 +68,6 @@ int imap_browse (char* path, struct browser_state* state) if (!(idata = imap_conn_find (&(mx.account), 0))) return -1; - conn = idata->conn; if (mx.mbox[0] == '\0') { @@ -84,24 +84,6 @@ int imap_browse (char* path, struct browser_state* state) if (browse_verify_namespace (idata, nsi, nns) != 0) return -1; } - /* What if you have a shared namespace of ""? You'll never be - * able to browse it. This isn't conjecture: connect to the Cyrus - * reference server (cyrus.andrew.cmu.edu) as anonymous. argh! */ -#if 0 - if (!mx.mbox) /* Any explicitly set imap_home_namespace wins */ - { - for (i = 0; i < nns; i++) - if (nsi[i].listable && - (nsi[i].type == IMAP_NS_PERSONAL || nsi[i].type == IMAP_NS_SHARED)) - { - mx.mbox = nsi->prefix; - nsi->home_namespace = 1; - break; - } - } - else - dprint (4, (debugfile, "Home namespace: %s\n", mx.mbox)); -#endif } mutt_message _("Getting folder list..."); @@ -116,7 +98,7 @@ int imap_browse (char* path, struct browser_state* state) strncpy (mbox, buf, sizeof (mbox) - 1); n = mutt_strlen (mbox); - dprint (3, (debugfile, "imap_init_browse: mbox: %s\n", mbox)); + dprint (3, (debugfile, "imap_browse: mbox: %s\n", mbox)); /* if our target exists and has inferiors, enter it if we * aren't already going to */ @@ -126,8 +108,8 @@ int imap_browse (char* path, struct browser_state* state) imap_cmd_start (idata, buf); do { - if (imap_parse_list_response(idata, buf, sizeof(buf), &cur_folder, - &noselect, &noinferiors, &(idata->delim)) != 0) + if (imap_parse_list_response (idata, &cur_folder, &noselect, + &noinferiors, &idata->delim) != 0) return -1; if (cur_folder) @@ -142,7 +124,7 @@ int imap_browse (char* path, struct browser_state* state) } } } - while ((mutt_strncmp (buf, idata->seq, SEQLEN) != 0)); + while (mutt_strncmp (idata->buf, idata->seq, SEQLEN)); } /* if we're descending a folder, mark it as current in browser_state */ @@ -247,7 +229,6 @@ int imap_browse (char* path, struct browser_state* state) static int browse_add_list_result (IMAP_DATA* idata, const char* cmd, struct browser_state* state, short isparent) { - char buf[LONG_STRING]; char *name; int noselect; int noinferiors; @@ -264,8 +245,8 @@ static int browse_add_list_result (IMAP_DATA* idata, const char* cmd, do { - if (imap_parse_list_response(idata, buf, sizeof(buf), &name, - &noselect, &noinferiors, &(idata->delim)) != 0) + if (imap_parse_list_response(idata, &name, &noselect, &noinferiors, + &idata->delim) != 0) return -1; if (name) @@ -279,7 +260,7 @@ static int browse_add_list_result (IMAP_DATA* idata, const char* cmd, isparent); } } - while ((mutt_strncmp (buf, idata->seq, SEQLEN) != 0)); + while ((mutt_strncmp (idata->buf, idata->seq, SEQLEN) != 0)); return 0; } @@ -351,13 +332,13 @@ static int compare_names(struct folder_file *a, struct folder_file *b) static int browse_get_namespace (IMAP_DATA* idata, char* nsbuf, int nsblen, IMAP_NAMESPACE_INFO* nsi, int nsilen, int* nns) { - char buf[LONG_STRING]; char *s; int n; char ns[LONG_STRING]; char delim = '/'; int type; int nsbused = 0; + int rc; *nns = 0; nsbuf[nsblen-1] = '\0'; @@ -366,89 +347,84 @@ static int browse_get_namespace (IMAP_DATA* idata, char* nsbuf, int nsblen, do { - if (mutt_socket_readln (buf, sizeof (buf), idata->conn) < 0) - return -1; + if ((rc = imap_cmd_resp (idata)) != IMAP_CMD_CONTINUE) + break; - if (buf[0] == '*') + s = imap_next_word (idata->buf); + if (mutt_strncasecmp ("NAMESPACE", s, 9) == 0) { - s = imap_next_word (buf); - if (mutt_strncasecmp ("NAMESPACE", s, 9) == 0) + /* There are three sections to the response, User, Other, Shared, + * and maybe more by extension */ + for (type = IMAP_NS_PERSONAL; *s; type++) { - /* There are three sections to the response, User, Other, Shared, - * and maybe more by extension */ - for (type = IMAP_NS_PERSONAL; *s; type++) + s = imap_next_word (s); + if (*s && strncmp (s, "NIL", 3)) { - s = imap_next_word (s); - if (*s && strncmp (s, "NIL", 3)) + s++; + while (*s && *s != ')') { - s++; - while (*s && *s != ')') - { - s++; /* skip ( */ - /* copy namespace */ - n = 0; - delim = '\0'; + s++; /* skip ( */ + /* copy namespace */ + n = 0; + delim = '\0'; - if (*s == '\"') + if (*s == '\"') + { + s++; + while (*s && *s != '\"') { - s++; - while (*s && *s != '\"') - { - if (*s == '\\') - s++; - ns[n++] = *s; + if (*s == '\\') s++; - } + ns[n++] = *s; + s++; } - else - while (*s && !ISSPACE (*s)) - { - ns[n++] = *s; - s++; - } - ns[n] = '\0'; - /* delim? */ - s = imap_next_word (s); - /* delimiter is meaningless if namespace is "". Why does - * Cyrus provide one?! */ - if (n && *s && *s == '\"') - { - if (s[1] && s[2] == '\"') - delim = s[1]; - else if (s[1] && s[1] == '\\' && s[2] && s[3] == '\"') - delim = s[2]; - } - /* skip "" namespaces, they are already listed at the root */ - if ((ns[0] != '\0') && (nsbused < nsblen) && (*nns < nsilen)) + } + else + while (*s && !ISSPACE (*s)) { - dprint (3, (debugfile, "browse_get_namespace: adding %s\n", ns)); - nsi->type = type; - /* Cyrus doesn't append the delimiter to the namespace, - * but UW-IMAP does. We'll strip it here and add it back - * as if it were a normal directory, from the browser */ - if (n && (ns[n-1] == delim)) - ns[--n] = '\0'; - strncpy(nsbuf+nsbused,ns,nsblen-nsbused-1); - nsi->prefix = nsbuf+nsbused; - nsbused += n+1; - nsi->delim = delim; - nsi++; - (*nns)++; + ns[n++] = *s; + s++; } - while (*s && *s != ')') s++; - s++; + ns[n] = '\0'; + /* delim? */ + s = imap_next_word (s); + /* delimiter is meaningless if namespace is "". Why does + * Cyrus provide one?! */ + if (n && *s && *s == '\"') + { + if (s[1] && s[2] == '\"') + delim = s[1]; + else if (s[1] && s[1] == '\\' && s[2] && s[3] == '\"') + delim = s[2]; + } + /* skip "" namespaces, they are already listed at the root */ + if ((ns[0] != '\0') && (nsbused < nsblen) && (*nns < nsilen)) + { + dprint (3, (debugfile, "browse_get_namespace: adding %s\n", ns)); + nsi->type = type; + /* Cyrus doesn't append the delimiter to the namespace, + * but UW-IMAP does. We'll strip it here and add it back + * as if it were a normal directory, from the browser */ + if (n && (ns[n-1] == delim)) + ns[--n] = '\0'; + strncpy (nsbuf+nsbused,ns,nsblen-nsbused-1); + nsi->prefix = nsbuf+nsbused; + nsbused += n+1; + nsi->delim = delim; + nsi++; + (*nns)++; } + while (*s && *s != ')') s++; + s++; } } } - else - { - if (imap_handle_untagged (idata, buf) != 0) - return (-1); - } } } - while ((mutt_strncmp (buf, idata->seq, SEQLEN) != 0)); + while (rc == IMAP_CMD_CONTINUE); + + if (rc != IMAP_CMD_DONE) + return -1; return 0; } @@ -481,12 +457,12 @@ static int browse_verify_namespace (IMAP_DATA* idata, nsi->home_namespace = 0; do { - if (imap_parse_list_response(idata, buf, sizeof(buf), &name, - &(nsi->noselect), &(nsi->noinferiors), &delim) != 0) + if (imap_parse_list_response(idata, &name, &nsi->noselect, + &nsi->noinferiors, &delim) != 0) return -1; nsi->listable |= (name != NULL); } - while ((mutt_strncmp (buf, idata->seq, SEQLEN) != 0)); + while ((mutt_strncmp (idata->buf, idata->seq, SEQLEN) != 0)); } return 0; diff --git a/imap/command.c b/imap/command.c index 02d2bb3c..8d628296 100644 --- a/imap/command.c +++ b/imap/command.c @@ -29,6 +29,8 @@ #include <ctype.h> #include <stdlib.h> +#define IMAP_CMD_BUFSIZE 512 + /* forward declarations */ static void cmd_make_sequence (char* buf, size_t buflen); static void cmd_parse_capabilities (IMAP_DATA* idata, char* s); @@ -60,6 +62,67 @@ void imap_cmd_start (IMAP_DATA* idata, const char* cmd) safe_free ((void**) &out); } +/* imap_cmd_resp: Reads server responses from an IMAP command, detects + * tagged completion response, handles untagged messages, can read + * arbitrarily large strings (using malloc, so don't make it _too_ + * large!). */ +int imap_cmd_resp (IMAP_DATA* idata) +{ + unsigned int len = 0; + int c; + + /* read into buffer, expanding buffer as necessary until we have a full + * line */ + do + { + if (len == idata->blen) + { + safe_realloc ((void**) &idata->buf, idata->blen + IMAP_CMD_BUFSIZE); + idata->blen = idata->blen + IMAP_CMD_BUFSIZE; + dprint (3, (debugfile, "imap_cmd_resp: grew buffer to %u bytes\n", idata->blen)); + } + + if ((c = mutt_socket_readln (idata->buf + len, idata->blen - len, + idata->conn)) < 0) + { + dprint (1, (debugfile, "imap_cmd_resp: Error while reading server response.\n")); + return IMAP_CMD_FAIL; + } + + len += c; + } + /* if we've read all the way to the end of the buffer, we haven't read a + * full line (mutt_socket_readln strips the \r, so we always have at least + * one character free when we've read a full line) */ + while (len == idata->blen); + + /* don't let one large string make idata->buf hog memory forever */ + if ((idata->blen > IMAP_CMD_BUFSIZE) && (len <= IMAP_CMD_BUFSIZE)) + { + safe_realloc ((void**) &idata->buf, IMAP_CMD_BUFSIZE); + idata->blen = IMAP_CMD_BUFSIZE; + dprint (3, (debugfile, "imap_cmd_resp: shrank buffer to %u bytes\n", idata->blen)); + } + + /* handle untagged messages. The caller still gets its shot afterwards. */ + if (!strncmp (idata->buf, "* ", 2) && + imap_handle_untagged (idata, idata->buf)) + return IMAP_CMD_FAIL; + + /* server demands a continuation response from us */ + if (!strncmp (idata->buf, "+ ", 2)) + return IMAP_CMD_RESPOND; + + /* tagged completion code */ + if (!mutt_strncmp (idata->buf, idata->seq, SEQLEN)) + { + imap_cmd_finish (idata); + return IMAP_CMD_DONE; + } + + return IMAP_CMD_CONTINUE; +} + /* imap_cmd_finish: When the caller has finished reading command responses, * it must call this routine to perform cleanup (eg fetch new mail if * detected, do expunge) */ @@ -104,7 +167,6 @@ void imap_cmd_finish (IMAP_DATA* idata) } idata->status = 0; - mutt_clear_error (); } /* imap_code: returns 1 if the command result was OK, or 0 if NO or BAD */ @@ -123,11 +185,11 @@ int imap_code (const char *s) * IMAP_CMD_PASS: command contains a password. Suppress logging. * Return 0 on success, -1 on Failure, -2 on OK Failure */ -int imap_exec (char* buf, size_t buflen, IMAP_DATA* idata, const char* cmd, - int flags) +int imap_exec (IMAP_DATA* idata, const char* cmd, int flags) { char* out; int outlen; + int rc; /* create sequence for command */ cmd_make_sequence (idata->seq, sizeof (idata->seq)); @@ -142,30 +204,24 @@ int imap_exec (char* buf, size_t buflen, IMAP_DATA* idata, const char* cmd, safe_free ((void**) &out); do - { - if (mutt_socket_readln (buf, buflen, idata->conn) < 0) - return -1; - - if (buf[0] == '*' && imap_handle_untagged (idata, buf) != 0) - return -1; - } - while (mutt_strncmp (buf, idata->seq, SEQLEN) != 0); + rc = imap_cmd_resp (idata); + while (rc == IMAP_CMD_CONTINUE); - imap_cmd_finish (idata); + if (rc != IMAP_CMD_DONE) + return -1; - if (!imap_code (buf)) + if (!imap_code (idata->buf)) { char *pc; if (flags & IMAP_CMD_FAIL_OK) return -2; - dprint (1, (debugfile, "imap_exec: command failed: %s\n", buf)); - pc = buf + SEQLEN; - SKIPWS (pc); + dprint (1, (debugfile, "imap_exec: command failed: %s\n", idata->buf)); + pc = idata->buf; pc = imap_next_word (pc); mutt_error ("%s", pc); - sleep (1); + sleep (2); return -1; } @@ -174,7 +230,7 @@ int imap_exec (char* buf, size_t buflen, IMAP_DATA* idata, const char* cmd, } /* imap_handle_untagged: fallback parser for otherwise unhandled messages. */ -int imap_handle_untagged (IMAP_DATA *idata, char *s) +int imap_handle_untagged (IMAP_DATA* idata, char* s) { char *pn; int count; @@ -191,6 +247,8 @@ int imap_handle_untagged (IMAP_DATA *idata, char *s) */ if (mutt_strncasecmp ("EXISTS", s, 6) == 0) { + dprint (2, (debugfile, "Handling EXISTS\n")); + /* new mail arrived */ count = atoi (pn); @@ -232,6 +290,12 @@ int imap_handle_untagged (IMAP_DATA *idata, char *s) cmd_parse_myrights (idata, s); else if (mutt_strncasecmp ("BYE", s, 3) == 0) { + dprint (2, (debugfile, "Handling BYE\n")); + + /* check if we're logging out */ + if (idata->status == IMAP_BYE) + return 0; + /* server shut down our connection */ s += 3; SKIPWS (s); @@ -246,13 +310,12 @@ int imap_handle_untagged (IMAP_DATA *idata, char *s) } else if (option (OPTIMAPSERVERNOISE) && (mutt_strncasecmp ("NO", s, 2) == 0)) { + dprint (2, (debugfile, "Handling untagged NO\n")); + /* Display the warning message from the server */ mutt_error ("%s", s+3); sleep (2); } - else - dprint (1, (debugfile, "imap_handle_untagged(): unhandled request: %s\n", - s)); return 0; } @@ -274,6 +337,8 @@ static void cmd_parse_capabilities (IMAP_DATA* idata, char* s) { int x; + dprint (2, (debugfile, "Handling CAPABILITY\n")); + idata->capstr = safe_strdup (imap_next_word (s)); while (*s) @@ -295,6 +360,8 @@ static void cmd_parse_expunge (IMAP_DATA* idata, char* s) int expno, cur; HEADER* h; + dprint (2, (debugfile, "Handling EXPUNGE\n")); + expno = atoi (s); /* walk headers, zero seqno of expunged message, decrement seqno of those @@ -317,6 +384,8 @@ static void cmd_parse_expunge (IMAP_DATA* idata, char* s) /* cmd_parse_myrights: set rights bits according to MYRIGHTS response */ static void cmd_parse_myrights (IMAP_DATA* idata, char* s) { + dprint (2, (debugfile, "Handling MYRIGHTS\n")); + s = imap_next_word (s); s = imap_next_word (s); diff --git a/imap/imap.c b/imap/imap.c index ca66b2f4..102b9820 100644 --- a/imap/imap.c +++ b/imap/imap.c @@ -52,11 +52,12 @@ int imap_create_mailbox (CONTEXT* ctx, char* mailbox) imap_munge_mbox_name (mbox, sizeof (mbox), mailbox); snprintf (buf, sizeof (buf), "CREATE %s", mbox); - if (imap_exec (buf, sizeof (buf), CTX_DATA, buf, 0) != 0) + if (imap_exec ((IMAP_DATA*) ctx->data, buf, 0) != 0) { - imap_error ("imap_create_mailbox()", buf); + imap_error ("imap_create_mailbox", CTX_DATA->buf); return -1; } + return 0; } @@ -67,8 +68,11 @@ int imap_delete_mailbox (CONTEXT* ctx, char* mailbox) imap_quote_string (mbox, sizeof (mbox), mailbox); snprintf (buf, sizeof (buf), "DELETE %s", mbox); - if (imap_exec (buf, sizeof (buf), CTX_DATA, buf, 0) != 0) + if (imap_exec ((IMAP_DATA*) ctx->data, buf, 0) != 0) + { + imap_error ("imap_delete_mailbox", CTX_DATA->buf); return -1; + } return 0; } @@ -429,8 +433,8 @@ int imap_reopen_mailbox (IMAP_DATA* idata) static int imap_get_delim (IMAP_DATA *idata) { - char buf[LONG_STRING]; char *s; + int rc; /* assume that the delim is /. If this fails, we're in bigger trouble * than getting the delim wrong */ @@ -440,31 +444,31 @@ static int imap_get_delim (IMAP_DATA *idata) do { - if (mutt_socket_readln (buf, sizeof (buf), idata->conn) < 0) - return -1; + if ((rc = imap_cmd_resp (idata)) != IMAP_CMD_CONTINUE) + break; - if (buf[0] == '*') + s = imap_next_word (idata->buf); + if (mutt_strncasecmp ("LIST", s, 4) == 0) { - s = imap_next_word (buf); - if (mutt_strncasecmp ("LIST", s, 4) == 0) - { - s = imap_next_word (s); - s = imap_next_word (s); - if (s && s[0] == '\"' && s[1] && s[2] == '\"') - idata->delim = s[1]; - else if (s && s[0] == '\"' && s[1] && s[1] == '\\' && s[2] && s[3] == '\"') - idata->delim = s[2]; - } - else - { - if (imap_handle_untagged (idata, buf) != 0) - return -1; - } + s = imap_next_word (s); + s = imap_next_word (s); + if (s && s[0] == '\"' && s[1] && s[2] == '\"') + idata->delim = s[1]; + else if (s && s[0] == '\"' && s[1] && s[1] == '\\' && s[2] && s[3] == '\"') + idata->delim = s[2]; } } - while ((mutt_strncmp (buf, idata->seq, SEQLEN) != 0)); + while (rc == IMAP_CMD_CONTINUE); - return 0; + if (rc != IMAP_CMD_DONE) + { + dprint (1, (debugfile, "imap_get_delim: failed.\n")); + return -1; + } + + dprint (2, (debugfile, "Delimiter: %c\n", idata->delim)); + + return -1; } /* get rights for folder, let imap_handle_untagged do the rest */ @@ -475,7 +479,7 @@ static int imap_check_acl (IMAP_DATA *idata) imap_munge_mbox_name (mbox, sizeof(mbox), idata->mailbox); snprintf (buf, sizeof (buf), "MYRIGHTS %s", mbox); - if (imap_exec (buf, sizeof (buf), idata, buf, 0) != 0) + if (imap_exec (idata, buf, 0) != 0) { imap_error ("imap_check_acl", buf); return -1; @@ -486,11 +490,9 @@ static int imap_check_acl (IMAP_DATA *idata) /* imap_check_capabilities: make sure we can log in to this server. */ static int imap_check_capabilities (IMAP_DATA* idata) { - char buf[LONG_STRING]; - - if (imap_exec (buf, sizeof (buf), idata, "CAPABILITY", 0) != 0) + if (imap_exec (idata, "CAPABILITY", 0) != 0) { - imap_error ("imap_check_capabilities", buf); + imap_error ("imap_check_capabilities", idata->buf); return -1; } @@ -566,17 +568,17 @@ int imap_open_connection (IMAP_DATA* idata) idata->state = IMAP_CONNECTED; - if (mutt_socket_readln (buf, sizeof (buf), idata->conn) < 0) + if (imap_cmd_resp (idata) != IMAP_CMD_CONTINUE) goto bail; - if (mutt_strncmp ("* OK", buf, 4) == 0) + if (mutt_strncmp ("* OK", idata->buf, 4) == 0) { if (imap_check_capabilities (idata) || imap_authenticate (idata)) goto bail; } - else if (mutt_strncmp ("* PREAUTH", buf, 9) == 0) + else if (mutt_strncmp ("* PREAUTH", idata->buf, 9) == 0) { - if (imap_check_capabilities(idata) != 0) + if (imap_check_capabilities (idata) != 0) goto bail; } else @@ -662,8 +664,8 @@ int imap_open_mailbox (CONTEXT* ctx) char buf[LONG_STRING]; char bufout[LONG_STRING]; int count = 0; - int n; IMAP_MBOX mx; + int rc; if (imap_parse_path (ctx->path, &mx)) { @@ -677,7 +679,7 @@ int imap_open_mailbox (CONTEXT* ctx) conn = idata->conn; /* once again the context is new */ - ctx->data = (void *) idata; + ctx->data = idata; /* Clean up path and replace the one in the ctx */ imap_fix_path (idata, mx.mbox, buf, sizeof (buf)); @@ -707,56 +709,53 @@ int imap_open_mailbox (CONTEXT* ctx) { char *pc; - if (mutt_socket_readln (buf, sizeof (buf), conn) < 0) + if ((rc = imap_cmd_resp (idata)) != IMAP_CMD_CONTINUE) break; - if (buf[0] == '*') + pc = idata->buf + 2; + pc = imap_next_word (pc); + if (!mutt_strncasecmp ("EXISTS", pc, 6)) { - pc = buf + 2; + /* imap_handle_untagged will have picked up the EXISTS message and + * set the NEW_MAIL flag. We clear it here. */ + idata->status = 0; + count = idata->newMailCount; + idata->newMailCount = 0; + } - if (isdigit (*pc)) - { - char *pn = pc; + pc = idata->buf + 2; - while (*pc && isdigit (*pc)) - pc++; - *pc++ = '\0'; - n = atoi (pn); - SKIPWS (pc); - if (mutt_strncasecmp ("EXISTS", pc, 6) == 0) - count = n; - } - /* Obtain list of available flags here, may be overridden by a - * PERMANENTFLAGS tag in the OK response */ - else if (mutt_strncasecmp ("FLAGS", pc, 5) == 0) - { - /* don't override PERMANENTFLAGS */ - if (!idata->flags) - { - dprint (2, (debugfile, "Getting mailbox FLAGS\n")); - if ((pc = imap_get_flags (&(idata->flags), pc)) == NULL) - return -1; - } - } - /* PERMANENTFLAGS are massaged to look like FLAGS, then override FLAGS */ - else if (mutt_strncasecmp ("OK [PERMANENTFLAGS", pc, 18) == 0) + /* Obtain list of available flags here, may be overridden by a + * PERMANENTFLAGS tag in the OK response */ + if (mutt_strncasecmp ("FLAGS", pc, 5) == 0) + { + /* don't override PERMANENTFLAGS */ + if (!idata-> |