[svn] GPGol - r104 - in trunk: . src
svn author wk
cvs at cvs.gnupg.org
Thu Sep 22 18:29:20 CEST 2005
Author: wk
Date: 2005-09-22 18:29:19 +0200 (Thu, 22 Sep 2005)
New Revision: 104
Modified:
trunk/ChangeLog
trunk/NEWS
trunk/README
trunk/TODO
trunk/configure.ac
trunk/src/ChangeLog
trunk/src/common.c
trunk/src/engine-gpgme.c
trunk/src/gpgmsg.cpp
trunk/src/intern.h
trunk/src/pgpmime.c
trunk/src/pgpmime.h
trunk/src/rfc822parse.c
Log:
Allow saving of PGP/MIME encrypted attachments.
Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog 2005-09-21 06:40:51 UTC (rev 103)
+++ trunk/ChangeLog 2005-09-22 16:29:19 UTC (rev 104)
@@ -1,3 +1,7 @@
+2005-09-22 Werner Koch <wk at g10code.com>
+
+ Released 0.9.2.
+
2005-09-19 Werner Koch <wk at g10code.com>
Released 0.9.1.
Modified: trunk/NEWS
===================================================================
--- trunk/NEWS 2005-09-21 06:40:51 UTC (rev 103)
+++ trunk/NEWS 2005-09-22 16:29:19 UTC (rev 104)
@@ -1,3 +1,9 @@
+Noteworthy changes for version 0.9.2 (2005-09-22)
+=================================================
+
+* Saving attachments from PGP/MIME encrypted messages works.
+
+
Noteworthy changes for version 0.9.1 (2005-09-19)
=================================================
Modified: trunk/README
===================================================================
--- trunk/README 2005-09-21 06:40:51 UTC (rev 103)
+++ trunk/README 2005-09-22 16:29:19 UTC (rev 104)
@@ -9,12 +9,12 @@
DLL will be named "gpgol.dll". It is to be build using
the Mingw toolchain.
-To install this plugin, copy it to some directory (e.g. where gpg lives),
-make sure that the libgpg-error.dll and gpgme.dll are available in a
-directory where Windows searches for DLLs (e.g. c:\winnt\system32),
-stop Outlook, run the command "regsvr32 gpgol.dll" and start
-Outlook. You should then find a new tab named "GnuPG" in Outlook's
-option menu.
+To install this plugin, copy "gpgol.dll" to some directory (e.g. where
+gpg lives), make sure that the libgpg-error.dll and gpgme.dll are
+available in a directory where Windows searches for DLLs
+(e.g. c:\winnt\system32), stop Outlook, run the command "regsvr32
+gpgol.dll" and start Outlook. You should then find a new tab named
+"GnuPG" in Outlook's option menu.
Note: For building in src/ you need to throw an original mapi32.dll
into this directory. This is due to a bug in the binutils: ld is not
Modified: trunk/TODO
===================================================================
--- trunk/TODO 2005-09-21 06:40:51 UTC (rev 103)
+++ trunk/TODO 2005-09-22 16:29:19 UTC (rev 104)
@@ -16,4 +16,6 @@
detect whether this is an encrypted message and change the
MessageClass accordingly.
+* Allow for symmetric encryption.
+
Modified: trunk/configure.ac
===================================================================
--- trunk/configure.ac 2005-09-21 06:40:51 UTC (rev 103)
+++ trunk/configure.ac 2005-09-22 16:29:19 UTC (rev 104)
@@ -15,7 +15,7 @@
# Version number: Remember to change it immediately *after* a release.
# Add a "-cvs" prefix for non-released code.
-AC_INIT(gpgol, 0.9.1, bug-gpgol at g10code.com)
+AC_INIT(gpgol, 0.9.2, bug-gpgol at g10code.com)
NEED_GPGME_API=1
NEED_GPGME_VERSION=1.1.0
Modified: trunk/src/ChangeLog
===================================================================
--- trunk/src/ChangeLog 2005-09-21 06:40:51 UTC (rev 103)
+++ trunk/src/ChangeLog 2005-09-22 16:29:19 UTC (rev 104)
@@ -1,3 +1,18 @@
+2005-09-22 Werner Koch <wk at g10code.com>
+
+ * engine-gpgme.c (decrypt_stream): Use gpgme_op_decrypt_verify.
+
+ * gpgmsg.cpp (gatherAttachmentInfo): Ignore attestations when
+ checking for pgp/mime.
+
+ * pgpmime.c (pgpmime_decrypt): Added arg HWND.
+ (message_cb, plaintext_handler): Write attachments.
+ * pgpmime.c (base64_decode): New.
+ * rfc822parse.c (parse_field): Treat Content-Disposition special.
+
+ * gpgmsg.cpp (get_save_filename): Moved to ..
+ * common.c (get_save_filename): .. here.
+
2005-09-20 Timo Schulz <ts at g10code.com>
* attach.c: New.
Modified: trunk/src/common.c
===================================================================
--- trunk/src/common.c 2005-09-21 06:40:51 UTC (rev 103)
+++ trunk/src/common.c 2005-09-22 16:29:19 UTC (rev 104)
@@ -72,6 +72,41 @@
}
+
+/* Return a filename to be used for saving an attachment. Returns a
+ malloced string on success. HWND is the current Window and SRCNAME
+ the filename to be used as suggestion. On error (i.e. cancel) NULL
+ is returned. */
+char *
+get_save_filename (HWND root, const char *srcname)
+
+{
+ char filter[] = "All Files (*.*)\0*.*\0\0";
+ char fname[MAX_PATH+1];
+ OPENFILENAME ofn;
+
+ memset (fname, 0, sizeof (fname));
+ strncpy (fname, srcname, MAX_PATH-1);
+ fname[MAX_PATH] = 0;
+
+
+ memset (&ofn, 0, sizeof (ofn));
+ ofn.lStructSize = sizeof (ofn);
+ ofn.hwndOwner = root;
+ ofn.lpstrFile = fname;
+ ofn.nMaxFile = MAX_PATH;
+ ofn.lpstrFileTitle = NULL;
+ ofn.nMaxFileTitle = 0;
+ ofn.Flags |= OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
+ ofn.lpstrTitle = "GPG - Save decrypted attachment";
+ ofn.lpstrFilter = filter;
+
+ if (GetSaveFileName (&ofn))
+ return xstrdup (fname);
+ return NULL;
+}
+
+
void
out_of_core (void)
{
Modified: trunk/src/engine-gpgme.c
===================================================================
--- trunk/src/engine-gpgme.c 2005-09-21 06:40:51 UTC (rev 103)
+++ trunk/src/engine-gpgme.c 2005-09-22 16:29:19 UTC (rev 104)
@@ -592,7 +592,7 @@
gpgme_set_passphrase_cb (ctx, passphrase_callback_box, &dk);
dk.ctx = ctx;
- err = gpgme_op_decrypt (ctx, in, out);
+ err = gpgme_op_decrypt_verify (ctx, in, out);
dk.ctx = NULL;
update_passphrase_cache (err, &dk);
/* Act upon the result of the decryption operation. */
Modified: trunk/src/gpgmsg.cpp
===================================================================
--- trunk/src/gpgmsg.cpp 2005-09-21 06:40:51 UTC (rev 103)
+++ trunk/src/gpgmsg.cpp 2005-09-22 16:29:19 UTC (rev 104)
@@ -970,7 +970,8 @@
return gpg_error (GPG_ERR_GENERAL);
}
- err = pgpmime_decrypt (from, opt.passwd_ttl, &plaintext, attestation);
+ err = pgpmime_decrypt (from, opt.passwd_ttl, &plaintext, attestation,
+ hwnd);
from->Release ();
att->Release ();
@@ -1690,40 +1691,6 @@
-
-/* Return a filename to be used for saving an attachment. Returns an
- malloced string on success. HWND is the current Window and SRCNAME
- the filename to be used as suggestion. On error; i.e. cancel NULL
- is returned. */
-static char *
-get_save_filename (HWND root, const char *srcname)
-
-{
- char filter[] = "All Files (*.*)\0*.*\0\0";
- char fname[MAX_PATH+1];
- OPENFILENAME ofn;
-
- memset (fname, 0, sizeof (fname));
- strncpy (fname, srcname, MAX_PATH-1);
- fname[MAX_PATH] = 0;
-
-
- memset (&ofn, 0, sizeof (ofn));
- ofn.lStructSize = sizeof (ofn);
- ofn.hwndOwner = root;
- ofn.lpstrFile = fname;
- ofn.nMaxFile = MAX_PATH;
- ofn.lpstrFileTitle = NULL;
- ofn.nMaxFileTitle = 0;
- ofn.Flags |= OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
- ofn.lpstrTitle = "GPG - Save decrypted attachment";
- ofn.lpstrFilter = filter;
-
- if (GetSaveFileName (&ofn))
- return xstrdup (fname);
- return NULL;
-}
-
/* Read the attachment ATT and try to detect whether this is a PGP
Armored message. METHOD is the attach method of ATT. Returns 0 if
@@ -1793,6 +1760,7 @@
attach_info_t table;
unsigned int pos, n_attach;
const char *s;
+ unsigned int attestation_count = 0;
is_pgpmime = false;
has_attestation = false;
@@ -1840,7 +1808,10 @@
&& !stricmp (table[pos].filename, "GPGol-Attestation.txt")
&& table[pos].content_type
&& !stricmp (table[pos].content_type, "text/plain"))
- has_attestation = true;
+ {
+ has_attestation = true;
+ attestation_count++;
+ }
att->Release ();
}
@@ -1913,9 +1884,12 @@
/* Simple check whether this is PGP/MIME encrypted. At least with
OL2003 the content-type of the body is also correctly set but we
don't make use of this as it is not clear whether this is true
- for othyer storage providers. */
+ for other storage providers. We use a hack to ignore extra
+ attesttation attachments: Those are assume to come after the both
+ PGP/MIME parts. */
if (!opt.compat.no_pgpmime
- && pos == 2 && table[0].content_type && table[1].content_type
+ && pos == 2 + attestation_count
+ && table[0].content_type && table[1].content_type
&& !stricmp (table[0].content_type, "application/pgp-encrypted")
&& !stricmp (table[1].content_type, "application/octet-stream")
&& isPgpmimeVersionPart (0))
@@ -1932,9 +1906,9 @@
-/* Verify the ATTachment at attachments and table position POS_DATA
- agains the signature at position POS_SIG. Display the status for
- each signature. */
+/* Verify the attachment as recorded in TABLE and at table position
+ POS_DATA against the signature at position POS_SIG. Display the
+ status for each signature. */
void
GpgMsgImpl::verifyAttachment (HWND hwnd, attach_info_t table,
unsigned int pos_data,
Modified: trunk/src/intern.h
===================================================================
--- trunk/src/intern.h 2005-09-21 06:40:51 UTC (rev 103)
+++ trunk/src/intern.h 2005-09-22 16:29:19 UTC (rev 104)
@@ -120,6 +120,7 @@
/*-- common.c --*/
void set_global_hinstance (HINSTANCE hinst);
void center_window (HWND childwnd, HWND style);
+char *get_save_filename (HWND root, const char *srcname);
HRESULT w32_shgetfolderpath (HWND a, int b, HANDLE c, DWORD d, LPSTR e);
Modified: trunk/src/pgpmime.c
===================================================================
--- trunk/src/pgpmime.c 2005-09-21 06:40:51 UTC (rev 103)
+++ trunk/src/pgpmime.c 2005-09-22 16:29:19 UTC (rev 104)
@@ -33,7 +33,9 @@
#include <assert.h>
#include <string.h>
+#define COBJMACROS
#include <windows.h>
+#include <objidl.h> /* For IStream. */
#include <gpgme.h>
@@ -41,6 +43,7 @@
#include "mymapitags.h"
#include "rfc822parse.h"
+#include "intern.h"
#include "util.h"
#include "pgpmime.h"
#include "engine.h"
@@ -50,20 +53,66 @@
only for 1000 bytes; thus 2000 seems to be a reasonable value. */
#define LINEBUFSIZE 2000
+/* The reverse base-64 list used for base-64 decoding. */
+static unsigned char const asctobin[256] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
+ 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
+ 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24,
+ 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
+ 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff
+};
+
+
+
+
/* The context object we use to track information. */
struct pgpmime_context
{
+ HWND hwnd; /* A window handle to be used for message boxes etc. */
rfc822parse_t msg; /* The handle of the RFC822 parser. */
int nesting_level; /* Current MIME nesting level. */
int in_data; /* We are currently in data (body or attachment). */
- gpgme_data_t body; /* NULL or a data object used to collect the
- body part we are going to display later. */
- int collect_body; /* True if we are collecting the body lines. */
- int is_qp_encoded; /* Current part is QP encoded. */
+ gpgme_data_t body; /* NULL or a data object used to collect the
+ body part we are going to display later. */
+ int collect_body; /* True if we are collecting the body lines. */
+ int collect_attachment; /* True if we are collecting an attachment. */
+ int is_qp_encoded; /* Current part is QP encoded. */
+ int is_base64_encoded; /* Current part is base 64 encoded. */
+ int part_counter; /* Counts the number of processed parts. */
+ char *filename; /* Current filename (malloced) or NULL. */
+
+ LPSTREAM outstream; /* NULL or a stream to write a part to. */
+
+ /* Helper to keep the state of the base64 decoder. */
+ struct
+ {
+ int idx;
+ unsigned char val;
+ int stop_seen;
+ int invalid_encoding;
+ } base64;
+
int line_too_long; /* Indicates that a received line was too long. */
int parser_error; /* Indicates that we encountered a error from
the parser. */
@@ -98,7 +147,73 @@
}
+/* Do in-place decoding of base-64 data of LENGTH in BUFFER. Returns
+ the new length of the buffer. CTX is required to return errors and
+ to maintain state of the decoder. */
+static size_t
+base64_decode (pgpmime_context_t ctx, char *buffer, size_t length)
+{
+ int idx = ctx->base64.idx;
+ unsigned char val = ctx->base64.val;
+ int c;
+ char *d, *s;
+ if (ctx->base64.stop_seen)
+ return 0;
+
+ for (s=d=buffer; length; length--, s++)
+ {
+ if (*s == '\n' || *s == ' ' || *s == '\r' || *s == '\t')
+ continue;
+ if (*s == '=')
+ {
+ /* Pad character: stop */
+ if (idx == 1)
+ *d++ = val;
+ ctx->base64.stop_seen = 1;
+ break;
+ }
+
+ if ((c = asctobin[*(unsigned char *)s]) == 255)
+ {
+ if (!ctx->base64.invalid_encoding)
+ log_debug ("%s: invalid base64 character %02X at pos %d skipped\n",
+ __func__, *(unsigned char*)s, (int)(s-buffer));
+ ctx->base64.invalid_encoding = 1;
+ continue;
+ }
+
+ switch (idx)
+ {
+ case 0:
+ val = c << 2;
+ break;
+ case 1:
+ val |= (c>>4)&3;
+ *d++ = val;
+ val = (c<<4)&0xf0;
+ break;
+ case 2:
+ val |= (c>>2)&15;
+ *d++ = val;
+ val = (c<<6)&0xc0;
+ break;
+ case 3:
+ val |= c&0x3f;
+ *d++ = val;
+ break;
+ }
+ idx = (idx+1) % 4;
+ }
+
+
+ ctx->base64.idx = idx;
+ ctx->base64.val = val;
+ return d - buffer;
+}
+
+
+
/* Print the message event EVENT. */
static void
debug_message_event (pgpmime_context_t ctx, rfc822parse_event_t event)
@@ -136,6 +251,7 @@
message_cb (void *opaque, rfc822parse_event_t event, rfc822parse_t msg)
{
pgpmime_context_t ctx = opaque;
+ HRESULT hr;
debug_message_event (ctx, event);
if (event == RFC822PARSE_T2BODY)
@@ -144,6 +260,7 @@
const char *s1, *s2;
size_t off;
char *p;
+ int is_text = 0;
field = rfc822parse_parse_field (msg, "Content-Type", -1);
if (field)
@@ -156,33 +273,117 @@
if (!strcmp (s1, "multipart"))
{
- if (!strcmp (s2, "signed"))
- ;
- else if (!strcmp (s2, "encrypted"))
- ;
+ /* We don't care about the top level multipart layer
+ but wait until it comes to the actual parts which
+ then will get stored as attachments.
+
+ For now encapsulated signed or encrypted
+ containers are not processed in a special way as
+ they should. */
}
else if (!strcmp (s1, "text"))
{
- if (!ctx->body)
- {
- if (!gpgme_data_new (&ctx->body))
- ctx->collect_body = 1;
- }
+ is_text = 1;
}
+ else /* Other type. */
+ {
+ ctx->collect_attachment = 1;
+ }
+
}
rfc822parse_release_field (field);
}
+ else
+ {
+ /* No content-type at all indicates text/plain. */
+ is_text = 1;
+ }
ctx->in_data = 1;
+ /* Need to 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;
+ ctx->base64.idx = 0;
+ ctx->base64.val = 0;
+ ctx->base64.stop_seen = 0;
+ ctx->base64.invalid_encoding = 0;
+ }
free (p);
}
+
+ /* If this is a text part, decide whether we treat it as our body. */
+ if (is_text)
+ {
+ /* If this is the first text part at all we will
+ start to collect it and use it later as the
+ regular body. An initialized ctx->BODY is an
+ indication that this is not the first text part -
+ we treat such a part like any other
+ attachment. */
+ if (!ctx->body)
+ {
+ if (!gpgme_data_new (&ctx->body))
+ ctx->collect_body = 1;
+ }
+ else
+ ctx->collect_attachment = 1;
+ }
+
+ /* Now that if we have an attachment prepare for writing it out. */
+ if (ctx->collect_attachment)
+ {
+ p = NULL;
+ field = rfc822parse_parse_field (msg, "Content-Disposition", -1);
+ if (field)
+ {
+ s1 = rfc822parse_query_parameter (field, "filename", 0);
+ if (s1)
+ p = xstrdup (s1);
+ rfc822parse_release_field (field);
+ }
+ if (!p)
+ {
+ p = xmalloc (50);
+ snprintf (p, 49, "unnamed-%d.dat", ctx->part_counter);
+ }
+ if (ctx->outstream)
+ {
+ IStream_Release (ctx->outstream);
+ ctx->outstream = NULL;
+ }
+ tryagain:
+ xfree (ctx->filename);
+ ctx->filename = get_save_filename (ctx->hwnd, p);
+ if (!ctx->filename)
+ ctx->collect_attachment = 0; /* User das not want to save it. */
+ else
+ {
+ hr = OpenStreamOnFile (MAPIAllocateBuffer, MAPIFreeBuffer,
+ (STGM_CREATE | STGM_READWRITE),
+ ctx->filename, NULL, &ctx->outstream);
+ if (FAILED (hr))
+ {
+ log_error ("%s:%s: can't create file `%s': hr=%#lx\n",
+ __FILE__, __func__, ctx->filename, hr);
+ MessageBox (ctx->hwnd, "Error creating file\n"
+ "Please select anther one",
+ "I/O-Error", MB_ICONERROR|MB_OK);
+ goto tryagain;
+ }
+ log_debug ("%s:%s: writing attachment to `%s'\n",
+ __FILE__, __func__, ctx->filename);
+ }
+ xfree (p);
+ }
}
else if (event == RFC822PARSE_LEVEL_DOWN)
{
@@ -203,10 +404,19 @@
{
ctx->in_data = 0;
ctx->collect_body = 0;
+ ctx->collect_attachment = 0;
+ xfree (ctx->filename);
+ ctx->filename = NULL;
+ if (ctx->outstream)
+ {
+ IStream_Commit (ctx->outstream, 0);
+ IStream_Release (ctx->outstream);
+ ctx->outstream = NULL;
+ }
}
else if (event == RFC822PARSE_BEGIN_HEADER)
{
-
+ ctx->part_counter++;
}
return 0;
@@ -219,12 +429,12 @@
{
pgpmime_context_t ctx = handle;
const char *s;
- size_t n, pos;
+ size_t nleft, pos, len;
s = buffer;
pos = ctx->linebufpos;
- n = size;
- for (; n ; n--, s++)
+ nleft = size;
+ for (; nleft ; nleft--, s++)
{
if (pos >= ctx->linebufsize)
{
@@ -250,17 +460,57 @@
if (ctx->in_data && ctx->collect_body && ctx->body)
{
- if (ctx->collect_body == 1)
+ /* We are inside the body of the message. Save it away
+ to a gpgme data object. Note that this gets only
+ used for the first text part. */
+ if (ctx->collect_body == 1) /* Need to skip the first line. */
ctx->collect_body = 2;
else
{
if (ctx->is_qp_encoded)
- pos = qp_decode (ctx->linebuf, pos);
- gpgme_data_write (ctx->body, ctx->linebuf, pos);
- gpgme_data_write (ctx->body, "\r\n", 2);
+ len = qp_decode (ctx->linebuf, pos);
+ else if (ctx->is_base64_encoded)
+ len = base64_decode (ctx, ctx->linebuf, pos);
+ else
+ len = pos;
+ if (len)
+ gpgme_data_write (ctx->body, ctx->linebuf, len);
+ if (!ctx->is_base64_encoded)
+ gpgme_data_write (ctx->body, "\r\n", 2);
}
}
+ else if (ctx->in_data && ctx->collect_attachment)
+ {
+ /* We are inside of an attachment part. Write it out. */
+ if (ctx->collect_attachment == 1) /* Skip the first line. */
+ ctx->collect_attachment = 2;
+ else if (ctx->outstream)
+ {
+ HRESULT hr = 0;
+ if (ctx->is_qp_encoded)
+ len = qp_decode (ctx->linebuf, pos);
+ else if (ctx->is_base64_encoded)
+ len = base64_decode (ctx, ctx->linebuf, pos);
+ else
+ len = pos;
+ if (len)
+ hr = IStream_Write (ctx->outstream, ctx->linebuf,
+ len, NULL);
+ if (!hr && !ctx->is_base64_encoded)
+ hr = IStream_Write (ctx->outstream, "\r\n", 2, NULL);
+ if (hr)
+ {
+ log_debug ("%s:%s: Write failed: hr=%#lx",
+ __FILE__, __func__, hr);
+ MessageBox (ctx->hwnd, "Error writing file",
+ "I/O-Error", MB_ICONERROR|MB_OK);
+ ctx->parser_error = 1;
+ return 0; /* Error. */
+ }
+ }
+ }
+
/* Continue with next line. */
pos = 0;
}
@@ -275,10 +525,11 @@
multipart/mixed) and allow saving of all attachments. On success a
newly allocated body will be stored at BODY. If ATTESTATION is not
NULL a text with the result of the signature verification will get
- printed to it. */
+ printed to it. HWND is the window to be used for message box and
+ such. */
int
pgpmime_decrypt (LPSTREAM instream, int ttl, char **body,
- gpgme_data_t attestation)
+ gpgme_data_t attestation, HWND hwnd)
{
gpg_error_t err;
struct gpgme_data_cbs cbs;
@@ -292,6 +543,7 @@
ctx = xcalloc (1, sizeof *ctx + LINEBUFSIZE);
ctx->linebufsize = LINEBUFSIZE;
+ ctx->hwnd = hwnd;
ctx->msg = rfc822parse_open (message_cb, ctx);
if (!ctx->msg)
@@ -306,7 +558,7 @@
goto leave;
err = op_decrypt_stream_to_gpgme (instream, plaintext, ttl,
- NULL, NULL);
+ NULL, attestation);
if (!err && (ctx->parser_error || ctx->line_too_long))
err = gpg_error (GPG_ERR_GENERAL);
@@ -326,11 +578,20 @@
}
leave:
- rfc822parse_close (ctx->msg);
if (plaintext)
gpgme_data_release (plaintext);
- if (ctx && ctx->body)
- gpgme_data_release (ctx->body);
- xfree (ctx);
+ if (ctx)
+ {
+ if (ctx->outstream)
+ {
+ IStream_Revert (ctx->outstream);
+ IStream_Release (ctx->outstream);
+ }
+ rfc822parse_close (ctx->msg);
+ if (ctx->body)
+ gpgme_data_release (ctx->body);
+ xfree (ctx->filename);
+ xfree (ctx);
+ }
return err;
}
Modified: trunk/src/pgpmime.h
===================================================================
--- trunk/src/pgpmime.h 2005-09-21 06:40:51 UTC (rev 103)
+++ trunk/src/pgpmime.h 2005-09-22 16:29:19 UTC (rev 104)
@@ -29,7 +29,7 @@
#endif
int pgpmime_decrypt (LPSTREAM instream, int ttl, char **body,
- gpgme_data_t attestation);
+ gpgme_data_t attestation, HWND hwnd);
Modified: trunk/src/rfc822parse.c
===================================================================
--- trunk/src/rfc822parse.c 2005-09-21 06:40:51 UTC (rev 103)
+++ trunk/src/rfc822parse.c 2005-09-22 16:29:19 UTC (rev 104)
@@ -757,7 +757,8 @@
static const char specials[] = "<>@.,;:\\[]\"()";
static const char specials2[] = "<>@.,;:";
static const char tspecials[] = "/?=<>@,;:\\[]\"()";
- static const char tspecials2[] = "/?=<>@.,;:";
+ static const char tspecials2[] = "/?=<>@.,;:"; /* FIXME: really
+ include '.'?*/
static struct
{
const unsigned char *name;
@@ -765,6 +766,7 @@
} tspecial_header[] = {
{ "Content-Type", 12},
{ "Content-Transfer-Encoding", 25},
+ { "Content-Disposition", 19},
{ NULL, 0}
};
const char *delimiters;
More information about the Gnupg-commits
mailing list