1 /* Copyright (c) 2006, 2007, 2008 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.
32 #endif /*HAVE_CONFIG_H */
34 #include "modest-tny-mime-part.h"
35 #include <tny-simple-list.h>
37 #include <string.h> /* for strlen */
38 #include <modest-tny-msg.h>
39 #include "modest-text-utils.h"
43 modest_tny_mime_part_get_header_value (TnyMimePart *part, const gchar *header)
49 g_return_val_if_fail (part && TNY_IS_MIME_PART(part), NULL);
50 g_return_val_if_fail (header, NULL);
52 pairs = tny_simple_list_new ();
54 tny_mime_part_get_header_pairs (part, pairs);
55 iter = tny_list_create_iterator (pairs);
58 while (!tny_iterator_is_done(iter) && !val) {
60 TnyPair *pair = (TnyPair*)tny_iterator_get_current(iter);
61 if (strcasecmp (header, tny_pair_get_name(pair)) == 0)
62 val = g_strdup (tny_pair_get_value(pair));
63 g_object_unref (pair);
65 tny_iterator_next (iter);
68 g_object_unref (pairs);
69 g_object_unref (iter);
77 /* we consider more things attachments than tinymail does...
80 modest_tny_mime_part_is_attachment_for_modest (TnyMimePart *part)
82 gchar *tmp, *content_type;
83 gboolean has_content_disp_name = FALSE;
85 g_return_val_if_fail (part && TNY_IS_MIME_PART(part), FALSE);
87 /* purged attachments were attachments in the past, so they're
88 * still attachments */
89 if (tny_mime_part_is_purged (part))
92 /* if tinymail thinks it's an attachment, it is. One exception: if it's
93 * a multipart and it's not a message/rfc822 it cannot be an attahcment */
94 if (tny_mime_part_is_attachment (part)) {
95 if (!TNY_IS_MSG (part)) {
96 const gchar *content_type;
97 gchar *down_content_type;
98 gboolean is_attachment;
100 content_type = tny_mime_part_get_content_type (part);
101 down_content_type = g_ascii_strdown (content_type, -1);
103 is_attachment = !g_str_has_prefix (down_content_type, "multipart/");
104 g_free (down_content_type);
105 return is_attachment;
111 /* if the mime part is a message itself (ie. embedded), it's an attachment */
112 if (TNY_IS_MSG (part))
115 tmp = modest_tny_mime_part_get_header_value (part, "Content-Disposition");
117 /* If the Content-Disposition header contains a "name"
118 * parameter, treat the mime part as an attachment */
119 gchar *content_disp = g_ascii_strdown(tmp, -1);
120 gint len = strlen (content_disp);
121 const gchar *substr = g_strstr_len (content_disp, len, "name");
122 if (substr != NULL) {
123 gint substrlen = len - (substr - content_disp);
124 /* The parameter can appear in muliple
125 * ways. See RFC 2231 for details */
126 has_content_disp_name =
127 g_strstr_len (substr, substrlen, "name=") != NULL ||
128 g_strstr_len (substr, substrlen, "name*=") != NULL ||
129 g_strstr_len (substr, substrlen, "name*0=") != NULL ||
130 g_strstr_len (substr, substrlen, "name*0*=") != NULL;
133 g_free (content_disp);
136 /* if it doesn't have a content deposition with a name= attribute, it's not an attachment */
137 if (!has_content_disp_name)
140 /* ok, it must be content-disposition "inline" then, because "attachment"
141 * is already handle above "...is_attachment". modest consider these "inline" things
142 * attachments as well, unless they are embedded images for html mail
144 content_type = g_ascii_strdown (tny_mime_part_get_content_type (part), -1);
145 if (!g_str_has_prefix (content_type, "image/")) {
146 g_free (content_type);
147 return TRUE; /* it's not an image, so it must be an attachment */
149 g_free (content_type);
152 /* now, if it's an inline-image, and it has a content-id or location, we
153 * we guess it's an inline image, and not an attachment */
154 if (tny_mime_part_get_content_id (part) || tny_mime_part_get_content_location(part))
157 /* in other cases... */
162 modest_tny_mime_part_is_msg (TnyMimePart *part)
164 const gchar *content_type;
165 gchar *down_content_type;
167 if (!TNY_IS_MSG (part))
170 content_type = tny_mime_part_get_content_type (part);
171 down_content_type = g_ascii_strdown (content_type, -1);
172 if ((g_str_has_prefix (down_content_type, "message/rfc822") ||
173 g_str_has_prefix (down_content_type, "multipart/") ||
174 g_str_has_prefix (down_content_type, "text/plain") ||
175 g_str_has_prefix (down_content_type, "text/html"))) {
176 g_free (down_content_type);
179 g_free (down_content_type);
185 modest_tny_mime_part_to_string (TnyMimePart *part, gint indent)
189 GString *indent_prefix;
190 TnyList *list, *pairs_list;
191 TnyIterator *iter, *pairs_iter;
193 indent_prefix = g_string_new ("");
194 for (i = 0; i < indent; i++) {
195 indent_prefix = g_string_append_c (indent_prefix, ' ');
198 if (TNY_IS_MSG (part)) {
201 header = tny_msg_get_header (TNY_MSG (part));
202 g_print ("(%s(MSG))\n", indent_prefix->str);
203 g_object_unref (header);
206 list = tny_simple_list_new ();
207 tny_mime_part_get_parts (part, list);
208 pairs_list = tny_simple_list_new ();
209 tny_mime_part_get_header_pairs (part, pairs_list);
210 g_print ("%s(content=%s parts=%d location=%s)\n", indent_prefix->str,
211 tny_mime_part_get_content_type (part),
212 tny_list_get_length (list),
213 tny_mime_part_get_content_location (part));
214 for (pairs_iter = tny_list_create_iterator (pairs_list);
215 !tny_iterator_is_done (pairs_iter);
216 tny_iterator_next (pairs_iter)) {
217 TnyPair *pair = TNY_PAIR (tny_iterator_get_current (pairs_iter));
218 g_print ("%s(%s:%s)\n", indent_prefix->str, tny_pair_get_name (pair), tny_pair_get_value (pair));
219 g_object_unref (pair);
221 for (iter = tny_list_create_iterator (list);
222 !tny_iterator_is_done (iter);
223 tny_iterator_next (iter)) {
225 child = (TnyMimePart *) tny_iterator_get_current (iter);
226 modest_tny_mime_part_to_string (child, indent + 3);
227 g_object_unref (child);
229 g_object_unref (iter);
230 g_object_unref (list);
232 g_string_free (indent_prefix, TRUE);
236 modest_tny_mime_part_get_headers_content_type (TnyMimePart *part)
238 gchar *header_content_type;
241 g_return_val_if_fail (TNY_IS_MIME_PART (part), NULL);
243 header_content_type = modest_tny_mime_part_get_header_value (part, "Content-Type");
245 /* See RFC2045 sec 5.2 */
246 if (!header_content_type)
247 return g_strdup ("text/plain; charset=us-ascii");
249 header_content_type = g_strstrip (header_content_type);
251 /* remove the ; suffix */
252 suffix = index (header_content_type, ';');
256 return g_ascii_strdown (header_content_type, -1);
260 modest_tny_mime_part_get_content_type (TnyMimePart *part)
262 const gchar *content_type;
263 gchar *retval = NULL;
265 g_return_val_if_fail (TNY_IS_MIME_PART (part), NULL);
266 content_type = tny_mime_part_get_content_type (part);
268 if (g_str_has_prefix (content_type, "message/rfc822")) {
269 retval = modest_tny_mime_part_get_headers_content_type (part);
272 if (retval == NULL) {
273 retval = g_ascii_strdown (content_type, -1);