Mercurial > pidgin
changeset 15163:fe05223b5d04
[gaim-migrate @ 17949]
Gmail notifications patch from Chris Stafford
- The plugin will only do anything if it sees "google:mail:notify" in disco.
- I decided to give Jabber a mail notification option for this, since the
feature has traditionally meant "notify me of new mail if I happen to have
a mail account that this server will notify me of"
- I decided to show the first unread mail in a thread, rather than all unread
messages[A
- I made a google.c/google.h file to keep code for Google Talk extensions
committer: Tailor Script <tailor@pidgin.im>
author | Sean Egan <seanegan@gmail.com> |
---|---|
date | Sun, 10 Dec 2006 23:08:45 +0000 |
parents | 96f3a7286375 |
children | 2c0e3ef91e37 |
files | gtk/gtknotify.c libgaim/protocols/jabber/Makefile.am libgaim/protocols/jabber/disco.c libgaim/protocols/jabber/google.c libgaim/protocols/jabber/google.h libgaim/protocols/jabber/iq.c libgaim/protocols/jabber/jabber.c libgaim/protocols/jabber/jabber.h |
diffstat | 8 files changed, 237 insertions(+), 18 deletions(-) [+] |
line wrap: on
line diff
--- a/gtk/gtknotify.c Sun Dec 10 22:01:22 2006 +0000 +++ b/gtk/gtknotify.c Sun Dec 10 23:08:45 2006 +0000 @@ -313,9 +313,7 @@ GaimNotifyMailData *data = NULL; GtkWidget *dialog = NULL; GtkWidget *vbox = NULL; - GtkWidget *hbox; GtkWidget *label; - GtkWidget *img; char *detail_text; char *label_text; GtkTreeIter iter; @@ -357,27 +355,15 @@ gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE); gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog)->vbox), GAIM_HIG_BORDER); - /* Setup the main horizontal box */ - hbox = gtk_hbox_new(FALSE, GAIM_HIG_BORDER); - gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox); - - /* Dialog icon */ - img = gtk_image_new_from_stock(GAIM_STOCK_DIALOG_INFO, - GTK_ICON_SIZE_DIALOG); - gtk_misc_set_alignment(GTK_MISC(img), 0, 0); - gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0); - /* Vertical box */ - vbox = gtk_vbox_new(FALSE, GAIM_HIG_BORDER); - - gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 0); + vbox = GTK_DIALOG(dialog)->vbox; if (mail_dialog == NULL && detailed) { GtkWidget *sw; /* Golden ratio it up! */ - gtk_widget_set_size_request(dialog, 475, 200); + gtk_widget_set_size_request(dialog, 550, 400); sw = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_IN);
--- a/libgaim/protocols/jabber/Makefile.am Sun Dec 10 22:01:22 2006 +0000 +++ b/libgaim/protocols/jabber/Makefile.am Sun Dec 10 23:08:45 2006 +0000 @@ -13,6 +13,8 @@ chat.h \ disco.c \ disco.h \ + google.c \ + google.h \ iq.c \ iq.h \ jabber.c \
--- a/libgaim/protocols/jabber/disco.c Sun Dec 10 22:01:22 2006 +0000 +++ b/libgaim/protocols/jabber/disco.c Sun Dec 10 23:08:45 2006 +0000 @@ -23,6 +23,7 @@ #include "prefs.h" #include "buddy.h" +#include "google.h" #include "iq.h" #include "disco.h" #include "jabber.h" @@ -250,6 +251,19 @@ if (!strcmp(name, "Google Talk")) js->googletalk = TRUE; } + + for (child = xmlnode_get_child(query, "feature"); child; + child = xmlnode_get_next_twin(child)) { + const char *var; + var = xmlnode_get_attrib(child, "var"); + if (!var) + continue; + + if (!strcmp("google:mail:notify", var)) { + js->server_caps |= JABBER_CAP_GMAIL_NOTIFY; + jabber_gmail_init(js); + } + } } static void
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libgaim/protocols/jabber/google.c Sun Dec 10 23:08:45 2006 +0000 @@ -0,0 +1,168 @@ + +/** + * Gaim is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "internal.h" +#include "debug.h" +#include "google.h" +#include "jabber.h" +#include "iq.h" + +static void +jabber_gmail_parse(JabberStream *js, xmlnode *packet, gpointer nul) +{ + const char *type = xmlnode_get_attrib(packet, "type"); + xmlnode *child; + xmlnode *message, *sender_node, *subject_node; + const char *from, *to, *subject, *url, *tid; + const char *in_str; + char *to_name; + int i, count = 1, returned_count; + + const char **tos, **froms, **subjects, **urls; + + if (strcmp(type, "result")) + return; + + child = xmlnode_get_child(packet, "mailbox"); + if (!child) + return; + + in_str = xmlnode_get_attrib(child, "total-matched"); + if (in_str && *in_str) + count = atoi(in_str); + + if (count == 0) + return; + + message = xmlnode_get_child(child, "mail-thread-info"); + + /* Loop once to see how many messages were returned so we can allocate arrays + * accordingly */ + if (!message) + return; + for (returned_count = 0; message; returned_count++, message=xmlnode_get_next_twin(message)); + + froms = g_new0(const char* , returned_count); + tos = g_new0(const char* , returned_count); + subjects = g_new0(const char* , returned_count); + urls = g_new0(const char* , returned_count); + + to = xmlnode_get_attrib(packet, "to"); + to_name = jabber_get_bare_jid(to); + url = xmlnode_get_attrib(child, "url"); + if (!url || !*url) + url = "http://www.gmail.com"; + + message= xmlnode_get_child(child, "mail-thread-info"); + for (i=0; message; message = xmlnode_get_next_twin(message), i++) { + subject_node = xmlnode_get_child(message, "subject"); + sender_node = xmlnode_get_child(message, "senders"); + sender_node = xmlnode_get_child(sender_node, "sender"); + + while (sender_node && (!xmlnode_get_attrib(sender_node, "unread") || + !strcmp(xmlnode_get_attrib(sender_node, "unread"),"0"))) + sender_node = xmlnode_get_next_twin(sender_node); + + if (!sender_node) { + i--; + continue; + } + + from = xmlnode_get_attrib(sender_node, "name"); + if (!from || !*from) + from = xmlnode_get_attrib(sender_node, "address"); + subject = xmlnode_get_data(subject_node); + /* + * url = xmlnode_get_attrib(message, "url"); + */ + tos[i] = (to_name != NULL ? to_name : ""); + froms[i] = (from != NULL ? from : ""); + subjects[i] = (subject != NULL ? subject : ""); + urls[i] = (url != NULL ? url : ""); + + tid = xmlnode_get_attrib(message, "tid"); + if (tid && + (js->gmail_last_tid == NULL || strcmp(tid, js->gmail_last_tid) > 0)) { + g_free(js->gmail_last_tid); + js->gmail_last_tid = g_strdup(tid); + } + } + + if (i>0) + gaim_notify_emails(js->gc, returned_count, TRUE, subjects, froms, tos, + urls, NULL, js->gc->account); + g_free(to_name); + g_free(tos); + g_free(froms); + g_free(subjects); + g_free(urls); + + in_str = xmlnode_get_attrib(child, "result-time"); + if (in_str && *in_str) { + g_free(js->gmail_last_time); + js->gmail_last_time = g_strdup(in_str); + } +} + +void +jabber_gmail_poke(JabberStream *js, xmlnode *packet) +{ + const char *type; + xmlnode *query; + JabberIq *iq; + + /* bail if the user isn't interested */ + if (!gaim_account_get_check_mail(js->gc->account)) + return; + + type = xmlnode_get_attrib(packet, "type"); + + + /* Is this an initial incoming mail notification? If so, send a request for more info */ + if (strcmp(type, "set") || !xmlnode_get_child(packet, "new-mail")) + return; + + gaim_debug(GAIM_DEBUG_MISC, "jabber", + "Got new mail notification. Sending request for more info\n"); + + iq = jabber_iq_new_query(js, JABBER_IQ_GET, "google:mail:notify"); + jabber_iq_set_callback(iq, jabber_gmail_parse, NULL); + query = xmlnode_get_child(iq->node, "query"); + + if (js->gmail_last_time) + xmlnode_set_attrib(query, "newer-than-time", js->gmail_last_time); + if (js->gmail_last_tid) + xmlnode_set_attrib(query, "newer-than-tid", js->gmail_last_tid); + + jabber_iq_send(iq); + return; +} + +void jabber_gmail_init(JabberStream *js) { + JabberIq *iq; + + if (!gaim_account_get_check_mail(js->gc->account)) + return; + + iq = jabber_iq_new_query(js, JABBER_IQ_GET, "google:mail:notify"); + jabber_iq_set_callback(iq, jabber_gmail_parse, NULL); + jabber_iq_send(iq); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libgaim/protocols/jabber/google.h Sun Dec 10 23:08:45 2006 +0000 @@ -0,0 +1,32 @@ +/** + * Gaim is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _GAIM_GOOGLE_H_ +#define _GAIM_GOOGLE_H_ + +/* This is a place for Google Talk-specific XMPP extensions to live + * such that they don't intermingle with code for the XMPP RFCs and XEPs :) */ + +#include "jabber.h" + +void jabber_gmail_init(JabberStream *js); +void jabber_gmail_poke(JabberStream *js, xmlnode *node); + +#endif /* _GAIM_GOOGLE_H_ */
--- a/libgaim/protocols/jabber/iq.c Sun Dec 10 22:01:22 2006 +0000 +++ b/libgaim/protocols/jabber/iq.c Sun Dec 10 23:08:45 2006 +0000 @@ -25,6 +25,7 @@ #include "buddy.h" #include "disco.h" +#include "google.h" #include "iq.h" #include "oob.h" #include "roster.h" @@ -279,12 +280,16 @@ } } - if(xmlnode_get_child_with_namespace(packet, "si", "http://jabber.org/protocol/si")) { jabber_si_parse(js, packet); return; } + if(xmlnode_get_child_with_namespace(packet, "new-mail", "google:mail:notify")) { + jabber_gmail_poke(js, packet); + return; + } + /* If we get here, send the default error reply mandated by XMPP-CORE */ if(type && (!strcmp(type, "set") || !strcmp(type, "get"))) { JabberIq *iq = jabber_iq_new(js, JABBER_IQ_ERROR);
--- a/libgaim/protocols/jabber/jabber.c Sun Dec 10 22:01:22 2006 +0000 +++ b/libgaim/protocols/jabber/jabber.c Sun Dec 10 23:08:45 2006 +0000 @@ -998,6 +998,8 @@ g_free(js->sasl_cb); #endif g_free(js->server_name); + g_free(js->gmail_last_time); + g_free(js->gmail_last_tid); g_free(js); gc->proto_data = NULL; @@ -1847,7 +1849,7 @@ static GaimPluginProtocolInfo prpl_info = { - OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME, + OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME | OPT_PROTO_MAIL_CHECK, NULL, /* user_splits */ NULL, /* protocol_options */ {"png,gif,jpeg", 0, 0, 96, 96, GAIM_ICON_SCALE_SEND | GAIM_ICON_SCALE_DISPLAY}, /* icon_spec */
--- a/libgaim/protocols/jabber/jabber.h Sun Dec 10 22:01:22 2006 +0000 +++ b/libgaim/protocols/jabber/jabber.h Sun Dec 10 23:08:45 2006 +0000 @@ -50,6 +50,12 @@ JABBER_CAP_CHAT_STATES = 1 << 6, JABBER_CAP_IQ_SEARCH = 1 << 7, JABBER_CAP_IQ_REGISTER = 1 << 8, + + /* Google Talk extensions: + * http://code.google.com/apis/talk/jep_extensions/extensions.html + */ + JABBER_CAP_GMAIL_NOTIFY = 1 << 9, + JABBER_CAP_RETRIEVED = 1 << 31 } JabberCapabilities; @@ -120,8 +126,12 @@ gboolean reinit; + JabberCapabilities server_caps; gboolean googletalk; char *server_name; + + char *gmail_last_time; + char *gmail_last_tid; /* OK, this stays at the end of the struct, so plugins can depend * on the rest of the stuff being in the right place