Initialize the gmime for upstream
[platform/upstream/gmime.git] / gmime / gmime-content-type.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*  GMime
3  *  Copyright (C) 2000-2012 Jeffrey Stedfast
4  *
5  *  This library is free software; you can redistribute it and/or
6  *  modify it under the terms of the GNU Lesser General Public License
7  *  as published by the Free Software Foundation; either version 2.1
8  *  of the License, or (at your option) any later version.
9  *
10  *  This library is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  *  Lesser General Public License for more details.
14  *
15  *  You should have received a copy of the GNU Lesser General Public
16  *  License along with this library; if not, write to the Free
17  *  Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
18  *  02110-1301, USA.
19  */
20
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdio.h>
27 #include <string.h>
28 #include <ctype.h>
29
30 #include "gmime-common.h"
31 #include "gmime-content-type.h"
32 #include "gmime-parse-utils.h"
33 #include "gmime-events.h"
34
35
36 #ifdef ENABLE_WARNINGS
37 #define w(x) x
38 #else
39 #define w(x)
40 #endif /* ENABLE_WARNINGS */
41
42 #define d(x)
43
44
45 /**
46  * SECTION: gmime-content-type
47  * @title: GMimeContentType
48  * @short_description: Content-Type fields
49  * @see_also:
50  *
51  * A #GMimeContentType represents the pre-parsed contents of a
52  * Content-Type header field.
53  **/
54
55
56 static void g_mime_content_type_class_init (GMimeContentTypeClass *klass);
57 static void g_mime_content_type_init (GMimeContentType *content_type, GMimeContentTypeClass *klass);
58 static void g_mime_content_type_finalize (GObject *object);
59
60
61 static GObjectClass *parent_class = NULL;
62
63
64 GType
65 g_mime_content_type_get_type (void)
66 {
67         static GType type = 0;
68         
69         if (!type) {
70                 static const GTypeInfo info = {
71                         sizeof (GMimeContentTypeClass),
72                         NULL, /* base_class_init */
73                         NULL, /* base_class_finalize */
74                         (GClassInitFunc) g_mime_content_type_class_init,
75                         NULL, /* class_finalize */
76                         NULL, /* class_data */
77                         sizeof (GMimeContentType),
78                         0,    /* n_preallocs */
79                         (GInstanceInitFunc) g_mime_content_type_init,
80                 };
81                 
82                 type = g_type_register_static (G_TYPE_OBJECT, "GMimeContentType", &info, 0);
83         }
84         
85         return type;
86 }
87
88
89 static void
90 g_mime_content_type_class_init (GMimeContentTypeClass *klass)
91 {
92         GObjectClass *object_class = G_OBJECT_CLASS (klass);
93         
94         parent_class = g_type_class_ref (G_TYPE_OBJECT);
95         
96         object_class->finalize = g_mime_content_type_finalize;
97 }
98
99 static void
100 g_mime_content_type_init (GMimeContentType *content_type, GMimeContentTypeClass *klass)
101 {
102         content_type->param_hash = g_hash_table_new (g_mime_strcase_hash, g_mime_strcase_equal);
103         content_type->priv = g_mime_event_new ((GObject *) content_type);
104         content_type->params = NULL;
105         content_type->subtype = NULL;
106         content_type->type = NULL;
107 }
108
109 static void
110 g_mime_content_type_finalize (GObject *object)
111 {
112         GMimeContentType *content_type = (GMimeContentType *) object;
113         
114         g_hash_table_destroy (content_type->param_hash);
115         g_mime_param_destroy (content_type->params);
116         g_mime_event_destroy (content_type->priv);
117         g_free (content_type->subtype);
118         g_free (content_type->type);
119         
120         G_OBJECT_CLASS (parent_class)->finalize (object);
121 }
122
123
124 /**
125  * g_mime_content_type_new:
126  * @type: MIME type (or %NULL for "text")
127  * @subtype: MIME subtype (or %NULL for "plain")
128  *
129  * Creates a Content-Type object with type @type and subtype @subtype.
130  *
131  * Returns: a new #GMimeContentType object.
132  **/
133 GMimeContentType *
134 g_mime_content_type_new (const char *type, const char *subtype)
135 {
136         GMimeContentType *mime_type;
137         
138         mime_type = g_object_newv (GMIME_TYPE_CONTENT_TYPE, 0, NULL);
139         
140         if (type && *type && subtype && *subtype) {
141                 mime_type->type = g_strdup (type);
142                 mime_type->subtype = g_strdup (subtype);
143         } else {
144                 if (type && *type) {
145                         mime_type->type = g_strdup (type);
146                         if (!g_ascii_strcasecmp (type, "text")) {
147                                 mime_type->subtype = g_strdup ("plain");
148                         } else if (!g_ascii_strcasecmp (type, "multipart")) {
149                                 mime_type->subtype = g_strdup ("mixed");
150                         } else {
151                                 g_free (mime_type->type);
152                                 mime_type->type = g_strdup ("application");
153                                 mime_type->subtype = g_strdup ("octet-stream");
154                         }
155                 } else {
156                         mime_type->type = g_strdup ("application");
157                         mime_type->subtype = g_strdup ("octet-stream");
158                 }
159                 
160                 w(g_warning ("Invalid or incomplete type: %s%s%s: defaulting to %s/%s",
161                              type ? type : "", subtype ? "/" : "", subtype ? subtype : "",
162                              mime_type->type, mime_type->subtype));
163         }
164         
165         return mime_type;
166 }
167
168
169 /**
170  * g_mime_content_type_new_from_string:
171  * @str: input string containing a content-type (and params)
172  *
173  * Constructs a new Content-Type object based on the input string.
174  *
175  * Returns: a new #GMimeContentType object based on the input string.
176  **/
177 GMimeContentType *
178 g_mime_content_type_new_from_string (const char *str)
179 {
180         GMimeContentType *mime_type;
181         const char *inptr = str;
182         char *type, *subtype;
183         
184         g_return_val_if_fail (str != NULL, NULL);
185         
186         if (!g_mime_parse_content_type (&inptr, &type, &subtype))
187                 return g_mime_content_type_new ("application", "octet-stream");
188         
189         mime_type = g_object_newv (GMIME_TYPE_CONTENT_TYPE, 0, NULL);
190         mime_type->subtype = subtype;
191         mime_type->type = type;
192         
193         /* skip past any remaining junk that shouldn't be here... */
194         decode_lwsp (&inptr);
195         while (*inptr && *inptr != ';')
196                 inptr++;
197         
198         if (*inptr++ == ';' && *inptr) {
199                 GMimeParam *param;
200                 
201                 param = mime_type->params = g_mime_param_new_from_string (inptr);
202                 while (param != NULL) {
203                         g_hash_table_insert (mime_type->param_hash, param->name, param);
204                         param = param->next;
205                 }
206         }
207         
208         return mime_type;
209 }
210
211
212 /**
213  * g_mime_content_type_to_string:
214  * @mime_type: a #GMimeContentType object
215  *
216  * Allocates a string buffer containing the type and subtype defined
217  * by the @mime_type.
218  *
219  * Returns: an allocated string containing the type and subtype of the
220  * content-type in the format: type/subtype.
221  **/
222 char *
223 g_mime_content_type_to_string (GMimeContentType *mime_type)
224 {
225         char *string;
226         
227         g_return_val_if_fail (GMIME_IS_CONTENT_TYPE (mime_type), NULL);
228         
229         /* type and subtype should never be NULL, but check anyway */
230         string = g_strdup_printf ("%s/%s", mime_type->type ? mime_type->type : "text",
231                                   mime_type->subtype ? mime_type->subtype : "plain");
232         
233         return string;
234 }
235
236
237 /**
238  * g_mime_content_type_is_type:
239  * @mime_type: a #GMimeContentType object
240  * @type: MIME type to compare against
241  * @subtype: MIME subtype to compare against
242  *
243  * Compares the given type and subtype with that of the given mime
244  * type object.
245  *
246  * Returns: TRUE if the MIME types match or FALSE otherwise. You may
247  * use "*" in place of @type and/or @subtype as a wilcard.
248  **/
249 gboolean
250 g_mime_content_type_is_type (GMimeContentType *mime_type, const char *type, const char *subtype)
251 {
252         g_return_val_if_fail (GMIME_IS_CONTENT_TYPE (mime_type), FALSE);
253         g_return_val_if_fail (mime_type->type != NULL, FALSE);
254         g_return_val_if_fail (mime_type->subtype != NULL, FALSE);
255         g_return_val_if_fail (type != NULL, FALSE);
256         g_return_val_if_fail (subtype != NULL, FALSE);
257         
258         if (!strcmp (type, "*") || !g_ascii_strcasecmp (mime_type->type, type)) {
259                 if (!strcmp (subtype, "*")) {
260                         /* special case */
261                         return TRUE;
262                 }
263                 
264                 if (!g_ascii_strcasecmp (mime_type->subtype, subtype))
265                         return TRUE;
266         }
267         
268         return FALSE;
269 }
270
271
272 /**
273  * g_mime_content_type_set_media_type:
274  * @mime_type: a #GMimeContentType object
275  * @type: media type
276  *
277  * Sets the Content-Type's media type.
278  **/
279 void
280 g_mime_content_type_set_media_type (GMimeContentType *mime_type, const char *type)
281 {
282         char *buf;
283         
284         g_return_if_fail (GMIME_IS_CONTENT_TYPE (mime_type));
285         g_return_if_fail (type != NULL);
286         
287         buf = g_strdup (type);
288         g_free (mime_type->type);
289         mime_type->type = buf;
290         
291         g_mime_event_emit (mime_type->priv, NULL);
292 }
293
294
295 /**
296  * g_mime_content_type_get_media_type:
297  * @mime_type: a #GMimeContentType object
298  *
299  * Gets the Content-Type's media type.
300  *
301  * Returns: the Content-Type's media type.
302  **/
303 const char *
304 g_mime_content_type_get_media_type (GMimeContentType *mime_type)
305 {
306         g_return_val_if_fail (GMIME_IS_CONTENT_TYPE (mime_type), NULL);
307         
308         return mime_type->type;
309 }
310
311
312 /**
313  * g_mime_content_type_set_media_subtype:
314  * @mime_type: a #GMimeContentType object
315  * @subtype: media subtype
316  *
317  * Sets the Content-Type's media subtype.
318  **/
319 void
320 g_mime_content_type_set_media_subtype (GMimeContentType *mime_type, const char *subtype)
321 {
322         char *buf;
323         
324         g_return_if_fail (GMIME_IS_CONTENT_TYPE (mime_type));
325         g_return_if_fail (subtype != NULL);
326         
327         buf = g_strdup (subtype);
328         g_free (mime_type->subtype);
329         mime_type->subtype = buf;
330         
331         g_mime_event_emit (mime_type->priv, NULL);
332 }
333
334
335 /**
336  * g_mime_content_type_get_media_subtype:
337  * @mime_type: a #GMimeContentType object
338  *
339  * Gets the Content-Type's media sub-type.
340  *
341  * Returns: the Content-Type's media sub-type.
342  **/
343 const char *
344 g_mime_content_type_get_media_subtype (GMimeContentType *mime_type)
345 {
346         g_return_val_if_fail (GMIME_IS_CONTENT_TYPE (mime_type), NULL);
347         
348         return mime_type->subtype;
349 }
350
351
352 /**
353  * g_mime_content_type_set_params:
354  * @mime_type: a #GMimeContentType object
355  * @params: a list of #GMimeParam objects
356  *
357  * Sets the Content-Type's parameter list.
358  **/
359 void
360 g_mime_content_type_set_params (GMimeContentType *mime_type, GMimeParam *params)
361 {
362         g_return_if_fail (GMIME_IS_CONTENT_TYPE (mime_type));
363         
364         /* clear the current list/hash */
365         g_hash_table_remove_all (mime_type->param_hash);
366         g_mime_param_destroy (mime_type->params);
367         mime_type->params = params;
368         
369         while (params != NULL) {
370                 g_hash_table_insert (mime_type->param_hash, params->name, params);
371                 params = params->next;
372         }
373         
374         g_mime_event_emit (mime_type->priv, NULL);
375 }
376
377
378 /**
379  * g_mime_content_type_get_params:
380  * @mime_type: a #GMimeContentType object
381  *
382  * Gets the Content-Type's parameter list.
383  *
384  * Returns: the Content-Type's parameter list.
385  **/
386 const GMimeParam *
387 g_mime_content_type_get_params (GMimeContentType *mime_type)
388 {
389         g_return_val_if_fail (GMIME_IS_CONTENT_TYPE (mime_type), NULL);
390         
391         return mime_type->params;
392 }
393
394
395 /**
396  * g_mime_content_type_set_parameter:
397  * @mime_type: MIME Content-Type
398  * @attribute: parameter name (aka attribute)
399  * @value: parameter value
400  *
401  * Sets a parameter on the Content-Type.
402  **/
403 void
404 g_mime_content_type_set_parameter (GMimeContentType *mime_type, const char *attribute, const char *value)
405 {
406         GMimeParam *param = NULL;
407         
408         g_return_if_fail (GMIME_IS_CONTENT_TYPE (mime_type));
409         g_return_if_fail (attribute != NULL);
410         g_return_if_fail (value != NULL);
411         
412         if ((param = g_hash_table_lookup (mime_type->param_hash, attribute))) {
413                 g_free (param->value);
414                 param->value = g_strdup (value);
415         } else {
416                 param = g_mime_param_new (attribute, value);
417                 mime_type->params = g_mime_param_append_param (mime_type->params, param);
418                 g_hash_table_insert (mime_type->param_hash, param->name, param);
419         }
420         
421         g_mime_event_emit (mime_type->priv, NULL);
422 }
423
424
425 /**
426  * g_mime_content_type_get_parameter:
427  * @mime_type: a #GMimeContentType object
428  * @attribute: parameter name (aka attribute)
429  *
430  * Gets the parameter value specified by @attribute if it's available.
431  *
432  * Returns: a const pointer to the paramer value specified by
433  * @attribute or %NULL on fail.
434  **/
435 const char *
436 g_mime_content_type_get_parameter (GMimeContentType *mime_type, const char *attribute)
437 {
438         GMimeParam *param;
439         
440         g_return_val_if_fail (GMIME_IS_CONTENT_TYPE (mime_type), NULL);
441         g_return_val_if_fail (attribute != NULL, NULL);
442         
443         if (!(param = g_hash_table_lookup (mime_type->param_hash, attribute)))
444                 return NULL;
445         
446         return param->value;
447 }