# HG changeset patch # User Daniel Atallah # Date 1171231130 0 # Node ID 71af5b6209d5d3bacd30b5044397dfb92c671ddc # Parent a2411e8dbe2dd6d1e3dd0e351df1c93462becd8c uri-handler support for AIM/ICQ, Yahoo and MSN diff -r a2411e8dbe2d -r 71af5b6209d5 libpurple/protocols/msn/msn.c --- a/libpurple/protocols/msn/msn.c Sun Feb 11 19:34:43 2007 +0000 +++ b/libpurple/protocols/msn/msn.c Sun Feb 11 21:58:50 2007 +0000 @@ -35,6 +35,7 @@ #include "state.h" #include "util.h" #include "cmds.h" +#include "core.h" #include "prpl.h" #include "msn-utils.h" #include "version.h" @@ -1928,6 +1929,71 @@ return TRUE; } +static GaimAccount *find_acct(const char *prpl, const char *acct_id) +{ + GaimAccount *acct = NULL; + + /* If we have a specific acct, use it */ + if (acct_id) { + acct = gaim_accounts_find(acct_id, prpl); + if (acct && !gaim_account_is_connected(acct)) + acct = NULL; + } else { /* Otherwise find an active account for the protocol */ + GList *l = gaim_accounts_get_all(); + while (l) { + if (!strcmp(prpl, gaim_account_get_protocol_id(l->data)) + && gaim_account_is_connected(l->data)) { + acct = l->data; + break; + } + l = l->next; + } + } + + return acct; +} + +static gboolean msn_uri_handler(const char *proto, const char *cmd, GHashTable *params) +{ + char *acct_id = g_hash_table_lookup(params, "account"); + GaimAccount *acct; + + if (g_ascii_strcasecmp(proto, "msnim")) + return FALSE; + + acct = find_acct("prpl-msn", acct_id); + + if (!acct) + return FALSE; + + /* msnim:chat?contact=user@domain.tld */ + if (!g_ascii_strcasecmp(cmd, "Chat")) { + char *sname = g_hash_table_lookup(params, "contact"); + if (sname) { + GaimConversation *conv = gaim_find_conversation_with_account( + GAIM_CONV_TYPE_IM, sname, acct); + if (conv == NULL) + conv = gaim_conversation_new(GAIM_CONV_TYPE_IM, acct, sname); + gaim_conversation_present(conv); + } + /*else + **If pidgindialogs_im() was in the core, we could use it here. + * It is all gaim_request_* based, but I'm not sure it really belongs in the core + pidgindialogs_im();*/ + + return TRUE; + } + /* msnim:add?contact=user@domain.tld */ + else if (!g_ascii_strcasecmp(cmd, "Add")) { + char *name = g_hash_table_lookup(params, "contact"); + gaim_blist_request_add_buddy(acct, name, NULL, NULL); + return TRUE; + } + + return FALSE; +} + + static GaimPluginProtocolInfo prpl_info = { OPT_PROTO_MAIL_CHECK, @@ -2055,6 +2121,9 @@ _("nudge: nudge a user to get their attention"), NULL); gaim_prefs_remove("/plugins/prpl/msn"); + + gaim_signal_connect(gaim_get_core(), "uri-handler", plugin, + GAIM_CALLBACK(msn_uri_handler), NULL); } GAIM_INIT_PLUGIN(msn, init_plugin, info); diff -r a2411e8dbe2d -r 71af5b6209d5 libpurple/protocols/oscar/libaim.c --- a/libpurple/protocols/oscar/libaim.c Sun Feb 11 19:34:43 2007 +0000 +++ b/libpurple/protocols/oscar/libaim.c Sun Feb 11 21:58:50 2007 +0000 @@ -128,24 +128,7 @@ static void init_plugin(GaimPlugin *plugin) { - GaimAccountOption *option; - - option = gaim_account_option_string_new(_("Server"), "server", OSCAR_DEFAULT_LOGIN_SERVER); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - - option = gaim_account_option_int_new(_("Port"), "port", OSCAR_DEFAULT_LOGIN_PORT); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - - option = gaim_account_option_bool_new( - _("Always use AIM/ICQ proxy server for file transfers\n(slower, but does not reveal your IP address)"), "always_use_rv_proxy", - OSCAR_DEFAULT_ALWAYS_USE_RV_PROXY); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - - /* Preferences */ - gaim_prefs_add_none("/plugins/prpl/oscar"); - gaim_prefs_add_bool("/plugins/prpl/oscar/recent_buddies", FALSE); - gaim_prefs_add_bool("/plugins/prpl/oscar/show_idle", FALSE); - gaim_prefs_remove("/plugins/prpl/oscar/always_use_rv_proxy"); + oscar_init(GAIM_PLUGIN_PROTOCOL_INFO(plugin)); } GAIM_INIT_PLUGIN(aim, init_plugin, info); diff -r a2411e8dbe2d -r 71af5b6209d5 libpurple/protocols/oscar/libicq.c --- a/libpurple/protocols/oscar/libicq.c Sun Feb 11 19:34:43 2007 +0000 +++ b/libpurple/protocols/oscar/libicq.c Sun Feb 11 21:58:50 2007 +0000 @@ -130,25 +130,10 @@ { GaimAccountOption *option; - option = gaim_account_option_string_new(_("Server"), "server", OSCAR_DEFAULT_LOGIN_SERVER); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - - option = gaim_account_option_int_new(_("Port"), "port", OSCAR_DEFAULT_LOGIN_PORT); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + oscar_init(GAIM_PLUGIN_PROTOCOL_INFO(plugin)); option = gaim_account_option_string_new(_("Encoding"), "encoding", OSCAR_DEFAULT_CUSTOM_ENCODING); prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - - option = gaim_account_option_bool_new( - _("Always use ICQ proxy server for file transfers\n(slower, but does not reveal your IP address)"), "always_use_rv_proxy", - OSCAR_DEFAULT_ALWAYS_USE_RV_PROXY); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - - /* Preferences */ - gaim_prefs_add_none("/plugins/prpl/oscar"); - gaim_prefs_add_bool("/plugins/prpl/oscar/recent_buddies", FALSE); - gaim_prefs_add_bool("/plugins/prpl/oscar/show_idle", FALSE); - gaim_prefs_remove("/plugins/prpl/oscar/always_use_rv_proxy"); } GAIM_INIT_PLUGIN(icq, init_plugin, info); diff -r a2411e8dbe2d -r 71af5b6209d5 libpurple/protocols/oscar/oscar.c --- a/libpurple/protocols/oscar/oscar.c Sun Feb 11 19:34:43 2007 +0000 +++ b/libpurple/protocols/oscar/oscar.c Sun Feb 11 21:58:50 2007 +0000 @@ -6514,3 +6514,130 @@ return (od->icq && aim_sn_is_icq(gaim_account_get_username(account))); } +/* TODO: Find somewhere to put this instead of including it in a bunch of places. + * Maybe just change gaim_accounts_find() to return anything for the prpl if there is no acct_id. + */ +static GaimAccount *find_acct(const char *prpl, const char *acct_id) +{ + GaimAccount *acct = NULL; + + /* If we have a specific acct, use it */ + if (acct_id) { + acct = gaim_accounts_find(acct_id, prpl); + if (acct && !gaim_account_is_connected(acct)) + acct = NULL; + } else { /* Otherwise find an active account for the protocol */ + GList *l = gaim_accounts_get_all(); + while (l) { + if (!strcmp(prpl, gaim_account_get_protocol_id(l->data)) + && gaim_account_is_connected(l->data)) { + acct = l->data; + break; + } + l = l->next; + } + } + + return acct; +} + + +static gboolean oscar_uri_handler(const char *proto, const char *cmd, GHashTable *params) +{ + char *acct_id = g_hash_table_lookup(params, "account"); + char prpl[11]; + GaimAccount *acct; + + if (g_ascii_strcasecmp(proto, "aim") && g_ascii_strcasecmp(proto, "icq")) + return FALSE; + + g_snprintf(prpl, sizeof(prpl), "prpl-%s", proto); + + acct = find_acct(prpl, acct_id); + + if (!acct) + return FALSE; + + /* aim:GoIM?screenname=SCREENNAME&message=MESSAGE */ + if (!g_ascii_strcasecmp(cmd, "GoIM")) { + char *sname = g_hash_table_lookup(params, "screenname"); + if (sname) { + char *message = g_hash_table_lookup(params, "message"); + + GaimConversation *conv = gaim_find_conversation_with_account( + GAIM_CONV_TYPE_IM, sname, acct); + if (conv == NULL) + conv = gaim_conversation_new(GAIM_CONV_TYPE_IM, acct, sname); + gaim_conversation_present(conv); + + if (message) { + /* Spaces are encoded as '+' */ + g_strdelimit(message, "+", ' '); + gaim_conv_im_send(GAIM_CONV_IM(conv), message); + } + } + /*else + **If pidgindialogs_im() was in the core, we could use it here. + * It is all gaim_request_* based, but I'm not sure it really belongs in the core + pidgindialogs_im();*/ + + return TRUE; + } + /* aim:GoChat?roomname=CHATROOMNAME&exchange=4 */ + else if (!g_ascii_strcasecmp(cmd, "GoChat")) { + char *rname = g_hash_table_lookup(params, "roomname"); + if (rname) { + /* This is somewhat hacky, but the params aren't useful after this command */ + g_hash_table_insert(params, g_strdup("exchange"), g_strdup("4")); + g_hash_table_insert(params, g_strdup("room"), g_strdup(rname)); + serv_join_chat(gaim_account_get_connection(acct), params); + } + /*else + ** Same as above (except that this would have to be re-written using gaim_request_*) + pidgin_blist_joinchat_show(); */ + + return TRUE; + } + /* aim:AddBuddy?screenname=SCREENNAME&groupname=GROUPNAME*/ + else if (!g_ascii_strcasecmp(cmd, "AddBuddy")) { + char *sname = g_hash_table_lookup(params, "screenname"); + char *gname = g_hash_table_lookup(params, "groupname"); + gaim_blist_request_add_buddy(acct, sname, gname, NULL); + return TRUE; + } + + return FALSE; +} + +void oscar_init(GaimPluginProtocolInfo *prpl_info) +{ + GaimAccountOption *option; + static gboolean init = FALSE; + + option = gaim_account_option_string_new(_("Server"), "server", OSCAR_DEFAULT_LOGIN_SERVER); + prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option); + + option = gaim_account_option_int_new(_("Port"), "port", OSCAR_DEFAULT_LOGIN_PORT); + prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option); + + option = gaim_account_option_bool_new( + _("Always use ICQ proxy server for file transfers\n(slower, but does not reveal your IP address)"), "always_use_rv_proxy", + OSCAR_DEFAULT_ALWAYS_USE_RV_PROXY); + prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option); + + if (init) + return; + init = TRUE; + + /* Preferences */ + gaim_prefs_add_none("/plugins/prpl/oscar"); + gaim_prefs_add_bool("/plugins/prpl/oscar/recent_buddies", FALSE); + gaim_prefs_add_bool("/plugins/prpl/oscar/show_idle", FALSE); + gaim_prefs_remove("/plugins/prpl/oscar/always_use_rv_proxy"); + + /* protocol handler */ + /* TODO: figure out a good instance to use here */ + gaim_signal_connect(gaim_get_core(), "uri-handler", &init, + GAIM_CALLBACK(oscar_uri_handler), NULL); +} + diff -r a2411e8dbe2d -r 71af5b6209d5 libpurple/protocols/oscar/oscarcommon.h --- a/libpurple/protocols/oscar/oscarcommon.h Sun Feb 11 19:34:43 2007 +0000 +++ b/libpurple/protocols/oscar/oscarcommon.h Sun Feb 11 21:58:50 2007 +0000 @@ -87,3 +87,4 @@ GaimXfer *oscar_new_xfer(GaimConnection *gc, const char *who); gboolean oscar_offline_message(const GaimBuddy *buddy); GList *oscar_actions(GaimPlugin *plugin, gpointer context); +void oscar_init(GaimPluginProtocolInfo *prpl_info); diff -r a2411e8dbe2d -r 71af5b6209d5 libpurple/protocols/yahoo/yahoo.c --- a/libpurple/protocols/yahoo/yahoo.c Sun Feb 11 19:34:43 2007 +0000 +++ b/libpurple/protocols/yahoo/yahoo.c Sun Feb 11 21:58:50 2007 +0000 @@ -28,6 +28,7 @@ #include "blist.h" #include "cipher.h" #include "cmds.h" +#include "core.h" #include "debug.h" #include "notify.h" #include "privacy.h" @@ -3794,6 +3795,107 @@ _("doodle: Request user to start a Doodle session"), NULL); } +static GaimAccount *find_acct(const char *prpl, const char *acct_id) +{ + GaimAccount *acct = NULL; + + /* If we have a specific acct, use it */ + if (acct_id) { + acct = gaim_accounts_find(acct_id, prpl); + if (acct && !gaim_account_is_connected(acct)) + acct = NULL; + } else { /* Otherwise find an active account for the protocol */ + GList *l = gaim_accounts_get_all(); + while (l) { + if (!strcmp(prpl, gaim_account_get_protocol_id(l->data)) + && gaim_account_is_connected(l->data)) { + acct = l->data; + break; + } + l = l->next; + } + } + + return acct; +} + +/* This may not be the best way to do this, but we find the first key w/o a value + * and assume it is the screenname */ +static void yahoo_find_uri_novalue_param(gpointer key, gpointer value, gpointer user_data) +{ + char **retval = user_data; + + if (value == NULL && *retval == NULL) { + *retval = key; + } +} + +static gboolean yahoo_uri_handler(const char *proto, const char *cmd, GHashTable *params) +{ + char *acct_id = g_hash_table_lookup(params, "account"); + GaimAccount *acct; + + if (g_ascii_strcasecmp(proto, "ymsgr")) + return FALSE; + + acct = find_acct(gaim_plugin_get_id(my_protocol), acct_id); + + if (!acct) + return FALSE; + + /* ymsgr:SendIM?screename&m=The+Message */ + if (!g_ascii_strcasecmp(cmd, "SendIM")) { + char *sname = NULL; + g_hash_table_foreach(params, yahoo_find_uri_novalue_param, &sname); + if (sname) { + char *message = g_hash_table_lookup(params, "m"); + + GaimConversation *conv = gaim_find_conversation_with_account( + GAIM_CONV_TYPE_IM, sname, acct); + if (conv == NULL) + conv = gaim_conversation_new(GAIM_CONV_TYPE_IM, acct, sname); + gaim_conversation_present(conv); + + if (message) { + /* Spaces are encoded as '+' */ + g_strdelimit(message, "+", ' '); + gaim_conv_im_send(GAIM_CONV_IM(conv), message); + } + } + /*else + **If pidgindialogs_im() was in the core, we could use it here. + * It is all gaim_request_* based, but I'm not sure it really belongs in the core + pidgindialogs_im();*/ + + return TRUE; + } + /* ymsgr:Chat?roomname */ + else if (!g_ascii_strcasecmp(cmd, "Chat")) { + char *rname = NULL; + g_hash_table_foreach(params, yahoo_find_uri_novalue_param, &rname); + if (rname) { + /* This is somewhat hacky, but the params aren't useful after this command */ + g_hash_table_insert(params, g_strdup("room"), g_strdup(rname)); + g_hash_table_insert(params, g_strdup("type"), g_strdup("Chat")); + serv_join_chat(gaim_account_get_connection(acct), params); + } + /*else + ** Same as above (except that this would have to be re-written using gaim_request_*) + pidgin_blist_joinchat_show(); */ + + return TRUE; + } + /* ymsgr:AddFriend?name */ + else if (!g_ascii_strcasecmp(cmd, "AddFriend")) { + char *name = NULL; + g_hash_table_foreach(params, yahoo_find_uri_novalue_param, &name); + gaim_blist_request_add_buddy(acct, name, NULL, NULL); + return TRUE; + } + + return FALSE; +} + static GaimWhiteboardPrplOps yahoo_whiteboard_prpl_ops = { yahoo_doodle_start, @@ -3950,6 +4052,9 @@ my_protocol = plugin; yahoogaim_register_commands(); yahoo_init_colorht(); + + gaim_signal_connect(gaim_get_core(), "uri-handler", plugin, + GAIM_CALLBACK(yahoo_uri_handler), NULL); } GAIM_INIT_PLUGIN(yahoo, init_plugin, info);