wks: Send a final message to the user.
[gnupg.git] / tools / mime-parser.c
1 /* mime-parser.c - Parse MIME structures (high level rfc822 parser).
2  * Copyright (C) 2016 g10 Code GmbH
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24
25 #include "util.h"
26 #include "rfc822parse.h"
27 #include "mime-parser.h"
28
29
30 enum pgpmime_states
31   {
32     PGPMIME_NONE = 0,
33     PGPMIME_WAIT_ENCVERSION,
34     PGPMIME_IN_ENCVERSION,
35     PGPMIME_WAIT_ENCDATA,
36     PGPMIME_IN_ENCDATA,
37     PGPMIME_GOT_ENCDATA,
38     PGPMIME_WAIT_SIGNEDDATA,
39     PGPMIME_IN_SIGNEDDATA,
40     PGPMIME_WAIT_SIGNATURE,
41     PGPMIME_IN_SIGNATURE,
42     PGPMIME_GOT_SIGNATURE,
43     PGPMIME_INVALID
44   };
45
46
47 /* Definition of the mime parser object.  */
48 struct mime_parser_context_s
49 {
50   void *cookie;                /* Cookie passed to all callbacks.  */
51
52   /* The callback to announce a new part.  */
53   gpg_error_t (*new_part) (void *cookie,
54                            const char *mediatype,
55                            const char *mediasubtype);
56   /* The callback to return data of a part.  */
57   gpg_error_t (*part_data) (void *cookie,
58                             const void *data,
59                             size_t datalen);
60   /* The callback to collect encrypted data.  */
61   gpg_error_t (*collect_encrypted) (void *cookie, const char *data);
62   /* The callback to collect signed data.  */
63   gpg_error_t (*collect_signeddata) (void *cookie, const char *data);
64   /* The callback to collect a signature.  */
65   gpg_error_t (*collect_signature) (void *cookie, const char *data);
66
67   /* Helper to convey error codes from user callbacks.  */
68   gpg_error_t err;
69
70   int nesting_level;           /* The current nesting level.  */
71   int hashing_at_level;        /* The nesting level at which we are hashing. */
72   enum pgpmime_states pgpmime; /* Current PGP/MIME state.  */
73   unsigned int delay_hashing:1;/* Helper for PGPMIME_IN_SIGNEDDATA. */
74   unsigned int want_part:1;    /* Return the current part.  */
75   unsigned int decode_part:2;  /* Decode the part.  1 = QP, 2 = Base64. */
76
77   unsigned int verbose:1;      /* Enable verbose mode.  */
78   unsigned int debug:1;        /* Enable debug mode.  */
79
80   /* Flags to help with debug output.  */
81   struct {
82     unsigned int n_skip;         /* Skip showing these number of lines.  */
83     unsigned int header:1;       /* Show the header lines.  */
84     unsigned int data:1;         /* Show the data lines.  */
85     unsigned int as_note:1;      /* Show the next data line as a note.  */
86     unsigned int boundary : 1;
87   } show;
88
89   struct b64state *b64state;     /* NULL or malloced Base64 decoder state.  */
90
91   /* A buffer for reading a mail line,  */
92   char line[5000];
93 };
94
95
96 /* Print the event received by the parser for debugging.  */
97 static void
98 show_message_parser_event (rfc822parse_event_t event)
99 {
100   const char *s;
101
102   switch (event)
103     {
104     case RFC822PARSE_OPEN: s= "Open"; break;
105     case RFC822PARSE_CLOSE: s= "Close"; break;
106     case RFC822PARSE_CANCEL: s= "Cancel"; break;
107     case RFC822PARSE_T2BODY: s= "T2Body"; break;
108     case RFC822PARSE_FINISH: s= "Finish"; break;
109     case RFC822PARSE_RCVD_SEEN: s= "Rcvd_Seen"; break;
110     case RFC822PARSE_LEVEL_DOWN: s= "Level_Down"; break;
111     case RFC822PARSE_LEVEL_UP: s= "Level_Up"; break;
112     case RFC822PARSE_BOUNDARY: s= "Boundary"; break;
113     case RFC822PARSE_LAST_BOUNDARY: s= "Last_Boundary"; break;
114     case RFC822PARSE_BEGIN_HEADER: s= "Begin_Header"; break;
115     case RFC822PARSE_PREAMBLE: s= "Preamble"; break;
116     case RFC822PARSE_EPILOGUE: s= "Epilogue"; break;
117     default: s= "[unknown event]"; break;
118     }
119   log_debug ("*** RFC822 event %s\n", s);
120 }
121
122
123 /* Do in-place decoding of quoted-printable data of LENGTH in BUFFER.
124    Returns the new length of the buffer and stores true at R_SLBRK if
125    the line ended with a soft line break; false is stored if not.
126    This fucntion asssumes that a complete line is passed in
127    buffer.  */
128 static size_t
129 qp_decode (char *buffer, size_t length, int *r_slbrk)
130 {
131   char *d, *s;
132
133   if (r_slbrk)
134     *r_slbrk = 0;
135
136   /* Fixme:  We should remove trailing white space first.  */
137   for (s=d=buffer; length; length--)
138     {
139       if (*s == '=')
140         {
141           if (length > 2 && hexdigitp (s+1) && hexdigitp (s+2))
142             {
143               s++;
144               *(unsigned char*)d++ = xtoi_2 (s);
145               s += 2;
146               length -= 2;
147             }
148           else if (length > 2 && s[1] == '\r' && s[2] == '\n')
149             {
150               /* Soft line break.  */
151               s += 3;
152               length -= 2;
153               if (r_slbrk && length == 1)
154                 *r_slbrk = 1;
155             }
156           else if (length > 1 && s[1] == '\n')
157             {
158               /* Soft line break with only a Unix line terminator. */
159               s += 2;
160               length -= 1;
161               if (r_slbrk && length == 1)
162                 *r_slbrk = 1;
163             }
164           else if (length == 1)
165             {
166               /* Soft line break at the end of the line. */
167               s += 1;
168               if (r_slbrk)
169                 *r_slbrk = 1;
170             }
171           else
172             *d++ = *s++;
173         }
174       else
175         *d++ = *s++;
176     }
177
178   return d - buffer;
179 }
180
181
182 /* This function is called by parse_mail to communicate events.  This
183  * callback communicates with the caller using a structure passed in
184  * OPAQUE.  Should return 0 on success or set ERRNO and return -1. */
185 static int
186 parse_message_cb (void *opaque, rfc822parse_event_t event, rfc822parse_t msg)
187 {
188   mime_parser_t ctx = opaque;
189   const char *s;
190   int rc = 0;
191
192   if (ctx->debug)
193     show_message_parser_event (event);
194
195   if (event == RFC822PARSE_BEGIN_HEADER || event == RFC822PARSE_T2BODY)
196     {
197       /* We need to check here whether to start collecting signed data
198        * because attachments might come without header lines and thus
199        * we won't see the BEGIN_HEADER event.  */
200       if (ctx->pgpmime == PGPMIME_WAIT_SIGNEDDATA)
201         {
202           if (ctx->debug)
203             log_debug ("begin_hash\n");
204           ctx->hashing_at_level = ctx->nesting_level;
205           ctx->pgpmime = PGPMIME_IN_SIGNEDDATA;
206           ctx->delay_hashing = 0;
207         }
208     }
209
210   if (event == RFC822PARSE_OPEN)
211     {
212       /* Initialize for a new message. */
213       ctx->show.header = 1;
214     }
215   else if (event == RFC822PARSE_T2BODY)
216     {
217       rfc822parse_field_t field;
218
219       ctx->want_part = 0;
220       ctx->decode_part = 0;
221       field = rfc822parse_parse_field (msg, "Content-Type", -1);
222       if (field)
223         {
224           const char *s1, *s2;
225
226           s1 = rfc822parse_query_media_type (field, &s2);
227           if (s1)
228             {
229               if (ctx->verbose)
230                 log_debug ("h media: %*s%s %s\n",
231                            ctx->nesting_level*2, "", s1, s2);
232               if (ctx->pgpmime == PGPMIME_WAIT_ENCVERSION)
233                 {
234                   if (!strcmp (s1, "application")
235                       && !strcmp (s2, "pgp-encrypted"))
236                     {
237                       if (ctx->debug)
238                         log_debug ("c begin_encversion\n");
239                       ctx->pgpmime = PGPMIME_IN_ENCVERSION;
240                     }
241                   else
242                     {
243                       log_error ("invalid PGP/MIME structure;"
244                                  " expected '%s', got '%s/%s'\n",
245                                  "application/pgp-encrypted", s1, s2);
246                       ctx->pgpmime = PGPMIME_INVALID;
247                     }
248                 }
249               else if (ctx->pgpmime == PGPMIME_WAIT_ENCDATA)
250                 {
251                   if (!strcmp (s1, "application")
252                       && !strcmp (s2, "octet-stream"))
253                     {
254                       if (ctx->debug)
255                         log_debug ("c begin_encdata\n");
256                       ctx->pgpmime = PGPMIME_IN_ENCDATA;
257                     }
258                   else
259                     {
260                       log_error ("invalid PGP/MIME structure;"
261                                  " expected '%s', got '%s/%s'\n",
262                                  "application/octet-stream", s1, s2);
263                       ctx->pgpmime = PGPMIME_INVALID;
264                     }
265                 }
266               else if (ctx->pgpmime == PGPMIME_WAIT_SIGNATURE)
267                 {
268                   if (!strcmp (s1, "application")
269                       && !strcmp (s2, "pgp-signature"))
270                     {
271                       if (ctx->debug)
272                         log_debug ("c begin_signature\n");
273                       ctx->pgpmime = PGPMIME_IN_SIGNATURE;
274                     }
275                   else
276                     {
277                       log_error ("invalid PGP/MIME structure;"
278                                  " expected '%s', got '%s/%s'\n",
279                                  "application/pgp-signature", s1, s2);
280                       ctx->pgpmime = PGPMIME_INVALID;
281                     }
282                 }
283               else if (!strcmp (s1, "multipart")
284                        && !strcmp (s2, "encrypted"))
285                 {
286                   s = rfc822parse_query_parameter (field, "protocol", 0);
287                   if (s)
288                     {
289                       if (ctx->debug)
290                         log_debug ("h encrypted.protocol: %s\n", s);
291                       if (!strcmp (s, "application/pgp-encrypted"))
292                         {
293                           if (ctx->pgpmime)
294                             log_error ("note: "
295                                        "ignoring nested PGP/MIME signature\n");
296                           else
297                             ctx->pgpmime = PGPMIME_WAIT_ENCVERSION;
298                         }
299                       else if (ctx->verbose)
300                         log_debug ("# this protocol is not supported\n");
301                     }
302                 }
303               else if (!strcmp (s1, "multipart")
304                        && !strcmp (s2, "signed"))
305                 {
306                   s = rfc822parse_query_parameter (field, "protocol", 1);
307                   if (s)
308                     {
309                       if (ctx->debug)
310                         log_debug ("h signed.protocol: %s\n", s);
311                       if (!strcmp (s, "application/pgp-signature"))
312                         {
313                           if (ctx->pgpmime)
314                             log_error ("note: "
315                                        "ignoring nested PGP/MIME signature\n");
316                           else
317                             ctx->pgpmime = PGPMIME_WAIT_SIGNEDDATA;
318                         }
319                       else if (ctx->verbose)
320                         log_debug ("# this protocol is not supported\n");
321                     }
322                 }
323               else if (ctx->new_part)
324                 {
325                   ctx->err = ctx->new_part (ctx->cookie, s1, s2);
326                   if (!ctx->err)
327                     ctx->want_part = 1;
328                   else if (gpg_err_code (ctx->err) == GPG_ERR_FALSE)
329                     ctx->err = 0;
330                   else if (gpg_err_code (ctx->err) == GPG_ERR_TRUE)
331                     {
332                       ctx->want_part = ctx->decode_part = 1;
333                       ctx->err = 0;
334                     }
335                 }
336             }
337           else
338             {
339               if (ctx->debug)
340                 log_debug ("h media: %*s none\n", ctx->nesting_level*2, "");
341               if (ctx->new_part)
342                 {
343                   ctx->err = ctx->new_part (ctx->cookie, "", "");
344                   if (!ctx->err)
345                     ctx->want_part = 1;
346                   else if (gpg_err_code (ctx->err) == GPG_ERR_FALSE)
347                     ctx->err = 0;
348                   else if (gpg_err_code (ctx->err) == GPG_ERR_TRUE)
349                     {
350                       ctx->want_part = ctx->decode_part = 1;
351                       ctx->err = 0;
352                     }
353                 }
354             }
355
356           rfc822parse_release_field (field);
357         }
358       else
359         {
360           if (ctx->verbose)
361             log_debug ("h media: %*stext plain [assumed]\n",
362                        ctx->nesting_level*2, "");
363           if (ctx->new_part)
364             {
365               ctx->err = ctx->new_part (ctx->cookie, "text", "plain");
366               if (!ctx->err)
367                 ctx->want_part = 1;
368               else if (gpg_err_code (ctx->err) == GPG_ERR_FALSE)
369                 ctx->err = 0;
370               else if (gpg_err_code (ctx->err) == GPG_ERR_TRUE)
371                 {
372                   ctx->want_part = ctx->decode_part = 1;
373                   ctx->err = 0;
374                 }
375             }
376         }
377
378       /* Figure out the encoding if needed.  */
379       if (ctx->decode_part)
380         {
381           char *value;
382           size_t valueoff;
383
384           ctx->decode_part = 0; /* Fallback for unknown encoding.  */
385           value = rfc822parse_get_field (msg, "Content-Transfer-Encoding", -1,
386                                          &valueoff);
387           if (value)
388             {
389               if (!stricmp (value+valueoff, "quoted-printable"))
390                 ctx->decode_part = 1;
391               else if (!stricmp (value+valueoff, "base64"))
392                 {
393                   ctx->decode_part = 2;
394                   if (ctx->b64state)
395                     b64dec_finish (ctx->b64state); /* Reuse state.  */
396                   else
397                     {
398                       ctx->b64state = xtrymalloc (sizeof *ctx->b64state);
399                       if (!ctx->b64state)
400                         rc = gpg_error_from_syserror ();
401                     }
402                   if (!rc)
403                     rc = b64dec_start (ctx->b64state, NULL);
404                 }
405               free (value); /* Right, we need a plain free.  */
406             }
407         }
408
409       ctx->show.header = 0;
410       ctx->show.data = 1;
411       ctx->show.n_skip = 1;
412     }
413   else if (event == RFC822PARSE_PREAMBLE)
414     ctx->show.as_note = 1;
415   else if (event == RFC822PARSE_LEVEL_DOWN)
416     {
417       if (ctx->debug)
418         log_debug ("b down\n");
419       ctx->nesting_level++;
420     }
421   else if (event == RFC822PARSE_LEVEL_UP)
422     {
423       if (ctx->debug)
424         log_debug ("b up\n");
425       if (ctx->nesting_level)
426         ctx->nesting_level--;
427       else
428         log_error ("invalid structure (bad nesting level)\n");
429     }
430   else if (event == RFC822PARSE_BOUNDARY || event == RFC822PARSE_LAST_BOUNDARY)
431     {
432       ctx->show.data = 0;
433       ctx->show.boundary = 1;
434       if (event == RFC822PARSE_BOUNDARY)
435         {
436           ctx->show.header = 1;
437           ctx->show.n_skip = 1;
438           if (ctx->debug)
439             log_debug ("b part\n");
440         }
441       else if (ctx->debug)
442         log_debug ("b last\n");
443
444       if (ctx->pgpmime == PGPMIME_IN_ENCDATA)
445         {
446           if (ctx->debug)
447             log_debug ("c end_encdata\n");
448           ctx->pgpmime = PGPMIME_GOT_ENCDATA;
449           /* FIXME: We should assert (event == LAST_BOUNDARY).  */
450         }
451       else if (ctx->pgpmime == PGPMIME_IN_SIGNEDDATA
452                && ctx->nesting_level == ctx->hashing_at_level)
453         {
454           if (ctx->debug)
455             log_debug ("c end_hash\n");
456           ctx->pgpmime = PGPMIME_WAIT_SIGNATURE;
457           if (ctx->collect_signeddata)
458             ctx->err = ctx->collect_signeddata (ctx->cookie, NULL);
459         }
460       else if (ctx->pgpmime == PGPMIME_IN_SIGNATURE)
461         {
462           if (ctx->debug)
463             log_debug ("c end_signature\n");
464           ctx->pgpmime = PGPMIME_GOT_SIGNATURE;
465           /* FIXME: We should assert (event == LAST_BOUNDARY).  */
466         }
467       else if (ctx->want_part)
468         {
469           if (ctx->part_data)
470             {
471               /* FIXME: We may need to flush things.  */
472               ctx->err = ctx->part_data (ctx->cookie, NULL, 0);
473             }
474           ctx->want_part = 0;
475         }
476     }
477
478   return rc;
479 }
480
481
482 /* Create a new mime parser object.  COOKIE is a values which will be
483  * used as first argument for all callbacks registered with this
484  * parser object.  */
485 gpg_error_t
486 mime_parser_new (mime_parser_t *r_parser, void *cookie)
487 {
488   mime_parser_t ctx;
489
490   *r_parser = NULL;
491
492   ctx = xtrycalloc (1, sizeof *ctx);
493   if (!ctx)
494     return gpg_error_from_syserror ();
495   ctx->cookie = cookie;
496
497   *r_parser = ctx;
498   return 0;
499 }
500
501
502 /* Release a mime parser object.  */
503 void
504 mime_parser_release (mime_parser_t ctx)
505 {
506   if (!ctx)
507     return;
508
509   if (ctx->b64state)
510     {
511       b64dec_finish (ctx->b64state);
512       xfree (ctx->b64state);
513     }
514   xfree (ctx);
515 }
516
517
518 /* Set verbose and debug mode.  */
519 void
520 mime_parser_set_verbose (mime_parser_t ctx, int level)
521 {
522   if (!level)
523     {
524       ctx->verbose = 0;
525       ctx->debug = 0;
526     }
527   else
528     {
529       ctx->verbose = 1;
530       if (level > 10)
531         ctx->debug = 1;
532     }
533 }
534
535
536 /* Set the callback used to announce a new part.  It will be called
537  * with the media type and media subtype of the part.  If no
538  * Content-type header was given both values are the empty string.
539  * The callback should return 0 on success or an error code.  The
540  * error code GPG_ERR_FALSE indicates that the caller is not
541  * interested in the part and data shall not be returned via a
542  * registered part_data callback.  The error code GPG_ERR_TRUE
543  * indicates that the parts shall be redurned in decoded format
544  * (i.e. base64 or QP encoding is removed).  */
545 void
546 mime_parser_set_new_part (mime_parser_t ctx,
547                           gpg_error_t (*fnc) (void *cookie,
548                                               const char *mediatype,
549                                               const char *mediasubtype))
550 {
551   ctx->new_part = fnc;
552 }
553
554
555 /* Set the callback used to return the data of a part to the caller.
556  * The end of the part is indicated by passing NUL for DATA.  */
557 void
558 mime_parser_set_part_data (mime_parser_t ctx,
559                            gpg_error_t (*fnc) (void *cookie,
560                                                const void *data,
561                                                size_t datalen))
562 {
563   ctx->part_data = fnc;
564 }
565
566
567 /* Set the callback to collect encrypted data.  A NULL passed to the
568  * callback indicates the end of the encrypted data; the callback may
569  * then decrypt the collected data.  */
570 void
571 mime_parser_set_collect_encrypted (mime_parser_t ctx,
572                                    gpg_error_t (*fnc) (void *cookie,
573                                                        const char *data))
574 {
575   ctx->collect_encrypted = fnc;
576 }
577
578
579 /* Set the callback to collect signed data.  A NULL passed to the
580  * callback indicates the end of the signed data.  */
581 void
582 mime_parser_set_collect_signeddata (mime_parser_t ctx,
583                                     gpg_error_t (*fnc) (void *cookie,
584                                                         const char *data))
585 {
586   ctx->collect_signeddata = fnc;
587 }
588
589
590 /* Set the callback to collect the signature.  A NULL passed to the
591  * callback indicates the end of the signature; the callback may the
592  * verify the signature.  */
593 void
594 mime_parser_set_collect_signature (mime_parser_t ctx,
595                                    gpg_error_t (*fnc) (void *cookie,
596                                                        const char *data))
597 {
598   ctx->collect_signature = fnc;
599 }
600
601
602 /* Read and parse a message from FP and call the appropriate
603  * callbacks.  */
604 gpg_error_t
605 mime_parser_parse (mime_parser_t ctx, estream_t fp)
606 {
607   gpg_error_t err;
608   rfc822parse_t msg = NULL;
609   unsigned int lineno = 0;
610   size_t length, nbytes;
611   char *line;
612
613   line = ctx->line;
614
615   msg = rfc822parse_open (parse_message_cb, ctx);
616   if (!msg)
617     {
618       err = gpg_error_from_syserror ();
619       log_error ("can't open mail parser: %s", gpg_strerror (err));
620       goto leave;
621     }
622
623   /* Fixme: We should not use fgets because it can't cope with
624      embedded nul characters. */
625   while (es_fgets (ctx->line, sizeof (ctx->line), fp))
626     {
627       lineno++;
628       if (lineno == 1 && !strncmp (line, "From ", 5))
629         continue;  /* We better ignore a leading From line. */
630
631       length = strlen (line);
632       if (length && line[length - 1] == '\n')
633         line[--length] = 0;
634       else
635         log_error ("mail parser detected too long or"
636                    " non terminated last line (lnr=%u)\n", lineno);
637       if (length && line[length - 1] == '\r')
638         line[--length] = 0;
639
640       ctx->err = 0;
641       if (rfc822parse_insert (msg, line, length))
642         {
643           err = gpg_error_from_syserror ();
644           log_error ("mail parser failed: %s", gpg_strerror (err));
645           goto leave;
646         }
647       if (ctx->err)
648         {
649           /* Error from a callback detected.  */
650           err = ctx->err;
651           goto leave;
652         }
653
654
655       /* Debug output.  Note that the boundary is shown before n_skip
656        * is evaluated.  */
657       if (ctx->show.boundary)
658         {
659           if (ctx->debug)
660             log_debug ("# Boundary: %s\n", line);
661           ctx->show.boundary = 0;
662         }
663       if (ctx->show.n_skip)
664         ctx->show.n_skip--;
665       else if (ctx->show.data)
666         {
667           if (ctx->show.as_note)
668             {
669               if (ctx->verbose)
670                 log_debug ("# Note: %s\n", line);
671               ctx->show.as_note = 0;
672             }
673           else if (ctx->debug)
674             log_debug ("# Data: %s\n", line);
675         }
676       else if (ctx->show.header && ctx->verbose)
677         log_debug ("# Header: %s\n", line);
678
679       if (ctx->pgpmime == PGPMIME_IN_ENCVERSION)
680         {
681           trim_trailing_spaces (line);
682           if (!*line)
683             ;  /* Skip empty lines.  */
684           else if (!strcmp (line, "Version: 1"))
685             ctx->pgpmime = PGPMIME_WAIT_ENCDATA;
686           else
687             {
688               log_error ("invalid PGP/MIME structure;"
689                          " garbage in pgp-encrypted part ('%s')\n", line);
690               ctx->pgpmime = PGPMIME_INVALID;
691             }
692         }
693       else if (ctx->pgpmime == PGPMIME_IN_ENCDATA)
694         {
695           if (ctx->collect_encrypted)
696             {
697               err = ctx->collect_encrypted (ctx->cookie, line);
698               if (!err)
699                 err = ctx->collect_encrypted (ctx->cookie, "\r\n");
700               if (err)
701                 goto leave;
702             }
703         }
704       else if (ctx->pgpmime == PGPMIME_GOT_ENCDATA)
705         {
706           ctx->pgpmime = PGPMIME_NONE;
707           if (ctx->collect_encrypted)
708             ctx->collect_encrypted (ctx->cookie, NULL);
709         }
710       else if (ctx->pgpmime == PGPMIME_IN_SIGNEDDATA)
711         {
712           /* If we are processing signed data, store the signed data.
713            * We need to delay the hashing of the CR/LF because the
714            * last line ending belongs to the next boundary.  This is
715            * the reason why we can't use the PGPMIME state as a
716            * condition.  */
717           if (ctx->debug)
718             log_debug ("# hashing %s'%s'\n",
719                        ctx->delay_hashing? "CR,LF+":"", line);
720           if (ctx->collect_signeddata)
721             {
722               if (ctx->delay_hashing)
723                 ctx->collect_signeddata (ctx->cookie, "\r\n");
724               ctx->collect_signeddata (ctx->cookie, line);
725             }
726           ctx->delay_hashing = 1;
727         }
728       else if (ctx->pgpmime == PGPMIME_IN_SIGNATURE)
729         {
730           if (ctx->collect_signeddata)
731             {
732               ctx->collect_signature (ctx->cookie, line);
733               ctx->collect_signature (ctx->cookie, "\r\n");
734             }
735         }
736       else if (ctx->pgpmime == PGPMIME_GOT_SIGNATURE)
737         {
738           ctx->pgpmime = PGPMIME_NONE;
739           if (ctx->collect_signeddata)
740             ctx->collect_signature (ctx->cookie, NULL);
741         }
742       else if (ctx->want_part)
743         {
744           if (ctx->part_data)
745             {
746               if (ctx->decode_part == 1)
747                 {
748                   length = qp_decode (line, length, NULL);
749                 }
750               else if (ctx->decode_part == 2)
751                 {
752                   log_assert (ctx->b64state);
753                   err = b64dec_proc (ctx->b64state, line, length, &nbytes);
754                   if (err)
755                     goto leave;
756                   length = nbytes;
757                 }
758               err = ctx->part_data (ctx->cookie, line, length);
759               if (err)
760                 goto leave;
761             }
762         }
763     }
764
765   rfc822parse_close (msg);
766   msg = NULL;
767   err = 0;
768
769  leave:
770   rfc822parse_cancel (msg);
771   return err;
772 }