[gmime] replaced GMimeSession with a simpler mechanism



commit 3e1fd5105f8a8d8503d38f693940aea71de0144d
Author: Jeffrey Stedfast <fejj gnome org>
Date:   Sun Apr 26 14:28:44 2009 -0400

    replaced GMimeSession with a simpler mechanism
    
    2009-04-26  Jeffrey Stedfast  <fejj novell com>
    
    	* gmime/gmime-session*.[c,h]: Removed.
    
    	* gmime/gmime-stream-pipe.[c,h]: New stream for pipes (where
    	seeking isn't allowed). Needed by GMimeGpgContext.
    
    	* gmime/gmime-gpg-context.c: Updated to use the new request_passwd
    	callback function instead of the GMimeSession.
    	(g_mime_gpg_context_set_auto_key_retrieve): New function for
    	disabling the auto-key-retrieve functionality of gpg.
    	(g_mime_gpg_context_get_auto_key_retrieve): New function to get
    	the state of auto-key-retrieve enabledness.
    
    	* gmime/gmime-cipher-context.[c,h]: No longer references a
    	GMimeSession. Instead, we now have a GMimePasswordRequestFunc used
    	for prompting the user.
---
 ChangeLog                         |   18 ++
 docs/reference/gmime-docs.sgml    |   10 +-
 docs/reference/gmime-sections.txt |   64 +++-----
 docs/reference/gmime.hierarchy    |    3 +-
 docs/reference/gmime.types        |   38 ----
 examples/basic-example.c          |   76 ++-------
 gmime/Makefile.am                 |    6 +-
 gmime/gmime-cipher-context.c      |   40 ++++-
 gmime/gmime-cipher-context.h      |   27 +++-
 gmime/gmime-gpg-context.c         |  188 ++++++++++----------
 gmime/gmime-gpg-context.h         |    6 +-
 gmime/gmime-session-simple.c      |  204 ---------------------
 gmime/gmime-session-simple.h      |   81 ---------
 gmime/gmime-session.c             |  189 --------------------
 gmime/gmime-session.h             |   83 ---------
 gmime/gmime-stream-fs.c           |   10 +-
 gmime/gmime-stream-pipe.c         |  352 +++++++++++++++++++++++++++++++++++++
 gmime/gmime-stream-pipe.h         |   71 ++++++++
 gmime/gmime.h                     |    3 +-
 tests/test-pgp.c                  |   74 +-------
 tests/test-pgpmime.c              |   73 +-------
 21 files changed, 655 insertions(+), 961 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index e886da3..cbf0c4b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,23 @@
 2009-04-26  Jeffrey Stedfast  <fejj novell com>
 
+	* gmime/gmime-session*.[c,h]: Removed.
+
+	* gmime/gmime-stream-pipe.[c,h]: New stream for pipes (where
+	seeking isn't allowed). Needed by GMimeGpgContext.
+
+	* gmime/gmime-gpg-context.c: Updated to use the new request_passwd
+	callback function instead of the GMimeSession.
+	(g_mime_gpg_context_set_auto_key_retrieve): New function for
+	disabling the auto-key-retrieve functionality of gpg.
+	(g_mime_gpg_context_get_auto_key_retrieve): New function to get
+	the state of auto-key-retrieve enabledness.
+
+	* gmime/gmime-cipher-context.[c,h]: No longer references a
+	GMimeSession. Instead, we now have a GMimePasswordRequestFunc used
+	for prompting the user.
+
+2009-04-26  Jeffrey Stedfast  <fejj novell com>
+
 	* gmime/gmime-multipart-encrypted.c: Removed stub virtual method
 	overloads that did nothing but call the base class'
 	implementation.
diff --git a/docs/reference/gmime-docs.sgml b/docs/reference/gmime-docs.sgml
index 3086580..2877754 100644
--- a/docs/reference/gmime-docs.sgml
+++ b/docs/reference/gmime-docs.sgml
@@ -2,8 +2,6 @@
 <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" 
                "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"; [
 <!ENTITY gmime-Init SYSTEM "xml/gmime.xml">
-<!ENTITY GMimeSession SYSTEM "xml/gmime-session.xml">
-<!ENTITY GMimeSessionSimple SYSTEM "xml/gmime-session-simple.xml">
 <!ENTITY GMimeParam SYSTEM "xml/gmime-param.xml">
 <!ENTITY GMimeHeader SYSTEM "xml/gmime-header.xml">
 <!ENTITY GMimeContentType SYSTEM "xml/gmime-content-type.xml">
@@ -35,6 +33,7 @@
 <!ENTITY GMimeStreamMem SYSTEM "xml/gmime-stream-mem.xml">
 <!ENTITY GMimeStreamMmap SYSTEM "xml/gmime-stream-mmap.xml">
 <!ENTITY GMimeStreamNull SYSTEM "xml/gmime-stream-null.xml">
+<!ENTITY GMimeStreamPipe SYSTEM "xml/gmime-stream-pipe.xml">
 <!ENTITY GMimeStreamFilter SYSTEM "xml/gmime-stream-filter.xml">
 <!ENTITY GMimeFilter SYSTEM "xml/gmime-filter.xml">
 <!ENTITY GMimeFilterBasic SYSTEM "xml/gmime-filter-basic.xml">
@@ -183,6 +182,7 @@ string utilities, file utilities, a main loop abstraction, and so on.
       &GMimeStreamNull;
       &GMimeStreamFilter;
       &GMimeStreamBuffer;
+      &GMimeStreamPipe;
       &GMimeStreamCat;
     </chapter>
 
@@ -246,11 +246,5 @@ string utilities, file utilities, a main loop abstraction, and so on.
       &GMimeCipherContext;
       &GMimeGpgContext;
     </chapter>
-
-    <chapter id="Sessions">
-      <title>Sessions</title>
-      &GMimeSession;
-      &GMimeSessionSimple;
-    </chapter>
   </part>
 </book>
diff --git a/docs/reference/gmime-sections.txt b/docs/reference/gmime-sections.txt
index c2db0f2..8074808 100644
--- a/docs/reference/gmime-sections.txt
+++ b/docs/reference/gmime-sections.txt
@@ -19,46 +19,6 @@ GMIME_ERROR_IS_SYSTEM
 </SECTION>
 
 <SECTION>
-<FILE>gmime-session</FILE>
-GMimeSession
-g_mime_session_request_passwd
-g_mime_session_forget_passwd
-g_mime_session_is_online
-
-<SUBSECTION Private>
-g_mime_session_get_type
-
-<SUBSECTION Standard>
-GMimeSessionClass
-GMIME_TYPE_SESSION
-GMIME_SESSION
-GMIME_IS_SESSION
-GMIME_SESSION_CLASS
-GMIME_IS_SESSION_CLASS
-GMIME_SESSION_GET_CLASS
-</SECTION>
-
-<SECTION>
-<FILE>gmime-session-simple</FILE>
-GMimeSessionSimple
-g_mime_session_simple_set_request_passwd
-g_mime_session_simple_set_forget_passwd
-g_mime_session_simple_set_is_online
-
-<SUBSECTION Private>
-g_mime_session_simple_get_type
-
-<SUBSECTION Standard>
-GMimeSessionSimpleClass
-GMIME_TYPE_SESSION_SIMPLE
-GMIME_SESSION_SIMPLE
-GMIME_IS_SESSION_SIMPLE
-GMIME_SESSION_SIMPLE_CLASS
-GMIME_IS_SESSION_SIMPLE_CLASS
-GMIME_SESSION_SIMPLE_GET_CLASS
-</SECTION>
-
-<SECTION>
 <FILE>gmime-stream</FILE>
 GMimeSeekWhence
 GMimeStreamIOVector
@@ -237,6 +197,26 @@ GMIME_STREAM_NULL_GET_CLASS
 </SECTION>
 
 <SECTION>
+<FILE>gmime-stream-pipe</FILE>
+GMimeStreamPipe
+g_mime_stream_pipe_new
+g_mime_stream_pipe_get_owner
+g_mime_stream_pipe_set_owner
+
+<SUBSECTION Private>
+g_mime_stream_pipe_get_type
+
+<SUBSECTION Standard>
+GMimeStreamPipeClass
+GMIME_TYPE_STREAM_PIPE
+GMIME_STREAM_PIPE
+GMIME_IS_STREAM_PIPE
+GMIME_STREAM_PIPE_CLASS
+GMIME_IS_STREAM_PIPE_CLASS
+GMIME_STREAM_PIPE_GET_CLASS
+</SECTION>
+
+<SECTION>
 <FILE>gmime-stream-filter</FILE>
 GMimeStreamFilter
 g_mime_stream_filter_new
@@ -1128,6 +1108,7 @@ g_mime_iconv_locale_to_utf8_length
 
 <SECTION>
 <FILE>gmime-cipher-context</FILE>
+GMimePasswordRequestFunc
 GMimeCipherHash
 GMimeCipherContext
 GMimeSignatureValidity
@@ -1136,6 +1117,7 @@ GMimeSignerStatus
 GMimeSignerTrust
 GMimeSignerError
 GMimeSigner
+g_mime_cipher_context_set_request_password
 g_mime_cipher_context_hash_id
 g_mime_cipher_context_hash_name
 g_mime_cipher_context_sign
@@ -1191,6 +1173,8 @@ GMimeGpgContext
 g_mime_gpg_context_new
 g_mime_gpg_context_get_always_trust
 g_mime_gpg_context_set_always_trust
+g_mime_gpg_context_get_auto_key_retrieve
+g_mime_gpg_context_set_auto_key_retrieve
 
 <SUBSECTION Private>
 g_mime_gpg_context_get_type
diff --git a/docs/reference/gmime.hierarchy b/docs/reference/gmime.hierarchy
index 6b97aeb..6776299 100644
--- a/docs/reference/gmime.hierarchy
+++ b/docs/reference/gmime.hierarchy
@@ -30,8 +30,6 @@ GObject
     GMimeFilterWindows
     GMimeFilterYenc
   GMimeParser
-  GMimeSession
-    GMimeSessionSimple
   GMimeStream
     GMimeStreamBuffer
     GMimeStreamCat
@@ -41,5 +39,6 @@ GObject
     GMimeStreamMem
     GMimeStreamMmap
     GMimeStreamNull
+    GMimeStreamPipe
 GInterface
   GTypePlugin
diff --git a/docs/reference/gmime.types b/docs/reference/gmime.types
deleted file mode 100644
index 8dbeb16..0000000
--- a/docs/reference/gmime.types
+++ /dev/null
@@ -1,38 +0,0 @@
-#include <gmime/gmime.h>
-
-g_mime_cipher_context_get_type
-g_mime_data_wrapper_get_type
-g_mime_filter_basic_get_type
-g_mime_filter_best_get_type
-g_mime_filter_charset_get_type
-g_mime_filter_crlf_get_type
-g_mime_filter_enriched_get_type
-g_mime_filter_from_get_type
-g_mime_filter_gzip_get_type
-g_mime_filter_get_type
-g_mime_filter_html_get_type
-g_mime_filter_md5_get_type
-g_mime_filter_strip_get_type
-g_mime_filter_windows_get_type
-g_mime_filter_yenc_get_type
-g_mime_gpg_context_get_type
-g_mime_message_get_type
-g_mime_message_part_get_type
-g_mime_message_partial_get_type
-g_mime_multipart_encrypted_get_type
-g_mime_multipart_get_type
-g_mime_multipart_signed_get_type
-g_mime_object_get_type
-g_mime_parser_get_type
-g_mime_part_get_type
-g_mime_session_get_type
-g_mime_session_simple_get_type
-g_mime_stream_buffer_get_type
-g_mime_stream_cat_get_type
-g_mime_stream_file_get_type
-g_mime_stream_filter_get_type
-g_mime_stream_fs_get_type
-g_mime_stream_get_type
-g_mime_stream_mem_get_type
-g_mime_stream_mmap_get_type
-g_mime_stream_null_get_type
diff --git a/examples/basic-example.c b/examples/basic-example.c
index 5d2d13e..6f21806 100644
--- a/examples/basic-example.c
+++ b/examples/basic-example.c
@@ -40,68 +40,16 @@
 static const char *path = "/usr/bin/gpg";
 static const char *passphrase = "no.secret";
 
-typedef struct _ExampleSession ExampleSession;
-typedef struct _ExampleSessionClass ExampleSessionClass;
-
-struct _ExampleSession {
-	GMimeSession parent_object;
-	
-};
-
-struct _ExampleSessionClass {
-	GMimeSessionClass parent_class;
-	
-};
-
-static void example_session_class_init (ExampleSessionClass *klass);
-
-static char *request_passwd (GMimeSession *session, const char *prompt,
-			     gboolean secret, const char *item,
-			     GError **err);
-
-
-static GMimeSessionClass *parent_class = NULL;
-
-
-static GType
-example_session_get_type (void)
+static gboolean
+request_passwd (GMimeCipherContext *ctx, const char *user_id, const char *prompt_ctx, gboolean reprompt, GMimeStream *response, GError **err)
 {
-	static GType type = 0;
-	
-	if (!type) {
-		static const GTypeInfo info = {
-			sizeof (ExampleSessionClass),
-			NULL, /* base_class_init */
-			NULL, /* base_class_finalize */
-			(GClassInitFunc) example_session_class_init,
-			NULL, /* class_finalize */
-			NULL, /* class_data */
-			sizeof (ExampleSession),
-			0,    /* n_preallocs */
-			NULL, /* object_init */
-		};
-		
-		type = g_type_register_static (GMIME_TYPE_SESSION, "ExampleSession", &info, 0);
+	if (g_mime_stream_write_string (response, passphrase) == -1 ||
+	    g_mime_stream_write (response, "\n", 1) == -1) {
+		g_set_error (err, GMIME_ERROR, errno, "%s", g_strerror (errno));
+		return FALSE;
 	}
 	
-	return type;
-}
-
-
-static void
-example_session_class_init (ExampleSessionClass *klass)
-{
-	GMimeSessionClass *session_class = GMIME_SESSION_CLASS (klass);
-	
-	parent_class = g_type_class_ref (GMIME_TYPE_SESSION);
-	
-	session_class->request_passwd = request_passwd;
-}
-
-static char *
-request_passwd (GMimeSession *session, const char *prompt, gboolean secret, const char *item, GError **err)
-{
-	return g_strdup (passphrase);
+	return TRUE;
 }
 #endif /* ! G_OS_WIN32 */
 
@@ -337,7 +285,6 @@ remove_a_mime_part (GMimeMessage *message)
 int main (int argc, char **argv)
 {
 #ifndef G_OS_WIN32
-	GMimeSession *session;
 	GMimeCipherContext *ctx;
 #endif
 	GMimeMessage *message;
@@ -363,10 +310,11 @@ int main (int argc, char **argv)
 	count_parts_in_message (message);
 	
 #ifndef G_OS_WIN32
-	/* create our cipher context (and session - which is used by the context to query the user) */
-	session = g_object_new (example_session_get_type (), NULL);
-	ctx = g_mime_gpg_context_new (session, path);
-	g_object_unref (session);
+	/* create our cipher context */
+	ctx = g_mime_gpg_context_new (request_passwd, path);
+	
+	/* don't allow auto key-retrival */
+	g_mime_gpg_context_set_auto_key_retrieve ((GMimeGpgContext *) ctx, FALSE);
 	
 	/* set the always_trust flag so that gpg will be spawned with `gpg --always-trust` */
 	g_mime_gpg_context_set_always_trust ((GMimeGpgContext *) ctx, TRUE);
diff --git a/gmime/Makefile.am b/gmime/Makefile.am
index f8037dd..2939637 100644
--- a/gmime/Makefile.am
+++ b/gmime/Makefile.am
@@ -54,8 +54,6 @@ libgmime_2_6_la_SOURCES = 		\
 	gmime-parse-utils.c		\
 	gmime-parser.c			\
 	gmime-part.c			\
-	gmime-session.c			\
-	gmime-session-simple.c		\
 	gmime-stream.c			\
 	gmime-stream-buffer.c		\
 	gmime-stream-cat.c		\
@@ -65,6 +63,7 @@ libgmime_2_6_la_SOURCES = 		\
 	gmime-stream-mem.c		\
 	gmime-stream-mmap.c		\
 	gmime-stream-null.c		\
+	gmime-stream-pipe.c		\
 	gmime-utils.c			\
 	internet-address.c
 
@@ -104,8 +103,6 @@ gmimeinclude_HEADERS = 			\
 	gmime-param.h			\
 	gmime-parser.h			\
 	gmime-part.h			\
-	gmime-session.h			\
-	gmime-session-simple.h		\
 	gmime-stream.h			\
 	gmime-stream-buffer.h		\
 	gmime-stream-cat.h		\
@@ -115,6 +112,7 @@ gmimeinclude_HEADERS = 			\
 	gmime-stream-mem.h		\
 	gmime-stream-mmap.h		\
 	gmime-stream-null.h		\
+	gmime-stream-pipe.h		\
 	gmime-utils.h			\
 	internet-address.h
 
diff --git a/gmime/gmime-cipher-context.c b/gmime/gmime-cipher-context.c
index ff98797..fad29dc 100644
--- a/gmime/gmime-cipher-context.c
+++ b/gmime/gmime-cipher-context.c
@@ -119,7 +119,7 @@ g_mime_cipher_context_class_init (GMimeCipherContextClass *klass)
 static void
 g_mime_cipher_context_init (GMimeCipherContext *ctx, GMimeCipherContextClass *klass)
 {
-	ctx->session = NULL;
+	ctx->request_passwd = NULL;
 }
 
 static void
@@ -127,9 +127,6 @@ g_mime_cipher_context_finalize (GObject *object)
 {
 	GMimeCipherContext *ctx = (GMimeCipherContext *) object;
 	
-	if (ctx->session)
-		g_object_unref (ctx->session);
-	
 	G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
@@ -142,6 +139,41 @@ cipher_hash_id (GMimeCipherContext *ctx, const char *hash)
 
 
 /**
+ * g_mime_cipher_context_set_request_password:
+ * @ctx: a #GMimeCipherContext
+ * @request_passwd: a callback function for requesting a password
+ *
+ * Sets the function used by the @ctx for requesting a password from
+ * the user.
+ **/
+void
+g_mime_cipher_context_set_request_password (GMimeCipherContext *ctx, GMimePasswordRequestFunc request_passwd)
+{
+	g_return_if_fail (GMIME_IS_CIPHER_CONTEXT (ctx));
+	
+	ctx->request_passwd = request_passwd;
+}
+
+
+/**
+ * g_mime_cipher_context_get_request_password:
+ * @ctx: a #GMimeCipherContext
+ *
+ * Gets the function used by the @ctx for requesting a password from
+ * the user.
+ *
+ * Returns: a #GMimePasswordRequestFunc or %NULL if not set.
+ **/
+GMimePasswordRequestFunc
+g_mime_cipher_context_get_request_password (GMimeCipherContext *ctx)
+{
+	g_return_val_if_fail (GMIME_IS_CIPHER_CONTEXT (ctx), NULL);
+	
+	return ctx->request_passwd;
+}
+
+
+/**
  * g_mime_cipher_context_hash_id:
  * @ctx: a #GMimeCipherContext
  * @hash: hash name
diff --git a/gmime/gmime-cipher-context.h b/gmime/gmime-cipher-context.h
index ae07f5d..a76a740 100644
--- a/gmime/gmime-cipher-context.h
+++ b/gmime/gmime-cipher-context.h
@@ -28,7 +28,6 @@
 #include <time.h>
 
 #include <gmime/gmime-stream.h>
-#include <gmime/gmime-session.h>
 
 G_BEGIN_DECLS
 
@@ -47,6 +46,24 @@ typedef struct _GMimeSignatureValidity GMimeSignatureValidity;
 
 
 /**
+ * GMimePasswordRequestFunc:
+ * @ctx: the #GMimeCipherContext making the request
+ * @user_id: the user_id of the password being requested
+ * @prompt_ctx: a string containing some helpful context for the prompt
+ * @reprompt: %TRUE if this password request is a reprompt due to a previously bad password response
+ * @response: a stream for the application to write the password to (followed by a newline '\n' character)
+ * @err: a #GError for the callback to set if an error occurs
+ *
+ * A password request callback allowing a #GMimeCipherContext to
+ * prompt the user for a password for a given key.
+ *
+ * Returns: %TRUE on success or %FALSE on error.
+ **/
+typedef gboolean (* GMimePasswordRequestFunc) (GMimeCipherContext *ctx, const char *user_id, const char *prompt_ctx,
+					       gboolean reprompt, GMimeStream *response, GError **err);
+
+
+/**
  * GMimeCipherHash:
  * @GMIME_CIPHER_HASH_DEFAULT: The default hash algorithm.
  * @GMIME_CIPHER_HASH_MD2: The MD2 hash algorithm.
@@ -80,7 +97,7 @@ typedef enum {
 /**
  * GMimeCipherContext:
  * @parent_object: parent #GObject
- * @session: a #GMimeSession
+ * @request_passwd: a callback for requesting a password
  * @sign_protocol: signature protocol (must be set by subclass)
  * @encrypt_protocol: encryption protocol (must be set by subclass)
  * @key_protocol: key exchange protocol (must be set by subclass)
@@ -90,9 +107,9 @@ typedef enum {
 struct _GMimeCipherContext {
 	GObject parent_object;
 	
-	GMimeSession *session;
+	GMimePasswordRequestFunc request_passwd;
 	
-	/* these must be set by the subclass */
+	/* these must be set by the subclass in the instance_init() */
 	const char *sign_protocol;
 	const char *encrypt_protocol;
 	const char *key_protocol;
@@ -131,6 +148,8 @@ struct _GMimeCipherContextClass {
 
 GType g_mime_cipher_context_get_type (void);
 
+void g_mime_cipher_context_set_request_password (GMimeCipherContext *ctx, GMimePasswordRequestFunc request_passwd);
+
 /* hash routines */
 GMimeCipherHash      g_mime_cipher_context_hash_id (GMimeCipherContext *ctx, const char *hash);
 
diff --git a/gmime/gmime-gpg-context.c b/gmime/gmime-gpg-context.c
index 2aa4012..8220761 100644
--- a/gmime/gmime-gpg-context.c
+++ b/gmime/gmime-gpg-context.c
@@ -44,6 +44,7 @@
 #include "gmime-gpg-context.h"
 #include "gmime-filter-charset.h"
 #include "gmime-stream-filter.h"
+#include "gmime-stream-pipe.h"
 #include "gmime-stream-mem.h"
 #include "gmime-stream-fs.h"
 #include "gmime-charset.h"
@@ -153,8 +154,9 @@ g_mime_gpg_context_init (GMimeGpgContext *ctx, GMimeGpgContextClass *klass)
 {
 	GMimeCipherContext *cipher = (GMimeCipherContext *) ctx;
 	
-	ctx->path = NULL;
+	ctx->auto_key_retrieve = FALSE;
 	ctx->always_trust = FALSE;
+	ctx->path = NULL;
 	
 	cipher->sign_protocol = "application/pgp-signature";
 	cipher->encrypt_protocol = "application/pgp-encrypted";
@@ -246,11 +248,10 @@ enum _GpgCtxMode {
 
 struct _GpgCtx {
 	enum _GpgCtxMode mode;
-	GMimeSession *session;
 	GHashTable *userid_hint;
+	GMimeGpgContext *ctx;
 	pid_t pid;
 	
-	char *path;
 	char *userid;
 	char *sigfile;
 	GPtrArray *recipients;
@@ -268,7 +269,6 @@ struct _GpgCtx {
 	guint statusleft;
 	
 	char *need_id;
-	char *passwd;
 	
 	GMimeStream *istream;
 	GMimeStream *ostream;
@@ -290,7 +290,6 @@ struct _GpgCtx {
 	unsigned int always_trust:1;
 	unsigned int armor:1;
 	unsigned int need_passwd:1;
-	unsigned int send_passwd:1;
 	
 	unsigned int bad_passwds:2;
 	
@@ -301,11 +300,11 @@ struct _GpgCtx {
 	unsigned int nopubkey:1;
 	unsigned int nodata:1;
 	
-	unsigned int padding:14;
+	unsigned int padding:15;
 };
 
 static struct _GpgCtx *
-gpg_ctx_new (GMimeSession *session, const char *path)
+gpg_ctx_new (GMimeGpgContext *ctx)
 {
 	struct _GpgCtx *gpg;
 	const char *charset;
@@ -313,8 +312,7 @@ gpg_ctx_new (GMimeSession *session, const char *path)
 	
 	gpg = g_slice_new (struct _GpgCtx);
 	gpg->mode = GPG_CTX_MODE_SIGN;
-	gpg->session = session;
-	g_object_ref (session);
+	gpg->ctx = ctx;
 	gpg->userid_hint = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
 	gpg->complete = FALSE;
 	gpg->seen_eof1 = TRUE;
@@ -324,7 +322,6 @@ gpg_ctx_new (GMimeSession *session, const char *path)
 	gpg->flushed = FALSE;
 	gpg->exited = FALSE;
 	
-	gpg->path = g_strdup (path);
 	gpg->userid = NULL;
 	gpg->sigfile = NULL;
 	gpg->recipients = NULL;
@@ -344,9 +341,7 @@ gpg_ctx_new (GMimeSession *session, const char *path)
 	
 	gpg->bad_passwds = 0;
 	gpg->need_passwd = FALSE;
-	gpg->send_passwd = FALSE;
 	gpg->need_id = NULL;
-	gpg->passwd = NULL;
 	
 	gpg->nodata = FALSE;
 	gpg->badsig = FALSE;
@@ -477,13 +472,8 @@ gpg_ctx_free (struct _GpgCtx *gpg)
 	GMimeSigner *signer, *next;
 	guint i;
 	
-	if (gpg->session)
-		g_object_unref (gpg->session);
-	
 	g_hash_table_destroy (gpg->userid_hint);
 	
-	g_free (gpg->path);
-	
 	g_free (gpg->userid);
 	
 	g_free (gpg->sigfile);
@@ -510,11 +500,6 @@ gpg_ctx_free (struct _GpgCtx *gpg)
 	
 	g_free (gpg->need_id);
 	
-	if (gpg->passwd) {
-		memset (gpg->passwd, 0, strlen (gpg->passwd));
-		g_free (gpg->passwd);
-	}
-	
 	if (gpg->istream)
 		g_object_unref (gpg->istream);
 	
@@ -609,12 +594,12 @@ gpg_ctx_get_argv (struct _GpgCtx *gpg, int status_fd, char **sfd, int passwd_fd,
 		g_ptr_array_add (argv, "-");
 		break;
 	case GPG_CTX_MODE_VERIFY:
-		if (!g_mime_session_is_online (gpg->session)) {
-			/* this is a deprecated flag to gpg since 1.0.7 */
-			/*g_ptr_array_add (argv, "--no-auto-key-retrieve");*/
+		if (!gpg->ctx->auto_key_retrieve) {
+			/* don't allow gpg to fetch keys from a server... */
 			g_ptr_array_add (argv, "--keyserver-options");
 			g_ptr_array_add (argv, "no-auto-key-retrieve");
 		}
+		
 		g_ptr_array_add (argv, "--verify");
 		if (gpg->sigfile)
 			g_ptr_array_add (argv, gpg->sigfile);
@@ -717,7 +702,7 @@ gpg_ctx_op_start (struct _GpgCtx *gpg)
 		}
 		
 		/* run gpg */
-		execvp (gpg->path, (char **) argv->pdata);
+		execvp (gpg->ctx->path, (char **) argv->pdata);
 		_exit (255);
 	} else if (gpg->pid < 0) {
 		g_ptr_array_free (argv, TRUE);
@@ -1012,12 +997,23 @@ gpg_ctx_parse_status (struct _GpgCtx *gpg, GError **err)
 		g_free (gpg->need_id);
 		gpg->need_id = userid;
 	} else if (!strncmp (status, "GET_HIDDEN ", 11)) {
+		GMimeStream *filtered_stream, *passwd;
+		GMimeCipherContext *ctx;
+		GMimeFilter *filter;
+		const char *charset;
 		char *prompt = NULL;
-		char *passwd = NULL;
 		const char *name;
+		gboolean ok;
 		
 		status += 11;
 		
+		ctx = (GMimeCipherContext *) gpg->ctx;
+		if (!ctx->request_passwd) {
+			/* can't ask for a passwd w/o a way to request it from the user... */
+			g_set_error (err, GMIME_ERROR, ECANCELED, _("Canceled."));
+			return -1;
+		}
+		
 		if (!(name = g_hash_table_lookup (gpg->userid_hint, gpg->need_id)))
 			name = gpg->userid;
 		
@@ -1035,39 +1031,41 @@ gpg_ctx_parse_status (struct _GpgCtx *gpg, GError **err)
 			return -1;
 		}
 		
-		if ((passwd = g_mime_session_request_passwd (gpg->session, prompt, TRUE, gpg->need_id, err))) {
-			g_free (prompt);
-			
-			if (!gpg->utf8) {
-				char *locale_passwd;
-				
-				if ((locale_passwd = g_locale_from_utf8 (passwd, -1, &nread, &nwritten, NULL))) {
-					memset (passwd, 0, strlen (passwd));
-					g_free (passwd);
-					passwd = locale_passwd;
-				}
-			}
-			
-			gpg->passwd = g_strdup_printf ("%s\n", passwd);
-			memset (passwd, 0, strlen (passwd));
-			g_free (passwd);
+		/* create a stream for the application to write the passwd to */
+		passwd = g_mime_stream_pipe_new (gpg->passwd_fd);
+		g_mime_stream_pipe_set_owner ((GMimeStreamPipe *) passwd, FALSE);
+		
+		if (!gpg->utf8) {
+			/* we'll need to transcode the UTF-8 password that the application
+			 * will write to our stream into the locale charset used by gpg */
+			filtered_stream = g_mime_stream_filter_new (passwd);
+			g_object_unref (passwd);
 			
-			gpg->send_passwd = TRUE;
-		} else {
-			if (err && *err == NULL)
-				g_set_error (err, GMIME_ERROR, ECANCELED, _("Canceled."));
+			charset = g_mime_locale_charset ();
+			filter = g_mime_filter_charset_new ("UTF-8", charset);
 			
-			g_free (prompt);
+			g_mime_stream_filter_add ((GMimeStreamFilter *) filtered_stream, filter);
+			g_object_unref (filter);
 			
-			return -1;
+			passwd = filtered_stream;
+		}
+		
+		if ((ok = ctx->request_passwd (ctx, name, prompt, gpg->bad_passwds > 0, passwd, err))) {
+			if (g_mime_stream_flush (passwd) == -1) {
+				
+				ok = FALSE;
+			}
 		}
+		g_object_unref (passwd);
+		g_free (prompt);
+		
+		if (!ok)
+			return -1;
 	} else if (!strncmp (status, "GOOD_PASSPHRASE", 15)) {
 		gpg->bad_passwds = 0;
 	} else if (!strncmp (status, "BAD_PASSPHRASE", 14)) {
 		gpg->bad_passwds++;
 		
-		g_mime_session_forget_passwd (gpg->session, gpg->userid, NULL);
-		
 		if (gpg->bad_passwds == 3) {
 			g_set_error (err, GMIME_ERROR, GMIME_ERROR_BAD_PASSWORD,
 				     _("Failed to unlock secret key: 3 bad passphrases given."));
@@ -1241,7 +1239,6 @@ enum {
 	GPG_STDOUT_FD,
 	GPG_STDERR_FD,
 	GPG_STATUS_FD,
-	GPG_PASSWD_FD,
 	GPG_N_FDS
 };
 
@@ -1353,9 +1350,6 @@ gpg_ctx_op_step (struct _GpgCtx *gpg, GError **err)
 	pfds[GPG_STDIN_FD].fd = gpg->stdin_fd;
 	pfds[GPG_STDIN_FD].events = POLLOUT;
 	
-	pfds[GPG_PASSWD_FD].fd = gpg->passwd_fd;
-	pfds[GPG_PASSWD_FD].events = POLLOUT;
-	
 	do {
 		for (n = 0; n < GPG_N_FDS; n++)
 			pfds[n].revents = 0;
@@ -1438,34 +1432,6 @@ gpg_ctx_op_step (struct _GpgCtx *gpg, GError **err)
 		}
 	}
 	
-	if ((pfds[GPG_PASSWD_FD].revents & (POLLOUT | POLLHUP)) && gpg->need_passwd && gpg->send_passwd) {
-		size_t n, nwritten = 0;
-		ssize_t w;
-		
-		d(printf ("sending gpg our passphrase...\n"));
-		
-		/* send the passphrase to gpg */
-		n = strlen (gpg->passwd);
-		do {
-			do {
-				w = write (gpg->passwd_fd, gpg->passwd + nwritten, n - nwritten);
-			} while (w == -1 && (errno == EINTR || errno == EAGAIN));
-			
-			if (w > 0)
-				nwritten += w;
-		} while (nwritten < n && w != -1);
-		
-		/* zero and free our passwd buffer */
-		memset (gpg->passwd, 0, n);
-		g_free (gpg->passwd);
-		gpg->passwd = NULL;
-		
-		if (w == -1)
-			goto exception;
-		
-		gpg->send_passwd = FALSE;
-	}
-	
 	if ((pfds[GPG_STDIN_FD].revents & (POLLOUT | POLLHUP)) && gpg->istream) {
 		char buffer[4096];
 		ssize_t nread;
@@ -1636,7 +1602,7 @@ gpg_sign (GMimeCipherContext *context, const char *userid, GMimeCipherHash hash,
 	GMimeGpgContext *ctx = (GMimeGpgContext *) context;
 	struct _GpgCtx *gpg;
 	
-	gpg = gpg_ctx_new (context->session, ctx->path);
+	gpg = gpg_ctx_new (ctx);
 	gpg_ctx_set_mode (gpg, GPG_CTX_MODE_SIGN);
 	gpg_ctx_set_hash (gpg, hash);
 	gpg_ctx_set_armor (gpg, TRUE);
@@ -1738,7 +1704,7 @@ gpg_verify (GMimeCipherContext *context, GMimeCipherHash hash,
 		}
 	}
 	
-	gpg = gpg_ctx_new (context->session, ctx->path);
+	gpg = gpg_ctx_new (ctx);
 	gpg_ctx_set_mode (gpg, GPG_CTX_MODE_VERIFY);
 	gpg_ctx_set_hash (gpg, hash);
 	gpg_ctx_set_sigfile (gpg, sigfile);
@@ -1810,7 +1776,7 @@ gpg_encrypt (GMimeCipherContext *context, gboolean sign, const char *userid,
 	struct _GpgCtx *gpg;
 	guint i;
 	
-	gpg = gpg_ctx_new (context->session, ctx->path);
+	gpg = gpg_ctx_new (ctx);
 	if (sign)
 		gpg_ctx_set_mode (gpg, GPG_CTX_MODE_SIGN_ENCRYPT);
 	else
@@ -1872,7 +1838,7 @@ gpg_decrypt (GMimeCipherContext *context, GMimeStream *istream,
 	struct _GpgCtx *gpg;
 	int save;
 	
-	gpg = gpg_ctx_new (context->session, ctx->path);
+	gpg = gpg_ctx_new (ctx);
 	gpg_ctx_set_mode (gpg, GPG_CTX_MODE_DECRYPT);
 	gpg_ctx_set_istream (gpg, istream);
 	gpg_ctx_set_ostream (gpg, ostream);
@@ -1939,7 +1905,7 @@ gpg_import_keys (GMimeCipherContext *context, GMimeStream *istream, GError **err
 	GMimeGpgContext *ctx = (GMimeGpgContext *) context;
 	struct _GpgCtx *gpg;
 	
-	gpg = gpg_ctx_new (context->session, ctx->path);
+	gpg = gpg_ctx_new (ctx);
 	gpg_ctx_set_mode (gpg, GPG_CTX_MODE_IMPORT);
 	gpg_ctx_set_istream (gpg, istream);
 	
@@ -1987,7 +1953,7 @@ gpg_export_keys (GMimeCipherContext *context, GPtrArray *keys, GMimeStream *ostr
 	struct _GpgCtx *gpg;
 	guint i;
 	
-	gpg = gpg_ctx_new (context->session, ctx->path);
+	gpg = gpg_ctx_new (ctx);
 	gpg_ctx_set_mode (gpg, GPG_CTX_MODE_EXPORT);
 	gpg_ctx_set_armor (gpg, TRUE);
 	gpg_ctx_set_ostream (gpg, ostream);
@@ -2036,7 +2002,7 @@ gpg_export_keys (GMimeCipherContext *context, GPtrArray *keys, GMimeStream *ostr
 
 /**
  * g_mime_gpg_context_new:
- * @session: a #GMimeSession
+ * @equest_passwd: a #GMimePasswordRequestFunc
  * @path: path to gpg binary
  *
  * Creates a new gpg cipher context object.
@@ -2044,26 +2010,58 @@ gpg_export_keys (GMimeCipherContext *context, GPtrArray *keys, GMimeStream *ostr
  * Returns: a new gpg cipher context object.
  **/
 GMimeCipherContext *
-g_mime_gpg_context_new (GMimeSession *session, const char *path)
+g_mime_gpg_context_new (GMimePasswordRequestFunc request_passwd, const char *path)
 {
 	GMimeCipherContext *cipher;
 	GMimeGpgContext *ctx;
 	
-	g_return_val_if_fail (GMIME_IS_SESSION (session), NULL);
 	g_return_val_if_fail (path != NULL, NULL);
 	
 	ctx = g_object_newv (GMIME_TYPE_GPG_CONTEXT, 0, NULL);
 	ctx->path = g_strdup (path);
 	
 	cipher = (GMimeCipherContext *) ctx;
-	cipher->session = session;
-	g_object_ref (session);
+	cipher->request_passwd = request_passwd;
 	
 	return cipher;
 }
 
 
 /**
+ * g_mime_gpg_context_get_auto_key_retrieve:
+ * @ctx: a #GMimeGpgContext
+ *
+ * Gets the @auto_key_retrieve flag on the gpg context.
+ *
+ * Returns: the @auto_key_retrieve flag on the gpg context.
+ **/
+gboolean
+g_mime_gpg_context_get_auto_key_retrieve (GMimeGpgContext *ctx)
+{
+	g_return_val_if_fail (GMIME_IS_GPG_CONTEXT (ctx), FALSE);
+	
+	return ctx->auto_key_retrieve;
+}
+
+
+/**
+ * g_mime_gpg_context_set_auto_key_retrieve:
+ * @ctx: a #GMimeGpgContext
+ * @auto_key_retrieve: auto-retrieve keys from a keys server
+ *
+ * Sets the @auto_key_retrieve flag on the gpg context which is used
+ * for signature verification.
+ **/
+void
+g_mime_gpg_context_set_auto_key_retrieve (GMimeGpgContext *ctx, gboolean auto_key_retrieve)
+{
+	g_return_if_fail (GMIME_IS_GPG_CONTEXT (ctx));
+	
+	ctx->auto_key_retrieve = auto_key_retrieve;
+}
+
+
+/**
  * g_mime_gpg_context_get_always_trust:
  * @ctx: a #GMimeGpgContext
  *
@@ -2083,7 +2081,7 @@ g_mime_gpg_context_get_always_trust (GMimeGpgContext *ctx)
 /**
  * g_mime_gpg_context_set_always_trust:
  * @ctx: a #GMimeGpgContext
- * @always_trust: always truct flag
+ * @always_trust: always trust flag
  *
  * Sets the @always_trust flag on the gpg context which is used for
  * encryption.
diff --git a/gmime/gmime-gpg-context.h b/gmime/gmime-gpg-context.h
index e75e049..0533ff8 100644
--- a/gmime/gmime-gpg-context.h
+++ b/gmime/gmime-gpg-context.h
@@ -47,6 +47,7 @@ typedef struct _GMimeGpgContextClass GMimeGpgContextClass;
  **/
 struct _GMimeGpgContext {
 	GMimeCipherContext parent_object;
+	gboolean auto_key_retrieve;
 	gboolean always_trust;
 	char *path;
 };
@@ -60,7 +61,10 @@ struct _GMimeGpgContextClass {
 GType g_mime_gpg_context_get_type (void);
 
 
-GMimeCipherContext *g_mime_gpg_context_new (GMimeSession *session, const char *path);
+GMimeCipherContext *g_mime_gpg_context_new (GMimePasswordRequestFunc request_passwd, const char *path);
+
+gboolean g_mime_gpg_context_get_auto_key_retrieve (GMimeGpgContext *ctx);
+void g_mime_gpg_context_set_auto_key_retrieve (GMimeGpgContext *ctx, gboolean auto_key_retrieve);
 
 gboolean g_mime_gpg_context_get_always_trust (GMimeGpgContext *ctx);
 void g_mime_gpg_context_set_always_trust (GMimeGpgContext *ctx, gboolean always_trust);
diff --git a/gmime/gmime-session-simple.c b/gmime/gmime-session-simple.c
deleted file mode 100644
index 3b92e69..0000000
--- a/gmime/gmime-session-simple.c
+++ /dev/null
@@ -1,204 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*  GMime
- *  Copyright (C) 2000-2009 Jeffrey Stedfast
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public License
- *  as published by the Free Software Foundation; either version 2.1
- *  of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free
- *  Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
- *  02110-1301, USA.
- */
-
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "gmime-error.h"
-#include "gmime-session-simple.h"
-
-
-/**
- * SECTION: gmime-session-simple
- * @title: GMimeSessionSimple
- * @short_description: A Simple Session
- * @see_also: #GMimeSession
- *
- * A #GMimeSessionSimple can be used for simple applications that
- * don't care to implement their own #GMimeSession.
- **/
-
-static void g_mime_session_simple_class_init (GMimeSessionSimpleClass *klass);
-static void g_mime_session_simple_init (GMimeSessionSimple *session, GMimeSessionSimpleClass *klass);
-static void g_mime_session_simple_finalize (GObject *object);
-
-static gboolean simple_is_online (GMimeSession *session);
-static char *simple_request_passwd (GMimeSession *session, const char *prompt,
-				    gboolean secret, const char *item,
-				    GError **err);
-static void simple_forget_passwd (GMimeSession *session, const char *item,
-				  GError **err);
-
-
-static GMimeSessionClass *parent_class = NULL;
-
-
-GType
-g_mime_session_simple_get_type (void)
-{
-	static GType type = 0;
-	
-	if (!type) {
-		static const GTypeInfo info = {
-			sizeof (GMimeSessionSimpleClass),
-			NULL, /* base_class_init */
-			NULL, /* base_class_finalize */
-			(GClassInitFunc) g_mime_session_simple_class_init,
-			NULL, /* class_finalize */
-			NULL, /* class_data */
-			sizeof (GMimeSessionSimple),
-			0,    /* n_preallocs */
-			(GInstanceInitFunc) g_mime_session_simple_init,
-		};
-		
-		type = g_type_register_static (GMIME_TYPE_SESSION, "GMimeSessionSimple", &info, 0);
-	}
-	
-	return type;
-}
-
-
-static void
-g_mime_session_simple_class_init (GMimeSessionSimpleClass *klass)
-{
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	GMimeSessionClass *session_class = GMIME_SESSION_CLASS (klass);
-	
-	parent_class = g_type_class_ref (GMIME_TYPE_SESSION);
-	
-	object_class->finalize = g_mime_session_simple_finalize;
-	
-	session_class->is_online = simple_is_online;
-	session_class->request_passwd = simple_request_passwd;
-	session_class->forget_passwd = simple_forget_passwd;
-}
-
-static void
-g_mime_session_simple_init (GMimeSessionSimple *session, GMimeSessionSimpleClass *klass)
-{
-	session->is_online = NULL;
-	session->request_passwd = NULL;
-	session->forget_passwd = NULL;
-}
-
-static void
-g_mime_session_simple_finalize (GObject *object)
-{
-	G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-
-static gboolean
-simple_is_online (GMimeSession *session)
-{
-	GMimeSessionSimple *simple = (GMimeSessionSimple *) session;
-	
-	if (simple->is_online)
-		return simple->is_online (session);
-	
-	return FALSE;
-}
-
-static char *
-simple_request_passwd (GMimeSession *session, const char *prompt,
-		       gboolean secret, const char *item,
-		       GError **err)
-{
-	GMimeSessionSimple *simple = (GMimeSessionSimple *) session;
-	
-	if (simple->request_passwd)
-		return simple->request_passwd (session, prompt, secret, item, err);
-	
-	g_set_error (err, GMIME_ERROR_QUARK, GMIME_ERROR_NOT_SUPPORTED,
-		     "Password request mechanism has not been defined.");
-	
-	return NULL;
-}
-
-
-static void
-simple_forget_passwd (GMimeSession *session, const char *item, GError **err)
-{
-	GMimeSessionSimple *simple = (GMimeSessionSimple *) session;
-	
-	if (simple->forget_passwd)
-		simple->forget_passwd (session, item, err);
-}
-
-
-/**
- * g_mime_session_simple_set_is_online:
- * @session: Simple Session object
- * @is_online: callback to return if the system is connected to the 'net
- *
- * Sets the @is_online callback function on the simple session
- * object. @is_online should return %TRUE if the network is reachable
- * or %FALSE otherwise.
- **/
-void
-g_mime_session_simple_set_is_online (GMimeSessionSimple *session, GMimeSimpleIsOnlineFunc is_online)
-{
-	g_return_if_fail (GMIME_IS_SESSION_SIMPLE (session));
-	
-	session->is_online = is_online;
-}
-
-
-/**
- * g_mime_session_simple_set_request_passwd:
- * @session: Simple Session object
- * @request_passwd: callback to prompt the user for a passwd
- *
- * Sets the @request_passwd callback function on the simple session
- * object. @request_passwd should return a malloc'd string containing
- * the password that the user entered or %NULL on fail as well as
- * setting the 'err' argument. The 'item' argument can be used as a
- * unique key identifier if @request_passwd decides to cache the
- * passwd. The 'prompt' argument should be used as the string to
- * display to the user requesting the passwd. Finally, 'secret' should
- * be used to determine whether or not to hide the user's input.
- **/
-void
-g_mime_session_simple_set_request_passwd (GMimeSessionSimple *session, GMimeSimpleRequestPasswdFunc request_passwd)
-{
-	g_return_if_fail (GMIME_IS_SESSION_SIMPLE (session));
-	
-	session->request_passwd = request_passwd;
-}
-
-
-/**
- * g_mime_session_simple_set_forget_passwd:
- * @session: Simple Session object
- * @forget_passwd: callback to forget the cached passwd keyed for 'item'
- *
- * Sets the @forget_passwd callback function on the simple session
- * object. @forget_passwd should uncache the passwd for 'item'. See
- * g_mime_session_simple_set_request_passwd() for further details.
- **/
-void
-g_mime_session_simple_set_forget_passwd (GMimeSessionSimple *session, GMimeSimpleForgetPasswdFunc forget_passwd)
-{
-	g_return_if_fail (GMIME_IS_SESSION_SIMPLE (session));
-	
-	session->forget_passwd = forget_passwd;
-}
diff --git a/gmime/gmime-session-simple.h b/gmime/gmime-session-simple.h
deleted file mode 100644
index de8f4b4..0000000
--- a/gmime/gmime-session-simple.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*  GMime
- *  Copyright (C) 2000-2009 Jeffrey Stedfast
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public License
- *  as published by the Free Software Foundation; either version 2.1
- *  of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free
- *  Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
- *  02110-1301, USA.
- */
-
-
-#ifndef __GMIME_SESSION_SIMPLE_H__
-#define __GMIME_SESSION_SIMPLE_H__
-
-#include <gmime/gmime-session.h>
-
-G_BEGIN_DECLS
-
-#define GMIME_TYPE_SESSION_SIMPLE            (g_mime_session_simple_get_type ())
-#define GMIME_SESSION_SIMPLE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMIME_TYPE_SESSION_SIMPLE, GMimeSessionSimple))
-#define GMIME_SESSION_SIMPLE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GMIME_TYPE_SESSION_SIMPLE, GMimeSessionSimpleClass))
-#define GMIME_IS_SESSION_SIMPLE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMIME_TYPE_SESSION_SIMPLE))
-#define GMIME_IS_SESSION_SIMPLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GMIME_TYPE_SESSION_SIMPLE))
-#define GMIME_SESSION_SIMPLE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GMIME_TYPE_SESSION_SIMPLE, GMimeSessionSimpleClass))
-
-typedef struct _GMimeSessionSimple GMimeSessionSimple;
-typedef struct _GMimeSessionSimpleClass GMimeSessionSimpleClass;
-
-typedef gboolean (* GMimeSimpleIsOnlineFunc) (GMimeSession *session);
-typedef char * (* GMimeSimpleRequestPasswdFunc) (GMimeSession *session, const char *prompt,
-						 gboolean secret, const char *item,
-						 GError **err);
-typedef void (* GMimeSimpleForgetPasswdFunc) (GMimeSession *session, const char *item,
-					      GError **err);
-
-
-/**
- * GMimeSessionSimple:
- * @parent_object: parent #GMimeSession
- * @is_online: callback to check network state
- * @request_passwd: password-request callback
- * @forget_passwd: callback to uncache a passwd
- *
- * A simple #GMimeSession for applications that don't want to
- * implement their own #GMimeSession context.
- **/
-struct _GMimeSessionSimple {
-	GMimeSession parent_object;
-	
-	GMimeSimpleIsOnlineFunc is_online;
-	GMimeSimpleRequestPasswdFunc request_passwd;
-	GMimeSimpleForgetPasswdFunc forget_passwd;
-};
-
-struct _GMimeSessionSimpleClass {
-	GMimeSessionClass parent_class;
-	
-};
-
-
-GType g_mime_session_simple_get_type (void);
-
-
-void g_mime_session_simple_set_is_online (GMimeSessionSimple *session, GMimeSimpleIsOnlineFunc is_online);
-void g_mime_session_simple_set_request_passwd (GMimeSessionSimple *session, GMimeSimpleRequestPasswdFunc request_passwd);
-void g_mime_session_simple_set_forget_passwd (GMimeSessionSimple *session, GMimeSimpleForgetPasswdFunc forget_passwd);
-
-
-G_END_DECLS
-
-#endif /* __GMIME_SESSION_SIMPLE_H__ */
diff --git a/gmime/gmime-session.c b/gmime/gmime-session.c
deleted file mode 100644
index c1e90e3..0000000
--- a/gmime/gmime-session.c
+++ /dev/null
@@ -1,189 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*  GMime
- *  Copyright (C) 2000-2009 Jeffrey Stedfast
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public License
- *  as published by the Free Software Foundation; either version 2.1
- *  of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free
- *  Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
- *  02110-1301, USA.
- */
-
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "gmime-session.h"
-#include "gmime-error.h"
-
-
-/**
- * SECTION: gmime-session
- * @title: GMimeSession
- * @short_description: Session interface
- * @see_also: #GMimeCipherContext
- *
- * A #GMimeSession provides a means for lower-levels of GMime to query
- * for user-input through the application.
- **/
-
-static void g_mime_session_class_init (GMimeSessionClass *klass);
-static void g_mime_session_init (GMimeSession *session, GMimeSessionClass *klass);
-static void g_mime_session_finalize (GObject *object);
-
-static gboolean session_is_online (GMimeSession *session);
-static char *session_request_passwd (GMimeSession *session, const char *prompt,
-				     gboolean secret, const char *item,
-				     GError **err);
-static void session_forget_passwd (GMimeSession *session, const char *item,
-				   GError **err);
-
-
-static GObjectClass *parent_class = NULL;
-
-
-GType
-g_mime_session_get_type (void)
-{
-	static GType type = 0;
-	
-	if (!type) {
-		static const GTypeInfo info = {
-			sizeof (GMimeSessionClass),
-			NULL, /* base_class_init */
-			NULL, /* base_class_finalize */
-			(GClassInitFunc) g_mime_session_class_init,
-			NULL, /* class_finalize */
-			NULL, /* class_data */
-			sizeof (GMimeSession),
-			0,    /* n_preallocs */
-			(GInstanceInitFunc) g_mime_session_init,
-		};
-		
-		type = g_type_register_static (G_TYPE_OBJECT, "GMimeSession", &info, 0);
-	}
-	
-	return type;
-}
-
-
-static void
-g_mime_session_class_init (GMimeSessionClass *klass)
-{
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	
-	parent_class = g_type_class_ref (G_TYPE_OBJECT);
-	
-	object_class->finalize = g_mime_session_finalize;
-	
-	klass->is_online = session_is_online;
-	klass->request_passwd = session_request_passwd;
-	klass->forget_passwd = session_forget_passwd;
-}
-
-static void
-g_mime_session_init (GMimeSession *session, GMimeSessionClass *klass)
-{
-	
-}
-
-static void
-g_mime_session_finalize (GObject *object)
-{
-	G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-
-static gboolean
-session_is_online (GMimeSession *session)
-{
-	return FALSE;
-}
-
-
-/**
- * g_mime_session_is_online:
- * @session: session object
- *
- * Gets whether or not the session is 'online' or not (online meaning
- * that we are connected to the internet).
- *
- * Returns: %TRUE if the session is online or %FALSE otherwise.
- **/
-gboolean
-g_mime_session_is_online (GMimeSession *session)
-{
-	g_return_val_if_fail (GMIME_IS_SESSION (session), FALSE);
-	
-	return GMIME_SESSION_GET_CLASS (session)->is_online (session);
-}
-
-
-static char *
-session_request_passwd (GMimeSession *session, const char *prompt,
-			gboolean secret, const char *item,
-			GError **err)
-{
-	g_set_error (err, GMIME_ERROR_QUARK, GMIME_ERROR_NOT_SUPPORTED,
-		     "Password request mechanism is not implemented.");
-	return NULL;
-}
-
-
-/**
- * g_mime_session_request_passwd:
- * @session: session object
- * @prompt: prompt to present to the user
- * @secret: %TRUE if the characters the user types should be hidden
- * @item: item name
- * @err: exception
- *
- * Requests the password for item @item.
- *
- * Returns: a string buffer containing the password for the requested
- * item or %NULL on fail.
- **/
-char *
-g_mime_session_request_passwd (GMimeSession *session, const char *prompt,
-			       gboolean secret, const char *item,
-			       GError **err)
-{
-	g_return_val_if_fail (GMIME_IS_SESSION (session), NULL);
-	
-	return GMIME_SESSION_GET_CLASS (session)->request_passwd (session, prompt, secret, item, err);
-}
-
-
-static void
-session_forget_passwd (GMimeSession *session, const char *item, GError **err)
-{
-	g_set_error (err, GMIME_ERROR_QUARK, GMIME_ERROR_NOT_SUPPORTED,
-		     "Password forget mechanism is not implemented.");
-}
-
-
-/**
- * g_mime_session_forget_passwd:
- * @session: session object
- * @item: item name
- * @err: exception
- *
- * Forgets the password for item @item.
- **/
-void
-g_mime_session_forget_passwd (GMimeSession *session, const char *item, GError **err)
-{
-	g_return_if_fail (GMIME_IS_SESSION (session));
-	
-	GMIME_SESSION_GET_CLASS (session)->forget_passwd (session, item, err);
-}
diff --git a/gmime/gmime-session.h b/gmime/gmime-session.h
deleted file mode 100644
index 9713e77..0000000
--- a/gmime/gmime-session.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*  GMime
- *  Copyright (C) 2000-2009 Jeffrey Stedfast
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public License
- *  as published by the Free Software Foundation; either version 2.1
- *  of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free
- *  Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
- *  02110-1301, USA.
- */
-
-
-#ifndef __GMIME_SESSION_H__
-#define __GMIME_SESSION_H__
-
-#include <glib.h>
-#include <glib-object.h>
-
-G_BEGIN_DECLS
-
-#define GMIME_TYPE_SESSION            (g_mime_session_get_type ())
-#define GMIME_SESSION(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMIME_TYPE_SESSION, GMimeSession))
-#define GMIME_SESSION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GMIME_TYPE_SESSION, GMimeSessionClass))
-#define GMIME_IS_SESSION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMIME_TYPE_SESSION))
-#define GMIME_IS_SESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GMIME_TYPE_SESSION))
-#define GMIME_SESSION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GMIME_TYPE_SESSION, GMimeSessionClass))
-
-typedef struct _GMimeSession GMimeSession;
-typedef struct _GMimeSessionClass GMimeSessionClass;
-
-
-/**
- * GMimeSession:
- * @parent_object: parent #GObject
- *
- * An object used for interfacing with the user through the
- * application. This object is meant to be subclassed by the
- * application.
- **/
-struct _GMimeSession {
-	GObject parent_object;
-	
-};
-
-struct _GMimeSessionClass {
-	GObjectClass parent_class;
-	
-	gboolean (* is_online) (GMimeSession *session);
-	
-	char *   (* request_passwd) (GMimeSession *session, const char *prompt,
-				     gboolean secret, const char *item,
-				     GError **err);
-	
-	void     (* forget_passwd)  (GMimeSession *session, const char *item,
-				     GError **err);
-};
-
-
-GType g_mime_session_get_type (void);
-
-
-gboolean g_mime_session_is_online (GMimeSession *session);
-
-char *g_mime_session_request_passwd (GMimeSession *session, const char *prompt,
-				     gboolean secret, const char *item,
-				     GError **err);
-
-void g_mime_session_forget_passwd (GMimeSession *session, const char *item,
-				   GError **err);
-
-
-G_END_DECLS
-
-#endif /* __GMIME_SESSION_H__ */
diff --git a/gmime/gmime-stream-fs.c b/gmime/gmime-stream-fs.c
index 41e3999..c367779 100644
--- a/gmime/gmime-stream-fs.c
+++ b/gmime/gmime-stream-fs.c
@@ -431,7 +431,7 @@ stream_substream (GMimeStream *stream, gint64 start, gint64 end)
 
 /**
  * g_mime_stream_fs_new:
- * @fd: file descriptor
+ * @fd: a file descriptor
  *
  * Creates a new #GMimeStreamFs object around @fd.
  *
@@ -458,7 +458,7 @@ g_mime_stream_fs_new (int fd)
 
 /**
  * g_mime_stream_fs_new_with_bounds:
- * @fd: file descriptor
+ * @fd: a file descriptor
  * @start: start boundary
  * @end: end boundary
  *
@@ -484,7 +484,7 @@ g_mime_stream_fs_new_with_bounds (int fd, gint64 start, gint64 end)
 
 /**
  * g_mime_stream_fs_get_owner:
- * @stream: fs stream
+ * @stream: a #GMimeStreamFs
  *
  * Gets whether or not @stream owns the backend file descriptor.
  *
@@ -502,10 +502,10 @@ g_mime_stream_fs_get_owner (GMimeStreamFs *stream)
 
 /**
  * g_mime_stream_fs_set_owner:
- * @stream: fs stream
+ * @stream: a #GMimeStreamFs
  * @owner: owner
  *
- * Sets whether or not @stream owns the backend FS pointer.
+ * Sets whether or not @stream owns the backend file descriptor.
  *
  * Note: @owner should be %TRUE if the stream should close() the
  * backend file descriptor when destroyed or %FALSE otherwise.
diff --git a/gmime/gmime-stream-pipe.c b/gmime/gmime-stream-pipe.c
new file mode 100644
index 0000000..28c6dd2
--- /dev/null
+++ b/gmime/gmime-stream-pipe.c
@@ -0,0 +1,352 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*  GMime
+ *  Copyright (C) 2000-2009 Jeffrey Stedfast
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+ *  02110-1301, USA.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <errno.h>
+#ifdef G_OS_WIN32
+#include <io.h>
+#endif
+
+#include "gmime-stream-pipe.h"
+
+#ifndef HAVE_FSYNC
+static int fsync (int fd) { return 0; }
+#endif
+
+
+/**
+ * SECTION: gmime-stream-pipe
+ * @title: GMimeStreamPipe
+ * @short_description: A low-level pipe stream
+ * @see_also: #GMimeStream
+ *
+ * A simple #GMimeStream implementation that sits on top of low-level
+ * POSIX pipes.
+ **/
+
+
+static void g_mime_stream_pipe_class_init (GMimeStreamPipeClass *klass);
+static void g_mime_stream_pipe_init (GMimeStreamPipe *stream, GMimeStreamPipeClass *klass);
+static void g_mime_stream_pipe_finalize (GObject *object);
+
+static ssize_t stream_read (GMimeStream *stream, char *buf, size_t len);
+static ssize_t stream_write (GMimeStream *stream, const char *buf, size_t len);
+static int stream_flush (GMimeStream *stream);
+static int stream_close (GMimeStream *stream);
+static gboolean stream_eos (GMimeStream *stream);
+static int stream_reset (GMimeStream *stream);
+static gint64 stream_seek (GMimeStream *stream, gint64 offset, GMimeSeekWhence whence);
+static gint64 stream_tell (GMimeStream *stream);
+static gint64 stream_length (GMimeStream *stream);
+static GMimeStream *stream_substream (GMimeStream *stream, gint64 start, gint64 end);
+
+
+static GMimeStreamClass *parent_class = NULL;
+
+
+GType
+g_mime_stream_pipe_get_type (void)
+{
+	static GType type = 0;
+	
+	if (!type) {
+		static const GTypeInfo info = {
+			sizeof (GMimeStreamPipeClass),
+			NULL, /* base_class_init */
+			NULL, /* base_class_finalize */
+			(GClassInitFunc) g_mime_stream_pipe_class_init,
+			NULL, /* class_finalize */
+			NULL, /* class_data */
+			sizeof (GMimeStreamPipe),
+			0,    /* n_preallocs */
+			(GInstanceInitFunc) g_mime_stream_pipe_init,
+		};
+		
+		type = g_type_register_static (GMIME_TYPE_STREAM, "GMimeStreamPipe", &info, 0);
+	}
+	
+	return type;
+}
+
+
+static void
+g_mime_stream_pipe_class_init (GMimeStreamPipeClass *klass)
+{
+	GMimeStreamClass *stream_class = GMIME_STREAM_CLASS (klass);
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	
+	parent_class = g_type_class_ref (GMIME_TYPE_STREAM);
+	
+	object_class->finalize = g_mime_stream_pipe_finalize;
+	
+	stream_class->read = stream_read;
+	stream_class->write = stream_write;
+	stream_class->flush = stream_flush;
+	stream_class->close = stream_close;
+	stream_class->eos = stream_eos;
+	stream_class->reset = stream_reset;
+	stream_class->seek = stream_seek;
+	stream_class->tell = stream_tell;
+	stream_class->length = stream_length;
+	stream_class->substream = stream_substream;
+}
+
+static void
+g_mime_stream_pipe_init (GMimeStreamPipe *stream, GMimeStreamPipeClass *klass)
+{
+	stream->owner = TRUE;
+	stream->eos = FALSE;
+	stream->fd = -1;
+}
+
+static void
+g_mime_stream_pipe_finalize (GObject *object)
+{
+	GMimeStreamPipe *stream = (GMimeStreamPipe *) object;
+	
+	if (stream->owner && stream->fd != -1)
+		close (stream->fd);
+	
+	G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static ssize_t
+stream_read (GMimeStream *stream, char *buf, size_t len)
+{
+	GMimeStreamPipe *pipes = (GMimeStreamPipe *) stream;
+	ssize_t nread;
+	
+	if (pipes->fd == -1) {
+		errno = EBADF;
+		return -1;
+	}
+	
+	if (stream->bound_end != -1 && stream->position >= stream->bound_end) {
+		errno = EINVAL;
+		return -1;
+	}
+	
+	if (stream->bound_end != -1)
+		len = (size_t) MIN (stream->bound_end - stream->position, (gint64) len);
+	
+	do {
+		nread = read (pipes->fd, buf, len);
+	} while (nread == -1 && errno == EINTR);
+	
+	if (nread > 0) {
+		stream->position += nread;
+	} else if (nread == 0) {
+		pipes->eos = TRUE;
+	}
+	
+	return nread;
+}
+
+static ssize_t
+stream_write (GMimeStream *stream, const char *buf, size_t len)
+{
+	GMimeStreamPipe *pipes = (GMimeStreamPipe *) stream;
+	size_t nwritten = 0;
+	ssize_t n;
+	
+	if (pipes->fd == -1) {
+		errno = EBADF;
+		return -1;
+	}
+	
+	if (stream->bound_end != -1 && stream->position >= stream->bound_end) {
+		errno = EINVAL;
+		return -1;
+	}
+	
+	if (stream->bound_end != -1)
+		len = (size_t) MIN (stream->bound_end - stream->position, (gint64) len);
+	
+	do {
+		do {
+			n = write (pipes->fd, buf + nwritten, len - nwritten);
+		} while (n == -1 && (errno == EINTR || errno == EAGAIN));
+		
+		if (n > 0)
+			nwritten += n;
+	} while (n != -1 && nwritten < len);
+	
+	if (n == -1 && (errno == EFBIG || errno == ENOSPC))
+		pipes->eos = TRUE;
+	
+	if (nwritten > 0) {
+		stream->position += nwritten;
+	} else if (n == -1) {
+		/* error and nothing written */
+		return -1;
+	}
+	
+	return nwritten;
+}
+
+static int
+stream_flush (GMimeStream *stream)
+{
+	GMimeStreamPipe *pipes = (GMimeStreamPipe *) stream;
+	
+	if (pipes->fd == -1) {
+		errno = EBADF;
+		return -1;
+	}
+	
+	return fsync (pipes->fd);
+}
+
+static int
+stream_close (GMimeStream *stream)
+{
+	GMimeStreamPipe *pipes = (GMimeStreamPipe *) stream;
+	int rv;
+	
+	if (pipes->fd == -1)
+		return 0;
+	
+	do {
+		if ((rv = close (pipes->fd)) == 0)
+			pipes->fd = -1;
+	} while (rv == -1 && errno == EINTR);
+	
+	return rv;
+}
+
+static gboolean
+stream_eos (GMimeStream *stream)
+{
+	GMimeStreamPipe *pipes = (GMimeStreamPipe *) stream;
+	
+	if (pipes->fd == -1)
+		return TRUE;
+	
+	return pipes->eos;
+}
+
+static int
+stream_reset (GMimeStream *stream)
+{
+	GMimeStreamPipe *pipes = (GMimeStreamPipe *) stream;
+	
+	if (pipes->fd == -1) {
+		errno = EBADF;
+		return -1;
+	}
+	
+	return 0;
+}
+
+static gint64
+stream_seek (GMimeStream *stream, gint64 offset, GMimeSeekWhence whence)
+{
+	return -1;
+}
+
+static gint64
+stream_tell (GMimeStream *stream)
+{
+	return -1;
+}
+
+static gint64
+stream_length (GMimeStream *stream)
+{
+	return -1;
+}
+
+static GMimeStream *
+stream_substream (GMimeStream *stream, gint64 start, gint64 end)
+{
+	return NULL;
+}
+
+
+/**
+ * g_mime_stream_pipe_new:
+ * @fd: a pipe descriptor
+ *
+ * Creates a new #GMimeStreamPipe object around @fd.
+ *
+ * Returns: a stream using @fd.
+ **/
+GMimeStream *
+g_mime_stream_pipe_new (int fd)
+{
+	GMimeStreamPipe *pipes;
+	
+	pipes = g_object_newv (GMIME_TYPE_STREAM_PIPE, 0, NULL);
+	g_mime_stream_construct (GMIME_STREAM (pipes), 0, -1);
+	pipes->owner = TRUE;
+	pipes->eos = FALSE;
+	pipes->fd = fd;
+	
+	return (GMimeStream *) pipes;
+}
+
+
+/**
+ * g_mime_stream_pipe_get_owner:
+ * @stream: a #GMimeStreamPipe
+ *
+ * Gets whether or not @stream owns the backend pipe descriptor.
+ *
+ * Returns: %TRUE if @stream owns the backend pipe descriptor or %FALSE
+ * otherwise.
+ **/
+gboolean
+g_mime_stream_pipe_get_owner (GMimeStreamPipe *stream)
+{
+	g_return_val_if_fail (GMIME_IS_STREAM_PIPE (stream), FALSE);
+	
+	return stream->owner;
+}
+
+
+/**
+ * g_mime_stream_pipe_set_owner:
+ * @stream: a #GMimeStreamPipe
+ * @owner: owner
+ *
+ * Sets whether or not @stream owns the backend pipe descriptor.
+ *
+ * Note: @owner should be %TRUE if the stream should close() the
+ * backend pipe descriptor when destroyed or %FALSE otherwise.
+ **/
+void
+g_mime_stream_pipe_set_owner (GMimeStreamPipe *stream, gboolean owner)
+{
+	g_return_if_fail (GMIME_IS_STREAM_PIPE (stream));
+	
+	stream->owner = owner;
+}
diff --git a/gmime/gmime-stream-pipe.h b/gmime/gmime-stream-pipe.h
new file mode 100644
index 0000000..61028fc
--- /dev/null
+++ b/gmime/gmime-stream-pipe.h
@@ -0,0 +1,71 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*  GMime
+ *  Copyright (C) 2000-2009 Jeffrey Stedfast
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+ *  02110-1301, USA.
+ */
+
+
+#ifndef __GMIME_STREAM_PIPE_H__
+#define __GMIME_STREAM_PIPE_H__
+
+#include <gmime/gmime-stream.h>
+
+G_BEGIN_DECLS
+
+#define GMIME_TYPE_STREAM_PIPE            (g_mime_stream_pipe_get_type ())
+#define GMIME_STREAM_PIPE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMIME_TYPE_STREAM_PIPE, GMimeStreamPipe))
+#define GMIME_STREAM_PIPE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GMIME_TYPE_STREAM_PIPE, GMimeStreamPipeClass))
+#define GMIME_IS_STREAM_PIPE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMIME_TYPE_STREAM_PIPE))
+#define GMIME_IS_STREAM_PIPE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GMIME_TYPE_STREAM_PIPE))
+#define GMIME_STREAM_PIPE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GMIME_TYPE_STREAM_PIPE, GMimeStreamPipeClass))
+
+typedef struct _GMimeStreamPipe GMimeStreamPipe;
+typedef struct _GMimeStreamPipeClass GMimeStreamPipeClass;
+
+/**
+ * GMimeStreamPipe:
+ * @parent_object: parent #GMimeStream
+ * @owner: %TRUE if this stream owns @fd
+ * @eos: %TRUE if end-of-stream
+ * @fd: pipe descriptor
+ *
+ * A #GMimeStream wrapper around pipes.
+ **/
+struct _GMimeStreamPipe {
+	GMimeStream parent_object;
+	
+	gboolean owner;
+	gboolean eos;
+	int fd;
+};
+
+struct _GMimeStreamPipeClass {
+	GMimeStreamClass parent_class;
+	
+};
+
+
+GType g_mime_stream_pipe_get_type (void);
+
+GMimeStream *g_mime_stream_pipe_new (int sockfd);
+
+gboolean g_mime_stream_pipe_get_owner (GMimeStreamPipe *stream);
+void g_mime_stream_pipe_set_owner (GMimeStreamPipe *stream, gboolean owner);
+
+G_END_DECLS
+
+#endif /* __GMIME_STREAM_PIPE_H__ */
diff --git a/gmime/gmime.h b/gmime/gmime.h
index e372315..93a8b79 100644
--- a/gmime/gmime.h
+++ b/gmime/gmime.h
@@ -52,6 +52,7 @@
 #include <gmime/gmime-stream-mem.h>
 #include <gmime/gmime-stream-mmap.h>
 #include <gmime/gmime-stream-null.h>
+#include <gmime/gmime-stream-pipe.h>
 #include <gmime/gmime-filter.h>
 #include <gmime/gmime-filter-basic.h>
 #include <gmime/gmime-filter-best.h>
@@ -65,8 +66,6 @@
 #include <gmime/gmime-filter-strip.h>
 #include <gmime/gmime-filter-windows.h>
 #include <gmime/gmime-filter-yenc.h>
-#include <gmime/gmime-session.h>
-#include <gmime/gmime-session-simple.h>
 #include <gmime/gmime-cipher-context.h>
 #include <gmime/gmime-gpg-context.h>
 
diff --git a/tests/test-pgp.c b/tests/test-pgp.c
index 8e51ffc..34ae10d 100644
--- a/tests/test-pgp.c
+++ b/tests/test-pgp.c
@@ -35,74 +35,14 @@ extern int verbose;
 
 #define v(x) if (verbose > 3) x
 
-
-typedef struct _TestSession TestSession;
-typedef struct _TestSessionClass TestSessionClass;
-
-struct _TestSession {
-	GMimeSession parent_object;
-	
-};
-
-struct _TestSessionClass {
-	GMimeSessionClass parent_class;
-	
-};
-
-static void test_session_class_init (TestSessionClass *klass);
-
-static char *request_passwd (GMimeSession *session, const char *prompt,
-			     gboolean secret, const char *item,
-			     GError **err);
-
-
-static GMimeSessionClass *parent_class = NULL;
-
-
-static GType
-test_session_get_type (void)
+static gboolean
+request_passwd (GMimeCipherContext *ctx, const char *user_id, const char *prompt_ctx, gboolean reprompt, GMimeStream *response, GError **err)
 {
-	static GType type = 0;
-	
-	if (!type) {
-		static const GTypeInfo info = {
-			sizeof (TestSessionClass),
-			NULL, /* base_class_init */
-			NULL, /* base_class_finalize */
-			(GClassInitFunc) test_session_class_init,
-			NULL, /* class_finalize */
-			NULL, /* class_data */
-			sizeof (TestSession),
-			0,    /* n_preallocs */
-			NULL, /* object_init */
-		};
-		
-		type = g_type_register_static (GMIME_TYPE_SESSION, "TestSession", &info, 0);
-	}
+	g_mime_stream_write_string (response, "no.secret\n");
 	
-	return type;
+	return TRUE;
 }
 
-
-static void
-test_session_class_init (TestSessionClass *klass)
-{
-	GMimeSessionClass *session_class = GMIME_SESSION_CLASS (klass);
-	
-	parent_class = g_type_class_ref (GMIME_TYPE_SESSION);
-	
-	session_class->request_passwd = request_passwd;
-}
-
-
-static char *
-request_passwd (GMimeSession *session, const char *prompt, gboolean secret, const char *item, GError **err)
-{
-	return g_strdup ("no.secret");
-}
-
-
-
 static void
 test_sign (GMimeCipherContext *ctx, GMimeStream *cleartext, GMimeStream *ciphertext)
 {
@@ -313,7 +253,6 @@ int main (int argc, char **argv)
 	const char *datadir = "data/pgp";
 	GMimeStream *istream, *ostream;
 	GMimeCipherContext *ctx;
-	GMimeSession *session;
 	const char *what;
 	struct stat st;
 	char *key;
@@ -341,9 +280,7 @@ int main (int argc, char **argv)
 	
 	testsuite_start ("GnuPG cipher context");
 	
-	session = g_object_new (test_session_get_type (), NULL);
-	
-	ctx = g_mime_gpg_context_new (session, "/usr/bin/gpg");
+	ctx = g_mime_gpg_context_new (request_passwd, "/usr/bin/gpg");
 	g_mime_gpg_context_set_always_trust ((GMimeGpgContext *) ctx, TRUE);
 	
 	testsuite_check ("GMimeGpgContext::import");
@@ -435,7 +372,6 @@ int main (int argc, char **argv)
 		testsuite_check_failed ("%s failed: %s", what, ex->message);
 	} finally;
 	
-	g_object_unref (session);
 	g_object_unref (istream);
 	g_object_unref (ostream);
 	g_object_unref (ctx);
diff --git a/tests/test-pgpmime.c b/tests/test-pgpmime.c
index bd63de1..674a234 100644
--- a/tests/test-pgpmime.c
+++ b/tests/test-pgpmime.c
@@ -39,73 +39,14 @@ extern int verbose;
 
 #define v(x) if (verbose > 3) x
 
-
-typedef struct _TestSession TestSession;
-typedef struct _TestSessionClass TestSessionClass;
-
-struct _TestSession {
-	GMimeSession parent_object;
-	
-};
-
-struct _TestSessionClass {
-	GMimeSessionClass parent_class;
-	
-};
-
-static void test_session_class_init (TestSessionClass *klass);
-
-static char *request_passwd (GMimeSession *session, const char *prompt,
-			     gboolean secret, const char *item,
-			     GError **err);
-
-
-static GMimeSessionClass *parent_class = NULL;
-
-
-static GType
-test_session_get_type (void)
-{
-	static GType type = 0;
-	
-	if (!type) {
-		static const GTypeInfo info = {
-			sizeof (TestSessionClass),
-			NULL, /* base_class_init */
-			NULL, /* base_class_finalize */
-			(GClassInitFunc) test_session_class_init,
-			NULL, /* class_finalize */
-			NULL, /* class_data */
-			sizeof (TestSession),
-			0,    /* n_preallocs */
-			NULL, /* object_init */
-		};
-		
-		type = g_type_register_static (GMIME_TYPE_SESSION, "TestSession", &info, 0);
-	}
-	
-	return type;
-}
-
-
-static void
-test_session_class_init (TestSessionClass *klass)
+static gboolean
+request_passwd (GMimeCipherContext *ctx, const char *user_id, const char *prompt_ctx, gboolean reprompt, GMimeStream *response, GError **err)
 {
-	GMimeSessionClass *session_class = GMIME_SESSION_CLASS (klass);
-	
-	parent_class = g_type_class_ref (GMIME_TYPE_SESSION);
+	g_mime_stream_write_string (response, "no.secret\n");
 	
-	session_class->request_passwd = request_passwd;
+	return TRUE;
 }
 
-static char *
-request_passwd (GMimeSession *session, const char *prompt, gboolean secret, const char *item, GError **err)
-{
-	return g_strdup ("no.secret");
-}
-
-
-
 static void
 print_verify_results (const GMimeSignatureValidity *validity)
 {
@@ -454,7 +395,6 @@ int main (int argc, char *argv[])
 {
 	const char *datadir = "data/pgpmime";
 	GMimeCipherContext *ctx;
-	GMimeSession *session;
 	struct stat st;
 	char *key;
 	int i;
@@ -481,9 +421,7 @@ int main (int argc, char *argv[])
 	
 	testsuite_start ("PGP/MIME implementation");
 	
-	session = g_object_new (test_session_get_type (), NULL);
-	
-	ctx = g_mime_gpg_context_new (session, "/usr/bin/gpg");
+	ctx = g_mime_gpg_context_new (request_passwd, "/usr/bin/gpg");
 	g_mime_gpg_context_set_always_trust ((GMimeGpgContext *) ctx, TRUE);
 	
 	testsuite_check ("GMimeGpgContext::import");
@@ -526,7 +464,6 @@ int main (int argc, char *argv[])
 		testsuite_check_failed ("multipart/encrypted+sign failed: %s", ex->message);
 	} finally;
 	
-	g_object_unref (session);
 	g_object_unref (ctx);
 	
 	testsuite_end ();



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]