Extending test-client-custom-summary to try e_book_client_get_contacts_uids()
[platform/upstream/evolution-data-server.git] / camel / camel-mime-filter-crlf.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  *  Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
4  *
5  *  Authors: Dan Winship <danw@ximian.com>
6  *           Jeffrey Stedfast <fejj@ximian.com>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of version 2 of the GNU Lesser General Public
10  * License as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this program; if not, write to the
19  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22
23 #include "camel-mime-filter-crlf.h"
24
25 #define CAMEL_MIME_FILTER_CRLF_GET_PRIVATE(obj) \
26         (G_TYPE_INSTANCE_GET_PRIVATE \
27         ((obj), CAMEL_TYPE_MIME_FILTER_CRLF, CamelMimeFilterCRLFPrivate))
28
29 struct _CamelMimeFilterCRLFPrivate {
30         CamelMimeFilterCRLFDirection direction;
31         CamelMimeFilterCRLFMode mode;
32         gboolean saw_cr;
33         gboolean saw_lf;
34         gboolean saw_dot;
35 };
36
37 G_DEFINE_TYPE (CamelMimeFilterCRLF, camel_mime_filter_crlf, CAMEL_TYPE_MIME_FILTER)
38
39 static void
40 mime_filter_crlf_filter (CamelMimeFilter *mime_filter,
41                          const gchar *in,
42                          gsize len,
43                          gsize prespace,
44                          gchar **out,
45                          gsize *outlen,
46                          gsize *outprespace)
47 {
48         CamelMimeFilterCRLFPrivate *priv;
49         register const gchar *inptr;
50         const gchar *inend;
51         gboolean do_dots;
52         gchar *outptr;
53
54         priv = CAMEL_MIME_FILTER_CRLF_GET_PRIVATE (mime_filter);
55
56         do_dots = priv->mode == CAMEL_MIME_FILTER_CRLF_MODE_CRLF_DOTS;
57
58         inptr = in;
59         inend = in + len;
60
61         if (priv->direction == CAMEL_MIME_FILTER_CRLF_ENCODE) {
62                 camel_mime_filter_set_size (mime_filter, 3 * len, FALSE);
63
64                 outptr = mime_filter->outbuf;
65                 while (inptr < inend) {
66                         if (*inptr == '\r') {
67                                 priv->saw_cr = TRUE;
68                         } else if (*inptr == '\n') {
69                                 priv->saw_lf = TRUE;
70                                 if (!priv->saw_cr)
71                                         *outptr++ = '\r';
72                                 priv->saw_cr = FALSE;
73                         } else {
74                                 if (do_dots && *inptr == '.' && priv->saw_lf)
75                                         *outptr++ = '.';
76
77                                 priv->saw_cr = FALSE;
78                                 priv->saw_lf = FALSE;
79                         }
80
81                         *outptr++ = *inptr++;
82                 }
83         } else {
84                 /* Output can "grow" by one byte if priv->saw_cr was set as
85                  * a carry-over from the previous invocation. This will happen
86                  * in practice, as the input is processed in arbitrarily-sized
87                  * blocks. */
88                 camel_mime_filter_set_size (mime_filter, len + 1, FALSE);
89
90                 outptr = mime_filter->outbuf;
91                 while (inptr < inend) {
92                         if (*inptr == '\r') {
93                                 priv->saw_cr = TRUE;
94                         } else {
95                                 if (priv->saw_cr) {
96                                         priv->saw_cr = FALSE;
97
98                                         if (*inptr == '\n') {
99                                                 priv->saw_lf = TRUE;
100                                                 *outptr++ = *inptr++;
101                                                 continue;
102                                         } else
103                                                 *outptr++ = '\r';
104                                 }
105
106                                 *outptr++ = *inptr;
107                         }
108
109                         if (do_dots && *inptr == '.') {
110                                 if (priv->saw_lf) {
111                                         priv->saw_dot = TRUE;
112                                         priv->saw_lf = FALSE;
113                                         inptr++;
114                                 } else if (priv->saw_dot) {
115                                         priv->saw_dot = FALSE;
116                                 }
117                         }
118
119                         priv->saw_lf = FALSE;
120
121                         inptr++;
122                 }
123         }
124
125         *out = mime_filter->outbuf;
126         *outlen = outptr - mime_filter->outbuf;
127         *outprespace = mime_filter->outpre;
128 }
129
130 static void
131 mime_filter_crlf_complete (CamelMimeFilter *mime_filter,
132                            const gchar *in,
133                            gsize len,
134                            gsize prespace,
135                            gchar **out,
136                            gsize *outlen,
137                            gsize *outprespace)
138 {
139         if (len)
140                 mime_filter_crlf_filter (
141                         mime_filter, in, len, prespace,
142                         out, outlen, outprespace);
143 }
144
145 static void
146 mime_filter_crlf_reset (CamelMimeFilter *mime_filter)
147 {
148         CamelMimeFilterCRLFPrivate *priv;
149
150         priv = CAMEL_MIME_FILTER_CRLF_GET_PRIVATE (mime_filter);
151
152         priv->saw_cr = FALSE;
153         priv->saw_lf = TRUE;
154         priv->saw_dot = FALSE;
155 }
156
157 static void
158 camel_mime_filter_crlf_class_init (CamelMimeFilterCRLFClass *class)
159 {
160         CamelMimeFilterClass *mime_filter_class;
161
162         g_type_class_add_private (class, sizeof (CamelMimeFilterCRLFPrivate));
163
164         mime_filter_class = CAMEL_MIME_FILTER_CLASS (class);
165         mime_filter_class->filter = mime_filter_crlf_filter;
166         mime_filter_class->complete = mime_filter_crlf_complete;
167         mime_filter_class->reset = mime_filter_crlf_reset;
168 }
169
170 static void
171 camel_mime_filter_crlf_init (CamelMimeFilterCRLF *filter)
172 {
173         filter->priv = CAMEL_MIME_FILTER_CRLF_GET_PRIVATE (filter);
174
175         filter->priv->saw_cr = FALSE;
176         filter->priv->saw_lf = TRUE;
177         filter->priv->saw_dot = FALSE;
178 }
179
180 /**
181  * camel_mime_filter_crlf_new:
182  * @direction: encode vs decode
183  * @mode: whether or not to perform SMTP dot-escaping
184  *
185  * Create a new #CamelMimeFiletrCRLF object.
186  *
187  * Returns: a new #CamelMimeFilterCRLF object
188  **/
189 CamelMimeFilter *
190 camel_mime_filter_crlf_new (CamelMimeFilterCRLFDirection direction,
191                             CamelMimeFilterCRLFMode mode)
192 {
193         CamelMimeFilter *filter;
194         CamelMimeFilterCRLFPrivate *priv;
195
196         filter = g_object_new (CAMEL_TYPE_MIME_FILTER_CRLF, NULL);
197         priv = CAMEL_MIME_FILTER_CRLF_GET_PRIVATE (filter);
198
199         priv->direction = direction;
200         priv->mode = mode;
201
202         return filter;
203 }