]> git.notmuchmail.org Git - notmuch/blob - show-message.c
Normalize part counting and formatting in show_message_part function.
[notmuch] / show-message.c
1 /* notmuch - Not much of an email program, (just index and search)
2  *
3  * Copyright © 2009 Carl Worth
4  * Copyright © 2009 Keith Packard
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see http://www.gnu.org/licenses/ .
18  *
19  * Authors: Carl Worth <cworth@cworth.org>
20  *          Keith Packard <keithp@keithp.com>
21  */
22
23 #include "notmuch-client.h"
24
25 static void
26 show_message_part (GMimeObject *part,
27                    int *part_count,
28                    const notmuch_show_format_t *format,
29                    int first)
30 {
31     *part_count += 1;
32
33     if (! (GMIME_IS_PART (part) || GMIME_IS_MULTIPART (part) || GMIME_IS_MESSAGE_PART (part))) {
34         fprintf (stderr, "Warning: Not displaying unknown mime part: %s.\n",
35                  g_type_name (G_OBJECT_TYPE (part)));
36         return;
37     }
38
39     if (!first)
40         fputs (format->part_sep, stdout);
41
42     format->part (part, part_count);
43
44     if (GMIME_IS_MULTIPART (part)) {
45         GMimeMultipart *multipart = GMIME_MULTIPART (part);
46         int i;
47
48         for (i = 0; i < g_mime_multipart_get_count (multipart); i++) {
49             show_message_part (g_mime_multipart_get_part (multipart, i),
50                                part_count, format, i == 0);
51         }
52
53     } else if (GMIME_IS_MESSAGE_PART (part)) {
54         GMimeMessage *mime_message;
55
56         mime_message = g_mime_message_part_get_message (GMIME_MESSAGE_PART (part));
57
58         show_message_part (g_mime_message_get_mime_part (mime_message),
59                            part_count, format, first);
60     }
61
62     if (format->part_end)
63         format->part_end (part);
64 }
65
66 notmuch_status_t
67 show_message_body (const char *filename,
68                    const notmuch_show_format_t *format)
69 {
70     GMimeStream *stream = NULL;
71     GMimeParser *parser = NULL;
72     GMimeMessage *mime_message = NULL;
73     notmuch_status_t ret = NOTMUCH_STATUS_SUCCESS;
74     FILE *file = NULL;
75     int part_count = 0;
76
77     file = fopen (filename, "r");
78     if (! file) {
79         fprintf (stderr, "Error opening %s: %s\n", filename, strerror (errno));
80         ret = NOTMUCH_STATUS_FILE_ERROR;
81         goto DONE;
82     }
83
84     stream = g_mime_stream_file_new (file);
85     g_mime_stream_file_set_owner (GMIME_STREAM_FILE (stream), FALSE);
86
87     parser = g_mime_parser_new_with_stream (stream);
88
89     mime_message = g_mime_parser_construct_message (parser);
90
91     show_message_part (g_mime_message_get_mime_part (mime_message),
92                        &part_count,
93                        format,
94                        TRUE);
95
96   DONE:
97     if (mime_message)
98         g_object_unref (mime_message);
99
100     if (parser)
101         g_object_unref (parser);
102
103     if (stream)
104         g_object_unref (stream);
105
106     if (file)
107         fclose (file);
108
109     return ret;
110 }
111
112 static void
113 show_one_part_output (GMimeObject *part)
114 {
115     GMimeStream *stream_filter = NULL;
116     GMimeDataWrapper *wrapper;
117     GMimeStream *stream_stdout = g_mime_stream_file_new (stdout);
118
119     stream_filter = g_mime_stream_filter_new(stream_stdout);
120     wrapper = g_mime_part_get_content_object (GMIME_PART (part));
121     if (wrapper && stream_filter)
122         g_mime_data_wrapper_write_to_stream (wrapper, stream_filter);
123     if (stream_filter)
124         g_object_unref(stream_filter);
125 }
126
127 static void
128 show_one_part_worker (GMimeObject *part, int *part_count, int desired_part)
129 {
130     if (GMIME_IS_MULTIPART (part)) {
131         GMimeMultipart *multipart = GMIME_MULTIPART (part);
132         int i;
133
134         *part_count = *part_count + 1;
135
136         for (i = 0; i < g_mime_multipart_get_count (multipart); i++) {
137                 show_one_part_worker (g_mime_multipart_get_part (multipart, i),
138                                       part_count, desired_part);
139         }
140         return;
141     }
142
143     if (GMIME_IS_MESSAGE_PART (part)) {
144         GMimeMessage *mime_message;
145
146         mime_message = g_mime_message_part_get_message (GMIME_MESSAGE_PART (part));
147
148         show_one_part_worker (g_mime_message_get_mime_part (mime_message),
149                               part_count, desired_part);
150
151         return;
152     }
153
154     if (! (GMIME_IS_PART (part)))
155         return;
156
157     *part_count = *part_count + 1;
158
159     if (*part_count == desired_part)
160             show_one_part_output (part);
161 }
162
163 notmuch_status_t
164 show_one_part (const char *filename, int part)
165 {
166         GMimeStream *stream = NULL;
167         GMimeParser *parser = NULL;
168         GMimeMessage *mime_message = NULL;
169         notmuch_status_t ret = NOTMUCH_STATUS_SUCCESS;
170         FILE *file = NULL;
171         int part_count = 0;
172
173         file = fopen (filename, "r");
174         if (! file) {
175                 fprintf (stderr, "Error opening %s: %s\n", filename, strerror (errno));
176                 ret = NOTMUCH_STATUS_FILE_ERROR;
177                 goto DONE;
178         }
179
180         stream = g_mime_stream_file_new (file);
181         g_mime_stream_file_set_owner (GMIME_STREAM_FILE (stream), FALSE);
182
183         parser = g_mime_parser_new_with_stream (stream);
184
185         mime_message = g_mime_parser_construct_message (parser);
186
187         show_one_part_worker (g_mime_message_get_mime_part (mime_message),
188                               &part_count, part);
189
190  DONE:
191         if (mime_message)
192                 g_object_unref (mime_message);
193
194         if (parser)
195                 g_object_unref (parser);
196
197         if (stream)
198                 g_object_unref (stream);
199
200         if (file)
201                 fclose (file);
202
203         return ret;
204 }