imap client: improve parsing of BODY[] items.
* include/mailutils/imap.h (mu_imap_fetch_body) <key>: Rename to section. <fields>: New member. * libproto/imap/fetch.c: Rewrite response item parser. * mu/imap.c: Improve fetch_response_printer
Showing
3 changed files
with
236 additions
and
172 deletions
... | @@ -175,7 +175,8 @@ struct mu_imap_fetch_body | ... | @@ -175,7 +175,8 @@ struct mu_imap_fetch_body |
175 | int type; | 175 | int type; |
176 | size_t *partv; | 176 | size_t *partv; |
177 | size_t partc; | 177 | size_t partc; |
178 | char *key; | 178 | char *section; |
179 | mu_list_t fields; | ||
179 | char *text; | 180 | char *text; |
180 | }; | 181 | }; |
181 | 182 | ... | ... |
... | @@ -86,7 +86,8 @@ _free_fetch_response (void *ptr) | ... | @@ -86,7 +86,8 @@ _free_fetch_response (void *ptr) |
86 | { | 86 | { |
87 | case MU_IMAP_FETCH_BODY: | 87 | case MU_IMAP_FETCH_BODY: |
88 | free (resp->body.partv); | 88 | free (resp->body.partv); |
89 | free (resp->body.key); | 89 | free (resp->body.section); |
90 | mu_list_destroy (&resp->body.fields); | ||
90 | free (resp->body.text); | 91 | free (resp->body.text); |
91 | break; | 92 | break; |
92 | 93 | ||
... | @@ -139,81 +140,94 @@ alloc_response (union mu_imap_fetch_response **resp, int type) | ... | @@ -139,81 +140,94 @@ alloc_response (union mu_imap_fetch_response **resp, int type) |
139 | return 0; | 140 | return 0; |
140 | } | 141 | } |
141 | 142 | ||
142 | static int | 143 | enum parse_response_state |
143 | _uid_mapper (struct imap_list_element **elt, | 144 | { |
144 | union mu_imap_fetch_response **return_resp) | 145 | resp_kw, |
146 | resp_val, | ||
147 | resp_body, | ||
148 | resp_body_section, | ||
149 | resp_skip, | ||
150 | resp_body_hlist, | ||
151 | resp_body_end | ||
152 | }; | ||
153 | |||
154 | struct parse_response_env; | ||
155 | |||
156 | typedef int (*mapper_fn) (union mu_imap_fetch_response *resp, | ||
157 | struct imap_list_element *elt, | ||
158 | struct parse_response_env *env); | ||
159 | |||
160 | struct parse_response_env | ||
145 | { | 161 | { |
162 | mu_list_t result; | ||
163 | struct imap_list_element *elt; | ||
164 | enum parse_response_state state; | ||
146 | union mu_imap_fetch_response *resp; | 165 | union mu_imap_fetch_response *resp; |
147 | int rc; | 166 | mapper_fn mapper; |
167 | const char *section; | ||
168 | mu_list_t hlist; | ||
169 | int status; | ||
170 | }; | ||
171 | |||
172 | |||
173 | static int | ||
174 | _uid_mapper (union mu_imap_fetch_response *resp, | ||
175 | struct imap_list_element *elt, | ||
176 | struct parse_response_env *parse_env) | ||
177 | { | ||
148 | char *p; | 178 | char *p; |
149 | size_t uid; | 179 | size_t uid; |
150 | 180 | ||
151 | if (elt[1]->type != imap_eltype_string) | 181 | if (elt->type != imap_eltype_string) |
152 | return MU_ERR_FAILURE; | 182 | return MU_ERR_FAILURE; |
153 | uid = strtoul (elt[1]->v.string, &p, 0); | 183 | uid = strtoul (elt->v.string, &p, 0); |
154 | if (*p) | 184 | if (*p) |
155 | return MU_ERR_FAILURE; | 185 | return MU_ERR_FAILURE; |
156 | rc = alloc_response (&resp, MU_IMAP_FETCH_UID); | ||
157 | if (rc) | ||
158 | return rc; | ||
159 | resp->uid.uid = uid; | 186 | resp->uid.uid = uid; |
160 | *return_resp = resp; | ||
161 | return 0; | 187 | return 0; |
162 | } | 188 | } |
163 | 189 | ||
164 | static int | 190 | static int |
165 | _size_mapper (struct imap_list_element **elt, | 191 | _size_mapper (union mu_imap_fetch_response *resp, |
166 | union mu_imap_fetch_response **return_resp) | 192 | struct imap_list_element *elt, |
193 | struct parse_response_env *parse_env) | ||
167 | { | 194 | { |
168 | union mu_imap_fetch_response *resp; | ||
169 | int rc; | ||
170 | char *p; | 195 | char *p; |
171 | size_t size; | 196 | size_t size; |
172 | 197 | ||
173 | if (elt[1]->type != imap_eltype_string) | 198 | if (elt->type != imap_eltype_string) |
174 | return MU_ERR_FAILURE; | 199 | return MU_ERR_FAILURE; |
175 | size = strtoul (elt[1]->v.string, &p, 0); | 200 | size = strtoul (elt->v.string, &p, 0); |
176 | if (*p) | 201 | if (*p) |
177 | return MU_ERR_FAILURE; | 202 | return MU_ERR_FAILURE; |
178 | rc = alloc_response (&resp, MU_IMAP_FETCH_RFC822_SIZE); | ||
179 | if (rc) | ||
180 | return rc; | ||
181 | resp->rfc822_size.size = size; | 203 | resp->rfc822_size.size = size; |
182 | *return_resp = resp; | ||
183 | return 0; | 204 | return 0; |
184 | } | 205 | } |
185 | 206 | ||
186 | static int | 207 | static int |
187 | _body_mapper (struct imap_list_element **elt, | 208 | _body_mapper (union mu_imap_fetch_response *resp, |
188 | union mu_imap_fetch_response **return_resp) | 209 | struct imap_list_element *elt, |
210 | struct parse_response_env *parse_env) | ||
189 | { | 211 | { |
190 | union mu_imap_fetch_response *resp; | 212 | const char *section, *p; |
191 | int rc; | ||
192 | char *section, *p; | ||
193 | size_t partc = 0; | 213 | size_t partc = 0; |
194 | size_t *partv = NULL; | 214 | size_t *partv = NULL; |
195 | 215 | ||
196 | if (elt[1]->type != imap_eltype_string) | 216 | if (elt->type != imap_eltype_string) |
197 | return MU_ERR_FAILURE; | 217 | return MU_ERR_FAILURE; |
198 | rc = alloc_response (&resp, MU_IMAP_FETCH_BODY); | ||
199 | if (rc) | ||
200 | return rc; | ||
201 | 218 | ||
202 | section = strchr (elt[0]->v.string, '['); | 219 | section = parse_env->section; |
203 | if (section) | 220 | if (section) |
204 | { | 221 | { |
205 | p = section; | 222 | p = section; |
206 | while (1) | 223 | while (mu_isdigit (*p)) |
207 | { | 224 | { |
225 | partc++; | ||
208 | p = strchr (p, '.'); | 226 | p = strchr (p, '.'); |
209 | if (*p) | 227 | if (p) |
210 | { | 228 | { |
211 | p++; | 229 | p++; |
212 | if (mu_isdigit (p[1])) | 230 | continue; |
213 | { | ||
214 | partc++; | ||
215 | continue; | ||
216 | } | ||
217 | } | 231 | } |
218 | 232 | ||
219 | break; | 233 | break; |
... | @@ -222,6 +236,16 @@ _body_mapper (struct imap_list_element **elt, | ... | @@ -222,6 +236,16 @@ _body_mapper (struct imap_list_element **elt, |
222 | else | 236 | else |
223 | p = NULL; | 237 | p = NULL; |
224 | 238 | ||
239 | if (p) | ||
240 | { | ||
241 | resp->body.section = strdup (p); | ||
242 | if (!resp->body.section) | ||
243 | { | ||
244 | free (resp); | ||
245 | return ENOMEM; | ||
246 | } | ||
247 | } | ||
248 | |||
225 | if (partc) | 249 | if (partc) |
226 | { | 250 | { |
227 | size_t i; | 251 | size_t i; |
... | @@ -237,51 +261,33 @@ _body_mapper (struct imap_list_element **elt, | ... | @@ -237,51 +261,33 @@ _body_mapper (struct imap_list_element **elt, |
237 | resp->body.partc = partc; | 261 | resp->body.partc = partc; |
238 | resp->body.partv = partv; | 262 | resp->body.partv = partv; |
239 | 263 | ||
240 | if (p && *p) | 264 | resp->body.fields = parse_env->hlist; |
241 | { | 265 | parse_env->hlist = NULL; |
242 | size_t len = strlen (p); | ||
243 | resp->body.key = malloc (len); | ||
244 | if (!resp->body.key) | ||
245 | { | ||
246 | free (resp->body.partv); | ||
247 | free (resp); | ||
248 | return ENOMEM; | ||
249 | } | ||
250 | len--; | ||
251 | memcpy (resp->body.key, p, len); | ||
252 | resp->body.key[len] = 0; | ||
253 | } | ||
254 | 266 | ||
255 | resp->body.text = strdup (elt[1]->v.string); | 267 | resp->body.text = strdup (elt->v.string); |
256 | if (!resp->body.text) | 268 | if (!resp->body.text) |
257 | { | 269 | { |
258 | free (resp->body.key); | 270 | free (resp->body.section); |
259 | free (resp->body.partv); | 271 | free (resp->body.partv); |
260 | free (resp); | 272 | free (resp); |
261 | return ENOMEM; | 273 | return ENOMEM; |
262 | } | 274 | } |
263 | *return_resp = resp; | ||
264 | return 0; | 275 | return 0; |
265 | } | 276 | } |
266 | 277 | ||
267 | static int | 278 | static int |
268 | _rfc822_mapper (const char *key, struct imap_list_element *elt, | 279 | _rfc822_mapper (union mu_imap_fetch_response *resp, |
269 | union mu_imap_fetch_response **return_resp) | 280 | struct imap_list_element *elt, |
281 | struct parse_response_env *parse_env) | ||
270 | { | 282 | { |
271 | union mu_imap_fetch_response *resp; | ||
272 | int rc; | ||
273 | |||
274 | if (elt->type != imap_eltype_string) | 283 | if (elt->type != imap_eltype_string) |
275 | return MU_ERR_FAILURE; | 284 | return MU_ERR_FAILURE; |
276 | rc = alloc_response (&resp, MU_IMAP_FETCH_BODY); | ||
277 | if (rc) | ||
278 | return rc; | ||
279 | 285 | ||
280 | resp->body.partc = 0; | 286 | resp->body.partc = 0; |
281 | resp->body.partv = NULL; | 287 | resp->body.partv = NULL; |
282 | 288 | ||
283 | resp->body.key = strdup (key); | 289 | resp->body.section = strdup (parse_env->section); |
284 | if (!resp->body.key) | 290 | if (!resp->body.section) |
285 | { | 291 | { |
286 | free (resp); | 292 | free (resp); |
287 | return ENOMEM; | 293 | return ENOMEM; |
... | @@ -290,74 +296,66 @@ _rfc822_mapper (const char *key, struct imap_list_element *elt, | ... | @@ -290,74 +296,66 @@ _rfc822_mapper (const char *key, struct imap_list_element *elt, |
290 | resp->body.text = strdup (elt->v.string); | 296 | resp->body.text = strdup (elt->v.string); |
291 | if (!resp->body.text) | 297 | if (!resp->body.text) |
292 | { | 298 | { |
293 | free (resp->body.key); | 299 | free (resp->body.section); |
294 | free (resp->body.partv); | 300 | free (resp->body.partv); |
295 | free (resp); | 301 | free (resp); |
296 | return ENOMEM; | 302 | return ENOMEM; |
297 | } | 303 | } |
298 | *return_resp = resp; | ||
299 | return 0; | 304 | return 0; |
300 | } | 305 | } |
301 | 306 | ||
302 | static int | 307 | static int |
303 | _rfc822_header_mapper (struct imap_list_element **elt, | 308 | _rfc822_header_mapper (union mu_imap_fetch_response *resp, |
304 | union mu_imap_fetch_response **return_resp) | 309 | struct imap_list_element *elt, |
310 | struct parse_response_env *parse_env) | ||
305 | { | 311 | { |
306 | return _rfc822_mapper ("HEADER", elt[1], return_resp); | 312 | parse_env->section = "HEADER"; |
313 | return _rfc822_mapper (resp, elt, parse_env); | ||
307 | } | 314 | } |
308 | 315 | ||
309 | static int | 316 | static int |
310 | _rfc822_text_mapper (struct imap_list_element **elt, | 317 | _rfc822_text_mapper (union mu_imap_fetch_response *resp, |
311 | union mu_imap_fetch_response **return_resp) | 318 | struct imap_list_element *elt, |
319 | struct parse_response_env *parse_env) | ||
312 | { | 320 | { |
313 | return _rfc822_mapper ("TEXT", elt[1], return_resp); | 321 | parse_env->section = "TEXT"; |
322 | return _rfc822_mapper (resp, elt, parse_env); | ||
314 | } | 323 | } |
315 | 324 | ||
316 | static int | 325 | static int |
317 | _flags_mapper (struct imap_list_element **elt, | 326 | _flags_mapper (union mu_imap_fetch_response *resp, |
318 | union mu_imap_fetch_response **return_resp) | 327 | struct imap_list_element *elt, |
328 | struct parse_response_env *parse_env) | ||
319 | { | 329 | { |
320 | union mu_imap_fetch_response *resp; | 330 | if (elt->type != imap_eltype_list) |
321 | int rc; | ||
322 | int flags; | ||
323 | |||
324 | if (elt[1]->type != imap_eltype_list) | ||
325 | return MU_ERR_FAILURE; | 331 | return MU_ERR_FAILURE; |
326 | if (_mu_imap_collect_flags (elt[1], &flags)) | 332 | if (_mu_imap_collect_flags (elt, &resp->flags.flags)) |
327 | return MU_ERR_FAILURE; | 333 | return MU_ERR_FAILURE; |
328 | |||
329 | rc = alloc_response (&resp, MU_IMAP_FETCH_FLAGS); | ||
330 | if (rc) | ||
331 | return rc; | ||
332 | resp->flags.flags = flags; | ||
333 | *return_resp = resp; | ||
334 | return 0; | 334 | return 0; |
335 | } | 335 | } |
336 | 336 | ||
337 | static int | 337 | static int |
338 | _date_mapper (struct imap_list_element **elt, | 338 | _date_mapper (union mu_imap_fetch_response *resp, |
339 | union mu_imap_fetch_response **return_resp) | 339 | struct imap_list_element *elt, |
340 | struct parse_response_env *parse_env) | ||
340 | { | 341 | { |
341 | union mu_imap_fetch_response *resp; | ||
342 | int rc; | ||
343 | const char *p; | 342 | const char *p; |
344 | struct tm tm; | 343 | struct tm tm; |
345 | struct mu_timezone tz; | 344 | struct mu_timezone tz; |
346 | 345 | ||
347 | if (elt[1]->type != imap_eltype_string) | 346 | if (elt->type != imap_eltype_string) |
348 | return MU_ERR_FAILURE; | 347 | return MU_ERR_FAILURE; |
349 | p = elt[1]->v.string; | 348 | p = elt->v.string; |
350 | if (mu_parse_imap_date_time (&p, &tm, &tz)) | 349 | if (mu_parse_imap_date_time (&p, &tm, &tz)) |
351 | return MU_ERR_FAILURE; | 350 | return MU_ERR_FAILURE; |
352 | rc = alloc_response (&resp, MU_IMAP_FETCH_INTERNALDATE); | ||
353 | if (rc) | ||
354 | return rc; | ||
355 | resp->internaldate.tm = tm; | 351 | resp->internaldate.tm = tm; |
356 | resp->internaldate.tz = tz; | 352 | resp->internaldate.tz = tz; |
357 | *return_resp = resp; | ||
358 | return 0; | 353 | return 0; |
359 | } | 354 | } |
360 | 355 | ||
356 | /* FIXME */ | ||
357 | #define _bodystructure_mapper NULL | ||
358 | |||
361 | struct fill_env | 359 | struct fill_env |
362 | { | 360 | { |
363 | struct mu_imap_fetch_envelope *envelope; | 361 | struct mu_imap_fetch_envelope *envelope; |
... | @@ -524,23 +522,17 @@ _fill_response (void *item, void *data) | ... | @@ -524,23 +522,17 @@ _fill_response (void *item, void *data) |
524 | } | 522 | } |
525 | 523 | ||
526 | static int | 524 | static int |
527 | _envelope_mapper (struct imap_list_element **elt, | 525 | _envelope_mapper (union mu_imap_fetch_response *resp, |
528 | union mu_imap_fetch_response **return_resp) | 526 | struct imap_list_element *elt, |
527 | struct parse_response_env *parse_env) | ||
529 | { | 528 | { |
530 | union mu_imap_fetch_response *resp; | ||
531 | int rc; | ||
532 | struct fill_env env; | 529 | struct fill_env env; |
533 | 530 | ||
534 | if (elt[1]->type != imap_eltype_list) | 531 | if (elt->type != imap_eltype_list) |
535 | return MU_ERR_FAILURE; | 532 | return MU_ERR_FAILURE; |
536 | rc = alloc_response (&resp, MU_IMAP_FETCH_ENVELOPE); | ||
537 | if (rc) | ||
538 | return rc; | ||
539 | env.envelope = &resp->envelope; | 533 | env.envelope = &resp->envelope; |
540 | env.n = 0; | 534 | env.n = 0; |
541 | mu_list_foreach (elt[1]->v.list, _fill_response, &env); | 535 | mu_list_foreach (elt->v.list, _fill_response, &env); |
542 | |||
543 | *return_resp = resp; | ||
544 | return 0; | 536 | return 0; |
545 | } | 537 | } |
546 | 538 | ||
... | @@ -548,81 +540,146 @@ struct mapper_tab | ... | @@ -548,81 +540,146 @@ struct mapper_tab |
548 | { | 540 | { |
549 | char *name; | 541 | char *name; |
550 | size_t size; | 542 | size_t size; |
551 | int prefix; | 543 | int type; |
552 | int (*mapper) (struct imap_list_element **, union mu_imap_fetch_response **); | 544 | mapper_fn mapper; |
553 | }; | 545 | }; |
554 | 546 | ||
555 | static struct mapper_tab mapper_tab[] = { | 547 | static struct mapper_tab mapper_tab[] = { |
556 | #define S(s) s, (sizeof (s) - 1) | 548 | #define S(s) s, (sizeof (s) - 1) |
557 | { S("BODYSTRUCTURE"), 0, }, | 549 | { S("BODYSTRUCTURE"), }, |
558 | { S("BODY["), 1, _body_mapper }, | 550 | { S("BODY"), MU_IMAP_FETCH_BODY, _body_mapper }, |
559 | { S("BODY"), 0, _body_mapper }, | 551 | { S("ENVELOPE"), MU_IMAP_FETCH_ENVELOPE, _envelope_mapper }, |
560 | { S("ENVELOPE"), 0, _envelope_mapper }, | 552 | { S("FLAGS"), MU_IMAP_FETCH_FLAGS, _flags_mapper }, |
561 | { S("FLAGS"), 0, _flags_mapper }, | 553 | { S("INTERNALDATE"), MU_IMAP_FETCH_INTERNALDATE, _date_mapper }, |
562 | { S("INTERNALDATE"), 0, _date_mapper }, | 554 | { S("RFC822"), MU_IMAP_FETCH_BODY, _body_mapper}, |
563 | { S("RFC822"), 0, _body_mapper}, | 555 | { S("RFC822.HEADER"), MU_IMAP_FETCH_BODY, _rfc822_header_mapper }, |
564 | { S("RFC822.HEADER"), 0, _rfc822_header_mapper }, | 556 | { S("RFC822.SIZE"), MU_IMAP_FETCH_RFC822_SIZE, _size_mapper }, |
565 | { S("RFC822.SIZE"), 0, _size_mapper }, | 557 | { S("RFC822.TEXT"), MU_IMAP_FETCH_BODY, _rfc822_text_mapper }, |
566 | { S("RFC822.TEXT"), 0, _rfc822_text_mapper }, | 558 | { S("UID"), MU_IMAP_FETCH_UID, _uid_mapper }, |
567 | { S("UID"), 0, _uid_mapper }, | ||
568 | #undef S | 559 | #undef S |
569 | { NULL } | 560 | { NULL } |
570 | }; | 561 | }; |
571 | 562 | ||
572 | static int | 563 | static int |
573 | _fetch_mapper (void **itmv, size_t itmc, void *call_data) | 564 | _extract_string (void **itmv, size_t itmc, void *call_data) |
574 | { | 565 | { |
575 | int *status = call_data; | 566 | struct imap_list_element *elt = itmv[0]; |
576 | struct mapper_tab *mt; | 567 | if (elt->type != imap_eltype_string) |
577 | struct imap_list_element *elt[2]; | 568 | return MU_LIST_MAP_SKIP; |
578 | char *kw; | 569 | itmv[0] = elt->v.string; |
579 | size_t kwlen; | 570 | return 0; |
580 | union mu_imap_fetch_response *resp; | 571 | } |
581 | 572 | ||
582 | elt[0] = itmv[0]; | 573 | static int |
583 | elt[1] = itmv[1]; | 574 | _fetch_fold (void *item, void *data) |
584 | 575 | { | |
585 | if (elt[0]->type != imap_eltype_string) | 576 | struct imap_list_element *elt = item; |
586 | { | 577 | struct parse_response_env *env = data; |
587 | *status = MU_ERR_FAILURE; | 578 | |
588 | return MU_LIST_MAP_STOP|MU_LIST_MAP_SKIP; | 579 | switch (env->state) |
589 | } | ||
590 | kw = elt[0]->v.string; | ||
591 | kwlen = strlen (kw); | ||
592 | for (mt = mapper_tab; mt->name; mt++) | ||
593 | { | 580 | { |
594 | if (mt->prefix) | 581 | case resp_kw: |
582 | { | ||
583 | int rc; | ||
584 | char *kw; | ||
585 | size_t kwlen; | ||
586 | struct mapper_tab *mt; | ||
587 | |||
588 | if (elt->type != imap_eltype_string) | ||
589 | { | ||
590 | env->status = MU_ERR_FAILURE; | ||
591 | return MU_ERR_FAILURE; | ||
592 | } | ||
593 | kw = elt->v.string; | ||
594 | kwlen = strlen (kw); | ||
595 | for (mt = mapper_tab; mt->name; mt++) | ||
596 | { | ||
597 | if (mt->size == kwlen && memcmp (mt->name, kw, kwlen) == 0) | ||
598 | break; | ||
599 | } | ||
600 | |||
601 | if (!mt->name) | ||
602 | { | ||
603 | mu_debug (MU_DEBCAT_MAILER, MU_DEBUG_TRACE9, | ||
604 | ("ignoring unknown FETCH item '%s'", kw)); | ||
605 | env->state = resp_skip; | ||
606 | return 0; | ||
607 | } | ||
608 | |||
609 | env->mapper = mt->mapper; | ||
610 | rc = alloc_response (&env->resp, mt->type); | ||
611 | if (rc) | ||
612 | { | ||
613 | env->status = rc; | ||
614 | return MU_ERR_FAILURE; | ||
615 | } | ||
616 | env->state = mt->type == MU_IMAP_FETCH_BODY ? resp_body : resp_val; | ||
617 | break; | ||
618 | } | ||
619 | |||
620 | case resp_val: | ||
621 | if (env->mapper) | ||
595 | { | 622 | { |
596 | if (mt->size >= kwlen && memcmp (mt->name, kw, kwlen) == 0) | 623 | int rc = env->mapper (env->resp, elt, env); |
597 | break; | 624 | if (rc) |
625 | _free_fetch_response (env->resp); | ||
626 | else | ||
627 | mu_list_append (env->result, env->resp); | ||
598 | } | 628 | } |
599 | else if (mt->size == kwlen && memcmp (mt->name, kw, kwlen) == 0) | 629 | env->resp = NULL; |
600 | break; | 630 | mu_list_destroy (&env->hlist); |
601 | } | 631 | env->state = resp_kw; |
602 | 632 | break; | |
603 | if (!mt->name) | 633 | |
604 | { | 634 | case resp_body: |
605 | mu_debug (MU_DEBCAT_MAILER, MU_DEBUG_TRACE9, | 635 | if (_mu_imap_list_element_is_string (elt, "[")) |
606 | ("ignoring unknown FETCH item '%s'", kw)); | 636 | env->state = resp_body_section; |
607 | return MU_LIST_MAP_SKIP; | 637 | else |
608 | } | ||
609 | |||
610 | if (mt->mapper) | ||
611 | { | ||
612 | int rc = mt->mapper (elt, &resp); | ||
613 | if (rc == 0) | ||
614 | { | 638 | { |
615 | itmv[0] = resp; | 639 | env->mapper = _bodystructure_mapper; |
616 | return MU_LIST_MAP_OK; | 640 | env->state = resp_val; |
617 | } | 641 | } |
642 | break; | ||
643 | |||
644 | case resp_body_section: | ||
645 | if (elt->type != imap_eltype_string) | ||
646 | { | ||
647 | env->status = MU_ERR_PARSE; | ||
648 | return MU_ERR_FAILURE; | ||
649 | } | ||
650 | else if (strncmp (elt->v.string, "HEADER.FIELDS", 13) == 0) | ||
651 | env->state = resp_body_hlist; | ||
618 | else | 652 | else |
653 | env->state = resp_body_end; | ||
654 | env->section = elt->v.string; | ||
655 | break; | ||
656 | |||
657 | case resp_skip: | ||
658 | mu_list_destroy (&env->hlist); | ||
659 | env->state = resp_kw; | ||
660 | break; | ||
661 | |||
662 | case resp_body_hlist: | ||
663 | if (elt->type != imap_eltype_list) | ||
619 | { | 664 | { |
620 | *status = rc; | 665 | env->status = MU_ERR_PARSE; |
621 | return MU_LIST_MAP_STOP|MU_LIST_MAP_SKIP; | 666 | return MU_ERR_FAILURE; |
622 | } | 667 | } |
623 | } | 668 | mu_list_map (elt->v.list, _extract_string, NULL, 1, &env->hlist); |
669 | env->state = resp_body_end; | ||
670 | break; | ||
624 | 671 | ||
625 | return MU_LIST_MAP_SKIP; | 672 | case resp_body_end: |
673 | if (_mu_imap_list_element_is_string (elt, "]")) | ||
674 | env->state = resp_val; | ||
675 | else | ||
676 | { | ||
677 | env->status = MU_ERR_PARSE; | ||
678 | return MU_ERR_FAILURE; | ||
679 | } | ||
680 | } | ||
681 | |||
682 | return 0; | ||
626 | } | 683 | } |
627 | 684 | ||
628 | int | 685 | int |
... | @@ -630,7 +687,8 @@ _mu_imap_parse_fetch_response (mu_list_t input, mu_list_t *result_list) | ... | @@ -630,7 +687,8 @@ _mu_imap_parse_fetch_response (mu_list_t input, mu_list_t *result_list) |
630 | { | 687 | { |
631 | mu_list_t result; | 688 | mu_list_t result; |
632 | int status; | 689 | int status; |
633 | 690 | struct parse_response_env env; | |
691 | |||
634 | status = mu_list_create (&result); | 692 | status = mu_list_create (&result); |
635 | if (status) | 693 | if (status) |
636 | { | 694 | { |
... | @@ -639,11 +697,14 @@ _mu_imap_parse_fetch_response (mu_list_t input, mu_list_t *result_list) | ... | @@ -639,11 +697,14 @@ _mu_imap_parse_fetch_response (mu_list_t input, mu_list_t *result_list) |
639 | return 1; | 697 | return 1; |
640 | } | 698 | } |
641 | mu_list_set_destroy_item (result, _free_fetch_response); | 699 | mu_list_set_destroy_item (result, _free_fetch_response); |
642 | mu_list_map (input, _fetch_mapper, &status, 2, &result); | 700 | memset (&env, 0, sizeof (env)); |
643 | if (status) | 701 | |
702 | env.result = result; | ||
703 | mu_list_foreach (input, _fetch_fold, &env); | ||
704 | if (env.status) | ||
644 | mu_list_destroy (&result); | 705 | mu_list_destroy (&result); |
645 | else | 706 | else |
646 | *result_list = result; | 707 | *result_list = result; |
647 | 708 | mu_list_destroy (&env.hlist); | |
648 | return status; | 709 | return status; |
649 | } | 710 | } | ... | ... |
... | @@ -241,17 +241,19 @@ fetch_response_printer (void *item, void *data) | ... | @@ -241,17 +241,19 @@ fetch_response_printer (void *item, void *data) |
241 | switch (resp->type) | 241 | switch (resp->type) |
242 | { | 242 | { |
243 | case MU_IMAP_FETCH_BODY: | 243 | case MU_IMAP_FETCH_BODY: |
244 | mu_stream_printf (str, "BODY [%s]", resp->body.key); | 244 | mu_stream_printf (str, "BODY ["); |
245 | if (resp->body.partv) | 245 | if (resp->body.partv) |
246 | { | 246 | { |
247 | size_t i; | 247 | size_t i; |
248 | 248 | ||
249 | mu_stream_printf (str, ", part: "); | ||
250 | for (i = 0; i < resp->body.partc; i++) | 249 | for (i = 0; i < resp->body.partc; i++) |
251 | mu_stream_printf (str, "%lu.", | 250 | mu_stream_printf (str, "%lu.", |
252 | (unsigned long) resp->body.partv[i]); | 251 | (unsigned long) resp->body.partv[i]); |
253 | } | 252 | } |
254 | mu_stream_printf (str, "\nBEGIN%s\nEND\n", resp->body.text); | 253 | if (resp->body.section) |
254 | mu_stream_printf (str, "%s", resp->body.section); | ||
255 | mu_stream_printf (str, "]"); | ||
256 | mu_stream_printf (str, "\nBEGIN\n%s\nEND\n", resp->body.text); | ||
255 | break; | 257 | break; |
256 | 258 | ||
257 | case MU_IMAP_FETCH_BODYSTRUCTURE: | 259 | case MU_IMAP_FETCH_BODYSTRUCTURE: | ... | ... |
-
Please register or sign in to post a comment