Preparing for a new release. gpgol-0.10.4
authorWerner Koch <wk@gnupg.org>
Wed, 6 Feb 2008 14:01:45 +0000 (14:01 +0000)
committerWerner Koch <wk@gnupg.org>
Wed, 6 Feb 2008 14:01:45 +0000 (14:01 +0000)
ChangeLog
NEWS
TODO
configure.ac
src/ChangeLog
src/mapihelp.cpp
src/mapihelp.h
src/message.cpp
src/mimemaker.c
src/mimeparser.c
src/mimeparser.h

index f312eda..a5c184c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2008-02-06  Werner Koch  <wk@g10code.com>
+
+       Released 0.10.4 development version.
+
 2007-12-10  Werner Koch  <wk@g10code.com>
 
        Released 0.10.3 development version.
diff --git a/NEWS b/NEWS
index af411cc..4bc4a5a 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,4 @@
-Noteworthy changes for version 0.10.4
+Noteworthy changes for version 0.10.4 (2008-02-06)
 ==================================================
 
  UNDER HEAVY DEVELOPMENT - DO NOT USE FOR PRODUCTION!
diff --git a/TODO b/TODO
index 7d87a12..9fe63e7 100644 (file)
--- a/TODO
+++ b/TODO
@@ -24,5 +24,5 @@
   presented file names and decrypt them only on OpenSzFile.  Need to
   find some documentation first.
 
-* We need to use the micalg as retruned my Kleopatra.
+* We need to use the micalg as returned by the UI-server.
 
index 52ff688..ac9cb65 100644 (file)
@@ -1,5 +1,5 @@
 # configure.ac - for GpgOL
-# Copyright (C) 2005, 2006, 2007 g10 Code GmbH
+# Copyright (C) 2005, 2006, 2007, 2008 g10 Code GmbH
 #
 # This file is free software; as a special exception the author gives
 # unlimited permission to copy and/or distribute it, with or without
@@ -17,7 +17,7 @@ min_automake_version="1.9.4"
 # Set my_issvn to "yes" for non-released code.  Remember to run an
 # "svn up" and "autogen.sh" right before creating a distribution.
 m4_define([my_version], [0.10.4])
-m4_define([my_issvn], [yes])
+m4_define([my_issvn], [no])
 
 m4_define([svn_revision], m4_esyscmd([echo -n $( (svn info 2>/dev/null \
             || echo 'Revision: 0')|sed -n '/^Revision:/ {s/[^0-9]//gp;q;}')]))
index 210b5a2..5e6f671 100644 (file)
@@ -1,3 +1,19 @@
+2008-02-06  Werner Koch  <wk@g10code.com>
+
+       * mimeparser.c (mime_decrypt): New arg IS_RFC822.
+       * message.cpp (message_decrypt): Add code to see whether to use
+       the new arg.
+
+2008-02-01  Werner Koch  <wk@g10code.com>
+
+       * mimeparser.c (ciphertext_handler, ciphermessage_cb)
+       (ciphermessage_t2body): New.
+       (mime_decrypt): Use an rfc822 parser to pass the message to the
+       engine.
+
+       * mapihelp.cpp (mapi_get_attach_as_stream): Add arg R_ATTACH.
+       (mapi_set_attach_hidden): New.
+
 2008-01-31  Werner Koch  <wk@g10code.com>
 
        * message.cpp (message_verify): Check that the body attachment is
index 2343f7e..fde1751 100644 (file)
@@ -1,5 +1,5 @@
 /* mapihelp.cpp - Helper functions for MAPI
- *     Copyright (C) 2005, 2007 g10 Code GmbH
+ *     Copyright (C) 2005, 2007, 2008 g10 Code GmbH
  * 
  * This file is part of GpgOL.
  * 
@@ -1180,14 +1180,20 @@ mapi_release_attach_table (mapi_attach_item_t *table)
 
 
 /* Return an attachment as a new IStream object.  Returns NULL on
-   failure. */
+   failure.  If R_ATATCH is not NULL the actual attachment will not be
+   released by stored at that address; the caller needs to release it
+   in this case.  */
 LPSTREAM
-mapi_get_attach_as_stream (LPMESSAGE message, mapi_attach_item_t *item)
+mapi_get_attach_as_stream (LPMESSAGE message, mapi_attach_item_t *item,
+                           LPATTACH *r_attach)
 {
   HRESULT hr;
   LPATTACH att;
   LPSTREAM stream;
 
+  if (r_attach)
+    *r_attach = NULL;
+
   if (!item || item->end_of_table || item->mapipos == -1)
     return NULL;
 
@@ -1215,7 +1221,10 @@ mapi_get_attach_as_stream (LPMESSAGE message, mapi_attach_item_t *item)
       return NULL;
     }
 
-  att->Release ();
+  if (r_attach)
+    *r_attach = att;
+  else
+    att->Release ();
 
   return stream;
 }
@@ -1362,7 +1371,7 @@ mapi_get_attach (LPMESSAGE message, mapi_attach_item_t *item, size_t *r_nbytes)
 
 
 /* Mark this attachment as the orginal MOSS message.  We set a custom
-   property as weel ast the hidden hidden flag on ot..  */
+   property as well as the hidden hidden flag.  */
 int 
 mapi_mark_moss_attach (LPMESSAGE message, mapi_attach_item_t *item)
 {
@@ -1427,6 +1436,47 @@ mapi_mark_moss_attach (LPMESSAGE message, mapi_attach_item_t *item)
 }
 
 
+/* If the hidden property has not been set on ATTACH, set it and save
+   the changes. */
+int 
+mapi_set_attach_hidden (LPATTACH attach)
+{
+  int retval = -1;
+  HRESULT hr;
+  LPSPropValue propval;
+  SPropValue prop;
+
+  hr = HrGetOneProp ((LPMAPIPROP)attach, PR_ATTACHMENT_HIDDEN, &propval);
+  if (SUCCEEDED (hr) 
+      && PROP_TYPE (propval->ulPropTag) == PT_BOOLEAN
+      && propval->Value.b)
+    return 0;/* Already set to hidden. */
+
+  prop.ulPropTag = PR_ATTACHMENT_HIDDEN;
+  prop.Value.b = TRUE;
+  hr = HrSetOneProp (attach, &prop);
+  if (hr)
+    {
+      log_error ("%s:%s: can't set hidden attach flag: hr=%#lx\n",
+                 SRCNAME, __func__, hr); 
+      goto leave;
+    }
+  
+  hr = attach->SaveChanges (KEEP_OPEN_READWRITE);
+  if (hr)
+    {
+      log_error ("%s:%s: SaveChanges(attachment) failed: hr=%#lx\n",
+                 SRCNAME, __func__, hr); 
+      goto leave;
+    }
+  
+  retval = 0;
+    
+ leave:
+  return retval;
+}
+
+
 
 /* Returns True if MESSAGE has the GpgOL Sig Status property.  */
 int
index c5f213e..26c45e4 100644 (file)
@@ -80,6 +80,10 @@ struct mapi_attach_item_s
 };
 typedef struct mapi_attach_item_s mapi_attach_item_t;
 
+/* The filename of the attachment we create as the result of sign or
+   encrypt operation.  Don't change this name as some tests rely on
+   it.  */
+#define MIMEATTACHFILENAME "gpgolXXX.dat"
 
 
 void log_mapi_property (LPMESSAGE message, ULONG prop, const char *propname);
@@ -104,7 +108,8 @@ char *mapi_get_body (LPMESSAGE message, size_t *r_nbytes);
 mapi_attach_item_t *mapi_create_attach_table (LPMESSAGE message, int fast);
 void mapi_release_attach_table (mapi_attach_item_t *table);
 LPSTREAM mapi_get_attach_as_stream (LPMESSAGE message, 
-                                    mapi_attach_item_t *item);
+                                    mapi_attach_item_t *item, 
+                                    LPATTACH *r_attach);
 char *mapi_get_attach (LPMESSAGE message, 
                        mapi_attach_item_t *item, size_t *r_nbytes);
 int mapi_mark_moss_attach (LPMESSAGE message, mapi_attach_item_t *item);
@@ -116,6 +121,8 @@ int mapi_set_sig_status (LPMESSAGE message, const char *status_string);
 
 int mapi_set_gpgol_msg_class (LPMESSAGE message, const char *name);
 
+int  mapi_set_attach_hidden (LPATTACH attach);
+
 char *mapi_get_mime_info (LPMESSAGE msg);
 
 char *mapi_get_message_content_type (LPMESSAGE message, 
index 43bc0b4..5bcb293 100644 (file)
@@ -598,6 +598,9 @@ message_decrypt (LPMESSAGE message, msgtype_t msgtype, int force, HWND hwnd)
   gpg_error_t err;
   int is_opaque = 0;
   protocol_t protocol;
+  LPATTACH saved_attach = NULL;
+  int need_saved_attach = 0;
+  int need_rfc822_parser = 0;
 
   switch (msgtype)
     {
@@ -632,7 +635,6 @@ message_decrypt (LPMESSAGE message, msgtype_t msgtype, int force, HWND hwnd)
     }
   else
     {
-  
       /* PGP/MIME or S/MIME stuff.  */
       table = mapi_create_attach_table (message, 0);
       if (!table)
@@ -641,7 +643,7 @@ message_decrypt (LPMESSAGE message, msgtype_t msgtype, int force, HWND hwnd)
       if (is_opaque)
         {
           /* S/MIME opaque encrypted message: We expect one
-             attachment.  As we don't know ether we are called the
+             attachment.  As we don't know wether we are called the
              first time, we first try to find this attachment by
              looking at all attachments.  Only if this fails we
              identify it by its order.  */
@@ -650,11 +652,12 @@ message_decrypt (LPMESSAGE message, msgtype_t msgtype, int force, HWND hwnd)
             if (table[tblidx].attach_type == ATTACHTYPE_MOSSTEMPL)
               {
                 /* This attachment has been generated by us in the
-                   course of sendeing a new message.  The content will
+                   course of sending a new message.  The content will
                    be multipart/signed because we used this to trick
                    out OL.  We stop here and use this part for further
                    processing.  */
                 part2_idx = tblidx;
+                need_rfc822_parser = 1;
                 break;
               }
             else if (table[tblidx].attach_type == ATTACHTYPE_MOSS)
@@ -692,7 +695,7 @@ message_decrypt (LPMESSAGE message, msgtype_t msgtype, int force, HWND hwnd)
         {
           /* Multipart/encrypted message: We expect 2 attachments.
              The first one with the version number and the second one
-             with the ciphertext.  As we don't know ether we are
+             with the ciphertext.  As we don't know wether we are
              called the first time, we first try to find these
              attachments by looking at all attachments.  Only if this
              fails we identify them by their order (i.e. the first 2
@@ -732,7 +735,31 @@ message_decrypt (LPMESSAGE message, msgtype_t msgtype, int force, HWND hwnd)
                   mapi_mark_moss_attach (message, table+part2_idx);
                 }
             }
-          if (part1_idx == -1 || part2_idx == -1)
+
+
+          if (part1_idx == -1 || part2_idx == -1 
+              && !table[0].end_of_table && table[1].end_of_table
+              && table[0].attach_type == ATTACHTYPE_MOSS
+              && table[0].filename 
+              && !strcmp (table[0].filename, MIMEATTACHFILENAME))
+            {
+              /* This is likely a PGP/MIME created by us.  Due to the
+                 way we created that message, the MAPI derived content
+                 type is wrong and there is only one attachtment
+                 (gpgolXXX.dat).  We simply assume that it is PGP/MIME
+                 encrypted and pass it on to the mime parser.  We also
+                 keep the attachment open so that we can later set it
+                 to hidden if not yet done.  I can't remember whether
+                 it is possible to set the hidden attribute when
+                 creating the message - probably not.  Thus we take
+                 care of it here. */
+              log_debug ("%s:%s: "
+                         "assuming self-created PGP/MIME encrypted message",
+                         SRCNAME, __func__);
+              part2_idx = 0;
+              need_saved_attach = 1;
+            }
+          else if (part1_idx == -1 || part2_idx == -1)
             {
               log_debug ("%s:%s: this is not a PGP/MIME encrypted message",
                          SRCNAME, __func__);
@@ -741,12 +768,15 @@ message_decrypt (LPMESSAGE message, msgtype_t msgtype, int force, HWND hwnd)
           protocol = PROTOCOL_OPENPGP;
         }
       
-      cipherstream = mapi_get_attach_as_stream (message, table+part2_idx);
+      cipherstream = mapi_get_attach_as_stream (message, table+part2_idx,
+                                                need_saved_attach? 
+                                                &saved_attach : NULL );
       if (!cipherstream)
         goto leave; /* Problem getting the attachment.  */
     }
 
-  err = mime_decrypt (protocol, cipherstream, message, hwnd, 0);
+  err = mime_decrypt (protocol, cipherstream, message, 
+                      need_rfc822_parser, hwnd, 0);
   log_debug ("mime_decrypt returned %d (%s)", err, gpg_strerror (err));
   if (err)
     {
@@ -755,10 +785,18 @@ message_decrypt (LPMESSAGE message, msgtype_t msgtype, int force, HWND hwnd)
       snprintf (buf, sizeof buf, "Decryption failed (%s)", gpg_strerror (err));
       MessageBox (NULL, buf, "GpgOL", MB_ICONINFORMATION|MB_OK);
     }
+  else
+    {
+      if (saved_attach)
+        mapi_set_attach_hidden (saved_attach);
+    }
   cipherstream->Release ();
   retval = 0;
 
+
  leave:
+  if (saved_attach)
+    saved_attach->Release ();
   mapi_release_attach_table (table);
   return retval;
 }
index 796deb5..76b658d 100644 (file)
@@ -44,9 +44,6 @@
                                      SRCNAME, __func__, __LINE__); \
                         } while (0)
 
-/* The filename of the attachment we create as the result of sign or
-   encrypt operation.  */
-#define MIMEATTACHFILENAME "gpgolXXX.dat"
 
 static const char oid_mimetag[] =
     {0x2A, 0x86, 0x48, 0x86, 0xf7, 0x14, 0x03, 0x0a, 0x04};
index 01a41c4..6a49e69 100644 (file)
@@ -120,6 +120,8 @@ struct mime_context
                              working on a MIME message and not just on
                              plain rfc822 message.  */
   
+  engine_filter_t outfilter; /* Fiter as used by ciphertext_handler.  */
+
   /* A linked list describing the structure of the mime message.  This
      list gets build up while parsing the message.  */
   mimestruct_item_t mimestruct;
@@ -732,9 +734,7 @@ t2body (mime_context_t ctx, rfc822parse_t msg)
 
   /* Process the Content-type and all its parameters.  */
   ctmain = ctsub = NULL;
-  field = rfc822parse_parse_field (msg, "GnuPG-Content-Type", -1);
-  if (!field)
-    field = rfc822parse_parse_field (msg, "Content-Type", -1);
+  field = rfc822parse_parse_field (msg, "Content-Type", -1);
   if (field)
     ctmain = rfc822parse_query_media_type (field, &ctsub);
   if (!ctmain)
@@ -1140,7 +1140,7 @@ mime_verify (protocol_t protocol, const char *message, size_t messagelen,
   while ( (s = memchr (message, '\n', messagelen)) )
     {
       len = s - message + 1;
-      log_debug ("passing '%.*s'\n", (int)len, message);
+/*       log_debug ("passing '%.*s'\n", (int)len, message); */
       plaintext_handler (ctx, message, len);
       if (ctx->parser_error || ctx->line_too_long)
         {
@@ -1233,19 +1233,218 @@ mime_verify (protocol_t protocol, const char *message, size_t messagelen,
 
 
 
+/* Process the transition to body event in the decryption parser.
+
+   This means we have received the empty line indicating the body and
+   should now check the headers to see what to do about this part.  */
+static int
+ciphermessage_t2body (mime_context_t ctx, rfc822parse_t msg)
+{
+  rfc822parse_field_t field;
+  const char *ctmain, *ctsub;
+  size_t off;
+  char *p;
+  int is_text = 0;
+        
+  /* Figure out the encoding.  */
+  ctx->is_qp_encoded = 0;
+  ctx->is_base64_encoded = 0;
+  p = rfc822parse_get_field (msg, "Content-Transfer-Encoding", -1, &off);
+  if (p)
+    {
+      if (!stricmp (p+off, "quoted-printable"))
+        ctx->is_qp_encoded = 1;
+      else if (!stricmp (p+off, "base64"))
+        {
+          ctx->is_base64_encoded = 1;
+          b64_init (&ctx->base64);
+        }
+      free (p);
+    }
+
+  /* Process the Content-type and all its parameters.  */
+  /* Fixme: Currently we don't make any use of it but consider all the
+     content to be the encrypted data.  */
+  ctmain = ctsub = NULL;
+  field = rfc822parse_parse_field (msg, "Content-Type", -1);
+  if (field)
+    ctmain = rfc822parse_query_media_type (field, &ctsub);
+  if (!ctmain)
+    {
+      /* Either there is no content type field or it is faulty; in
+         both cases we fall back to text/plain.  */
+      ctmain = "text";
+      ctsub  = "plain";
+    }
+
+#ifdef DEBUG_PARSER  
+  log_debug ("%s:%s: ctx=%p, ct=`%s/%s'\n",
+             SRCNAME, __func__, ctx, ctmain, ctsub);
+#endif
+  rfc822parse_release_field (field); /* (Content-type) */
+  ctx->in_data = 1;
+
+#ifdef DEBUG_PARSER
+  log_debug ("%s:%s: this body: nesting=%d part_counter=%d is_text=%d\n",
+             SRCNAME, __func__, 
+             ctx->nesting_level, ctx->part_counter, is_text);
+#endif
+
+
+  return 0;
+}
+
+/* This routine gets called by the RFC822 decryption parser for all
+   kind of events.  Should return 0 on success or -1 as well as
+   setting errno on failure.  */
+static int
+ciphermessage_cb (void *opaque, rfc822parse_event_t event, rfc822parse_t msg)
+{
+  int retval = 0;
+  mime_context_t decctx = opaque;
+
+  debug_message_event (decctx, event);
+
+  switch (event)
+    {
+    case RFC822PARSE_T2BODY:
+      retval = ciphermessage_t2body (decctx, msg);
+      break;
+
+    case RFC822PARSE_LEVEL_DOWN:
+      decctx->nesting_level++;
+      break;
+
+    case RFC822PARSE_LEVEL_UP:
+      if (decctx->nesting_level)
+        decctx->nesting_level--;
+      else 
+        {
+          log_error ("%s: decctx=%p, invalid structure: bad nesting level\n",
+                     SRCNAME, decctx);
+          decctx->parser_error = 1;
+        }
+      break;
+    
+    case RFC822PARSE_BOUNDARY:
+    case RFC822PARSE_LAST_BOUNDARY:
+      decctx->any_boundary = 1;
+      decctx->in_data = 0;
+      break;
+    
+    case RFC822PARSE_BEGIN_HEADER:
+      decctx->part_counter++;
+      break;
+
+    default:  /* Ignore all other events. */
+      break;
+    }
+
+  return retval;
+}
+
+
+/* This handler is called by us with the MIME message containing the
+   ciphertext. */
+static int
+ciphertext_handler (void *handle, const void *buffer, size_t size)
+{
+  mime_context_t ctx = handle;
+  const char *s;
+  size_t nleft, pos, len;
+  gpg_error_t err;
+
+  s = buffer;
+  pos = ctx->linebufpos;
+  nleft = size;
+  for (; nleft ; nleft--, s++)
+    {
+      if (pos >= ctx->linebufsize)
+        {
+          log_error ("%s:%s: ctx=%p, rfc822 parser failed: line too long\n",
+                     SRCNAME, __func__, ctx);
+          ctx->line_too_long = 1;
+          return -1; /* Error. */
+        }
+      if (*s != '\n')
+        ctx->linebuf[pos++] = *s;
+      else
+        { /* Got a complete line.  Remove the last CR.  */
+          if (pos && ctx->linebuf[pos-1] == '\r')
+            pos--;
+
+          if (rfc822parse_insert (ctx->msg, ctx->linebuf, pos))
+            {
+              log_error ("%s:%s: ctx=%p, rfc822 parser failed: %s\n",
+                         SRCNAME, __func__, ctx, strerror (errno));
+              ctx->parser_error = 1;
+              return -1; /* Error. */
+            }
+
+          if (ctx->in_data)
+            {
+              /* We are inside the data.  That should be the actual
+                 ciphertext in the given encoding.  Pass it on to the
+                 crypto engine. */
+              if (ctx->is_qp_encoded)
+                len = qp_decode (ctx->linebuf, pos);
+              else if (ctx->is_base64_encoded)
+                len = b64_decode (&ctx->base64, ctx->linebuf, pos);
+              else
+                len = pos;
+              if (len)
+                err = engine_filter (ctx->outfilter, ctx->linebuf, len);
+              else
+                err = 0;
+              if (!err && !ctx->is_base64_encoded)
+                {
+                  char tmp[3] = "\r\n";
+                  err = engine_filter (ctx->outfilter, tmp, 2);
+                }
+              if (err)
+                {
+                  log_debug ("%s:%s: sending ciphertext to engine failed: %s",
+                             SRCNAME, __func__, gpg_strerror (err));
+                  ctx->parser_error = 1;
+                  return -1; /* Error. */
+                }
+            }
+          
+          /* Continue with next line. */
+          pos = 0;
+        }
+    }
+  ctx->linebufpos = pos;
+
+  return size;
+}
+
+
+
 /* Decrypt the PGP or S/MIME message taken from INSTREAM.  HWND is the
    window to be used for message box and such.  In PREVIEW_MODE no
    verification will be done, no messages saved and no messages boxes
-   will pop up. */
+   will pop up.  If IS_RFC822 is set, the message is expected to be in
+   rfc822 format.  */
 int
 mime_decrypt (protocol_t protocol, LPSTREAM instream, LPMESSAGE mapi_message,
-              HWND hwnd, int preview_mode)
+              int is_rfc822, HWND hwnd, int preview_mode)
 {
   gpg_error_t err;
-  mime_context_t ctx;
+  mime_context_t decctx, ctx;
   engine_filter_t filter = NULL;
 
-  log_debug ("%s:%s: enter (protocol=%d)", SRCNAME, __func__, protocol);
+  log_debug ("%s:%s: enter (protocol=%d, is_rfc822=%d)",
+             SRCNAME, __func__, protocol, is_rfc822);
+
+  if (is_rfc822)
+    {
+      decctx = xcalloc (1, sizeof *decctx + LINEBUFSIZE);
+      decctx->linebufsize = LINEBUFSIZE;
+      decctx->hwnd = hwnd;
+    }
+  else
+    decctx = NULL;
 
   ctx = xcalloc (1, sizeof *ctx + LINEBUFSIZE);
   ctx->linebufsize = LINEBUFSIZE;
@@ -1255,6 +1454,18 @@ mime_decrypt (protocol_t protocol, LPSTREAM instream, LPMESSAGE mapi_message,
   ctx->mapi_message = mapi_message;
   ctx->mimestruct_tail = &ctx->mimestruct;
 
+  if (decctx)
+    {
+      decctx->msg = rfc822parse_open (ciphermessage_cb, decctx);
+      if (!decctx->msg)
+        {
+          err = gpg_error_from_syserror ();
+          log_error ("%s:%s: failed to open the RFC822 decryption parser: %s", 
+                     SRCNAME, __func__, gpg_strerror (err));
+          goto leave;
+        }
+    }
+
   ctx->msg = rfc822parse_open (message_cb, ctx);
   if (!ctx->msg)
     {
@@ -1272,6 +1483,8 @@ mime_decrypt (protocol_t protocol, LPSTREAM instream, LPMESSAGE mapi_message,
   if ((err=engine_decrypt_start (filter, hwnd, protocol, !preview_mode)))
     goto leave;
 
+  if (decctx)
+    decctx->outfilter = filter;
   
   /* Filter the stream.  */
   do
@@ -1298,7 +1511,17 @@ mime_decrypt (protocol_t protocol, LPSTREAM instream, LPMESSAGE mapi_message,
         }
       else if (nread)
         {
-          err = engine_filter (filter, buffer, nread);
+          if (decctx)
+            {
+               ciphertext_handler (decctx, buffer, nread);
+               if (ctx->parser_error || ctx->line_too_long)
+                 {
+                   err = gpg_error (GPG_ERR_GENERAL);
+                   break;
+                 }
+            }
+          else
+            err = engine_filter (filter, buffer, nread);
         }
       else
         break; /* EOF */
@@ -1347,6 +1570,11 @@ mime_decrypt (protocol_t protocol, LPSTREAM instream, LPMESSAGE mapi_message,
       symenc_close (ctx->body_saved.symenc);
       xfree (ctx);
     }
+  if (decctx)
+    {
+      rfc822parse_close (decctx->msg);
+      xfree (decctx);
+    }
   return err;
 }
 
index 6099ae1..21a4ef3 100644 (file)
@@ -32,7 +32,7 @@ int mime_verify (protocol_t protocol, const char *message, size_t messagelen,
                  LPMESSAGE mapi_message, 
                  HWND hwnd, int preview_mode);
 int mime_decrypt (protocol_t protocol, 
-                  LPSTREAM instream, LPMESSAGE mapi_message,
+                  LPSTREAM instream, LPMESSAGE mapi_message, int is_rfc822,
                   HWND hwnd, int preview_mode);