Mercurial > pidgin
changeset 3694:e941bfbacf7c
[gaim-migrate @ 3824]
Adds an option for unread mail notification for AIM over oscar. Yippy.
This involves making a connection to the email AIM servers (parallel to
chatnav, bos, auth, ads, etc.). Also added were functions n' stuff to
handle getting mail status updates.
AIM does this in a very silly way. They only tell you how many messages
you have when you sign on, so I had to change connection_has_mail so it
will just say "bleh has new mail," without saying the number of new
messages.
Also, I haven't really looked into having you auto-login to webmail,
though it is possible. This is good for now.
Oh, and since I'm sure people will ask... AIM screen names come with an
email account @netscape.net. You have to sign in to netscape.net to
activate it.
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Mon, 14 Oct 2002 07:47:51 +0000 |
parents | 2d1b14529fa2 |
children | 21d16e3164eb |
files | ChangeLog src/protocols/oscar/.cvsignore src/protocols/oscar/Makefile.am src/protocols/oscar/aim.h src/protocols/oscar/aim_cbtypes.h src/protocols/oscar/aim_internal.h src/protocols/oscar/conn.c src/protocols/oscar/email.c src/protocols/oscar/oscar.c src/prpl.c |
diffstat | 10 files changed, 318 insertions(+), 4 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog Mon Oct 14 06:34:42 2002 +0000 +++ b/ChangeLog Mon Oct 14 07:47:51 2002 +0000 @@ -90,6 +90,8 @@ * DCC File Receive support for IRC * File receive support for Jabber (Thanks, Nathan Walp) * File send/receive support for Oscar (Thanks, William T. Mahan) + * Option to have AIM over oscar notify you if you have + unread mail (Thanks, Mark Doliner) version 0.59 (06/24/2002): * Hungarian translation added (Thanks, Sutto Zoltan)
--- a/src/protocols/oscar/.cvsignore Mon Oct 14 06:34:42 2002 +0000 +++ b/src/protocols/oscar/.cvsignore Mon Oct 14 07:47:51 2002 +0000 @@ -10,6 +10,7 @@ chat.lo chatnav.lo conn.lo +email.lo ft.lo im.lo info.lo
--- a/src/protocols/oscar/Makefile.am Mon Oct 14 06:34:42 2002 +0000 +++ b/src/protocols/oscar/Makefile.am Mon Oct 14 07:47:51 2002 +0000 @@ -20,6 +20,7 @@ chat.c \ chatnav.c \ conn.c \ + email.c \ ft.c \ icq.c \ im.c \ @@ -58,6 +59,7 @@ chat.c \ chatnav.c \ conn.c \ + email.c \ ft.c \ icq.c \ im.c \
--- a/src/protocols/oscar/aim.h Mon Oct 14 06:34:42 2002 +0000 +++ b/src/protocols/oscar/aim.h Mon Oct 14 07:47:51 2002 +0000 @@ -216,6 +216,7 @@ #define AIM_CONN_TYPE_BOS 0x0002 #define AIM_CONN_TYPE_CHAT 0x000e #define AIM_CONN_TYPE_CHATNAV 0x000d +#define AIM_CONN_TYPE_EMAIL 0x0018 /* they start getting arbitrary in rendezvous stuff =) */ #define AIM_CONN_TYPE_RENDEZVOUS 0x0101 /* these do not speak FLAP! */ @@ -340,6 +341,8 @@ aim_frame_t *holding_queue; } ssi; + struct aim_emailinfo *emailinfo; + /* Connection information */ aim_conn_t *connlist; @@ -1123,6 +1126,21 @@ faim_export int aim_icq_ackofflinemsgs(aim_session_t *sess); faim_export int aim_icq_getsimpleinfo(aim_session_t *sess, const char *uin); +/* email.c */ +struct aim_emailinfo { + fu8_t *cookie16; + fu8_t *cookie8; + char *url; + fu16_t nummsgs; + fu8_t unread; + char *domain; + fu16_t flag; + struct aim_emailinfo *next; +}; + +faim_export int aim_email_sendcookies(aim_session_t *sess, aim_conn_t *conn); +faim_export int aim_email_activate(aim_session_t *sess, aim_conn_t *conn); + /* aim_util.c */ /* * These are really ugly. You'd think this was LISP. I wish it was.
--- a/src/protocols/oscar/aim_cbtypes.h Mon Oct 14 06:34:42 2002 +0000 +++ b/src/protocols/oscar/aim_cbtypes.h Mon Oct 14 07:47:51 2002 +0000 @@ -26,6 +26,7 @@ #define AIM_CB_FAM_SSI 0x0013 /* Server stored information */ #define AIM_CB_FAM_ICQ 0x0015 #define AIM_CB_FAM_ATH 0x0017 +#define AIM_CB_FAM_EML 0x0018 #define AIM_CB_FAM_OFT 0xfffe /* OFT/Rvous */ #define AIM_CB_FAM_SPECIAL 0xffff /* Internal libfaim use */ @@ -215,6 +216,18 @@ #define AIM_CB_ATH_AUTHRESPONSE 0x0007 /* + * SNAC Family: Email + * + * Used for getting information on the email address + * associated with your screen name. + * + */ +#define AIM_CB_EML_ERROR 0x0001 +#define AIM_CB_EML_SENDCOOKIES 0x0006 +#define AIM_CB_EML_MAILSTATUS 0x0007 +#define AIM_CB_EML_INIT 0x0016 + +/* * OFT Services * * See non-SNAC note below.
--- a/src/protocols/oscar/aim_internal.h Mon Oct 14 06:34:42 2002 +0000 +++ b/src/protocols/oscar/aim_internal.h Mon Oct 14 07:47:51 2002 +0000 @@ -52,6 +52,7 @@ faim_internal int popups_modfirst(aim_session_t *sess, aim_module_t *mod); faim_internal int adverts_modfirst(aim_session_t *sess, aim_module_t *mod); faim_internal int icq_modfirst(aim_session_t *sess, aim_module_t *mod); +faim_internal int email_modfirst(aim_session_t *sess, aim_module_t *mod); faim_internal int aim_genericreq_n(aim_session_t *, aim_conn_t *conn, fu16_t family, fu16_t subtype); faim_internal int aim_genericreq_n_snacid(aim_session_t *, aim_conn_t *conn, fu16_t family, fu16_t subtype);
--- a/src/protocols/oscar/conn.c Mon Oct 14 06:34:42 2002 +0000 +++ b/src/protocols/oscar/conn.c Mon Oct 14 07:47:51 2002 +0000 @@ -965,6 +965,8 @@ sess->ssi.items = NULL; sess->ssi.timestamp = (time_t)0; + sess->emailinfo = NULL; + /* * Default to SNAC login unless XORLOGIN is explicitly set. */ @@ -1003,6 +1005,7 @@ aim__registermodule(sess, icq_modfirst); /* missing 0x16 */ aim__registermodule(sess, auth_modfirst); + aim__registermodule(sess, email_modfirst); return; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/protocols/oscar/email.c Mon Oct 14 07:47:51 2002 +0000 @@ -0,0 +1,180 @@ +/* + * Family 0x0018 - Email notification + * + * Used for being alerted when the email address(es) associated with + * your screen name get new electronic-m. For normal AIM accounts, you + * get the email address screenname@netscape.net. AOL accounts have + * screenname@aol.com, and can also activate a netscape.net account. + * + */ + +#define FAIM_INTERNAL +#include <aim.h> + +/* + * Subtype 0x0006 - Request information about your email account + */ +faim_export int aim_email_sendcookies(aim_session_t *sess, aim_conn_t *conn) +{ + aim_frame_t *fr; + aim_snacid_t snacid; + + if (!sess || !conn) + return -EINVAL; + + if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+2+16+16))) + return -ENOMEM; + snacid = aim_cachesnac(sess, 0x0018, 0x0006, 0x0000, NULL, 0); + aim_putsnac(&fr->data, 0x0018, 0x0006, 0x0000, snacid); + + /* Number of cookies to follow */ + aimbs_put16(&fr->data, 0x0002); + + /* Cookie */ + aimbs_put16(&fr->data, 0x5d5e); + aimbs_put16(&fr->data, 0x1708); + aimbs_put16(&fr->data, 0x55aa); + aimbs_put16(&fr->data, 0x11d3); + aimbs_put16(&fr->data, 0xb143); + aimbs_put16(&fr->data, 0x0060); + aimbs_put16(&fr->data, 0xb0fb); + aimbs_put16(&fr->data, 0x1ecb); + + /* Cookie */ + aimbs_put16(&fr->data, 0xb380); + aimbs_put16(&fr->data, 0x9ad8); + aimbs_put16(&fr->data, 0x0dba); + aimbs_put16(&fr->data, 0x11d5); + aimbs_put16(&fr->data, 0x9f8a); + aimbs_put16(&fr->data, 0x0060); + aimbs_put16(&fr->data, 0xb0ee); + aimbs_put16(&fr->data, 0x0631); + + aim_tx_enqueue(sess, fr); + + return 0; +} + + +/* + * Subtype 0x0007 - Receive information about your email account + * So I don't even know if you can have 2 different 16 byte keys, + * but this is coded so it will handle that, and handle it well. + */ +static int parseinfo(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) +{ + aim_rxcallback_t userfunc; + struct aim_emailinfo *new; + aim_tlvlist_t *tlvlist; + fu8_t *cookie8, *cookie16; + + cookie8 = aimbs_getraw(bs, 8); /* Possibly the code used to log you in to mail? */ + cookie16 = aimbs_getraw(bs, 16); /* Mail cookie sent above */ + + /* See if we already have some info associated with this cookie */ + for (new=sess->emailinfo; (new && strncmp(cookie16, new->cookie16, 16)); new=new->next); + if (new) { + /* Free some of the old info, if existant */ + if (new->cookie8) free(new->cookie8); + if (new->cookie16) free(new->cookie16); + if (new->url) free(new->url); + if (new->domain) free(new->domain); + } else { + /* We don't already have info, so create a new struct for it */ + if (!(new = malloc(sizeof(struct aim_emailinfo)))) + return -ENOMEM; + + new->next = sess->emailinfo; + sess->emailinfo = new; + } + + new->cookie8 = cookie8; + new->cookie16 = cookie16; + new->url = NULL; + new->nummsgs = 0; + new->unread = 0; + new->domain = NULL; + new->flag = 0; + + aimbs_get16(bs); /* Number of TLVs to follow */ + tlvlist = aim_readtlvchain(bs); + + new->url = aim_gettlv_str(tlvlist, 0x0007, 1); + new->nummsgs = aim_gettlv16(tlvlist, 0x0080, 1); + new->unread = aim_gettlv8(tlvlist, 0x0081, 1); + new->domain = aim_gettlv_str(tlvlist, 0x0082, 1); + new->flag = aim_gettlv16(tlvlist, 0x0084, 1); + + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + return userfunc(sess, rx, new); + + return 0; +} + +/* + * Subtype 0x0016 - Send something or other + */ +faim_export int aim_email_activate(aim_session_t *sess, aim_conn_t *conn) +{ + aim_frame_t *fr; + aim_snacid_t snacid; + + if (!sess || !conn) + return -EINVAL; + + if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+1+16))) + return -ENOMEM; + snacid = aim_cachesnac(sess, 0x0018, 0x0016, 0x0000, NULL, 0); + aim_putsnac(&fr->data, 0x0018, 0x0016, 0x0000, snacid); + + /* I would guess this tells AIM that you want updates for your mail accounts */ + /* ...but I really have no idea */ + aimbs_put8(&fr->data, 0x02); + aimbs_put32(&fr->data, 0x04000000); + aimbs_put32(&fr->data, 0x04000000); + aimbs_put32(&fr->data, 0x04000000); + aimbs_put32(&fr->data, 0x00000000); + + aim_tx_enqueue(sess, fr); + + return 0; +} + +static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) +{ + + if (snac->subtype == 0x0007) + return parseinfo(sess, mod, rx, snac, bs); + + return 0; +} + +static void email_shutdown(aim_session_t *sess, aim_module_t *mod) +{ + while (sess->emailinfo) { + struct aim_emailinfo *tmp = sess->emailinfo; + sess->emailinfo = sess->emailinfo->next; + if (tmp->cookie16) free(tmp->cookie16); + if (tmp->cookie8) free(tmp->cookie8); + if (tmp->url) free(tmp->url); + if (tmp->domain) free(tmp->domain); + free(tmp); + } + + return; +} + +faim_internal int email_modfirst(aim_session_t *sess, aim_module_t *mod) +{ + + mod->family = 0x0018; + mod->version = 0x0001; + mod->toolid = 0x0010; + mod->toolversion = 0x0629; + mod->flags = 0; + strncpy(mod->name, "email", sizeof(mod->name)); + mod->snachandler = snachandler; + mod->shutdown = email_shutdown; + + return 0; +}
--- a/src/protocols/oscar/oscar.c Mon Oct 14 06:34:42 2002 +0000 +++ b/src/protocols/oscar/oscar.c Mon Oct 14 07:47:51 2002 +0000 @@ -108,6 +108,7 @@ guint cnpa; guint paspa; + guint emlpa; GSList *create_rooms; @@ -344,6 +345,7 @@ static int gaim_chat_leave (aim_session_t *, aim_frame_t *, ...); static int gaim_chat_info_update (aim_session_t *, aim_frame_t *, ...); static int gaim_chat_incoming_msg(aim_session_t *, aim_frame_t *, ...); +static int gaim_email_parseupdate(aim_session_t *, aim_frame_t *, ...); static int gaim_parse_msgack (aim_session_t *, aim_frame_t *, ...); static int gaim_parse_ratechange (aim_session_t *, aim_frame_t *, ...); static int gaim_parse_evilnotify (aim_session_t *, aim_frame_t *, ...); @@ -354,6 +356,7 @@ static int conninitdone_admin (aim_session_t *, aim_frame_t *, ...); static int conninitdone_chat (aim_session_t *, aim_frame_t *, ...); static int conninitdone_chatnav (aim_session_t *, aim_frame_t *, ...); +static int conninitdone_email (aim_session_t *, aim_frame_t *, ...); static int gaim_parse_msgerr (aim_session_t *, aim_frame_t *, ...); static int gaim_parse_mtn (aim_session_t *, aim_frame_t *, ...); static int gaim_parse_locaterights(aim_session_t *, aim_frame_t *, ...); @@ -535,6 +538,12 @@ odata->paspa = 0; debug_printf("removing authconn input watcher\n"); aim_conn_kill(odata->sess, &conn); + } else if (conn->type == AIM_CONN_TYPE_EMAIL) { + if (odata->emlpa > 0) + gaim_input_remove(odata->emlpa); + odata->emlpa = 0; + debug_printf("removing email input watcher\n"); + aim_conn_kill(odata->sess, &conn); } else if (conn->type == AIM_CONN_TYPE_RENDEZVOUS) { if (conn->subtype == AIM_CONN_SUBTYPE_OFT_DIRECTIM) gaim_directim_disconnect(odata->sess, conn); @@ -719,6 +728,8 @@ gaim_input_remove(odata->cnpa); if (odata->paspa > 0) gaim_input_remove(odata->paspa); + if (odata->emlpa > 0) + gaim_input_remove(odata->emlpa); aim_session_kill(odata->sess); g_free(odata->sess); odata->sess = NULL; @@ -1134,6 +1145,18 @@ return 1; } +static int conninitdone_email(aim_session_t *sess, aim_frame_t *fr, ...) { + + aim_conn_addhandler(sess, fr->conn, 0x0018, 0x0001, gaim_parse_genericerr, 0); + aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_EML, AIM_CB_EML_MAILSTATUS, gaim_email_parseupdate, 0); + + aim_email_sendcookies(sess, fr->conn); + aim_email_activate(sess, fr->conn); + aim_clientready(sess, fr->conn); + + return 1; +} + static void oscar_chatnav_connect(gpointer data, gint source, GaimInputCondition cond) { struct gaim_connection *gc = data; struct oscar_data *odata; @@ -1236,6 +1259,32 @@ odata->oscar_chats = g_slist_append(odata->oscar_chats, ccon); } +static void oscar_email_connect(gpointer data, gint source, GaimInputCondition cond) { + struct gaim_connection *gc = data; + struct oscar_data *odata; + aim_session_t *sess; + aim_conn_t *tstconn; + + if (!g_slist_find(connections, gc)) { + close(source); + return; + } + + odata = gc->proto_data; + sess = odata->sess; + tstconn = aim_getconn_type_all(sess, AIM_CONN_TYPE_EMAIL); + + if (source < 0) { + aim_conn_kill(sess, &tstconn); + debug_printf("unable to connect to email server\n"); + return; + } + + aim_conn_completeconnect(sess, tstconn); + odata->emlpa = gaim_input_add(tstconn->fd, GAIM_INPUT_READ, oscar_callback, tstconn); + debug_printf("email: connected\n"); +} + /* Hrmph. I don't know how to make this look better. --mid */ static int gaim_handle_redirect(aim_session_t *sess, aim_frame_t *fr, ...) { va_list ap; @@ -1342,6 +1391,26 @@ debug_printf("Connected to chat room %s exchange %d\n", ccon->name, ccon->exchange); } break; + + case 0x0018: { /* email */ + if (!(tstconn = aim_newconn(sess, AIM_CONN_TYPE_EMAIL, NULL))) { + debug_printf("unable to connect to email server\n"); + g_free(host); + return 1; + } + aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, conninitdone_email, 0); + + tstconn->status |= AIM_CONN_STATUS_INPROGRESS; + tstconn->fd = proxy_connect(host, port, oscar_email_connect, gc); + if (tstconn->fd < 0) { + aim_conn_kill(sess, &tstconn); + debug_printf("unable to connect to email server\n"); + g_free(host); + return 1; + } + aim_sendcookie(sess, tstconn, redir->cookie); + } break; + default: /* huh? */ debug_printf("got redirect for unknown service 0x%04x\n", redir->group); break; @@ -2765,6 +2834,27 @@ return 1; } +static int gaim_email_parseupdate(aim_session_t *sess, aim_frame_t *fr, ...) { + va_list ap; + struct gaim_connection *gc = sess->aux_data; + struct aim_emailinfo *emailinfo; + + va_start(ap, fr); + emailinfo = va_arg(ap, struct aim_emailinfo *); + va_end(ap); + + while (emailinfo) { + debug_printf("Got email info. webmail address for screenname@%s is %s, new email: %hd, number new: %d, flag is %d\n", emailinfo->domain, emailinfo->url, emailinfo->unread, emailinfo->nummsgs, emailinfo->flag); + if (emailinfo->unread) + connection_has_mail(gc, emailinfo->nummsgs ? emailinfo->nummsgs : -1, NULL, NULL, emailinfo->url); + else + connection_has_mail(gc, 0, NULL, NULL, emailinfo->url); + emailinfo = emailinfo->next; + } + + return 1; +} + /* * Recieved in response to an IM sent with the AIM_IMFLAGS_ACK option. */ @@ -3025,6 +3115,7 @@ aim_icq_reqofflinemsgs(sess); aim_reqservice(sess, fr->conn, AIM_CONN_TYPE_CHATNAV); + aim_reqservice(sess, fr->conn, AIM_CONN_TYPE_EMAIL); if (!odata->icq) { debug_printf("ssi: requesting ssi list\n"); @@ -4640,7 +4731,7 @@ G_MODULE_EXPORT void oscar_init(struct prpl *ret) { struct proto_user_opt *puo; ret->protocol = PROTO_OSCAR; - ret->options = OPT_PROTO_BUDDY_ICON | OPT_PROTO_IM_IMAGE; + ret->options = OPT_PROTO_MAIL_CHECK | OPT_PROTO_BUDDY_ICON | OPT_PROTO_IM_IMAGE; ret->name = g_strdup("Oscar"); ret->list_icon = oscar_list_icon; ret->away_states = oscar_away_states;
--- a/src/prpl.c Mon Oct 14 06:34:42 2002 +0000 +++ b/src/prpl.c Mon Oct 14 07:47:51 2002 +0000 @@ -412,9 +412,12 @@ mailnots = g_slist_append(mailnots, mn); } - if (count < 0 && from && subject) { - g_snprintf(buf, sizeof buf, "%s has mail from %s: %s", gc->username, from, subject); - } else if (count) { + if (count < 0) { + if (from && subject) + g_snprintf(buf, sizeof buf, "%s has mail from %s: %s", gc->username, from, subject); + else + g_snprintf(buf, sizeof buf, "%s has new mail.", gc->username); + } else if (count > 0) { g_snprintf(buf, sizeof buf, "%s has %d new message%s.", gc->username, count, count == 1 ? "" : "s"); } else if (mn->email_win) {