static gboolean emqfe_headers_format (EMailFormatterExtension *extension, EMailFormatter *formatter, EMailFormatterContext *context, EMailPart *part, GOutputStream *stream, GCancellable *cancellable) { CamelContentType *ct; CamelMimePart *mime_part; const gchar *charset; GString *buffer; gchar **default_headers; guint ii, length = 0; g_return_val_if_fail (E_IS_MAIL_PART_HEADERS (part), FALSE); mime_part = e_mail_part_ref_mime_part (part); ct = camel_mime_part_get_content_type (mime_part); charset = camel_content_type_param (ct, "charset"); charset = camel_iconv_charset_name (charset); buffer = g_string_new (""); /* dump selected headers */ default_headers = e_mail_part_headers_dup_default_headers ( E_MAIL_PART_HEADERS (part)); if (default_headers != NULL) length = g_strv_length (default_headers); for (ii = 0; ii < length; ii++) emfqe_format_header ( formatter, context, buffer, part, default_headers[ii], charset); g_strfreev (default_headers); g_string_append (buffer, HEADER_PREFIX); g_string_append (buffer, "<br>"); g_string_append (buffer, HEADER_SUFFIX); g_output_stream_write_all ( stream, buffer->str, buffer->len, NULL, cancellable, NULL); g_string_free (buffer, TRUE); g_object_unref (mime_part); return TRUE; }
const gchar * camel_iconv_charset_language (const gchar *charset) { gint i; if (!charset) return NULL; charset = camel_iconv_charset_name (charset); for (i = 0; i < G_N_ELEMENTS (cjkr_lang_map); i++) { if (!g_ascii_strcasecmp (cjkr_lang_map[i].charset, charset)) return cjkr_lang_map[i].lang; } return NULL; }
static CamelSExpResult * check_header (struct _CamelSExp *f, gint argc, struct _CamelSExpResult **argv, FilterMessageSearch *fms, camel_search_match_t how) { gboolean matched = FALSE; CamelSExpResult *r; gint i; if (argc > 1 && argv[0]->type == CAMEL_SEXP_RES_STRING) { gchar *name = argv[0]->value.string; /* shortcut: a match for "" against any header always matches */ for (i = 1; i < argc && !matched; i++) matched = argv[i]->type == CAMEL_SEXP_RES_STRING && argv[i]->value.string[0] == 0; if (g_ascii_strcasecmp (name, "x-camel-mlist") == 0) { const gchar *list = camel_message_info_mlist (fms->info); if (list) { for (i = 1; i < argc && !matched; i++) { if (argv[i]->type == CAMEL_SEXP_RES_STRING) matched = camel_search_header_match (list, argv[i]->value.string, how, CAMEL_SEARCH_TYPE_MLIST, NULL); } } } else if (fms->message || !check_header_in_message_info (fms->info, argc, argv, how, &matched)) { CamelMimeMessage *message; CamelMimePart *mime_part; struct _camel_header_raw *header; const gchar *charset = NULL; camel_search_t type = CAMEL_SEARCH_TYPE_ENCODED; CamelContentType *ct; message = camel_filter_search_get_message (fms, f); mime_part = CAMEL_MIME_PART (message); /* FIXME: what about Resent-To, Resent-Cc and Resent-From? */ if (g_ascii_strcasecmp ("to", name) == 0 || g_ascii_strcasecmp ("cc", name) == 0 || g_ascii_strcasecmp ("from", name) == 0) type = CAMEL_SEARCH_TYPE_ADDRESS_ENCODED; else if (message) { ct = camel_mime_part_get_content_type (mime_part); if (ct) { charset = camel_content_type_param (ct, "charset"); charset = camel_iconv_charset_name (charset); } } for (header = mime_part->headers; header && !matched; header = header->next) { /* empty name means any header */ if (!name || !*name || !g_ascii_strcasecmp (header->name, name)) { for (i = 1; i < argc && !matched; i++) { if (argv[i]->type == CAMEL_SEXP_RES_STRING) matched = camel_search_header_match (header->value, argv[i]->value.string, how, type, charset); } } } } } r = camel_sexp_result_new (f, CAMEL_SEXP_RES_BOOL); r->value.boolean = matched; return r; }
/* FIXME: check format of fields. */ static gboolean process_header (CamelMedium *medium, const gchar *name, const gchar *value) { CamelHeaderType header_type; CamelMimeMessage *message = CAMEL_MIME_MESSAGE (medium); CamelInternetAddress *addr; const gchar *charset; gchar *unfolded; header_type = (CamelHeaderType) g_hash_table_lookup (header_name_table, name); switch (header_type) { case HEADER_FROM: addr = camel_internet_address_new (); unfolded = camel_header_unfold (value); if (camel_address_decode ((CamelAddress *) addr, unfolded) <= 0) { g_object_unref (addr); } else { if (message->from) g_object_unref (message->from); message->from = addr; } g_free (unfolded); break; case HEADER_REPLY_TO: addr = camel_internet_address_new (); unfolded = camel_header_unfold (value); if (camel_address_decode ((CamelAddress *) addr, unfolded) <= 0) { g_object_unref (addr); } else { if (message->reply_to) g_object_unref (message->reply_to); message->reply_to = addr; } g_free (unfolded); break; case HEADER_SUBJECT: g_free (message->subject); if (((CamelDataWrapper *) message)->mime_type) { charset = camel_content_type_param (((CamelDataWrapper *) message)->mime_type, "charset"); charset = camel_iconv_charset_name (charset); } else charset = NULL; unfolded = camel_header_unfold (value); message->subject = g_strstrip (camel_header_decode_string (unfolded, charset)); g_free (unfolded); break; case HEADER_TO: case HEADER_CC: case HEADER_BCC: case HEADER_RESENT_TO: case HEADER_RESENT_CC: case HEADER_RESENT_BCC: addr = g_hash_table_lookup (message->recipients, name); if (value) { unfolded = camel_header_unfold (value); camel_address_decode (CAMEL_ADDRESS (addr), unfolded); g_free (unfolded); } else { camel_address_remove (CAMEL_ADDRESS (addr), -1); } return FALSE; case HEADER_DATE: if (value) { message->date = camel_header_decode_date (value, &message->date_offset); } else { message->date = CAMEL_MESSAGE_DATE_CURRENT; message->date_offset = 0; } break; case HEADER_MESSAGE_ID: g_free (message->message_id); if (value) message->message_id = camel_header_msgid_decode (value); else message->message_id = NULL; break; default: return FALSE; } return TRUE; }
/* This should run pretty quick, its called a lot */ iconv_t camel_iconv_open (const gchar *oto, const gchar *ofrom) { const gchar *to, *from; gchar *tofrom; struct _iconv_cache *ic; struct _iconv_cache_node *in; gint errnosav; iconv_t ip; if (oto == NULL || ofrom == NULL) { errno = EINVAL; return (iconv_t) -1; } to = camel_iconv_charset_name (oto); from = camel_iconv_charset_name (ofrom); tofrom = g_alloca (strlen (to) + strlen (from) + 2); sprintf (tofrom, "%s%%%s", to, from); G_LOCK (iconv); ic = g_hash_table_lookup (iconv_cache, tofrom); if (ic) { g_queue_remove (&iconv_cache_list, ic); } else { GList *link; link = g_queue_peek_tail_link (&iconv_cache_list); while (link != NULL && iconv_cache_list.length > E_ICONV_CACHE_SIZE) { GList *prev = g_list_previous (link); ic = (struct _iconv_cache *) link->data; in = g_queue_peek_head (&ic->open); if (in != NULL && !in->busy) { cd (printf ("Flushing iconv converter '%s'\n", ic->conv)); g_queue_delete_link (&iconv_cache_list, link); g_hash_table_remove (iconv_cache, ic->conv); flush_entry (ic); } link = prev; } ic = g_malloc (sizeof (*ic)); g_queue_init (&ic->open); ic->conv = g_strdup (tofrom); g_hash_table_insert (iconv_cache, ic->conv, ic); cd (printf ("Creating iconv converter '%s'\n", ic->conv)); } g_queue_push_head (&iconv_cache_list, ic); /* If we have a free iconv, use it */ in = g_queue_peek_tail (&ic->open); if (in != NULL && !in->busy) { cd (printf ("using existing iconv converter '%s'\n", ic->conv)); ip = in->ip; if (ip != (iconv_t) - 1) { /* work around some broken iconv implementations * that die if the length arguments are NULL */ gsize buggy_iconv_len = 0; gchar *buggy_iconv_buf = NULL; /* resets the converter */ iconv (ip, &buggy_iconv_buf, &buggy_iconv_len, &buggy_iconv_buf, &buggy_iconv_len); in->busy = TRUE; g_queue_remove (&ic->open, in); g_queue_push_head (&ic->open, in); } } else { cd (printf ("creating new iconv converter '%s'\n", ic->conv)); ip = iconv_open (to, from); in = g_malloc (sizeof (*in)); in->ip = ip; in->parent = ic; g_queue_push_head (&ic->open, in); if (ip != (iconv_t) - 1) { g_hash_table_insert (iconv_cache_open, ip, in); in->busy = TRUE; } else { errnosav = errno; g_warning ("Could not open converter for '%s' to '%s' charset", from, to); in->busy = FALSE; errno = errnosav; } } G_UNLOCK (iconv); return ip; }