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);
}
Example #5
0
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);
	}
}