From 3ea562e600eebb308edbfd5d4120aaf9b51b89a6 Mon Sep 17 00:00:00 2001 From: Pierre Pronchery Date: Thu, 19 Jul 2012 19:53:48 +0000 Subject: [PATCH] Reviewing Mailer's API --- include/Mailer/account.h | 41 ++++++++++++++++++++++++++++++++++++++- src/account.c | 34 +++++++++++++------------------- src/account.h | 2 +- src/account/imap4.c | 25 ++++++++++++++++++++---- src/account/pop3.c | 33 ++++++++++++++++++++++++------- src/mailer.c | 42 ++++++++++++++++++++++++++++++++++++---- 6 files changed, 139 insertions(+), 38 deletions(-) diff --git a/include/Mailer/account.h b/include/Mailer/account.h index ff9918b..82c670f 100644 --- a/include/Mailer/account.h +++ b/include/Mailer/account.h @@ -59,6 +59,45 @@ typedef struct _AccountConfig } AccountConfig; +/* AccountStatus */ +typedef enum _AccountStatus +{ + AS_CONNECTING = 0, + AS_CONNECTED, + AS_DISCONNECTED, + AS_AUTHENTICATED, + AS_READY +} AccountStatus; + + +/* AccountEvent */ +typedef enum _AccountEventType +{ + AET_ERROR = 0, + AET_STATUS +} AccountEventType; + +typedef union _AccountEvent +{ + AccountEventType type; + + /* AET_ERROR */ + struct + { + AccountEventType type; + char const * message; + } error; + + /* AET_STATUS */ + struct + { + AccountEventType type; + AccountStatus status; + char const * message; + } status; +} AccountEvent; + + /* AccountPlugin */ typedef struct _AccountPluginHelper { @@ -67,7 +106,7 @@ typedef struct _AccountPluginHelper SSL_CTX * (*get_ssl_context)(Account * account); /* useful */ int (*error)(Account * account, char const * message, int ret); - void (*status)(Account * account, char const * format, ...); + void (*event)(Account * account, AccountEvent * event); /* authentication */ char * (*authenticate)(Account * account, char const * message); int (*confirm)(Account * account, char const * message); diff --git a/src/account.c b/src/account.c index 6945f4a..f0c9007 100644 --- a/src/account.c +++ b/src/account.c @@ -69,7 +69,7 @@ static SSL_CTX * _account_helper_get_ssl_context(Account * account); /* useful */ static int _account_helper_error(Account * account, char const * message, int ret); -static void _account_helper_status(Account * account, char const * format, ...); +static void _account_helper_event(Account * account, AccountEvent * event); static char * _account_helper_authenticate(Account * account, char const * message); static int _account_helper_confirm(Account * account, char const * message); @@ -90,7 +90,7 @@ static const AccountPluginHelper _account_plugin_helper = NULL, _account_helper_get_ssl_context, _account_helper_error, - _account_helper_status, + _account_helper_event, _account_helper_authenticate, _account_helper_confirm, _account_helper_folder_new, @@ -187,7 +187,7 @@ void account_delete(Account * account) /* accessors */ /* account_get_config */ -AccountConfig * account_get_config(Account * account) +AccountConfig const * account_get_config(Account * account) { if(account->account == NULL) return account->definition->config; @@ -436,28 +436,20 @@ static int _account_helper_error(Account * account, char const * message, } -/* account_helper_status */ -static void _account_helper_status(Account * account, char const * format, ...) +/* account_helper_event */ +static void _account_helper_event(Account * account, AccountEvent * event) { - va_list ap; - int res; - size_t size; - char * p = NULL; + Mailer * mailer = account->mailer; - va_start(ap, format); - res = vsprintf(NULL, format, ap); - va_end(ap); - if(res >= 0) + switch(event->type) { - va_start(ap, format); - size = res; - if((p = malloc(++size)) != NULL) - vsnprintf(p, size, format, ap); - va_end(ap); + case AET_ERROR: + mailer_error(mailer, event->error.message, 1); + break; + case AET_STATUS: + mailer_set_status(mailer, event->status.message); + break; } - if(p != NULL) - mailer_set_status(account->mailer, p); - free(p); } diff --git a/src/account.h b/src/account.h index a5f03db..c7d5cd5 100644 --- a/src/account.h +++ b/src/account.h @@ -35,7 +35,7 @@ void account_delete(Account * account); int account_get_enabled(Account * account); void account_set_enabled(Account * account, int enabled); -AccountConfig * account_get_config(Account * account); +AccountConfig const * account_get_config(Account * account); char const * account_get_name(Account * account); char const * account_get_title(Account * account); char const * account_get_type(Account * account); diff --git a/src/account/imap4.c b/src/account/imap4.c index 140f8b3..6acdcc2 100644 --- a/src/account/imap4.c +++ b/src/account/imap4.c @@ -943,11 +943,13 @@ static gboolean _on_connect(gpointer data) { IMAP4 * imap4 = data; AccountPluginHelper * helper = imap4->helper; + AccountEvent event; char const * hostname; char const * p; uint16_t port; struct sockaddr_in sa; int res; + char buf[128]; #ifdef DEBUG fprintf(stderr, "DEBUG: %s()\n", __func__); @@ -956,7 +958,7 @@ static gboolean _on_connect(gpointer data) /* get the hostname and port */ if((hostname = imap4->config[I4CV_HOSTNAME].value) == NULL) { - helper->error(NULL, "No hostname set", 1); + helper->error(helper->account, "No hostname set", 1); return FALSE; } if((p = imap4->config[I4CV_PORT].value) == NULL) @@ -978,9 +980,15 @@ static gboolean _on_connect(gpointer data) && fcntl(imap4->fd, F_SETFL, res | O_NONBLOCK) == -1) /* ignore this error */ helper->error(NULL, strerror(errno), 1); - /* connect to the remote host */ - helper->status(helper->account, "Connecting to %s (%s:%u)", hostname, + /* report the current status */ + memset(&event, 0, sizeof(event)); + event.status.type = AET_STATUS; + event.status.status = AS_CONNECTING; + snprintf(buf, sizeof(buf), "Connecting to %s (%s:%u)", hostname, inet_ntoa(sa.sin_addr), port); + event.status.message = buf; + helper->event(helper->account, &event); + /* connect to the remote host */ if((connect(imap4->fd, (struct sockaddr *)&sa, sizeof(sa)) != 0 && errno != EINPROGRESS) || _connect_channel(imap4) != 0) @@ -1050,6 +1058,7 @@ static gboolean _on_watch_can_connect(GIOChannel * source, { IMAP4 * imap4 = data; AccountPluginHelper * helper = imap4->helper; + AccountEvent event; char const * hostname = imap4->config[I4CV_HOSTNAME].value; uint16_t port = (unsigned long)imap4->config[I4CV_PORT].value; struct sockaddr_in sa; @@ -1063,8 +1072,16 @@ static gboolean _on_watch_can_connect(GIOChannel * source, #endif /* XXX remember the address instead */ if(_imap4_lookup(imap4, hostname, port, &sa) == 0) - helper->status(helper->account, "Connected to %s (%s:%u)", + { + /* report the current status */ + memset(&event, 0, sizeof(event)); + event.status.type = AET_STATUS; + event.status.status = AS_CONNECTED; + snprintf(buf, sizeof(buf), "Connected to %s (%s:%u)", hostname, inet_ntoa(sa.sin_addr), port); + event.status.message = buf; + helper->event(helper->account, &event); + } imap4->wr_source = 0; /* setup SSL */ if(imap4->config[I4CV_SSL].value != NULL) diff --git a/src/account/pop3.c b/src/account/pop3.c index 6de8edf..0a23d85 100644 --- a/src/account/pop3.c +++ b/src/account/pop3.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -155,7 +156,7 @@ static int _pop3_refresh(POP3 * pop3, AccountFolder * folder, /* useful */ static POP3Command * _pop3_command(POP3 * pop3, POP3Context context, char const * command); -static int _pop3_lookup(POP3 * pop3, char const * hostname, unsigned short port, +static int _pop3_lookup(POP3 * pop3, char const * hostname, uint16_t port, struct sockaddr_in * sa); static int _pop3_parse(POP3 * pop3); static void _pop3_reset(POP3 * pop3); @@ -316,7 +317,7 @@ static POP3Command * _pop3_command(POP3 * pop3, POP3Context context, /* pop3_lookup */ -static int _pop3_lookup(POP3 * pop3, char const * hostname, unsigned short port, +static int _pop3_lookup(POP3 * pop3, char const * hostname, uint16_t port, struct sockaddr_in * sa) { struct hostent * he; @@ -587,11 +588,13 @@ static gboolean _on_connect(gpointer data) { POP3 * pop3 = data; AccountPluginHelper * helper = pop3->helper; + AccountEvent event; char const * hostname; char const * p; - unsigned short port; + uint16_t port; struct sockaddr_in sa; int res; + char buf[128]; #ifdef DEBUG fprintf(stderr, "DEBUG: %s()\n", __func__); @@ -612,6 +615,7 @@ static gboolean _on_connect(gpointer data) helper->error(NULL, error_get(), 1); return FALSE; } + /* create the socket */ if((pop3->fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { helper->error(NULL, strerror(errno), 1); @@ -621,9 +625,15 @@ static gboolean _on_connect(gpointer data) && fcntl(pop3->fd, F_SETFL, res | O_NONBLOCK) == -1) /* ignore this error */ helper->error(NULL, strerror(errno), 1); - /* connect to the remote host */ - helper->status(helper->account, "Connecting to %s (%s:%u)", hostname, + /* report the current status */ + memset(&event, 0, sizeof(event)); + event.status.type = AET_STATUS; + event.status.status = AS_CONNECTING; + snprintf(buf, sizeof(buf), "Connecting to %s (%s:%u)", hostname, inet_ntoa(sa.sin_addr), port); + event.status.message = buf; + helper->event(helper->account, &event); + /* connect to the remote host */ if((connect(pop3->fd, (struct sockaddr *)&sa, sizeof(sa)) != 0 && errno != EINPROGRESS) || _connect_channel(pop3) != 0) @@ -691,8 +701,9 @@ static gboolean _on_watch_can_connect(GIOChannel * source, { POP3 * pop3 = data; AccountPluginHelper * helper = pop3->helper; + AccountEvent event; char const * hostname = pop3->config[P3CV_HOSTNAME].value; - unsigned short port = (unsigned long)pop3->config[P3CV_PORT].value; + uint16_t port = (unsigned long)pop3->config[P3CV_PORT].value; struct sockaddr_in sa; SSL_CTX * ssl_ctx; char buf[128]; @@ -704,8 +715,16 @@ static gboolean _on_watch_can_connect(GIOChannel * source, #endif /* XXX remember the address instead */ if(_pop3_lookup(pop3, hostname, port, &sa) == 0) - helper->status(helper->account, "Connected to %s (%s:%u)", + { + /* report the current status */ + memset(&event, 0, sizeof(event)); + event.status.type = AET_STATUS; + event.status.status = AS_CONNECTED; + snprintf(buf, sizeof(buf), "Connected to %s (%s:%u)", hostname, inet_ntoa(sa.sin_addr), port); + event.status.message = buf; + helper->event(helper->account, &event); + } pop3->wr_source = 0; /* setup SSL */ if(pop3->config[P3CV_SSL].value != NULL) diff --git a/src/mailer.c b/src/mailer.c index bd123a0..7e3d032 100644 --- a/src/mailer.c +++ b/src/mailer.c @@ -92,6 +92,10 @@ struct _Mailer /* widgets */ /* folders */ GtkWidget * fo_window; +#if GTK_CHECK_VERSION(2, 18, 0) + GtkWidget * fo_infobar; + GtkWidget * fo_infobar_label; +#endif GtkTreeStore * fo_store; GtkWidget * fo_view; /* headers */ @@ -397,6 +401,25 @@ Mailer * mailer_new(void) /* toolbar */ widget = desktop_toolbar_create(_mailer_fo_toolbar, mailer, group); gtk_box_pack_start(GTK_BOX(vbox), widget, FALSE, TRUE, 0); +#if GTK_CHECK_VERSION(2, 18, 0) + /* infobar */ + mailer->fo_infobar = gtk_info_bar_new_with_buttons(GTK_STOCK_CLOSE, + GTK_RESPONSE_CLOSE, NULL); + gtk_info_bar_set_message_type(GTK_INFO_BAR(mailer->fo_infobar), + GTK_MESSAGE_ERROR); + g_signal_connect(mailer->fo_infobar, "close", G_CALLBACK( + gtk_widget_hide), NULL); + g_signal_connect(mailer->fo_infobar, "response", G_CALLBACK( + gtk_widget_hide), NULL); + widget = gtk_info_bar_get_content_area(GTK_INFO_BAR( + mailer->fo_infobar)); + mailer->fo_infobar_label = gtk_label_new(NULL); + gtk_widget_show(mailer->fo_infobar_label); + gtk_box_pack_start(GTK_BOX(widget), mailer->fo_infobar_label, TRUE, + TRUE, 0); + gtk_widget_set_no_show_all(mailer->fo_infobar, TRUE); + gtk_box_pack_start(GTK_BOX(vbox), mailer->fo_infobar, FALSE, TRUE, 0); +#endif /* folders */ widget = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(widget), @@ -457,9 +480,9 @@ Mailer * mailer_new(void) mailer->bo_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_add_accel_group(GTK_WINDOW(mailer->bo_window), group); gtk_window_set_default_size(GTK_WINDOW(mailer->bo_window), 200, 300); -#if GTK_CHECK_VERSION(2, 6, 0) +# if GTK_CHECK_VERSION(2, 6, 0) gtk_window_set_icon_name(GTK_WINDOW(mailer->bo_window), "mailer"); -#endif +# endif gtk_window_set_title(GTK_WINDOW(mailer->bo_window), _("Message")); g_signal_connect_swapped(G_OBJECT(mailer->bo_window), "delete-event", G_CALLBACK(on_body_closex), mailer); @@ -992,17 +1015,25 @@ void mailer_set_status(Mailer * mailer, char const * status) /* mailer_error */ int mailer_error(Mailer * mailer, char const * message, int ret) { +#if !GTK_CHECK_VERSION(2, 18, 0) GtkWidget * dialog; +#endif if(mailer == NULL) return error_set_print("mailer", ret, "%s", message); +#if GTK_CHECK_VERSION(2, 18, 0) + /* info bar */ + gtk_label_set_text(GTK_LABEL(mailer->fo_infobar_label), message); + gtk_widget_show(mailer->fo_infobar); +#else + /* dialog window */ dialog = gtk_message_dialog_new(GTK_WINDOW(mailer->fo_window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, -#if GTK_CHECK_VERSION(2, 6, 0) +# if GTK_CHECK_VERSION(2, 6, 0) "%s", _("Error")); gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), -#endif +# endif "%s", message); gtk_window_set_title(GTK_WINDOW(dialog), _("Error")); gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW( @@ -1010,6 +1041,7 @@ int mailer_error(Mailer * mailer, char const * message, int ret) g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK( gtk_widget_destroy), NULL); gtk_widget_show(dialog); +#endif return ret; } @@ -2058,6 +2090,8 @@ static GtkWidget * _assistant_account_select(AccountData * ad) _on_account_name_changed), ad); gtk_box_pack_start(GTK_BOX(hbox), widget, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); + /* default identity */ + /* FIXME seems to not be remembered */ hbox = gtk_hbox_new(FALSE, 4); _account_add_label(hbox, NULL, group, _("Your name")); widget = gtk_entry_new();