static int envelope_decode_date (CamelIMAP4Engine *engine, time_t *date, CamelException *ex) { unsigned char *literal = NULL; camel_imap4_token_t token; const char *nstring; size_t n; if (camel_imap4_engine_next_token (engine, &token, ex) == -1) return -1; switch (token.token) { case CAMEL_IMAP4_TOKEN_NIL: *date = (time_t) -1; return 0; case CAMEL_IMAP4_TOKEN_ATOM: nstring = token.v.atom; break; case CAMEL_IMAP4_TOKEN_QSTRING: nstring = token.v.qstring; break; case CAMEL_IMAP4_TOKEN_LITERAL: if (camel_imap4_engine_literal (engine, &literal, &n, ex) == -1) return -1; nstring = literal; break; default: camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); return -1; } *date = camel_header_decode_date (nstring, NULL); g_free (literal); return 0; }
static void create_mime_message_cb (ESoapMessage *msg, gpointer user_data) { struct _create_mime_msg_data *create_data = user_data; CamelStream *mem, *filtered; CamelMimeFilter *filter; CamelContentType *content_type; GByteArray *bytes; gchar *base64; gint msgflag; guint32 message_camel_flags = 0; if (create_data->info) message_camel_flags = camel_message_info_flags (create_data->info); e_soap_message_start_element (msg, "Message", NULL, NULL); e_soap_message_start_element (msg, "MimeContent", NULL, NULL); /* This is horrid. We really need to extend ESoapMessage to allow us * to stream this directly rather than storing it in RAM. Which right * now we are doing about four times: the GByteArray in the mem stream, * then the base64 version, then the xmlDoc, then the soup request. */ camel_mime_message_set_best_encoding ( create_data->message, CAMEL_BESTENC_GET_ENCODING, CAMEL_BESTENC_8BIT); mem = camel_stream_mem_new (); filtered = camel_stream_filter_new (mem); filter = camel_mime_filter_crlf_new ( CAMEL_MIME_FILTER_CRLF_ENCODE, CAMEL_MIME_FILTER_CRLF_MODE_CRLF_ONLY); camel_stream_filter_add (CAMEL_STREAM_FILTER (filtered), filter); g_object_unref (filter); camel_data_wrapper_write_to_stream_sync ( CAMEL_DATA_WRAPPER (create_data->message), filtered, NULL, NULL); camel_stream_flush (filtered, NULL, NULL); camel_stream_flush (mem, NULL, NULL); bytes = camel_stream_mem_get_byte_array (CAMEL_STREAM_MEM (mem)); base64 = g_base64_encode (bytes->data, bytes->len); g_object_unref (mem); g_object_unref (filtered); e_soap_message_write_string (msg, base64); g_free (base64); e_soap_message_end_element (msg); /* MimeContent */ content_type = camel_mime_part_get_content_type (CAMEL_MIME_PART (create_data->message)); if (content_type && camel_content_type_is (content_type, "multipart", "report") && camel_content_type_param (content_type, "report-type") && g_ascii_strcasecmp (camel_content_type_param (content_type, "report-type"), "disposition-notification") == 0) { /* it's a disposition notification reply, set ItemClass too */ e_soap_message_start_element (msg, "ItemClass", NULL, NULL); e_soap_message_write_string (msg, "REPORT.IPM.NOTE.IPNRN"); e_soap_message_end_element (msg); /* ItemClass */ } e_ews_message_write_string_parameter_with_attribute ( msg, "Importance", NULL, (message_camel_flags & CAMEL_MESSAGE_FLAGGED) != 0 ? "High" : "Normal", NULL, NULL); /* more MAPI crap. You can't just set the IsDraft property * here you have to use the MAPI MSGFLAG_UNSENT extended * property Further crap is that Exchange 2007 assumes when it * sees this property that you're setting the value to 0 * ... it never checks */ msgflag = MAPI_MSGFLAG_READ; /* draft or sent is always read */ if ((message_camel_flags & CAMEL_MESSAGE_DRAFT) != 0) msgflag |= MAPI_MSGFLAG_UNSENT; e_ews_message_add_extended_property_tag_int (msg, 0x0e07, msgflag); if ((message_camel_flags & (CAMEL_MESSAGE_FORWARDED | CAMEL_MESSAGE_ANSWERED)) != 0) { gint icon; icon = (message_camel_flags & CAMEL_MESSAGE_ANSWERED) != 0 ? 0x105 : 0x106; e_ews_message_add_extended_property_tag_int (msg, 0x1080, icon); } if (create_data->info) { const gchar *followup, *completed, *dueby; time_t completed_tt = (time_t) 0 , dueby_tt = (time_t) 0; /* follow-up flags */ followup = camel_message_info_user_tag (create_data->info, "follow-up"); completed = camel_message_info_user_tag (create_data->info, "completed-on"); dueby = camel_message_info_user_tag (create_data->info, "due-by"); if (followup && !*followup) followup = NULL; if (completed && *completed) completed_tt = camel_header_decode_date (completed, NULL); if (dueby && *dueby) dueby_tt = camel_header_decode_date (dueby, NULL); /* PidTagFlagStatus */ e_ews_message_add_extended_property_tag_int (msg, 0x1090, followup ? (completed_tt != (time_t) 0 ? 0x01 /* followupComplete */: 0x02 /* followupFlagged */) : 0x0); if (followup) { /* PidLidFlagRequest */ e_ews_message_add_extended_property_distinguished_tag_string (msg, "Common", 0x8530, followup); /* PidTagToDoItemFlags */ e_ews_message_add_extended_property_tag_int (msg, 0x0e2b, 1); } if (followup && completed_tt != (time_t) 0) { /* minute precision */ completed_tt = completed_tt - (completed_tt % 60); /* PidTagFlagCompleteTime */ e_ews_message_add_extended_property_tag_time (msg, 0x1091, completed_tt); /* PidLidTaskDateCompleted */ e_ews_message_add_extended_property_distinguished_tag_time (msg, "Task", 0x810f, completed_tt); /* PidLidTaskStatus */ e_ews_message_add_extended_property_distinguished_tag_int (msg, "Task", 0x8101, 2); /* PidLidPercentComplete */ e_ews_message_add_extended_property_distinguished_tag_double (msg, "Task", 0x8102, 1.0); /* PidLidTaskComplete */ e_ews_message_add_extended_property_distinguished_tag_boolean (msg, "Task", 0x811c, TRUE); } if (followup && dueby_tt != (time_t) 0 && completed_tt == (time_t) 0) { /* PidLidTaskStatus */ e_ews_message_add_extended_property_distinguished_tag_int (msg, "Task", 0x8101, 0); /* PidLidPercentComplete */ e_ews_message_add_extended_property_distinguished_tag_double (msg, "Task", 0x8102, 0.0); /* PidLidTaskDueDate */ e_ews_message_add_extended_property_distinguished_tag_time (msg, "Task", 0x8105, dueby_tt); /* PidLidTaskComplete */ e_ews_message_add_extended_property_distinguished_tag_boolean (msg, "Task", 0x811c, FALSE); } } if (create_data->recipients) { GHashTable *recip_to, *recip_cc, *recip_bcc; recip_to = g_hash_table_new (camel_strcase_hash, camel_strcase_equal); recip_cc = g_hash_table_new (camel_strcase_hash, camel_strcase_equal); recip_bcc = g_hash_table_new (camel_strcase_hash, camel_strcase_equal); filter_recipients (create_data->message, create_data->recipients, recip_to, recip_cc, recip_bcc); write_recipients (msg, "ToRecipients", recip_to); write_recipients (msg, "CcRecipients", recip_cc); write_recipients (msg, "BccRecipients", recip_bcc); g_hash_table_destroy (recip_to); g_hash_table_destroy (recip_cc); g_hash_table_destroy (recip_bcc); } e_ews_message_write_string_parameter_with_attribute ( msg, "IsRead", NULL, (message_camel_flags & CAMEL_MESSAGE_SEEN) != 0 ? "true" : "false", NULL, NULL); e_soap_message_end_element (msg); /* Message */ g_free (create_data); }
/* 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; }
void e_mail_formatter_format_header (EMailFormatter *formatter, GString *buffer, const gchar *header_name, const gchar *header_value, guint32 flags, const gchar *charset) { gchar *canon_name, *buf, *value = NULL; const gchar *label, *txt; gboolean addrspec = FALSE; gchar *str_field = NULL; gint i; g_return_if_fail (E_IS_MAIL_FORMATTER (formatter)); g_return_if_fail (buffer != NULL); g_return_if_fail (header_name != NULL); g_return_if_fail (header_value != NULL); canon_name = g_alloca (strlen (header_name) + 1); strcpy (canon_name, header_name); e_mail_formatter_canon_header_name (canon_name); for (i = 0; addrspec_hdrs[i]; i++) { if (g_ascii_strcasecmp (canon_name, addrspec_hdrs[i]) == 0) { addrspec = TRUE; break; } } label = _(canon_name); if (addrspec) { struct _camel_header_address *addrs; GString *html; gchar *img; gchar *charset; charset = e_mail_formatter_dup_charset (formatter); if (charset == NULL) charset = e_mail_formatter_dup_default_charset (formatter); buf = camel_header_unfold (header_value); addrs = camel_header_address_decode (buf, charset); if (addrs == NULL) { g_free (charset); g_free (buf); return; } g_free (charset); g_free (buf); html = g_string_new (""); img = e_mail_formatter_format_address ( formatter, html, addrs, label, (flags & E_MAIL_FORMATTER_HEADER_FLAG_NOLINKS), !(flags & E_MAIL_FORMATTER_HEADER_FLAG_NOELIPSIZE)); if (img != NULL) { str_field = g_strdup_printf ("%s: %s", label, img); label = str_field; flags |= E_MAIL_FORMATTER_HEADER_FLAG_NODEC; g_free (img); } camel_header_address_list_clear (&addrs); txt = value = html->str; g_string_free (html, FALSE); flags |= E_MAIL_FORMATTER_HEADER_FLAG_HTML; flags |= E_MAIL_FORMATTER_HEADER_FLAG_BOLD; } else if (g_str_equal (canon_name, "Subject")) { buf = camel_header_unfold (header_value); txt = value = camel_header_decode_string (buf, charset); g_free (buf); flags |= E_MAIL_FORMATTER_HEADER_FLAG_BOLD; } else if (g_str_equal (canon_name, "X-Evolution-Mailer")) { /* pseudo-header */ label = _("Mailer"); txt = value = camel_header_format_ctext (header_value, charset); flags |= E_MAIL_FORMATTER_HEADER_FLAG_BOLD; } else if (g_str_equal (canon_name, "Date") || g_str_equal (canon_name, "Resent-Date")) { CamelMimeFilterToHTMLFlags text_format_flags; gint msg_offset, local_tz; time_t msg_date; struct tm local; gchar *html; gboolean hide_real_date; hide_real_date = !e_mail_formatter_get_show_real_date (formatter); txt = header_value; while (*txt == ' ' || *txt == '\t') txt++; text_format_flags = e_mail_formatter_get_text_format_flags (formatter); html = camel_text_to_html (txt, text_format_flags, 0); msg_date = camel_header_decode_date (txt, &msg_offset); e_localtime_with_offset (msg_date, &local, &local_tz); /* Convert message offset to minutes (e.g. -0400 --> -240) */ msg_offset = ((msg_offset / 100) * 60) + (msg_offset % 100); /* Turn into offset from localtime, not UTC */ msg_offset -= local_tz / 60; /* value will be freed at the end */ if (!hide_real_date && !msg_offset) { /* No timezone difference; just * show the real Date: header. */ txt = value = html; } else { gchar *date_str; date_str = e_datetime_format_format ( "mail", "header", DTFormatKindDateTime, msg_date); if (hide_real_date) { /* Show only the local-formatted date, losing * all timezone information like Outlook does. * Should we attempt to show it somehow? */ txt = value = date_str; } else { txt = value = g_strdup_printf ( "%s (<I>%s</I>)", html, date_str); g_free (date_str); } g_free (html); } flags |= E_MAIL_FORMATTER_HEADER_FLAG_HTML; flags |= E_MAIL_FORMATTER_HEADER_FLAG_BOLD; } else if (g_str_equal (canon_name, "Newsgroups")) { GSList *ng, *scan; GString *html; buf = camel_header_unfold (header_value); if (!(ng = camel_header_newsgroups_decode (buf))) { g_free (buf); return; } g_free (buf); html = g_string_new (""); scan = ng; while (scan) { const gchar *newsgroup = scan->data; if (flags & E_MAIL_FORMATTER_HEADER_FLAG_NOLINKS) g_string_append_printf ( html, "%s", newsgroup); else g_string_append_printf ( html, "<a href=\"news:%s\">%s</a>", newsgroup, newsgroup); scan = g_slist_next (scan); if (scan) g_string_append_printf (html, ", "); } g_slist_free_full (ng, g_free); txt = html->str; value = g_string_free (html, FALSE); flags |= E_MAIL_FORMATTER_HEADER_FLAG_HTML; flags |= E_MAIL_FORMATTER_HEADER_FLAG_BOLD; } else if (g_str_equal (canon_name, "Received") || g_str_has_prefix (canon_name, "X-")) { /* don't unfold Received nor extension headers */ txt = value = camel_header_decode_string (header_value, charset); } else { /* don't unfold Received nor extension headers */ buf = camel_header_unfold (header_value); txt = value = camel_header_decode_string (buf, charset); g_free (buf); } e_mail_formatter_format_text_header ( formatter, buffer, label, txt, flags); g_free (value); g_free (str_field); }
void ews_utils_update_followup_flags (ESoapMessage *msg, CamelMessageInfo *mi) { const gchar *followup, *completed, *dueby; time_t completed_tt = (time_t) 0 , dueby_tt = (time_t) 0; g_return_if_fail (msg != NULL); g_return_if_fail (mi != NULL); followup = camel_message_info_get_user_tag (mi, "follow-up"); completed = camel_message_info_get_user_tag (mi, "completed-on"); dueby = camel_message_info_get_user_tag (mi, "due-by"); if (followup && !*followup) followup = NULL; if (completed && *completed) completed_tt = camel_header_decode_date (completed, NULL); if (dueby && *dueby) dueby_tt = camel_header_decode_date (dueby, NULL); if (followup) { time_t now_tt = time (NULL); /* PidTagFlagStatus */ e_ews_message_add_set_item_field_extended_tag_int (msg, NULL, "Message", 0x1090, completed_tt != (time_t) 0 ? 0x01 /* followupComplete */: 0x02 /* followupFlagged */); /* PidLidFlagRequest */ e_ews_message_add_set_item_field_extended_distinguished_tag_string (msg, NULL, "Message", "Common", 0x8530, followup); /* PidTagToDoItemFlags */ e_ews_message_add_set_item_field_extended_tag_int (msg, NULL, "Message", 0x0e2b, 1); if (completed_tt == (time_t) 0 && dueby_tt == (time_t) 0) { /* PidLidTaskStatus */ e_ews_message_add_set_item_field_extended_distinguished_tag_int (msg, NULL, "Message", "Task", 0x8101, 0); /* PidLidPercentComplete */ e_ews_message_add_set_item_field_extended_distinguished_tag_double (msg, NULL, "Message", "Task", 0x8102, 0.0); /* PidLidTaskStartDate */ e_ews_message_add_set_item_field_extended_distinguished_tag_time (msg, NULL, "Message", "Task", 0x8104, now_tt); /* PidLidTaskDueDate */ e_ews_message_add_set_item_field_extended_distinguished_tag_time (msg, NULL, "Message", "Task", 0x8105, now_tt); /* PidLidTaskComplete */ e_ews_message_add_set_item_field_extended_distinguished_tag_boolean (msg, NULL, "Message", "Task", 0x811c, FALSE); } } else { /* PidTagFlagStatus */ e_ews_message_add_delete_item_field_extended_tag (msg, 0x1090, E_EWS_MESSAGE_DATA_TYPE_INT); /* PidTagFlagCompleteTime */ e_ews_message_add_delete_item_field_extended_tag (msg, 0x1091, E_EWS_MESSAGE_DATA_TYPE_TIME); /* PidTagToDoItemFlags */ e_ews_message_add_delete_item_field_extended_tag (msg, 0x0e2b, E_EWS_MESSAGE_DATA_TYPE_INT); /* PidTagFollowupIcon */ e_ews_message_add_delete_item_field_extended_tag (msg, 0x1095, E_EWS_MESSAGE_DATA_TYPE_INT); /* PidLidFlagRequest */ e_ews_message_add_delete_item_field_extended_distinguished_tag (msg, "Common", 0x8530, E_EWS_MESSAGE_DATA_TYPE_STRING); /* PidLidFlagString */ e_ews_message_add_delete_item_field_extended_distinguished_tag (msg, "Common", 0x85c0, E_EWS_MESSAGE_DATA_TYPE_INT); /* PidLidTaskStatus */ e_ews_message_add_delete_item_field_extended_distinguished_tag (msg, "Task", 0x8101, E_EWS_MESSAGE_DATA_TYPE_INT); /* PidLidPercentComplete */ e_ews_message_add_delete_item_field_extended_distinguished_tag (msg, "Task", 0x8102, E_EWS_MESSAGE_DATA_TYPE_DOUBLE); /* PidLidTaskStartDate */ e_ews_message_add_delete_item_field_extended_distinguished_tag (msg, "Task", 0x8104, E_EWS_MESSAGE_DATA_TYPE_TIME); /* PidLidTaskDueDate */ e_ews_message_add_delete_item_field_extended_distinguished_tag (msg, "Task", 0x8105, E_EWS_MESSAGE_DATA_TYPE_TIME); /* PidLidTaskDateCompleted */ e_ews_message_add_delete_item_field_extended_distinguished_tag (msg, "Task", 0x810f, E_EWS_MESSAGE_DATA_TYPE_TIME); /* PidLidTaskComplete */ e_ews_message_add_delete_item_field_extended_distinguished_tag (msg, "Task", 0x811c, E_EWS_MESSAGE_DATA_TYPE_BOOLEAN); } if (followup && completed_tt != (time_t) 0) { /* minute precision */ completed_tt = completed_tt - (completed_tt % 60); /* PidTagFlagCompleteTime */ e_ews_message_add_set_item_field_extended_tag_time (msg, NULL, "Message", 0x1091, completed_tt); /* PidTagFollowupIcon */ e_ews_message_add_delete_item_field_extended_tag (msg, 0x1095, E_EWS_MESSAGE_DATA_TYPE_INT); /* PidLidTaskDateCompleted */ e_ews_message_add_set_item_field_extended_distinguished_tag_time (msg, NULL, "Message", "Task", 0x810f, completed_tt); /* PidLidTaskStatus */ e_ews_message_add_set_item_field_extended_distinguished_tag_int (msg, NULL, "Message", "Task", 0x8101, 2); /* PidLidPercentComplete */ e_ews_message_add_set_item_field_extended_distinguished_tag_double (msg, NULL, "Message", "Task", 0x8102, 1.0); /* PidLidTaskComplete */ e_ews_message_add_set_item_field_extended_distinguished_tag_boolean (msg, NULL, "Message", "Task", 0x811c, TRUE); } if (followup && dueby_tt != (time_t) 0 && completed_tt == (time_t) 0) { time_t now_tt = time (NULL); if (now_tt > dueby_tt) now_tt = dueby_tt - 1; /* PidLidTaskStatus */ e_ews_message_add_set_item_field_extended_distinguished_tag_int (msg, NULL, "Message", "Task", 0x8101, 0); /* PidLidPercentComplete */ e_ews_message_add_set_item_field_extended_distinguished_tag_double (msg, NULL, "Message", "Task", 0x8102, 0.0); /* PidLidTaskStartDate */ e_ews_message_add_set_item_field_extended_distinguished_tag_time (msg, NULL, "Message", "Task", 0x8104, now_tt); /* PidLidTaskDueDate */ e_ews_message_add_set_item_field_extended_distinguished_tag_time (msg, NULL, "Message", "Task", 0x8105, dueby_tt); /* PidLidTaskComplete */ e_ews_message_add_set_item_field_extended_distinguished_tag_boolean (msg, NULL, "Message", "Task", 0x811c, FALSE); } }