imapio: improve getline parser
* libmailutils/imapio/create.c (mu_imapio_create): Treat [ and ] as delimiters. Use MU_WRDSF_DQUOTE flag instead of MU_WRDSF_QUOTE. Use MU_WRDSF_APPEND * libmailutils/imapio/getline.c (mu_imapio_getline): Use incremental wordsplit mode. Return human-readable part of status responses as a single token.
Showing
2 changed files
with
119 additions
and
8 deletions
... | @@ -28,15 +28,16 @@ mu_imapio_create (mu_imapio_t *iop, mu_stream_t str) | ... | @@ -28,15 +28,16 @@ mu_imapio_create (mu_imapio_t *iop, mu_stream_t str) |
28 | return ENOMEM; | 28 | return ENOMEM; |
29 | io->_imap_stream = str; | 29 | io->_imap_stream = str; |
30 | mu_stream_ref (str); | 30 | mu_stream_ref (str); |
31 | io->_imap_ws.ws_delim = " \t()"; | 31 | io->_imap_ws.ws_delim = " \t()[]"; |
32 | io->_imap_ws.ws_escape = "\\\""; | 32 | io->_imap_ws.ws_escape = "\\\""; |
33 | io->_imap_ws_flags = MU_WRDSF_DELIM | | 33 | io->_imap_ws_flags = MU_WRDSF_DELIM | |
34 | MU_WRDSF_ESCAPE | | 34 | MU_WRDSF_ESCAPE | |
35 | MU_WRDSF_NOVAR | | 35 | MU_WRDSF_NOVAR | |
36 | MU_WRDSF_NOCMD | | 36 | MU_WRDSF_NOCMD | |
37 | MU_WRDSF_QUOTE | | 37 | MU_WRDSF_DQUOTE | |
38 | MU_WRDSF_RETURN_DELIMS | | 38 | MU_WRDSF_RETURN_DELIMS | |
39 | MU_WRDSF_WS; | 39 | MU_WRDSF_WS | |
40 | MU_WRDSF_APPEND; | ||
40 | *iop = io; | 41 | *iop = io; |
41 | return 0; | 42 | return 0; |
42 | } | 43 | } | ... | ... |
... | @@ -23,16 +23,86 @@ | ... | @@ -23,16 +23,86 @@ |
23 | #include <mailutils/cstr.h> | 23 | #include <mailutils/cstr.h> |
24 | #include <mailutils/cctype.h> | 24 | #include <mailutils/cctype.h> |
25 | #include <mailutils/errno.h> | 25 | #include <mailutils/errno.h> |
26 | #include <mailutils/kwd.h> | ||
26 | #include <mailutils/sys/imapio.h> | 27 | #include <mailutils/sys/imapio.h> |
27 | 28 | ||
29 | #define STATUS_RESPONSE 1 | ||
30 | #define STATUS_RESPONSE_UNTAGGED 2 | ||
31 | |||
32 | static int | ||
33 | is_status_response (const char *word) | ||
34 | { | ||
35 | static struct mu_kwd resptab[] = { | ||
36 | /* RFC 3501, 7.1: | ||
37 | |||
38 | Status responses are OK, NO, BAD, PREAUTH and BYE. OK, NO, and BAD | ||
39 | can be tagged or untagged. PREAUTH and BYE are always untagged. | ||
40 | */ | ||
41 | { "OK", STATUS_RESPONSE }, | ||
42 | { "NO", STATUS_RESPONSE }, | ||
43 | { "BAD", STATUS_RESPONSE }, | ||
44 | { "PREAUTH", STATUS_RESPONSE_UNTAGGED }, | ||
45 | { "BYE", STATUS_RESPONSE_UNTAGGED }, | ||
46 | { NULL } | ||
47 | }; | ||
48 | int result; | ||
49 | |||
50 | if (mu_kwd_xlat_name (resptab, word, &result)) | ||
51 | return 0; | ||
52 | return result; | ||
53 | } | ||
54 | |||
55 | static int | ||
56 | get_response_code (struct _mu_imapio *io) | ||
57 | { | ||
58 | size_t end = io->_imap_ws.ws_endp; | ||
59 | size_t wc = io->_imap_ws.ws_wordc; | ||
60 | int rc, i; | ||
61 | |||
62 | do | ||
63 | { | ||
64 | if ((rc = mu_wordsplit (NULL, &io->_imap_ws, MU_WRDSF_INCREMENTAL))) | ||
65 | { | ||
66 | if (rc == MU_WRDSE_NOINPUT) | ||
67 | break; | ||
68 | return MU_ERR_PARSE; | ||
69 | } | ||
70 | |||
71 | if (strcmp (io->_imap_ws.ws_wordv[io->_imap_ws.ws_wordc-1], "[") == 0) | ||
72 | { | ||
73 | do | ||
74 | { | ||
75 | /* Get word */ | ||
76 | if ((rc = mu_wordsplit (NULL, &io->_imap_ws, MU_WRDSF_INCREMENTAL))) | ||
77 | { | ||
78 | if (rc == MU_WRDSE_NOINPUT) | ||
79 | break; | ||
80 | return MU_ERR_PARSE; | ||
81 | } | ||
82 | } | ||
83 | while (strcmp (io->_imap_ws.ws_wordv[io->_imap_ws.ws_wordc-1], "]")); | ||
84 | if (rc) | ||
85 | break; | ||
86 | return 0; | ||
87 | } | ||
88 | } | ||
89 | while (0); | ||
90 | |||
91 | for (i = wc; i < io->_imap_ws.ws_wordc; i++) | ||
92 | free (io->_imap_ws.ws_wordv[i]); | ||
93 | io->_imap_ws.ws_wordv[wc] = NULL; | ||
94 | io->_imap_ws.ws_wordc = wc; | ||
95 | io->_imap_ws.ws_endp = end; | ||
96 | return 0; | ||
97 | } | ||
98 | |||
28 | int | 99 | int |
29 | mu_imapio_getline (struct _mu_imapio *io) | 100 | mu_imapio_getline (struct _mu_imapio *io) |
30 | { | 101 | { |
31 | int rc; | 102 | int rc; |
32 | char *last_arg; | 103 | char *last_arg; |
104 | int type; | ||
33 | 105 | ||
34 | io->_imap_ws_flags &= ~MU_WRDSF_APPEND; | ||
35 | |||
36 | if (io->_imap_reply_ready) | 106 | if (io->_imap_reply_ready) |
37 | { | 107 | { |
38 | mu_wordsplit_free_words (&io->_imap_ws); | 108 | mu_wordsplit_free_words (&io->_imap_ws); |
... | @@ -50,11 +120,51 @@ mu_imapio_getline (struct _mu_imapio *io) | ... | @@ -50,11 +120,51 @@ mu_imapio_getline (struct _mu_imapio *io) |
50 | break; | 120 | break; |
51 | io->_imap_buf_level = mu_rtrim_class (io->_imap_buf_base, | 121 | io->_imap_buf_level = mu_rtrim_class (io->_imap_buf_base, |
52 | MU_CTYPE_ENDLN); | 122 | MU_CTYPE_ENDLN); |
123 | if ((rc = mu_wordsplit_len (io->_imap_buf_base, io->_imap_buf_level, | ||
124 | &io->_imap_ws, | ||
125 | io->_imap_ws_flags | MU_WRDSF_INCREMENTAL))) | ||
126 | { | ||
127 | if (rc == MU_WRDSE_NOINPUT) | ||
128 | break; | ||
129 | return MU_ERR_PARSE; | ||
130 | } | ||
131 | io->_imap_ws_flags |= MU_WRDSF_REUSE; | ||
132 | |||
133 | if ((rc = mu_wordsplit (NULL, &io->_imap_ws, MU_WRDSF_INCREMENTAL))) | ||
134 | { | ||
135 | if (rc == MU_WRDSE_NOINPUT) | ||
136 | break; | ||
137 | return MU_ERR_PARSE; | ||
138 | } | ||
139 | |||
140 | if ((type = is_status_response (io->_imap_ws.ws_wordv[1])) | ||
141 | && (type == STATUS_RESPONSE || | ||
142 | strcmp (io->_imap_ws.ws_wordv[0], "*") == 0)) | ||
143 | { | ||
144 | rc = get_response_code (io); | ||
145 | if (rc) | ||
146 | return MU_ERR_PARSE; | ||
147 | while (io->_imap_ws.ws_endp < io->_imap_ws.ws_len && | ||
148 | mu_isblank (io->_imap_ws.ws_input[io->_imap_ws.ws_endp])) | ||
149 | io->_imap_ws.ws_endp++; | ||
150 | io->_imap_ws.ws_flags |= MU_WRDSF_NOSPLIT; | ||
151 | rc = mu_wordsplit (NULL, &io->_imap_ws, MU_WRDSF_INCREMENTAL); | ||
152 | io->_imap_ws.ws_flags &= ~MU_WRDSF_NOSPLIT; | ||
153 | if (rc) | ||
154 | { | ||
155 | if (rc == MU_WRDSE_NOINPUT) | ||
156 | break; | ||
157 | return MU_ERR_PARSE; | ||
158 | } | ||
159 | break; | ||
160 | } | ||
53 | 161 | ||
54 | if (mu_wordsplit_len (io->_imap_buf_base, io->_imap_buf_level, | 162 | |
55 | &io->_imap_ws, io->_imap_ws_flags)) | 163 | rc = mu_wordsplit_len (io->_imap_buf_base + io->_imap_ws.ws_endp, |
164 | io->_imap_buf_level - io->_imap_ws.ws_endp, | ||
165 | &io->_imap_ws, io->_imap_ws_flags); | ||
166 | if (rc) | ||
56 | return MU_ERR_PARSE; | 167 | return MU_ERR_PARSE; |
57 | io->_imap_ws_flags |= MU_WRDSF_REUSE|MU_WRDSF_APPEND; | ||
58 | 168 | ||
59 | last_arg = io->_imap_ws.ws_wordv[io->_imap_ws.ws_wordc - 1]; | 169 | last_arg = io->_imap_ws.ws_wordv[io->_imap_ws.ws_wordc - 1]; |
60 | if (last_arg[0] == '{' && last_arg[strlen (last_arg)-1] == '}') | 170 | if (last_arg[0] == '{' && last_arg[strlen (last_arg)-1] == '}') | ... | ... |
-
Please register or sign in to post a comment