1 /* Copyright (c) 2007, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 /* modest-stream-text-to-html.c */
33 #include "modest-stream-text-to-html.h"
34 #include <tny-stream.h>
36 #include <modest-text-utils.h>
38 #define HTML_PREFIX "<html><head>" \
39 "<meta http-equiv=\"content-type\" content=\"text/html; charset=utf8\">" \
42 #define HTML_SUFFIX "</p></body></html>"
45 /* 'private'/'protected' functions */
46 static void modest_stream_text_to_html_class_init (ModestStreamTextToHtmlClass *klass);
47 static void modest_stream_text_to_html_init (ModestStreamTextToHtml *obj);
48 static void modest_stream_text_to_html_finalize (GObject *obj);
50 static void modest_stream_text_to_html_iface_init (gpointer g_iface, gpointer iface_data);
51 static gboolean write_line (TnyStream *self, const gchar *str, gboolean convert_to_html);
54 typedef struct _ModestStreamTextToHtmlPrivate ModestStreamTextToHtmlPrivate;
55 struct _ModestStreamTextToHtmlPrivate {
56 TnyStream *out_stream;
58 gboolean written_prefix;
63 gsize total_lines_output;
65 #define MODEST_STREAM_TEXT_TO_HTML_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
66 MODEST_TYPE_STREAM_TEXT_TO_HTML, \
67 ModestStreamTextToHtmlPrivate))
69 static GObjectClass *parent_class = NULL;
72 modest_stream_text_to_html_get_type (void)
74 static GType my_type = 0;
76 static const GTypeInfo my_info = {
77 sizeof(ModestStreamTextToHtmlClass),
79 NULL, /* base finalize */
80 (GClassInitFunc) modest_stream_text_to_html_class_init,
81 NULL, /* class finalize */
82 NULL, /* class data */
83 sizeof(ModestStreamTextToHtml),
85 (GInstanceInitFunc) modest_stream_text_to_html_init,
89 static const GInterfaceInfo iface_info = {
90 (GInterfaceInitFunc) modest_stream_text_to_html_iface_init,
91 NULL, /* interface_finalize */
92 NULL /* interface_data */
95 my_type = g_type_register_static (G_TYPE_OBJECT,
96 "ModestStreamTextToHtml",
99 g_type_add_interface_static (my_type, TNY_TYPE_STREAM,
107 modest_stream_text_to_html_class_init (ModestStreamTextToHtmlClass *klass)
109 GObjectClass *gobject_class;
110 gobject_class = (GObjectClass*) klass;
112 parent_class = g_type_class_peek_parent (klass);
113 gobject_class->finalize = modest_stream_text_to_html_finalize;
115 g_type_class_add_private (gobject_class, sizeof(ModestStreamTextToHtmlPrivate));
119 modest_stream_text_to_html_init (ModestStreamTextToHtml *obj)
121 ModestStreamTextToHtmlPrivate *priv;
122 priv = MODEST_STREAM_TEXT_TO_HTML_GET_PRIVATE(obj);
124 priv->out_stream = NULL;
125 priv->written_prefix = FALSE;
126 priv->line_buffer = NULL;
127 priv->linkify_limit = 0;
128 priv->full_limit = 0;
129 priv->total_output = 0;
130 priv->total_lines_output = 0;
131 modest_text_utils_hyperlinkify_begin ();
135 modest_stream_text_to_html_finalize (GObject *obj)
137 ModestStreamTextToHtmlPrivate *priv;
139 priv = MODEST_STREAM_TEXT_TO_HTML_GET_PRIVATE(obj);
140 if (priv->out_stream)
141 g_object_unref (priv->out_stream);
142 priv->out_stream = NULL;
143 if (priv->line_buffer != NULL) {
144 g_string_free (priv->line_buffer, TRUE);
146 modest_text_utils_hyperlinkify_end ();
150 modest_stream_text_to_html_new (TnyStream *out_stream)
153 ModestStreamTextToHtmlPrivate *priv;
155 obj = G_OBJECT(g_object_new(MODEST_TYPE_STREAM_TEXT_TO_HTML, NULL));
156 priv = MODEST_STREAM_TEXT_TO_HTML_GET_PRIVATE(obj);
158 g_return_val_if_fail (out_stream, NULL);
160 priv->out_stream = g_object_ref (out_stream);
166 modest_stream_text_to_html_set_line_limit (ModestStreamTextToHtml *self, gssize limit)
168 ModestStreamTextToHtmlPrivate *priv = MODEST_STREAM_TEXT_TO_HTML_GET_PRIVATE (self);
169 priv->line_limit = limit;
173 modest_stream_text_to_html_set_linkify_limit (ModestStreamTextToHtml *self, gssize limit)
175 ModestStreamTextToHtmlPrivate *priv = MODEST_STREAM_TEXT_TO_HTML_GET_PRIVATE (self);
176 priv->linkify_limit = limit;
180 modest_stream_text_to_html_set_full_limit (ModestStreamTextToHtml *self, gssize limit)
182 ModestStreamTextToHtmlPrivate *priv = MODEST_STREAM_TEXT_TO_HTML_GET_PRIVATE (self);
183 priv->full_limit = limit;
187 modest_stream_text_to_html_limit_reached (ModestStreamTextToHtml *self)
189 ModestStreamTextToHtmlPrivate *priv = MODEST_STREAM_TEXT_TO_HTML_GET_PRIVATE (self);
191 return (priv->full_limit > 0 && priv->total_output > priv->full_limit) ||
192 (priv->line_limit > 0 && priv->total_lines_output > priv->line_limit);
196 /* the rest are interface functions */
200 text_to_html_read (TnyStream *self, char *buffer, size_t n)
202 return -1; /* we cannot read */
206 write_line (TnyStream *self, const gchar *str, gboolean convert_to_html)
208 ModestStreamTextToHtmlPrivate *priv = MODEST_STREAM_TEXT_TO_HTML_GET_PRIVATE (self);
211 gssize pending_bytes;
212 gboolean hyperlinkify = TRUE;
214 /* we only leave for full limit if we're converting to html, so that we
215 preserve the prefix and suffix */
216 if (convert_to_html && (priv->full_limit > 0) &&(priv->total_output > priv->full_limit))
218 if (convert_to_html && (priv->line_limit > 0) && (priv->total_lines_output > priv->line_limit))
220 if ((priv->linkify_limit > 0) && (priv->total_output > priv->linkify_limit))
221 hyperlinkify = FALSE;
222 if (convert_to_html) {
223 html_buffer = modest_text_utils_convert_to_html_body (str, -1, hyperlinkify);
225 html_buffer = (gchar *) str;
228 pending_bytes = strlen (html_buffer);
229 priv->total_output += pending_bytes;
230 priv->total_lines_output ++;
231 offset = html_buffer;
233 while (pending_bytes > 0) {
234 gssize written_bytes = 0;
235 written_bytes = tny_stream_write (priv->out_stream, offset, pending_bytes);
236 if (written_bytes < 0) {
238 g_free (html_buffer);
241 offset += written_bytes;
242 pending_bytes -= written_bytes;
245 g_free (html_buffer);
251 text_to_html_write (TnyStream *self, const char *buffer, size_t n)
254 ModestStreamTextToHtmlPrivate *priv = MODEST_STREAM_TEXT_TO_HTML_GET_PRIVATE (self);
257 modest_text_utils_hyperlinkify_begin ();
258 if ((!priv->written_prefix) && (n > 0)) {
259 if (!write_line (self, HTML_PREFIX, FALSE)) {
260 modest_text_utils_hyperlinkify_end ();
263 priv->written_prefix = TRUE;
269 if ((priv->full_limit > 0) && (priv->total_output > priv->full_limit))
271 if ((priv->line_limit > 0) && (priv->total_lines_output > priv->line_limit))
274 if (priv->line_buffer == NULL)
275 priv->line_buffer = g_string_new (NULL);
277 priv->line_buffer = g_string_append_c (priv->line_buffer, c);
279 if (tny_stream_flush (self) == -1) {
280 modest_text_utils_hyperlinkify_end ();
287 modest_text_utils_hyperlinkify_end ();
293 text_to_html_flush (TnyStream *self)
295 ModestStreamTextToHtmlPrivate *priv = MODEST_STREAM_TEXT_TO_HTML_GET_PRIVATE (self);
297 if (priv->line_buffer != NULL) {
298 if (!write_line (self, priv->line_buffer->str, TRUE))
300 g_string_free (priv->line_buffer, TRUE);
301 priv->line_buffer = NULL;
308 text_to_html_close (TnyStream *self)
310 ModestStreamTextToHtmlPrivate *priv;
311 g_return_val_if_fail (self, 0);
312 priv = MODEST_STREAM_TEXT_TO_HTML_GET_PRIVATE(self);
314 tny_stream_flush (self);
315 if (!write_line (self, HTML_SUFFIX, FALSE))
318 tny_stream_close (priv->out_stream);
320 priv->out_stream = NULL;
327 text_to_html_is_eos (TnyStream *self)
335 text_to_html_reset (TnyStream *self)
342 text_to_html_write_to_stream (TnyStream *self, TnyStream *output)
349 modest_stream_text_to_html_iface_init (gpointer g_iface, gpointer iface_data)
351 TnyStreamIface *klass;
353 g_return_if_fail (g_iface);
355 klass = (TnyStreamIface*) g_iface;
357 klass->read = text_to_html_read;
358 klass->write = text_to_html_write;
359 klass->flush = text_to_html_flush;
360 klass->close = text_to_html_close;
361 klass->is_eos = text_to_html_is_eos;
362 klass->reset = text_to_html_reset;
363 klass->write_to_stream = text_to_html_write_to_stream;