Commit 54eb0674 54eb06740c906c696749cd04c9afa6c43694f647 by Sergey Poznyakoff

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.
1 parent 0e8d5bfe
...@@ -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] == '}')
......