]> git.notmuchmail.org Git - notmuch/blob - gmime-filter-reply.c
configure: fix mktemp call for macOS
[notmuch] / gmime-filter-reply.c
1 /*
2  * Copyright © 2009 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
17  */
18
19 #include <stdbool.h>
20
21 #include "gmime-filter-reply.h"
22 #include "notmuch-client.h"
23
24 /**
25  * SECTION: gmime-filter-reply
26  * @title: GMimeFilterReply
27  * @short_description: Add/remove reply markers
28  *
29  * A #GMimeFilter for adding or removing reply markers
30  **/
31
32
33 static void g_mime_filter_reply_class_init (GMimeFilterReplyClass *klass, void *class_data);
34 static void g_mime_filter_reply_init (GMimeFilterReply *filter, GMimeFilterReplyClass *klass);
35 static void g_mime_filter_reply_finalize (GObject *object);
36
37 static GMimeFilter *filter_copy (GMimeFilter *filter);
38 static void filter_filter (GMimeFilter *filter, char *in, size_t len, size_t prespace,
39                            char **out, size_t *outlen, size_t *outprespace);
40 static void filter_complete (GMimeFilter *filter, char *in, size_t len, size_t prespace,
41                              char **out, size_t *outlen, size_t *outprespace);
42 static void filter_reset (GMimeFilter *filter);
43
44
45 static GMimeFilterClass *parent_class = NULL;
46
47 GType
48 g_mime_filter_reply_get_type (void)
49 {
50         static GType type = 0;
51
52         if (!type) {
53                 static const GTypeInfo info = {
54                         .class_size = sizeof (GMimeFilterReplyClass),
55                         .base_init = NULL,
56                         .base_finalize = NULL,
57                         .class_init = (GClassInitFunc) g_mime_filter_reply_class_init,
58                         .class_finalize = NULL,
59                         .class_data = NULL,
60                         .instance_size = sizeof (GMimeFilterReply),
61                         .n_preallocs = 0,
62                         .instance_init = (GInstanceInitFunc) g_mime_filter_reply_init,
63                         .value_table = NULL,
64                 };
65
66                 type = g_type_register_static (GMIME_TYPE_FILTER, "GMimeFilterReply", &info, (GTypeFlags) 0);
67         }
68
69         return type;
70 }
71
72
73 static void
74 g_mime_filter_reply_class_init (GMimeFilterReplyClass *klass, unused (void *class_data))
75 {
76         GObjectClass *object_class = G_OBJECT_CLASS (klass);
77         GMimeFilterClass *filter_class = GMIME_FILTER_CLASS (klass);
78
79         parent_class = (GMimeFilterClass *) g_type_class_ref (GMIME_TYPE_FILTER);
80
81         object_class->finalize = g_mime_filter_reply_finalize;
82
83         filter_class->copy = filter_copy;
84         filter_class->filter = filter_filter;
85         filter_class->complete = filter_complete;
86         filter_class->reset = filter_reset;
87 }
88
89 static void
90 g_mime_filter_reply_init (GMimeFilterReply *filter, GMimeFilterReplyClass *klass)
91 {
92         (void) klass;
93         filter->saw_nl = true;
94         filter->saw_angle = false;
95 }
96
97 static void
98 g_mime_filter_reply_finalize (GObject *object)
99 {
100         G_OBJECT_CLASS (parent_class)->finalize (object);
101 }
102
103
104 static GMimeFilter *
105 filter_copy (GMimeFilter *filter)
106 {
107         GMimeFilterReply *reply = (GMimeFilterReply *) filter;
108
109         return g_mime_filter_reply_new (reply->encode);
110 }
111
112 static void
113 filter_filter (GMimeFilter *filter, char *inbuf, size_t inlen, size_t prespace,
114                char **outbuf, size_t *outlen, size_t *outprespace)
115 {
116         GMimeFilterReply *reply = (GMimeFilterReply *) filter;
117         const char *inptr = inbuf;
118         const char *inend = inbuf + inlen;
119         char *outptr;
120
121         (void) prespace;
122         if (reply->encode) {
123                 g_mime_filter_set_size (filter, 3 * inlen, false);
124
125                 outptr = filter->outbuf;
126                 while (inptr < inend) {
127                         if (reply->saw_nl) {
128                                 *outptr++ = '>';
129                                 *outptr++ = ' ';
130                                 reply->saw_nl = false;
131                         }
132                         if (*inptr == '\n')
133                                 reply->saw_nl = true;
134                         else
135                                 reply->saw_nl = false;
136                         if (*inptr != '\r')
137                                 *outptr++ = *inptr;
138                         inptr++;
139                 }
140         } else {
141                 g_mime_filter_set_size (filter, inlen + 1, false);
142
143                 outptr = filter->outbuf;
144                 while (inptr < inend) {
145                         if (reply->saw_nl) {
146                                 if (*inptr == '>')
147                                         reply->saw_angle = true;
148                                 else
149                                         *outptr++ = *inptr;
150                                 reply->saw_nl = false;
151                         } else if (reply->saw_angle) {
152                                 if (*inptr == ' ')
153                                         ;
154                                 else
155                                         *outptr++ = *inptr;
156                                 reply->saw_angle = false;
157                         } else if (*inptr != '\r') {
158                                 if (*inptr == '\n')
159                                         reply->saw_nl = true;
160                                 *outptr++ = *inptr;
161                         }
162
163                         inptr++;
164                 }
165         }
166
167         *outlen = outptr - filter->outbuf;
168         *outprespace = filter->outpre;
169         *outbuf = filter->outbuf;
170 }
171
172 static void
173 filter_complete (GMimeFilter *filter, char *inbuf, size_t inlen, size_t prespace,
174                  char **outbuf, size_t *outlen, size_t *outprespace)
175 {
176         if (inbuf && inlen)
177                 filter_filter (filter, inbuf, inlen, prespace, outbuf, outlen, outprespace);
178 }
179
180 static void
181 filter_reset (GMimeFilter *filter)
182 {
183         GMimeFilterReply *reply = (GMimeFilterReply *) filter;
184
185         reply->saw_nl = true;
186         reply->saw_angle = false;
187 }
188
189
190 /**
191  * g_mime_filter_reply_new:
192  * @encode: %true if the filter should encode or %false otherwise
193  * @dots: encode/decode dots (as for SMTP)
194  *
195  * Creates a new #GMimeFilterReply filter.
196  *
197  * If @encode is %true, then all lines will be prefixed by "> ",
198  * otherwise any lines starting with "> " will have that removed
199  *
200  * Returns: a new #GMimeFilterReply filter.
201  **/
202 GMimeFilter *
203 g_mime_filter_reply_new (gboolean encode)
204 {
205         GMimeFilterReply *new_reply;
206
207         new_reply = (GMimeFilterReply *) g_object_new (GMIME_TYPE_FILTER_REPLY, NULL);
208         new_reply->encode = encode;
209
210         return (GMimeFilter *) new_reply;
211 }
212