1555d27e7b3ed8ad902343b7aa2f9df4826c5836
[platform/upstream/evolution-data-server.git] / camel / gmime-utils.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /* mime-utils.c : misc utilities for mime  */
3
4 /* 
5  *
6  * Copyright (C) 1999 Bertrand Guiheneuf <Bertrand.Guiheneuf@inria.fr> .
7  *
8  * This program is free software; you can redistribute it and/or 
9  * modify it under the terms of the GNU General Public License as 
10  * published by the Free Software Foundation; either version 2 of the
11  * License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21  * USA
22  */
23
24
25
26 #include "gmime-utils.h"
27 #include "gstring-util.h"
28 #include "camel-log.h"
29 #include "camel-stream.h"
30
31 void
32 gmime_write_header_pair_to_stream (CamelStream *stream, gchar* name, GString *value)
33 {
34
35         GString *strtmp;
36         guint len;
37
38         g_assert(name);
39
40         if (!value || !(value->str)) return;
41         len = strlen (name) + strlen (value->str) +3;
42         /* 3 is for ": " and "\n" */
43         strtmp = g_string_sized_new (len);
44         
45         sprintf(strtmp->str, "%s: %s\n", name, value->str);
46         camel_stream_write (stream, strtmp->str, len);
47         CAMEL_LOG (FULL_DEBUG, "gmime_write_header_pair_to_stream:\n  writing %s\n", strtmp->str);
48         g_string_free (strtmp, FALSE);
49 }
50
51
52 static void
53 _write_one_header_to_stream (gpointer key, gpointer value, gpointer user_data)
54 {
55         GString *header_name = (GString *)key;
56         GString *header_value = (GString *)value;
57         CamelStream *stream = (CamelStream *)user_data;
58
59         if ( (header_name) && (header_name->str) && 
60              (header_value) && (header_value->str) )
61                 gmime_write_header_pair_to_stream (stream, header_name->str, header_value);             
62 }
63
64 void 
65 write_header_table_to_stream (CamelStream *stream, GHashTable *header_table)
66 {
67         g_hash_table_foreach (header_table, 
68                               _write_one_header_to_stream, 
69                               (gpointer)stream);
70 }
71
72
73 void 
74 write_header_with_glist_to_stream (CamelStream *stream, gchar *header_name, GList *header_values, gchar *separator)
75 {
76         
77         GString *current;
78         
79         if ( (header_name) && (header_values) )
80                 {
81                         gboolean first;
82                         
83                         camel_stream_write (stream, header_name, strlen (header_name) );
84                         camel_stream_write (stream, ": ", 2);
85                         first = TRUE;
86                         while (header_values) {
87                                 current = (GString *)header_values->data;
88                                 if ( (current) && (current->str) ) {
89                                         if (!first) camel_stream_write_string (stream, separator);
90                                         else first = FALSE;
91                                         camel_stream_write (stream, current->str, strlen (current->str));
92                                 }
93                                 header_values = g_list_next(header_values);
94                         }
95                         camel_stream_write (stream, "\n", 1);
96                 }
97         
98 }       
99
100
101
102
103
104 /* * * * * * * * * * * */
105 /* scanning functions  */
106
107 static void
108 _store_header_pair_from_gstring (GHashTable *header_table, GString *header_line)
109 {
110         gchar dich_result;
111         GString *header_name, *header_value;
112         
113         g_assert (header_table);
114         if ( (header_line) && (header_line->str) ) {
115                 dich_result = g_string_dichotomy(header_line, ':', &header_name, &header_value, DICHOTOMY_NONE);
116                 if (dich_result != 'o')
117                         camel_log(WARNING, 
118                                   "store_header_pair_from_gstring : dichotomy result is %c"
119                                   "header line is :\n--\n%s\n--\n");
120                 
121                 else {
122                         g_string_trim (header_value, " \t", TRIM_STRIP_LEADING | TRIM_STRIP_TRAILING);
123                         g_hash_table_insert (header_table, header_name, header_value);
124                 }
125         }
126                 
127 }
128
129
130         
131                 
132 GHashTable *
133 get_header_table_from_stream (CamelStream *stream)
134 {
135         gchar next_char;
136
137         gboolean crlf = FALSE;
138         gboolean end_of_header_line = FALSE;
139         gboolean end_of_headers = FALSE;
140         gboolean end_of_file = FALSE;
141         GString *header_line=NULL;
142         GHashTable *header_table;
143
144         header_table = g_hash_table_new (g_string_hash, g_string_equal_for_hash);
145         camel_stream_read (stream, &next_char, 1);
146         do {
147                 header_line = g_string_new("");
148                 end_of_header_line = FALSE;
149                 crlf = FALSE;
150                 
151                 /* read a whole header line */
152                 do {
153                         switch (next_char) {
154                         case -1:
155                                 end_of_file=TRUE;
156                                 end_of_header_line = TRUE;
157                                 break;
158                         case '\n': /* a blank line means end of headers */
159                                 if (crlf) {
160                                         end_of_headers=TRUE;
161                                         end_of_header_line = TRUE;
162                                 }
163                                 else crlf = TRUE;
164                                 break;
165                         case ' ':
166                         case '\t':
167                                 if (crlf) {
168                                         crlf = FALSE; 
169                                         next_char = ' ';
170                                 }
171                                 
172                         default:
173                                 if (!crlf) header_line = g_string_append_c (header_line, next_char);
174                                 else end_of_header_line = TRUE;
175                         }
176                         /* if we have read a whole header line, we have also read
177                            the first character of the next line to be sure the 
178                            crlf was not followed by a space or a tab char */
179                         if (!end_of_header_line) camel_stream_read (stream, &next_char, 1);
180
181                 } while ( !end_of_header_line );
182                 if ( strlen(header_line->str) ) 
183                         _store_header_pair_from_gstring (header_table, header_line);
184                 g_string_free (header_line, FALSE);
185
186         } while ( (!end_of_headers) && (!end_of_file) );
187
188         return header_table;
189 }
190                 
191