1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Copyright (C) 2000-2012 Jeffrey Stedfast
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.
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.
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
29 #include "gmime-stream-mem.h"
30 #include "gmime-common.h"
31 #include "gmime-header.h"
32 #include "gmime-events.h"
33 #include "gmime-utils.h"
39 * SECTION: gmime-header
41 * @short_description: Message and MIME part headers
42 * @see_also: #GMimeObject
44 * A #GMimeHeader is a collection of rfc822 header fields and their
51 * @next: pointer to the next header
52 * @prev: pointer to the previous header
53 * @offset: file/stream offset
55 * @value: header value
57 * A message/rfc822 header.
68 struct _GMimeHeaderList {
78 static GMimeHeader *g_mime_header_new (const char *name, const char *value, gint64 offset);
79 static void g_mime_header_free (GMimeHeader *header);
85 * @value: header value
86 * @offset: file/stream offset for the start of the header (or %-1 if unknown)
88 * Creates a new #GMimeHeader.
90 * Returns: a new #GMimeHeader with the specified values.
93 g_mime_header_new (const char *name, const char *value, gint64 offset)
97 header = g_slice_new (GMimeHeader);
98 header->name = g_strdup (name);
99 header->value = g_strdup (value);
100 /*header->offset = offset;*/
109 * g_mime_header_free:
110 * @header: a #GMimeHeader
112 * Frees a single #GMimeHeader node.
115 g_mime_header_free (GMimeHeader *header)
117 g_free (header->name);
118 g_free (header->value);
120 g_slice_free (GMimeHeader, header);
125 * g_mime_header_iter_new:
127 * Dynamically allocates a #GMimeHeaderIter on the heap. This is
128 * intended for use in language bindings but may also be useful in
129 * applications as well. You must free this iter with
130 * g_mime_header_iter_free().
132 * Returns: a newly-allocated #GMimeHeaderIter.
135 g_mime_header_iter_new (void)
137 GMimeHeaderIter *iter;
139 iter = g_slice_new (GMimeHeaderIter);
140 iter->hdrlist = NULL;
149 * g_mime_header_iter_copy:
150 * @iter: a #GMimeHeaderIter
152 * Creates a dynamically allocated header iterator as a copy of
153 * @iter. You must free this iter with g_mime_header_iter_free().
155 * Returns: a newly-allocated copy of @iter.
158 g_mime_header_iter_copy (GMimeHeaderIter *iter)
160 GMimeHeaderIter *copy;
162 g_return_val_if_fail (iter != NULL, NULL);
164 copy = g_mime_header_iter_new ();
165 memcpy (copy, iter, sizeof (GMimeHeaderIter));
172 * g_mime_header_iter_copy_to:
173 * @src: a #GMimeHeaderIter
174 * @dest: a #GMimeHeaderIter
176 * Copies @src to @dest.
179 g_mime_header_iter_copy_to (GMimeHeaderIter *src, GMimeHeaderIter *dest)
181 g_return_if_fail (dest != NULL);
182 g_return_if_fail (src != NULL);
184 memcpy (dest, src, sizeof (GMimeHeaderIter));
189 * g_mime_header_iter_free:
190 * @iter: a #GMimeHeaderIter
192 * Frees a dynamically-allocated #GMimeHeaderIter as created by
193 * g_mime_header_iter_new() or g_mime_header_iter_copy().
196 g_mime_header_iter_free (GMimeHeaderIter *iter)
198 g_return_if_fail (iter != NULL);
200 g_slice_free (GMimeHeaderIter, iter);
205 * g_mime_header_iter_equal:
206 * @iter1: a #GMimeHeaderIter
207 * @iter2: a #GMimeHeaderIter
209 * Check that @iter1 and @iter2 reference the same header.
211 * Returns: %TRUE if @iter1 and @iter2 refer to the same header or
215 g_mime_header_iter_equal (GMimeHeaderIter *iter1, GMimeHeaderIter *iter2)
217 g_return_val_if_fail (iter1 != NULL, FALSE);
218 g_return_val_if_fail (iter2 != NULL, FALSE);
220 return iter1->hdrlist == iter2->hdrlist &&
221 iter1->version == iter2->version &&
222 iter1->cursor == iter2->cursor;
227 * g_mime_header_iter_is_valid:
228 * @iter: a #GMimeHeaderIter
230 * Checks if a #GMimeHeaderIter is valid. An iterator may become
231 * invalid if the #GMimeHeaderList that the iterator refers to
234 * Returns: %TRUE if @iter is still valid or %FALSE otherwise.
237 g_mime_header_iter_is_valid (GMimeHeaderIter *iter)
239 g_return_val_if_fail (iter != NULL, FALSE);
241 if (!iter->hdrlist || iter->version != iter->hdrlist->version)
244 if (!iter->cursor || !iter->cursor->next)
252 * g_mime_header_iter_first:
253 * @iter: a #GMimeHeaderIter
255 * Updates @iter to point to the first header.
257 * Returns: %TRUE on success or %FALSE otherwise.
260 g_mime_header_iter_first (GMimeHeaderIter *iter)
264 g_return_val_if_fail (iter != NULL, FALSE);
266 /* make sure we can actually do as requested */
267 if (!iter->hdrlist || list_is_empty (&iter->hdrlist->list))
270 first = (GMimeHeader *) iter->hdrlist->list.head;
272 iter->version = iter->hdrlist->version;
273 iter->cursor = first;
280 * g_mime_header_iter_last:
281 * @iter: a #GMimeHeaderIter
283 * Updates @iter to point to the last header.
285 * Returns: %TRUE on success or %FALSE otherwise.
288 g_mime_header_iter_last (GMimeHeaderIter *iter)
292 g_return_val_if_fail (iter != NULL, FALSE);
294 /* make sure we can actually do as requested */
295 if (!iter->hdrlist || list_is_empty (&iter->hdrlist->list))
298 last = (GMimeHeader *) iter->hdrlist->list.tailpred;
300 iter->version = iter->hdrlist->version;
308 * g_mime_header_iter_next:
309 * @iter: a #GMimeHeaderIter
311 * Advances to the next header.
313 * Returns: %TRUE on success or %FALSE otherwise.
316 g_mime_header_iter_next (GMimeHeaderIter *iter)
320 g_return_val_if_fail (iter != NULL, FALSE);
322 /* make sure current cursor is valid */
323 if (!g_mime_header_iter_is_valid (iter))
326 /* make sure next item is valid */
327 next = iter->cursor->next;
338 * g_mime_header_iter_prev:
339 * @iter: a #GMimeHeaderIter
341 * Advances to the previous header.
343 * Returns: %TRUE on success or %FALSE otherwise.
346 g_mime_header_iter_prev (GMimeHeaderIter *iter)
350 g_return_val_if_fail (iter != NULL, FALSE);
352 /* make sure current cursor is valid */
353 if (!g_mime_header_iter_is_valid (iter))
356 /* make sure prev item is valid */
357 prev = iter->cursor->prev;
358 if (!prev || !prev->prev)
369 * g_mime_header_iter_get_offset:
370 * @iter: a #GMimeHeaderIter
372 * Gets the current header's file/stream offset.
374 * Returns: the file/stream offset or %-1 if unknown or invalid.
377 g_mime_header_iter_get_offset (GMimeHeaderIter *iter)
379 g_return_val_if_fail (iter != NULL, -1);
381 if (!g_mime_header_iter_is_valid (iter))
384 return iter->cursor->offset;
390 * g_mime_header_iter_get_name:
391 * @iter: a #GMimeHeaderIter
393 * Gets the current header's name.
395 * Returns: the header name or %NULL if invalid.
398 g_mime_header_iter_get_name (GMimeHeaderIter *iter)
400 g_return_val_if_fail (iter != NULL, NULL);
402 if (!g_mime_header_iter_is_valid (iter))
405 return iter->cursor->name;
410 * g_mime_header_iter_set_value:
411 * @iter: a #GMimeHeaderIter
412 * @value: new header value
414 * Sets the current header's value to the new value.
416 * Returns: %TRUE if the value was set or %FALSE otherwise (indicates
420 g_mime_header_iter_set_value (GMimeHeaderIter *iter, const char *value)
422 g_return_val_if_fail (iter != NULL, FALSE);
424 if (!g_mime_header_iter_is_valid (iter))
427 g_free (iter->cursor->value);
428 iter->cursor->value = g_strdup (value);
430 g_mime_header_list_set_stream (iter->hdrlist, NULL);
437 * g_mime_header_iter_get_value:
438 * @iter: a #GMimeHeaderIter
440 * Gets the current header's name.
442 * Returns: the header name or %NULL if invalid.
445 g_mime_header_iter_get_value (GMimeHeaderIter *iter)
447 g_return_val_if_fail (iter != NULL, NULL);
449 if (!g_mime_header_iter_is_valid (iter))
452 return iter->cursor->value;
457 * g_mime_header_iter_remove:
458 * @iter: a #GMimeHeaderIter
460 * Removes the current header and advances to the next header.
462 * Note: If you remove the last header in the list, then @iter will
463 * become invalid regardless of whether or not other headers remain.
465 * Returns: %TRUE on success or %FALSE otherwise.
468 g_mime_header_iter_remove (GMimeHeaderIter *iter)
470 GMimeHeader *cursor, *header, *next;
471 GMimeHeaderList *hdrlist;
473 g_return_val_if_fail (iter != NULL, FALSE);
475 if (!g_mime_header_iter_is_valid (iter))
478 /* save iter state */
479 hdrlist = iter->hdrlist;
480 cursor = iter->cursor;
483 if (!(header = g_hash_table_lookup (hdrlist->hash, cursor->name)))
486 if (cursor == header) {
487 /* update the header lookup table */
488 GMimeHeader *node = next;
490 g_hash_table_remove (hdrlist->hash, cursor->name);
493 if (!g_ascii_strcasecmp (node->name, cursor->name)) {
494 /* enter this node into the lookup table */
495 g_hash_table_insert (hdrlist->hash, node->name, node);
503 /* remove/free the header */
504 list_unlink ((ListNode *) cursor);
505 g_mime_header_free (cursor);
508 /* update iter state */
509 iter->version = hdrlist->version;
517 * g_mime_header_list_new:
519 * Creates a new #GMimeHeaderList object.
521 * Returns: a new header list object.
524 g_mime_header_list_new (void)
526 GMimeHeaderList *headers;
528 headers = g_slice_new (GMimeHeaderList);
529 headers->writers = g_hash_table_new_full (g_mime_strcase_hash,
530 g_mime_strcase_equal,
532 headers->hash = g_hash_table_new (g_mime_strcase_hash,
533 g_mime_strcase_equal);
534 list_init (&headers->list);
535 headers->changed = g_mime_event_new (headers);
536 headers->stream = NULL;
537 headers->version = 0;
544 * g_mime_header_list_destroy:
545 * @headers: a #GMimeHeaderList
547 * Destroy the header list.
550 g_mime_header_list_destroy (GMimeHeaderList *headers)
552 GMimeHeader *header, *next;
557 header = (GMimeHeader *) headers->list.head;
558 while (header->next) {
560 g_mime_header_free (header);
564 g_hash_table_destroy (headers->writers);
565 g_hash_table_destroy (headers->hash);
568 g_object_unref (headers->stream);
570 g_mime_event_destroy (headers->changed);
572 g_slice_free (GMimeHeaderList, headers);
577 * g_mime_header_list_clear:
578 * @headers: a #GMimeHeaderList
580 * Removes all of the headers from the #GMimeHeaderList.
583 g_mime_header_list_clear (GMimeHeaderList *headers)
585 GMimeHeader *header, *next;
587 g_return_if_fail (headers != NULL);
589 header = (GMimeHeader *) headers->list.head;
590 while (header->next) {
592 g_mime_header_free (header);
596 g_hash_table_remove_all (headers->hash);
597 list_init (&headers->list);
599 g_mime_header_list_set_stream (headers, NULL);
604 * g_mime_header_list_contains:
605 * @headers: a #GMimeHeaderList
608 * Checks whether or not a header exists.
610 * Returns: %TRUE if the specified header exists or %FALSE otherwise.
613 g_mime_header_list_contains (const GMimeHeaderList *headers, const char *name)
615 const GMimeHeader *header;
617 g_return_val_if_fail (headers != NULL, FALSE);
618 g_return_val_if_fail (name != NULL, FALSE);
620 if (!(header = g_hash_table_lookup (headers->hash, name)))
628 * g_mime_header_list_prepend:
629 * @headers: a #GMimeHeaderList
631 * @value: header value
633 * Prepends a header. If @value is %NULL, a space will be set aside
634 * for it (useful for setting the order of headers before values can
635 * be obtained for them) otherwise the header will be unset.
638 g_mime_header_list_prepend (GMimeHeaderList *headers, const char *name, const char *value)
642 g_return_if_fail (headers != NULL);
643 g_return_if_fail (name != NULL);
645 header = g_mime_header_new (name, value, -1);
646 list_prepend (&headers->list, (ListNode *) header);
647 g_hash_table_replace (headers->hash, header->name, header);
649 g_mime_header_list_set_stream (headers, NULL);
654 * g_mime_header_list_append:
655 * @headers: a #GMimeHeaderList
657 * @value: header value
659 * Appends a header. If @value is %NULL, a space will be set aside for it
660 * (useful for setting the order of headers before values can be
661 * obtained for them) otherwise the header will be unset.
664 g_mime_header_list_append (GMimeHeaderList *headers, const char *name, const char *value)
668 g_return_if_fail (headers != NULL);
669 g_return_if_fail (name != NULL);
671 header = g_mime_header_new (name, value, -1);
672 list_append (&headers->list, (ListNode *) header);
674 if (!g_hash_table_lookup (headers->hash, name))
675 g_hash_table_insert (headers->hash, header->name, header);
677 g_mime_header_list_set_stream (headers, NULL);
682 * g_mime_header_list_get:
683 * @headers: a #GMimeHeaderList
686 * Gets the value of the first header with the name requested.
688 * Returns: the value of the header requested.
691 g_mime_header_list_get (const GMimeHeaderList *headers, const char *name)
693 const GMimeHeader *header;
695 g_return_val_if_fail (headers != NULL, NULL);
696 g_return_val_if_fail (name != NULL, NULL);
698 if (!(header = g_hash_table_lookup (headers->hash, name)))
701 return header->value;
706 * g_mime_header_list_set:
707 * @headers: a #GMimeHeaderList
709 * @value: header value
711 * Set the value of the specified header. If @value is %NULL and the
712 * header, @name, had not been previously set, a space will be set
713 * aside for it (useful for setting the order of headers before values
714 * can be obtained for them) otherwise the header will be unset.
716 * Note: If there are multiple headers with the specified field name,
717 * the first instance of the header will be replaced and further
718 * instances will be removed.
721 g_mime_header_list_set (GMimeHeaderList *headers, const char *name, const char *value)
723 GMimeHeader *header, *next;
725 g_return_if_fail (headers != NULL);
726 g_return_if_fail (name != NULL);
728 if ((header = g_hash_table_lookup (headers->hash, name))) {
729 g_free (header->value);
730 header->value = g_strdup (value);
732 header = header->next;
733 while (header->next) {
736 if (!g_ascii_strcasecmp (header->name, name)) {
737 /* remove/free the header */
738 list_unlink ((ListNode *) header);
739 g_mime_header_free (header);
746 header = g_mime_header_new (name, value, -1);
747 list_append (&headers->list, (ListNode *) header);
748 g_hash_table_insert (headers->hash, header->name, header);
751 g_mime_header_list_set_stream (headers, NULL);
756 * g_mime_header_list_remove:
757 * @headers: a #GMimeHeaderList
760 * Remove the specified header.
762 * Returns: %TRUE if the header was successfully removed or %FALSE if
763 * the specified header could not be found.
766 g_mime_header_list_remove (GMimeHeaderList *headers, const char *name)
768 GMimeHeader *header, *node;
770 g_return_val_if_fail (headers != NULL, FALSE);
771 g_return_val_if_fail (name != NULL, FALSE);
773 if (!(header = g_hash_table_lookup (headers->hash, name)))
776 /* look for another header with the same name... */
779 if (!g_ascii_strcasecmp (node->name, name)) {
780 /* enter this node into the lookup table */
781 g_hash_table_replace (headers->hash, node->name, node);
788 /* invalidate all our outstanding iterators matching @header */
791 /* remove/free the header */
792 list_unlink ((ListNode *) header);
793 g_mime_header_free (header);
795 g_mime_header_list_set_stream (headers, NULL);
802 * g_mime_header_list_get_iter:
803 * @headers: a #GMimeHeaderList
804 * @iter: a #GMimeHeaderIter
806 * Initializes an iterator for traversing @headers.
808 * Returns: a %TRUE if successful or %FALSE if there are no headers to
812 g_mime_header_list_get_iter (GMimeHeaderList *headers, GMimeHeaderIter *iter)
816 g_return_val_if_fail (headers != NULL, FALSE);
818 cursor = (GMimeHeader *) headers->list.head;
822 iter->version = headers->version;
823 iter->hdrlist = headers;
824 iter->cursor = cursor;
831 * g_mime_header_list_foreach:
832 * @headers: A #GMimeHeaderList
833 * @func: function to be called for each header.
834 * @user_data: User data to be passed to the func.
836 * Calls @func for each header name/value pair.
839 g_mime_header_list_foreach (const GMimeHeaderList *headers, GMimeHeaderForeachFunc func, gpointer user_data)
841 const GMimeHeader *header;
843 g_return_if_fail (headers != NULL);
844 g_return_if_fail (func != NULL);
846 header = (const GMimeHeader *) headers->list.head;
848 while (header->next) {
849 func (header->name, header->value, user_data);
850 header = header->next;
856 default_writer (GMimeStream *stream, const char *name, const char *value)
861 val = g_mime_utils_header_printf ("%s: %s\n", name, value);
862 nwritten = g_mime_stream_write_string (stream, val);
870 * g_mime_header_list_write_to_stream:
871 * @headers: a #GMimeHeaderList
872 * @stream: output stream
874 * Write the headers to a stream.
876 * Returns: the number of bytes written or %-1 on fail.
879 g_mime_header_list_write_to_stream (const GMimeHeaderList *headers, GMimeStream *stream)
881 ssize_t nwritten, total = 0;
882 GMimeHeaderWriter writer;
886 g_return_val_if_fail (headers != NULL, -1);
887 g_return_val_if_fail (stream != NULL, -1);
889 if (headers->stream) {
890 g_mime_stream_reset (headers->stream);
891 return g_mime_stream_write_to_stream (headers->stream, stream);
894 header = (GMimeHeader *) headers->list.head;
895 writers = headers->writers;
897 while (header->next) {
899 if (!(writer = g_hash_table_lookup (writers, header->name)))
900 writer = default_writer;
902 if ((nwritten = writer (stream, header->name, header->value)) == -1)
908 header = header->next;
916 * g_mime_header_list_to_string:
917 * @headers: a #GMimeHeaderList
919 * Allocates a string buffer containing the raw rfc822 headers
920 * contained in @headers.
922 * Returns: a string containing the header block.
925 g_mime_header_list_to_string (const GMimeHeaderList *headers)
931 g_return_val_if_fail (headers != NULL, NULL);
933 array = g_byte_array_new ();
934 stream = g_mime_stream_mem_new ();
935 g_mime_stream_mem_set_byte_array (GMIME_STREAM_MEM (stream), array);
937 if (headers->stream) {
938 g_mime_stream_reset (headers->stream);
939 g_mime_stream_write_to_stream (headers->stream, stream);
941 g_mime_header_list_write_to_stream (headers, stream);
944 g_object_unref (stream);
946 g_byte_array_append (array, (unsigned char *) "", 1);
947 str = (char *) array->data;
948 g_byte_array_free (array, FALSE);
955 * g_mime_header_list_register_writer:
956 * @headers: a #GMimeHeaderList
958 * @writer: writer function
960 * Changes the function used to write @name headers to @writer (or the
961 * default if @writer is %NULL). This is useful if you want to change
962 * the default header folding style for a particular header.
965 g_mime_header_list_register_writer (GMimeHeaderList *headers, const char *name, GMimeHeaderWriter writer)
969 g_return_if_fail (headers != NULL);
970 g_return_if_fail (name != NULL);
972 if (g_hash_table_lookup (headers->writers, name)) {
973 g_hash_table_lookup_extended (headers->writers, name, &okey, &oval);
974 g_hash_table_remove (headers->writers, name);
979 g_hash_table_insert (headers->writers, g_strdup (name), writer);
985 * g_mime_header_list_set_stream:
986 * @headers: a #GMimeHeaderList
987 * @stream: a #GMimeStream
989 * Set the raw header stream.
992 g_mime_header_list_set_stream (GMimeHeaderList *headers, GMimeStream *stream)
994 g_return_if_fail (stream == NULL || GMIME_IS_STREAM (stream));
995 g_return_if_fail (headers != NULL);
997 if (headers->stream == stream)
1001 g_object_ref (stream);
1003 if (headers->stream)
1004 g_object_unref (headers->stream);
1006 headers->stream = stream;
1008 g_mime_event_emit (headers->changed, NULL);
1013 * g_mime_header_list_get_stream:
1014 * @headers: a #GMimeHeaderList
1016 * Gets the raw stream representing @headers.
1018 * Returns: a #GMimeStream if set or %NULL otherwise.
1021 g_mime_header_list_get_stream (GMimeHeaderList *headers)
1023 g_return_val_if_fail (headers != NULL, NULL);
1025 return headers->stream;
1030 _g_mime_header_list_get_changed_event (GMimeHeaderList *headers)
1032 g_return_val_if_fail (headers != NULL, NULL);
1034 return headers->changed;