diff --git a/Makefile.local b/Makefile.local index 84043fe6..b7cd266d 100644 --- a/Makefile.local +++ b/Makefile.local @@ -255,7 +255,6 @@ notmuch_client_srcs = \ command-line-arguments.c\ debugger.c \ gmime-filter-reply.c \ - gmime-filter-headers.c \ hooks.c \ notmuch.c \ notmuch-config.c \ diff --git a/gmime-filter-headers.c b/gmime-filter-headers.c deleted file mode 100644 index 7db3779b..00000000 --- a/gmime-filter-headers.c +++ /dev/null @@ -1,263 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * Copyright © 2010 Michal Sojka - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program 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 - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "gmime-filter-headers.h" -#include -#include -#include -#include -#include - -/** - * SECTION: gmime-filter-headers - * @title: GMimeFilterHeaders - * @short_description: Add/remove headers markers - * - * A #GMimeFilter for decoding rfc2047 encoded headers to UTF-8 - **/ - - -static void g_mime_filter_headers_class_init (GMimeFilterHeadersClass *klass); -static void g_mime_filter_headers_init (GMimeFilterHeaders *filter, GMimeFilterHeadersClass *klass); -static void g_mime_filter_headers_finalize (GObject *object); - -static GMimeFilter *filter_copy (GMimeFilter *filter); -static void filter_filter (GMimeFilter *filter, char *in, size_t len, size_t prespace, - char **out, size_t *outlen, size_t *outprespace); -static void filter_complete (GMimeFilter *filter, char *in, size_t len, size_t prespace, - char **out, size_t *outlen, size_t *outprespace); -static void filter_reset (GMimeFilter *filter); - - -static GMimeFilterClass *parent_class = NULL; - -GType -g_mime_filter_headers_get_type (void) -{ - static GType type = 0; - - if (!type) { - static const GTypeInfo info = { - sizeof (GMimeFilterHeadersClass), - NULL, /* base_class_init */ - NULL, /* base_class_finalize */ - (GClassInitFunc) g_mime_filter_headers_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (GMimeFilterHeaders), - 0, /* n_preallocs */ - (GInstanceInitFunc) g_mime_filter_headers_init, - NULL /* value_table */ - }; - - type = g_type_register_static (GMIME_TYPE_FILTER, "GMimeFilterHeaders", &info, (GTypeFlags) 0); - } - - return type; -} - - -static void -g_mime_filter_headers_class_init (GMimeFilterHeadersClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GMimeFilterClass *filter_class = GMIME_FILTER_CLASS (klass); - - parent_class = (GMimeFilterClass *) g_type_class_ref (GMIME_TYPE_FILTER); - - object_class->finalize = g_mime_filter_headers_finalize; - - filter_class->copy = filter_copy; - filter_class->filter = filter_filter; - filter_class->complete = filter_complete; - filter_class->reset = filter_reset; -} - -static void -g_mime_filter_headers_init (GMimeFilterHeaders *filter, GMimeFilterHeadersClass *klass) -{ - (void) klass; - filter->saw_nl = TRUE; - filter->line = NULL; - filter->line_size = 0; - filter->lineptr = NULL; -} - -static void -g_mime_filter_headers_finalize (GObject *object) -{ - free (GMIME_FILTER_HEADERS (object)->line); - G_OBJECT_CLASS (parent_class)->finalize (object); -} - - -static GMimeFilter * -filter_copy (GMimeFilter *filter) -{ - (void) filter; - return g_mime_filter_headers_new (); -} - -static void -output_decoded_header (GMimeFilterHeaders *headers, char **outptr) -{ - char *colon, *name, *s, *decoded_value; - size_t offset; - gint ret; - - colon = strchr (headers->line, ':'); - if (colon == NULL) - return; - - name = headers->line; - *colon = '\0'; - s = colon + 1; - while (*s == ' ' || *s == '\t') - s++; - decoded_value = g_mime_utils_header_decode_text(s); - if (decoded_value == NULL) - return; - offset = *outptr - GMIME_FILTER (headers)->outbuf; - g_mime_filter_set_size (GMIME_FILTER (headers), strlen(name) + 2 + - strlen(decoded_value) + 2, TRUE); - *outptr = GMIME_FILTER (headers)->outbuf + offset; - ret = g_sprintf (*outptr, "%s: %s\n", name, decoded_value); - if (ret > 0) - *outptr += ret; - free (decoded_value); -} - -static void -output_final_newline (GMimeFilterHeaders *headers, char **outptr) -{ - size_t offset; - - offset = *outptr - GMIME_FILTER (headers)->outbuf; - g_mime_filter_set_size (GMIME_FILTER (headers), 1, TRUE); - *outptr = GMIME_FILTER (headers)->outbuf + offset; - *(*outptr)++ = '\n'; -} - -static void -filter_filter (GMimeFilter *filter, char *inbuf, size_t inlen, size_t prespace, - char **outbuf, size_t *outlen, size_t *outprespace) -{ - GMimeFilterHeaders *headers = (GMimeFilterHeaders *) filter; - register const char *inptr = inbuf; - const char *inend = inbuf + inlen; - char *lineptr, *lineend, *outptr; - - (void) prespace; - if (headers->line == NULL) { - headers->line_size = 200; - headers->lineptr = headers->line = malloc (headers->line_size); - } - lineptr = headers->lineptr; - lineend = headers->line + headers->line_size - 1; - if (lineptr == NULL) - return; - outptr = filter->outbuf; - while (inptr < inend) { - if (*inptr == '\n') { - if (headers->saw_nl) - output_final_newline(headers, &outptr); - headers->saw_nl = TRUE; - inptr++; - continue; - } - - if (lineptr == lineend) { - headers->line_size *= 2; - headers->line = xrealloc (headers->line, headers->line_size); - lineptr = headers->line + (headers->line_size / 2) - 1; - lineend = headers->line + headers->line_size - 1; - } - - if (headers->saw_nl && *inptr != ' ' && *inptr != '\t') { - *lineptr = '\0'; - output_decoded_header (headers, &outptr); - lineptr = headers->line; - } - if (headers->saw_nl && (*inptr == ' ' || *inptr == '\t')) { - *lineptr = ' '; - lineptr++; - while (inptr < inend && (*inptr == ' ' || *inptr == '\t')) - inptr++; - headers->saw_nl = FALSE; - continue; - } - headers->saw_nl = FALSE; - - if (*inptr != '\r') - *lineptr++ = *inptr; - inptr++; - } - if (headers->saw_nl) { - *lineptr = '\0'; - output_decoded_header (headers, &outptr); - lineptr = headers->line; - } - headers->lineptr = lineptr; - *outlen = outptr - filter->outbuf; - *outprespace = filter->outpre; - *outbuf = filter->outbuf; -} - -static void -filter_complete (GMimeFilter *filter, char *inbuf, size_t inlen, size_t prespace, - char **outbuf, size_t *outlen, size_t *outprespace) -{ - if (inbuf && inlen) - filter_filter (filter, inbuf, inlen, prespace, outbuf, outlen, outprespace); -} - -static void -filter_reset (GMimeFilter *filter) -{ - GMimeFilterHeaders *headers = (GMimeFilterHeaders *) filter; - - headers->saw_nl = TRUE; - free(headers->line); - headers->line = NULL; - headers->line_size = 0; -} - - -/** - * g_mime_filter_headers_new: - * @encode: %TRUE if the filter should encode or %FALSE otherwise - * @dots: encode/decode dots (as for SMTP) - * - * Creates a new #GMimeFilterHeaders filter. - * - * If @encode is %TRUE, then all lines will be prefixed by "> ", - * otherwise any lines starting with "> " will have that removed - * - * Returns: a new #GMimeFilterHeaders filter. - **/ -GMimeFilter * -g_mime_filter_headers_new (void) -{ - GMimeFilterHeaders *new_headers; - - new_headers = (GMimeFilterHeaders *) g_object_newv (GMIME_TYPE_FILTER_HEADERS, 0, NULL); - - return (GMimeFilter *) new_headers; -} - diff --git a/gmime-filter-headers.h b/gmime-filter-headers.h deleted file mode 100644 index 1d1a3ebb..00000000 --- a/gmime-filter-headers.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * Copyright © 2010 Michal Sojka - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program 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 - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef _GMIME_FILTER_HEADERS_H_ -#define _GMIME_FILTER_HEADERS_H_ - -#include - -G_BEGIN_DECLS - -#define GMIME_TYPE_FILTER_HEADERS (g_mime_filter_headers_get_type ()) -#define GMIME_FILTER_HEADERS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMIME_TYPE_FILTER_HEADERS, GMimeFilterHeaders)) -#define GMIME_FILTER_HEADERS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMIME_TYPE_FILTER_HEADERS, GMimeFilterHeadersClass)) -#define GMIME_IS_FILTER_HEADERS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMIME_TYPE_FILTER_HEADERS)) -#define GMIME_IS_FILTER_HEADERS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GMIME_TYPE_FILTER_HEADERS)) -#define GMIME_FILTER_HEADERS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMIME_TYPE_FILTER_HEADERS, GMimeFilterHeadersClass)) - -typedef struct _GMimeFilterHeaders GMimeFilterHeaders; -typedef struct _GMimeFilterHeadersClass GMimeFilterHeadersClass; - -/** - * GMimeFilterHeaders: - * @parent_object: parent #GMimeFilter - * @saw_nl: previous char was a \n - * @line: temporary buffer for line unfolding - * @line_size: size of currently allocated memory for @line - * @lineptr: pointer to the first unused character in @line - * - * A filter to decode rfc2047 encoded headers - **/ -struct _GMimeFilterHeaders { - GMimeFilter parent_object; - - gboolean saw_nl; - char *line; - size_t line_size; - char *lineptr; -}; - -struct _GMimeFilterHeadersClass { - GMimeFilterClass parent_class; - -}; - - -GType g_mime_filter_headers_get_type (void); - -GMimeFilter *g_mime_filter_headers_new (void); - -G_END_DECLS - - -#endif /* _GMIME_FILTER_HEADERS_H_ */ diff --git a/man/man1/notmuch-reply.1 b/man/man1/notmuch-reply.1 index ac76b07f..e5531456 100644 --- a/man/man1/notmuch-reply.1 +++ b/man/man1/notmuch-reply.1 @@ -41,7 +41,7 @@ include .RS .TP 4 .BR default -Includes subject and quoted message body. +Includes subject and quoted message body as an RFC 2822 message. .TP .BR json Produces JSON output containing headers for a reply message and the diff --git a/notmuch-reply.c b/notmuch-reply.c index 472a002e..ac46d026 100644 --- a/notmuch-reply.c +++ b/notmuch-reply.c @@ -21,28 +21,18 @@ */ #include "notmuch-client.h" -#include "gmime-filter-headers.h" #include "sprinter.h" static void show_reply_headers (GMimeMessage *message) { - GMimeStream *stream_stdout = NULL, *stream_filter = NULL; + GMimeStream *stream_stdout = NULL; stream_stdout = g_mime_stream_file_new (stdout); if (stream_stdout) { g_mime_stream_file_set_owner (GMIME_STREAM_FILE (stream_stdout), FALSE); - stream_filter = g_mime_stream_filter_new(stream_stdout); - if (stream_filter) { - // g_mime_object_write_to_stream will produce - // RFC2047-encoded headers, but we want to present the - // user with decoded headers and let whatever - // ultimately sends the mail do the RFC2047 encoding. - g_mime_stream_filter_add(GMIME_STREAM_FILTER(stream_filter), - g_mime_filter_headers_new()); - g_mime_object_write_to_stream(GMIME_OBJECT(message), stream_filter); - g_object_unref(stream_filter); - } + /* Output RFC 2822 formatted (and RFC 2047 encoded) headers. */ + g_mime_object_write_to_stream (GMIME_OBJECT(message), stream_stdout); g_object_unref(stream_stdout); } } diff --git a/test/reply b/test/reply index a85ebe56..d4389cf5 100755 --- a/test/reply +++ b/test/reply @@ -132,7 +132,9 @@ add_message '[subject]="This subject is exactly 200 bytes in length. Other than '[body]="200-byte header"' output=$(notmuch reply id:${gen_msg_id}) test_expect_equal "$output" "From: Notmuch Test Suite -Subject: Re: This subject is exactly 200 bytes in length. Other than its length there is not much of note here. Note that the length of 200 bytes includes the Subject: and Re: prefixes with two spaces +Subject: Re: This subject is exactly 200 bytes in length. Other than its + length there is not much of note here. Note that the length of 200 bytes + includes the Subject: and Re: prefixes with two spaces In-Reply-To: <${gen_msg_id}> References: <${gen_msg_id}> @@ -200,10 +202,11 @@ add_message '[subject]="=?iso-8859-1?q?=e0=df=e7?="' \ '[body]="Encoding"' output=$(notmuch reply id:${gen_msg_id}) +# Note that GMime changes from Q- to B-encoding test_expect_equal "$output" "\ From: Notmuch Test Suite -Subject: Re: àßç -To: ☃ +Subject: Re: =?iso-8859-1?b?4N/n?= +To: =?UTF-8?b?4piD?= In-Reply-To: <${gen_msg_id}> References: <${gen_msg_id}> diff --git a/test/reply-to-sender b/test/reply-to-sender index c7d15bbe..30e5e385 100755 --- a/test/reply-to-sender +++ b/test/reply-to-sender @@ -200,7 +200,9 @@ add_message '[subject]="This subject is exactly 200 bytes in length. Other than '[body]="200-byte header"' output=$(notmuch reply --reply-to=sender id:${gen_msg_id}) test_expect_equal "$output" "From: Notmuch Test Suite -Subject: Re: This subject is exactly 200 bytes in length. Other than its length there is not much of note here. Note that the length of 200 bytes includes the Subject: and Re: prefixes with two spaces +Subject: Re: This subject is exactly 200 bytes in length. Other than its + length there is not much of note here. Note that the length of 200 bytes + includes the Subject: and Re: prefixes with two spaces In-Reply-To: <${gen_msg_id}> References: <${gen_msg_id}>