1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /* camelMedium.c : Abstract class for a medium
3  *
4  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
5  *
6  * This library is free software: you can redistribute it and/or modify it
7  * under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation.
9  *
10  * This library is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13  * for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with this library. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * Authors: Bertrand Guiheneuf <bertrand@helixcode.com>
19  *	    Michael Zucchi <notzed@ximian.com>
20  */
21 
22 #include "evolution-data-server-config.h"
23 
24 #include <ctype.h>
25 #include <stdio.h>
26 
27 #include "camel-medium.h"
28 
29 #define d(x)
30 
31 struct _CamelMediumPrivate {
32 	/* The content of the medium, as opposed to our parent
33 	 * CamelDataWrapper, which wraps both the headers and
34 	 * the content. */
35 	CamelDataWrapper *content;
36 };
37 
38 enum {
39 	PROP_0,
40 	PROP_CONTENT
41 };
42 
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE(CamelMedium,camel_medium,CAMEL_TYPE_DATA_WRAPPER)43 G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (CamelMedium, camel_medium, CAMEL_TYPE_DATA_WRAPPER)
44 
45 static void
46 medium_set_property (GObject *object,
47                      guint property_id,
48                      const GValue *value,
49                      GParamSpec *pspec)
50 {
51 	switch (property_id) {
52 		case PROP_CONTENT:
53 			camel_medium_set_content (
54 				CAMEL_MEDIUM (object),
55 				g_value_get_object (value));
56 			return;
57 	}
58 
59 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
60 }
61 
62 static void
medium_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)63 medium_get_property (GObject *object,
64                      guint property_id,
65                      GValue *value,
66                      GParamSpec *pspec)
67 {
68 	switch (property_id) {
69 		case PROP_CONTENT:
70 			g_value_set_object (
71 				value, camel_medium_get_content (
72 				CAMEL_MEDIUM (object)));
73 			return;
74 	}
75 
76 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
77 }
78 
79 static void
medium_dispose(GObject * object)80 medium_dispose (GObject *object)
81 {
82 	CamelMediumPrivate *priv;
83 
84 	priv = CAMEL_MEDIUM (object)->priv;
85 	g_clear_object (&priv->content);
86 
87 	/* Chain up to parent's dispose() method. */
88 	G_OBJECT_CLASS (camel_medium_parent_class)->dispose (object);
89 }
90 
91 static gboolean
medium_is_offline(CamelDataWrapper * data_wrapper)92 medium_is_offline (CamelDataWrapper *data_wrapper)
93 {
94 	CamelDataWrapper *content;
95 
96 	content = camel_medium_get_content (CAMEL_MEDIUM (data_wrapper));
97 
98 	return CAMEL_DATA_WRAPPER_CLASS (camel_medium_parent_class)->is_offline (data_wrapper) ||
99 		camel_data_wrapper_is_offline (content);
100 }
101 
102 static void
medium_set_content(CamelMedium * medium,CamelDataWrapper * content)103 medium_set_content (CamelMedium *medium,
104                     CamelDataWrapper *content)
105 {
106 	if (medium->priv->content == content)
107 		return;
108 
109 	if (content != NULL)
110 		g_object_ref (content);
111 
112 	if (medium->priv->content != NULL)
113 		g_object_unref (medium->priv->content);
114 
115 	medium->priv->content = content;
116 
117 	g_object_notify (G_OBJECT (medium), "content");
118 }
119 
120 static CamelDataWrapper *
medium_get_content(CamelMedium * medium)121 medium_get_content (CamelMedium *medium)
122 {
123 	return medium->priv->content;
124 }
125 
126 static void
camel_medium_class_init(CamelMediumClass * class)127 camel_medium_class_init (CamelMediumClass *class)
128 {
129 	GObjectClass *object_class;
130 	CamelDataWrapperClass *data_wrapper_class;
131 
132 	object_class = G_OBJECT_CLASS (class);
133 	object_class->set_property = medium_set_property;
134 	object_class->get_property = medium_get_property;
135 	object_class->dispose = medium_dispose;
136 
137 	data_wrapper_class = CAMEL_DATA_WRAPPER_CLASS (class);
138 	data_wrapper_class->is_offline = medium_is_offline;
139 
140 	class->set_content = medium_set_content;
141 	class->get_content = medium_get_content;
142 
143 	g_object_class_install_property (
144 		object_class,
145 		PROP_CONTENT,
146 		g_param_spec_object (
147 			"content",
148 			"Content",
149 			NULL,
150 			CAMEL_TYPE_DATA_WRAPPER,
151 			G_PARAM_READWRITE |
152 			G_PARAM_EXPLICIT_NOTIFY));
153 }
154 
155 static void
camel_medium_init(CamelMedium * medium)156 camel_medium_init (CamelMedium *medium)
157 {
158 	medium->priv = camel_medium_get_instance_private (medium);
159 }
160 
161 /**
162  * camel_medium_add_header:
163  * @medium: a #CamelMedium object
164  * @name: name of the header
165  * @value: value of the header
166  *
167  * Adds a header to a #CamelMedium.
168  **/
169 void
camel_medium_add_header(CamelMedium * medium,const gchar * name,const gchar * value)170 camel_medium_add_header (CamelMedium *medium,
171                          const gchar *name,
172                          const gchar *value)
173 {
174 	CamelMediumClass *class;
175 
176 	g_return_if_fail (CAMEL_IS_MEDIUM (medium));
177 	g_return_if_fail (name != NULL);
178 	g_return_if_fail (value != NULL);
179 
180 	class = CAMEL_MEDIUM_GET_CLASS (medium);
181 	g_return_if_fail (class != NULL);
182 	g_return_if_fail (class->add_header != NULL);
183 
184 	class->add_header (medium, name, value);
185 }
186 
187 /**
188  * camel_medium_set_header:
189  * @medium: a #CamelMedium object
190  * @name: name of the header
191  * @value: value of the header
192  *
193  * Sets the value of a header.  Any other occurances of the header
194  * will be removed.  Setting a %NULL header can be used to remove
195  * the header also.
196  **/
197 void
camel_medium_set_header(CamelMedium * medium,const gchar * name,const gchar * value)198 camel_medium_set_header (CamelMedium *medium,
199                          const gchar *name,
200                          const gchar *value)
201 {
202 	CamelMediumClass *class;
203 
204 	g_return_if_fail (CAMEL_IS_MEDIUM (medium));
205 	g_return_if_fail (name != NULL);
206 
207 	if (value == NULL) {
208 		camel_medium_remove_header (medium, name);
209 		return;
210 	}
211 
212 	class = CAMEL_MEDIUM_GET_CLASS (medium);
213 	g_return_if_fail (class != NULL);
214 	g_return_if_fail (class->set_header != NULL);
215 
216 	class->set_header (medium, name, value);
217 }
218 
219 /**
220  * camel_medium_remove_header:
221  * @medium: a #CamelMedium
222  * @name: the name of the header
223  *
224  * Removes the named header from the medium.  All occurances of the
225  * header are removed.
226  **/
227 void
camel_medium_remove_header(CamelMedium * medium,const gchar * name)228 camel_medium_remove_header (CamelMedium *medium,
229                             const gchar *name)
230 {
231 	CamelMediumClass *class;
232 
233 	g_return_if_fail (CAMEL_IS_MEDIUM (medium));
234 	g_return_if_fail (name != NULL);
235 
236 	class = CAMEL_MEDIUM_GET_CLASS (medium);
237 	g_return_if_fail (class != NULL);
238 	g_return_if_fail (class->remove_header != NULL);
239 
240 	class->remove_header (medium, name);
241 }
242 
243 /**
244  * camel_medium_get_header:
245  * @medium: a #CamelMedium
246  * @name: the name of the header
247  *
248  * Gets the value of the named header in the medium, or %NULL if
249  * it is unset. The caller should not modify or free the data.
250  *
251  * If the header occurs more than once, only retrieve the first
252  * instance of the header.  For multi-occuring headers, use
253  * camel_medium_dup_headers() or camel_medium_get_headers().
254  *
255  * Returns: (nullable): the value of the named header, or %NULL
256  **/
257 const gchar *
camel_medium_get_header(CamelMedium * medium,const gchar * name)258 camel_medium_get_header (CamelMedium *medium,
259                          const gchar *name)
260 {
261 	CamelMediumClass *class;
262 
263 	g_return_val_if_fail (CAMEL_IS_MEDIUM (medium), NULL);
264 	g_return_val_if_fail (name != NULL, NULL);
265 
266 	class = CAMEL_MEDIUM_GET_CLASS (medium);
267 	g_return_val_if_fail (class != NULL, NULL);
268 	g_return_val_if_fail (class->get_header != NULL, NULL);
269 
270 	return class->get_header (medium, name);
271 }
272 
273 /**
274  * camel_medium_dup_headers:
275  * @medium: a #CamelMedium object
276  *
277  * Gets an array of all header name/value pairs. The values will be
278  * decoded to UTF-8 for any headers that are recognized by Camel.
279  * See also camel_medium_get_headers().
280  *
281  * Returns: (transfer full): the array of headers, which must be freed with camel_name_value_array_free().
282  *
283  * Since: 3.24
284  **/
285 CamelNameValueArray *
camel_medium_dup_headers(CamelMedium * medium)286 camel_medium_dup_headers (CamelMedium *medium)
287 {
288 	CamelMediumClass *class;
289 
290 	g_return_val_if_fail (CAMEL_IS_MEDIUM (medium), NULL);
291 
292 	class = CAMEL_MEDIUM_GET_CLASS (medium);
293 	g_return_val_if_fail (class != NULL, NULL);
294 	g_return_val_if_fail (class->dup_headers != NULL, NULL);
295 
296 	return class->dup_headers (medium);
297 }
298 
299 /**
300  * camel_medium_get_headers:
301  * @medium: a #CamelMedium object
302  *
303  * Gets an array of all header name/value pairs. The values will be
304  * decoded to UTF-8 for any headers that are recognized by Camel.
305  * See also camel_medium_dup_headers().
306  *
307  * Returns: (transfer none): the array of headers, owned by @medium.
308  *
309  * Since: 3.24
310  **/
311 const CamelNameValueArray *
camel_medium_get_headers(CamelMedium * medium)312 camel_medium_get_headers (CamelMedium *medium)
313 {
314 	CamelMediumClass *class;
315 
316 	g_return_val_if_fail (CAMEL_IS_MEDIUM (medium), NULL);
317 
318 	class = CAMEL_MEDIUM_GET_CLASS (medium);
319 	g_return_val_if_fail (class != NULL, NULL);
320 	g_return_val_if_fail (class->get_headers != NULL, NULL);
321 
322 	return class->get_headers (medium);
323 }
324 
325 /**
326  * camel_medium_get_content:
327  * @medium: a #CamelMedium object
328  *
329  * Gets a data wrapper that represents the content of the medium,
330  * without its headers.
331  *
332  * Returns: (transfer none) (nullable): a #CamelDataWrapper containing
333  * @medium's content. Can return NULL.
334  **/
335 CamelDataWrapper *
camel_medium_get_content(CamelMedium * medium)336 camel_medium_get_content (CamelMedium *medium)
337 {
338 	CamelMediumClass *class;
339 
340 	g_return_val_if_fail (CAMEL_IS_MEDIUM (medium), NULL);
341 
342 	class = CAMEL_MEDIUM_GET_CLASS (medium);
343 	g_return_val_if_fail (class != NULL, NULL);
344 	g_return_val_if_fail (class->get_content != NULL, NULL);
345 
346 	return class->get_content (medium);
347 }
348 
349 /**
350  * camel_medium_set_content:
351  * @medium: a #CamelMedium object
352  * @content: a #CamelDataWrapper object
353  *
354  * Sets the content of @medium to be @content.
355  **/
356 void
camel_medium_set_content(CamelMedium * medium,CamelDataWrapper * content)357 camel_medium_set_content (CamelMedium *medium,
358                           CamelDataWrapper *content)
359 {
360 	CamelMediumClass *class;
361 
362 	g_return_if_fail (CAMEL_IS_MEDIUM (medium));
363 
364 	if (content != NULL)
365 		g_return_if_fail (CAMEL_IS_DATA_WRAPPER (content));
366 
367 	class = CAMEL_MEDIUM_GET_CLASS (medium);
368 	g_return_if_fail (class != NULL);
369 	g_return_if_fail (class->set_content != NULL);
370 
371 	class->set_content (medium, content);
372 }
373