[balsa] [Patch] ical improvements
- From: Peter Bloomfield <peterb src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [balsa] [Patch] ical improvements
- Date: Sat, 1 Feb 2020 19:11:48 +0000 (UTC)
commit ad3f57b29bd184a23661c0bee403f98320d95116
Author: Albrecht Dreß <albrecht dress arcor de>
Date: Sat Feb 1 14:08:55 2020 -0500
[Patch] ical improvements
* README, configure.ac, meson.build: require libical >= 2.0.0 instead of 3.0.0;
* libbalsa/rfc2445.c: libbalsa_vevent_reply(): add several optional fields
to the “REPLY” message as to work around a M$ Exchange/Outlook bug;
* src/balsa-mime-widget-vcalendar.c: balsa_vevent_widget():
ref the VCal object containing the time zone data if we show
the buttons for sending a reply;
vevent_reply(): construct the reply as multipart/alternative,
store it the the sentbox.
ChangeLog | 13 +++++++
README | 2 +-
configure.ac | 2 +-
libbalsa/rfc2445.c | 24 ++++++++++++
meson.build | 2 +-
src/balsa-mime-widget-vcalendar.c | 80 +++++++++++++++++++++++++++------------
6 files changed, 96 insertions(+), 27 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 139c201c5..b4ff2d365 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2020-02-01 Albrecht Dreß <albrecht dress arcor de>
+
+ [Patch] ical improvements
+
+ * README, configure.ac, meson.build: require libical >= 2.0.0 instead of 3.0.0
+ * libbalsa/rfc2445.c: libbalsa_vevent_reply(): add several
+ optional fields to the “REPLY” message as to work around a M$
+ Exchange/Outlook bug
+ * src/balsa-mime-widget-vcalendar.c: balsa_vevent_widget():
+ ref the VCal object containing the time zone data if we show
+ the buttons for sending a reply; vevent_reply(): construct he
+ reply as multipart/alternative, store it the the sentbox
+
2020-02-01 Peter Bloomfield <pbloomfield bellsouth net>
mailbox: Remove another idle handler when closing the mailbox
diff --git a/README b/README
index 8e6dd3ba2..d6d318d1a 100644
--- a/README
+++ b/README
@@ -46,7 +46,7 @@ Basically, Balsa requires
- gthread-2.0
- gnutls >= 3.0
- gpgme >= 1.6.0
-- libical >= 3.0.0
+- libical >= 2.0.0
- fribidi
--disable-more-warnings
diff --git a/configure.ac b/configure.ac
index 0ab69bb36..080678d73 100644
--- a/configure.ac
+++ b/configure.ac
@@ -230,7 +230,7 @@ gio-2.0
gthread-2.0
gnutls >= 3.0
fribidi
-libical >= 3.0.0
+libical >= 2.0.0
])
PKG_CHECK_MODULES(BALSA_AB, [
diff --git a/libbalsa/rfc2445.c b/libbalsa/rfc2445.c
index ee358b236..17c1e3ed6 100644
--- a/libbalsa/rfc2445.c
+++ b/libbalsa/rfc2445.c
@@ -860,6 +860,9 @@ libbalsa_vevent_recurrence_str(LibBalsaVEvent *event, const gchar *format_str)
* According to RFC 5546, Sect. 3.2.3., the REPLY shall include the following components and properties:
* METHOD: MUST be REPLY
* VEVENT: ATTENDEE, DTSTAMP, ORGANIZER, RECURRENCE-ID (if present in the request), UID, SEQUENCE (if
present in the request)
+ *
+ * However, M$ Outlook/Exchange is broken and does not process these standard-compliant parts correctly.
The trivial fix is to add
+ * several optional fields (I did not figure out which are needed to work around the issue, so we just add
them all...).
*/
gchar *
libbalsa_vevent_reply(const LibBalsaVEvent *event,
@@ -922,6 +925,27 @@ libbalsa_vevent_reply(const LibBalsaVEvent *event,
icalcomponent_add_property(ev_data, icalproperty_new_sequence(event->sequence));
}
+ /* the following fields are *optional* in a reply according to RFC 5546, Sect. 3.2.3, but are apparently
required by broken
+ * software like Exchange/Outlook */
+ if (icaltime_is_null_time(event->start) == 0) {
+ icalcomponent_add_property(ev_data, icalproperty_new_dtstart(event->start));
+ }
+ if (icaltime_is_null_time(event->end) == 0) {
+ icalcomponent_add_property(ev_data, icalproperty_new_dtend(event->end));
+ }
+ if (event->summary != NULL) {
+ icalcomponent_add_property(ev_data, icalproperty_new_summary(event->summary));
+ }
+ if (event->description != NULL) {
+ icalcomponent_add_property(ev_data, icalproperty_new_description(event->description));
+ }
+ if (event->status != ICAL_STATUS_NONE) {
+ icalcomponent_add_property(ev_data, icalproperty_new_status(event->status));
+ }
+ if (event->location != NULL) {
+ icalcomponent_add_property(ev_data, icalproperty_new_location(event->location));
+ }
+
reply_str = icalcomponent_as_ical_string(reply);
icalcomponent_free(reply);
return reply_str;
diff --git a/meson.build b/meson.build
index 64e1ca627..ec05689c9 100644
--- a/meson.build
+++ b/meson.build
@@ -136,7 +136,7 @@ gthread_dep = dependency('gthread-2.0')
gnutls_dep = dependency('gnutls', version : '>= 3.0')
gpgme_dep = dependency('gpgme', version : '>= 1.6.0')
fribidi_dep = dependency('fribidi')
-libical_dep = dependency('libical', version : '>= 3.0.0')
+libical_dep = dependency('libical', version : '>= 2.0.0')
# Dependencies for balsa
balsa_deps = [glib_dep,
diff --git a/src/balsa-mime-widget-vcalendar.c b/src/balsa-mime-widget-vcalendar.c
index d1410c25e..e9f814489 100644
--- a/src/balsa-mime-widget-vcalendar.c
+++ b/src/balsa-mime-widget-vcalendar.c
@@ -31,9 +31,10 @@
#include "balsa-mime-widget-callbacks.h"
-static GtkWidget *balsa_vevent_widget(LibBalsaVEvent * event,
- gboolean may_reply,
- InternetAddress * sender);
+static GtkWidget *balsa_vevent_widget(LibBalsaVEvent *event,
+ LibBalsaVCal *vcal,
+ gboolean may_reply,
+ InternetAddress *sender);
static void vevent_reply(GObject * button, GtkWidget * box);
@@ -103,7 +104,7 @@ balsa_mime_widget_new_vcalendar(BalsaMessage * bm,
frame = gtk_frame_new(NULL);
gtk_container_add(GTK_CONTAINER(mw), frame);
- event = balsa_vevent_widget(libbalsa_vcal_vevent(vcal_obj, event_no), may_reply, sender);
+ event = balsa_vevent_widget(libbalsa_vcal_vevent(vcal_obj, event_no), vcal_obj, may_reply, sender);
gtk_container_set_border_width(GTK_CONTAINER(event), 6U);
gtk_container_add(GTK_CONTAINER(frame), event);
}
@@ -168,8 +169,8 @@ balsa_mime_widget_new_vcalendar(BalsaMessage * bm,
} while (0)
static GtkWidget *
-balsa_vevent_widget(LibBalsaVEvent * event, gboolean may_reply,
- InternetAddress * sender)
+balsa_vevent_widget(LibBalsaVEvent *event, LibBalsaVCal *vcal, gboolean may_reply,
+ InternetAddress *sender)
{
GtkGrid *grid;
int row = 0;
@@ -252,7 +253,6 @@ balsa_vevent_widget(LibBalsaVEvent * event, gboolean may_reply,
GtkWidget *button;
/* add the callback data to the event object */
- g_object_ref(event);
g_object_set_data_full(G_OBJECT(event), "ev:sender",
internet_address_to_string(sender, FALSE),
(GDestroyNotify) g_free);
@@ -271,8 +271,12 @@ balsa_vevent_widget(LibBalsaVEvent * event, gboolean may_reply,
gtk_container_add(GTK_CONTAINER(box), bbox);
button = gtk_button_new_with_label(_("Accept"));
- g_object_set_data_full(G_OBJECT(button), "event", event,
- (GDestroyNotify) g_object_unref);
+ g_object_set_data(G_OBJECT(button), "event", event);
+
+ /* Note: we must ref the full VCal object here as time zone information is stored in it. Only
ref'ing the event would thus
+ * lead to a segfault when a reply message is actually created. */
+ g_object_set_data_full(G_OBJECT(button), "vcal", g_object_ref(vcal),
+ (GDestroyNotify) g_object_unref);
g_object_set_data(G_OBJECT(button), "mode",
GINT_TO_POINTER(ICAL_PARTSTAT_ACCEPTED));
g_signal_connect(button, "clicked",
@@ -300,6 +304,22 @@ balsa_vevent_widget(LibBalsaVEvent * event, gboolean may_reply,
return GTK_WIDGET(grid);
}
+#define BUFFER_APPEND(b, l, s) \
+ G_STMT_START { \
+ if (s != NULL) { \
+ g_string_append_printf(b, "%s %s\n", l, s); \
+ }
\
+ } G_STMT_END
+
+#define BUFFER_APPEND_DATE(b, l, e, i)
\
+ G_STMT_START {
\
+ gchar *_dstr = libbalsa_vevent_time_str(e, i, balsa_app.date_string); \
+ if (_dstr != NULL) {
\
+ BUFFER_APPEND(b, l, _dstr);
\
+ g_free(_dstr); \
+ } \
+ } G_STMT_END
+
static void
vevent_reply(GObject * button, GtkWidget * box)
{
@@ -312,8 +332,8 @@ vevent_reply(GObject * button, GtkWidget * box)
LibBalsaMessageHeaders *headers;
LibBalsaMessageBody *body;
const gchar *summary;
+ GString *textbuf;
gchar *dummy;
- gchar **params;
GError *error = NULL;
LibBalsaMsgCreateResult result;
LibBalsaIdentity *ident;
@@ -344,26 +364,38 @@ vevent_reply(GObject * button, GtkWidget * box)
libbalsa_vcal_part_stat_to_str(pstat));
libbalsa_message_set_subject(message, dummy);
g_free(dummy);
+ libbalsa_message_set_subtype(message, "alternative");
- /* the only message part is the calendar object */
+ /* add an informational text part */
body = libbalsa_message_body_new(message);
- body->buffer =
- libbalsa_vevent_reply(event,
- INTERNET_ADDRESS_MAILBOX(ia)->addr,
- pstat);
- if (body->buffer == NULL) return;
body->charset = g_strdup("utf-8");
- body->content_type = g_strdup("text/calendar");
+ body->content_type = NULL;
+ textbuf = g_string_new(NULL);
+ g_string_append_printf(textbuf, _("%s %s the following iTIP calendar request:\n\n"),
+ internet_address_get_name(ia), libbalsa_vcal_part_stat_to_str(pstat));
+ BUFFER_APPEND(textbuf, _("Summary:"), libbalsa_vevent_summary(event));
+ BUFFER_APPEND_DATE(textbuf, _("Start:"), event, VEVENT_DATETIME_START);
+ BUFFER_APPEND_DATE(textbuf, _("End:"), event, VEVENT_DATETIME_END);
+ BUFFER_APPEND(textbuf, _("Location:"), libbalsa_vevent_location(event));
+ BUFFER_APPEND(textbuf, _("Description:"), libbalsa_vevent_description(event));
+ body->buffer = g_string_free(textbuf, FALSE);
+ if (balsa_app.wordwrap) {
+ libbalsa_wrap_string(body->buffer, balsa_app.wraplength);
+ }
libbalsa_message_append_part(message, body);
- /* set the text/calendar parameters */
- params = g_new(gchar *, 3);
- params[0] = g_strdup("method");
- params[1] = g_strdup("reply");
- params[2] = NULL;
- libbalsa_message_add_parameters(message, params);
+ /* the next message part is the calendar object */
+ body = libbalsa_message_body_new(message);
+ body->buffer = libbalsa_vevent_reply(event, INTERNET_ADDRESS_MAILBOX(ia)->addr, pstat);
+ if (body->buffer == NULL) {
+ g_object_unref(message);
+ return;
+ }
+ body->charset = g_strdup("utf-8");
+ body->content_type = g_strdup("text/calendar; method=reply");
+ libbalsa_message_append_part(message, body);
- result = libbalsa_message_send(message, balsa_app.outbox, NULL,
+ result = libbalsa_message_send(message, balsa_app.outbox, balsa_app.sentbox,
balsa_find_sentbox_by_url,
libbalsa_identity_get_smtp_server(ident),
balsa_app.send_progress_dialog,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]