pidgin/purple-plugin-pack
Add Eion's ning prpl. No idea if this compiles yet.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ning/Makefile.am Mon Jul 04 23:23:31 2011 -0400
@@ -0,0 +1,53 @@
+# $(PIXMAPS) #add \ to the line above and uncomment this line if we get pixmaps +ningdir = $(PURPLE_LIBDIR) +ning_la_LDFLAGS = -module -avoid-version +ning_LTLIBRARIES = ning.la +# uncomment the lines below if we get pixmaps +#ningpix16dir=$(PIDGIN_PIXMAPSDIR)/protocols/16 +#ningpix16_DATA=16/ning.png +#ningpix22dir=$(PIDGIN_PIXMAPSDIR)/protocols/22 +#ningpix22_DATA=22/ning.png +#ningpix48dir=$(PIDGIN_PIXMAPSDIR)/protocols/48 +#ningpix48_DATA=48/ning.png + -DLIBDIR=\"$(PURPLE_LIBDIR)\" \ + -DDATADIR=\"$(PURPLE_DATADIR)\" \ --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ning/Makefile.mingw Mon Jul 04 23:23:31 2011 -0400
@@ -0,0 +1,16 @@
+# Description: Makefile for ning plugin. +include $(PP_TOP)/win_pp.mak --- a/ning/libning.c Mon Jul 04 23:17:15 2011 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,555 +0,0 @@
- * libning is the property of its developers. See the COPYRIGHT file
- * 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 3 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, see <http://www.gnu.org/licenses/>.
-#include "ning_connection.h"
-JsonObject *ning_json_parse(const gchar *data, gssize data_len)
- parser = json_parser_new();
- json_parser_load_from_data(parser, data, (gssize) data_len, NULL);
- root_node = json_parser_get_root(parser);
- root_obj = json_node_dup_object(root_node);
- g_object_unref(parser);
-build_user_json(NingAccount *na)
- escaped_name = g_strescape(na->name, "");
- escaped_name = g_strdup("");
- if (na && na->icon_url)
- escaped_icon = g_strescape(na->icon_url, "");
- escaped_icon = g_strdup("");
- escaped_id = g_strescape(na->ning_id, "");
- escaped_id = g_strdup("");
- user_json = g_strdup_printf("{\"name\":\"%s\",\"iconUrl\":\"%s\",\"isAdmin\":\"0\",\"ningId\":\"%s\",\"isNC\":\"0\"}",
- escaped_name, escaped_icon, escaped_id);
-/******************************************************************************/
-/******************************************************************************/
-static const char *ning_list_icon(PurpleAccount *account, PurpleBuddy *buddy)
-static GList *ning_statuses(PurpleAccount *account)
- PurpleStatusType *status;
- purple_debug_info("ning", "statuses\n");
- /* Ning people are either online or offline */
- status = purple_status_type_new_full(PURPLE_STATUS_AVAILABLE, NULL, NULL, TRUE, TRUE, FALSE);
- types = g_list_append(types, status);
- status = purple_status_type_new_full(PURPLE_STATUS_OFFLINE, NULL, NULL, TRUE, TRUE, FALSE);
- types = g_list_append(types, status);
- purple_debug_info("ning", "statuses return\n");
-void ning_chat_login_cb(NingAccount *na, gchar *data, gsize data_len, gpointer userdata)
- obj = ning_json_parse(data, data_len);
- purple_debug_info("ning", "chat_login_cb: %s\n", data?data:"(null)");
- if (data == NULL || data_len == 0)
- //{"command": "login","result": "ok","roomId": "thoughtleaders.thoughtleaders",
- // "count": 2,"token": "37lfxean70eqh_122d86d5cf7_6f95cb8e_122d49f8e48"}
- result = json_node_get_string(json_object_get_member(obj, "result"));
- if (!result || !g_str_equal(result, "ok"))
- purple_connection_error(na->pc, _("Could not log on"));
- purple_connection_update_progress(na->pc, _("Joining public chat"), 5, 5);
- purple_connection_set_state(na->pc, PURPLE_CONNECTED);
- g_free(na->chat_token);
- na->chat_token = g_strdup(json_node_get_string(json_object_get_member(obj, "token")));
- roomId = json_node_get_string(json_object_get_member(obj, "roomId"));
- ning_join_chat_by_name(na, roomId);
- json_object_unref(obj);
-void ning_chat_redir_cb(NingAccount *na, gchar *data, gsize data_len, gpointer userdata)
- gchar *postdata, *encoded_app, *encoded_id;
- gchar *user_json, *user_encoded;
- purple_debug_info("ning", "ning_chat_redir_cb: %s\n", data?data:"(null)");
- //We get a randomly generated chat domain to use
- // eg {"domain": "3841.chat07.ningim.com"}
- obj = ning_json_parse(data, data_len);
- g_free(na->chat_domain);
- na->chat_domain = g_strdup(json_node_get_string(json_object_get_member(obj, "domain")));
- json_object_unref(obj);
- //Use our new domain to log into the chat servers
- purple_connection_update_progress(na->pc, _("Logging into chat"), 4, 5);
- encoded_app = g_strdup(purple_url_encode(na->ning_app));
- encoded_id = g_strdup(purple_url_encode(na->ning_id));
- user_json = build_user_json(na);
- user_encoded = g_strdup(purple_url_encode(user_json));
- postdata = g_strdup_printf("a=%s&t=%s%s&i=%s&user=%s", encoded_app, encoded_app, encoded_id, encoded_id, user_encoded);
- ning_post_or_get(na, NING_METHOD_POST, na->chat_domain,
- "/xn/presence/login", postdata, ning_chat_login_cb, NULL, FALSE);
-void ning_login_home_cb(NingAccount *na, gchar *data, gsize data_len, gpointer userdata)
- //<script>window.bzplcm.add({"app":"thoughtleaders","user":"37lfxean70eqh"
- //xg.token = 'b1a7f3ce1719481334cdcc5fe8eabcaa';
- const gchar *start_string = "\nning = ";
- const gchar *mid_string = "}};\n";
- const gchar *xgtoken_start = "xg.token = '";
- gchar *tmp, *ning_json_string, *xg_token;
- JsonObject *obj, *profile;
- tmp = g_strstr_len(data, data_len, start_string);
- purple_connection_error(na->pc, _("NingID not found"));
- tmp += strlen(start_string);
- ning_json_string = g_strndup(tmp, strstr(tmp, mid_string) - tmp + 2);
- purple_debug_info("ning", "ning_json_string: %s\n", ning_json_string);
- obj = ning_json_parse(ning_json_string, strlen(ning_json_string));
- profile = json_node_get_object(json_object_get_member(obj, "CurrentProfile"));
- na->ning_id = g_strdup(json_node_get_string(json_object_get_member(profile, "id")));
- na->name = g_strdup(json_node_get_string(json_object_get_member(profile, "fullName")));
- na->icon_url = g_strdup_printf("%s&width=16&height=16", json_node_get_string(json_object_get_member(profile, "photoUrl")));
- tmp = g_strstr_len(data, data_len, xgtoken_start);
- purple_connection_error(na->pc, _("xgToken not found"));
- tmp += strlen(xgtoken_start);
- xg_token = g_strndup(tmp, strchr(tmp, '\'') - tmp);
- na->xg_token = xg_token;
- //Now we should have everything we need to sign into chat
- purple_connection_update_progress(na->pc, _("Fetching chat server"), 3, 5);
- url = g_strdup_printf("/xn/redirector/redirect?a=%s", purple_url_encode(na->ning_app));
- ning_post_or_get(na, NING_METHOD_GET, "chat01.ningim.com",
- url, NULL, ning_chat_redir_cb, NULL, FALSE);
-void ning_scan_cookies_for_id(gchar *key, gchar *value, NingAccount *na)
- if (g_str_has_prefix(key, "xn_id_"))
- na->ning_app = g_strdup(&key[6]);
-static void ning_login_cb(NingAccount *na, gchar *response, gsize len,
- purple_connection_update_progress(na->pc, _("Fetching token"), 2, 4);
- // ok, we're logged into the host website now
- // Pull the host's Ning account id from the cookie
- g_hash_table_foreach(na->cookie_table, (GHFunc)ning_scan_cookies_for_id, na);
- //Load the homepage to grab the interesting info
- ning_post_or_get(na, NING_METHOD_GET, purple_account_get_string(na->account, "host", NULL),
- "/", NULL, ning_login_home_cb, NULL, FALSE);
-static void ning_login(PurpleAccount *account)
- gchar *postdata, *encoded_username, *encoded_password;
- gchar *encoded_host, *url;
- purple_debug_info("ning", "login\n");
- /* Create account and initialize state */
- na = g_new0(NingAccount, 1);
- na->pc = purple_account_get_connection(account);
- na->last_messages_download_time = time(NULL) - 60; /* 60 secs is a safe buffer */
- na->cookie_table = g_hash_table_new_full(g_str_hash, g_str_equal,
- na->hostname_ip_cache = g_hash_table_new_full(g_str_hash, g_str_equal,
- g_hash_table_replace(na->cookie_table, g_strdup("xg_cookie_check"),
- account->gc->proto_data = na;
- purple_connection_set_state(na->pc, PURPLE_CONNECTING);
- purple_connection_update_progress(na->pc, _("Logging in"), 1, 4);
- encoded_username = g_strdup(purple_url_encode(purple_account_get_username(account)));
- encoded_password = g_strdup(purple_url_encode(purple_account_get_password(account)));
- postdata = g_strdup_printf("xg_token=&emailAddress=%s&password=%s",
- encoded_username, encoded_password);
- g_free(encoded_username);
- g_free(encoded_password);
- host = purple_account_get_string(account, "host", NULL);
- if (host == NULL || host[0] == '\0')
- purple_connection_error(na->pc, _("Host not set"));
- encoded_host = g_strdup(purple_url_encode(host));
- url = g_strdup_printf("/main/authorization/doSignIn?target=http%%3A%%2F%%2F%s", host);
- ning_post_or_get(na, NING_METHOD_POST | NING_METHOD_SSL, host,
- url, postdata, ning_login_cb, NULL, FALSE);
-static void ning_close(PurpleConnection *pc)
- gchar *xg_token_encoded;
- PurpleDnsQueryData *dns_query;
- purple_debug_info("ning", "disconnecting account\n");
- host_encoded = g_strdup(purple_url_encode(purple_account_get_string(na->account, "host", "")));
- xg_token_encoded = g_strdup(purple_url_encode(na->xg_token));
- postdata = g_strdup_printf("target=%s&xg_token=%s", host_encoded, xg_token_encoded);
- ning_post_or_get(na, NING_METHOD_POST, purple_account_get_string(na->account, "host", NULL),
- "/main/authorization/signOut", postdata, NULL, NULL, FALSE);
- g_free(xg_token_encoded);
- purple_debug_info("ning", "destroying %d incomplete connections\n",
- g_slist_length(na->conns));
- while (na->conns != NULL)
- ning_connection_destroy(na->conns->data);
- while (na->dns_queries != NULL) {
- dns_query = na->dns_queries->data;
- purple_debug_info("ning", "canceling dns query for %s\n",
- purple_dnsquery_get_host(dns_query));
- na->dns_queries = g_slist_remove(na->dns_queries, dns_query);
- purple_dnsquery_destroy(dns_query);
- g_hash_table_destroy(na->cookie_table);
- g_hash_table_destroy(na->hostname_ip_cache);
- while (na->chats != NULL)
- NingChat *chat = na->chats->data;
- na->chats = g_list_remove(na->chats, chat);
- purple_timeout_remove(chat->userlist_timer);
- purple_timeout_remove(chat->message_poll_timer);
- purple_conv_chat_left(PURPLE_CONV_CHAT(purple_find_chat(pc, chat->purple_id)));
- g_free(chat->ning_hash);
-#if PURPLE_MAJOR_VERSION >= 2 && PURPLE_MINOR_VERSION >= 5
-static GHashTable *ning_get_account_text_table(PurpleAccount *account)
- table = g_hash_table_new(g_str_hash, g_str_equal);
- g_hash_table_insert(table, "login_label", (gpointer)_("Email Address..."));
-ning_change_passwd(PurpleConnection *pc, const char *old_pass, const char *new_pass)
- PurpleAccount *account;
- gchar *encoded_username;
- gchar *encoded_password;
- if (na == NULL || na->xg_token == NULL)
- encoded_username = g_strdup(purple_url_encode(purple_account_get_username(account)));
- encoded_password = g_strdup(purple_url_encode(new_pass));
- encoded_token = g_strdup(purple_url_encode(na->xg_token));
- postdata = g_strdup_printf("emailAddress=%s&password=%s&xg_token=%s",
- encoded_username, encoded_password, encoded_token);
- ning_post_or_get(na, NING_METHOD_POST, purple_account_get_string(na->account, "host", NULL),
- "/profiles/settings/updateEmailAddress", postdata, NULL, NULL, FALSE);
- g_free(encoded_password);
- g_free(encoded_username);
-/******************************************************************************/
-/******************************************************************************/
-static gboolean plugin_load(PurplePlugin *plugin)
-static gboolean plugin_unload(PurplePlugin *plugin)
-static void plugin_init(PurplePlugin *plugin)
- PurpleAccountOption *option;
- PurplePluginInfo *info = plugin->info;
- PurplePluginProtocolInfo *prpl_info = info->extra_info;
- option = purple_account_option_string_new("Host", "host", "");
- prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option);
-static PurplePluginProtocolInfo prpl_info = {
- NULL, /* user_splits */
- NULL, /* protocol_options */
- NO_BUDDY_ICONS /* icon_spec */
- /*{"jpg", 0, 0, 50, 50, -1, PURPLE_ICON_SCALE_SEND}*/, /* icon_spec */
- ning_list_icon, /* list_icon */
- NULL, /* list_emblems */
- NULL, /* status_text */
- NULL, /* tooltip_text */
- ning_statuses, /* status_types */
- NULL, /* blist_node_menu */
- NULL, /* chat_info_defaults */
- ning_login, /* login */
- ning_close, /* close */
- ning_send_im, /* send_im */
- NULL, /* send_typing */
- ning_change_passwd, /* change_passwd */
- NULL, /* add_buddies */
- NULL, /* remove_buddy */
- NULL, /* remove_buddies */
- NULL, /* set_permit_deny */
- ning_join_chat, /* join_chat */
- NULL, /* reject chat invite */
- NULL, /* get_chat_name */
- NULL, /* chat_invite */
- ning_chat_whisper, /* chat_whisper */
- ning_chat_send, /* chat_send */
- NULL, /* register_user */
- NULL, /* get_cb_info */
- NULL, /* get_cb_away */
- NULL, /* alias_buddy */
- NULL, /* group_buddy */
- NULL, /* rename_group */
- NULL, /* convo_closed */
- purple_normalize_nocase,/* normalize */
- NULL, /* set_buddy_icon */
- NULL, /* remove_group */
- NULL, /* get_cb_real_name */
- NULL, /* set_chat_topic */
- NULL, /* find_blist_chat */
- NULL, /* roomlist_get_list */
- NULL, /* roomlist_cancel */
- NULL, /* roomlist_expand_category */
- NULL, /* can_receive_file */
- NULL, /* offline_message */
- NULL, /* whiteboard_prpl_ops */
- NULL, /* roomlist_room_serialize */
- NULL, /* unregister_user */
- NULL, /* send_attention */
- NULL, /* attention_types */
-#if PURPLE_MAJOR_VERSION >= 2 && PURPLE_MINOR_VERSION >= 5
- sizeof(PurplePluginProtocolInfo), /* struct_size */
- ning_get_account_text_table, /* get_account_text_table */
- (gpointer) sizeof(PurplePluginProtocolInfo)
-static PurplePluginInfo info = {
- PURPLE_PLUGIN_PROTOCOL, /* type */
- NULL, /* ui_requirement */
- NULL, /* dependencies */
- PURPLE_PRIORITY_DEFAULT, /* priority */
- "prpl-bigbrownchunx-ning", /* id */
- NING_PLUGIN_VERSION, /* version */
- N_("Ning Protocol Plugin"), /* summary */
- N_("Ning Protocol Plugin"), /* description */
- "Eion Robb <eionrobb@gmail.com>", /* author */
- plugin_load, /* load */
- plugin_unload, /* unload */
- &prpl_info, /* extra_info */
-PURPLE_INIT_PLUGIN(ning, plugin_init, info);
--- a/ning/libning.h Mon Jul 04 23:17:15 2011 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,100 +0,0 @@
- * libning is the property of its developers. See the COPYRIGHT file
- * 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 3 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, see <http://www.gnu.org/licenses/>.
-#define NING_PLUGIN_VERSION "0.01"
-#define NING_TEMP_GROUP_NAME "Ning Temp"
-#include <json-glib/json-glib.h>
-#ifndef G_GNUC_NULL_TERMINATED
-# define G_GNUC_NULL_TERMINATED __attribute__((__sentinel__))
-# define G_GNUC_NULL_TERMINATED
-# endif /* __GNUC__ >= 4 */
-#endif /* G_GNUC_NULL_TERMINATED */
-# define dlopen(a,b) LoadLibrary(a)
-# define dlsym(a,b) GetProcAddress(a,b)
-# define dlclose(a) FreeLibrary(a)
-# include <netinet/in.h>
-# include <sys/socket.h>
-typedef struct _NingAccount NingAccount;
- PurpleAccount *account;
- GHashTable *hostname_ip_cache;
- GSList *conns; /**< A list of all active connections */
- GHashTable *cookie_table;
- time_t last_messages_download_time;
-JsonObject *ning_json_parse(const gchar *data, gssize data_len);
-gchar *build_user_json(NingAccount *na);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ning/ning.c Mon Jul 04 23:23:31 2011 -0400
@@ -0,0 +1,555 @@
+ * libning is the property of its developers. See the COPYRIGHT file + * 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 3 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, see <http://www.gnu.org/licenses/>. +#include "ning_connection.h" +JsonObject *ning_json_parse(const gchar *data, gssize data_len) + parser = json_parser_new(); + json_parser_load_from_data(parser, data, (gssize) data_len, NULL); + root_node = json_parser_get_root(parser); + root_obj = json_node_dup_object(root_node); + g_object_unref(parser); +build_user_json(NingAccount *na) + escaped_name = g_strescape(na->name, ""); + escaped_name = g_strdup(""); + if (na && na->icon_url) + escaped_icon = g_strescape(na->icon_url, ""); + escaped_icon = g_strdup(""); + escaped_id = g_strescape(na->ning_id, ""); + escaped_id = g_strdup(""); + user_json = g_strdup_printf("{\"name\":\"%s\",\"iconUrl\":\"%s\",\"isAdmin\":\"0\",\"ningId\":\"%s\",\"isNC\":\"0\"}", + escaped_name, escaped_icon, escaped_id); +/******************************************************************************/ +/******************************************************************************/ +static const char *ning_list_icon(PurpleAccount *account, PurpleBuddy *buddy) +static GList *ning_statuses(PurpleAccount *account) + PurpleStatusType *status; + purple_debug_info("ning", "statuses\n"); + /* Ning people are either online or offline */ + status = purple_status_type_new_full(PURPLE_STATUS_AVAILABLE, NULL, NULL, TRUE, TRUE, FALSE); + types = g_list_append(types, status); + status = purple_status_type_new_full(PURPLE_STATUS_OFFLINE, NULL, NULL, TRUE, TRUE, FALSE); + types = g_list_append(types, status); + purple_debug_info("ning", "statuses return\n"); +void ning_chat_login_cb(NingAccount *na, gchar *data, gsize data_len, gpointer userdata) + obj = ning_json_parse(data, data_len); + purple_debug_info("ning", "chat_login_cb: %s\n", data?data:"(null)"); + if (data == NULL || data_len == 0) + //{"command": "login","result": "ok","roomId": "thoughtleaders.thoughtleaders", + // "count": 2,"token": "37lfxean70eqh_122d86d5cf7_6f95cb8e_122d49f8e48"} + result = json_node_get_string(json_object_get_member(obj, "result")); + if (!result || !g_str_equal(result, "ok")) + purple_connection_error(na->pc, _("Could not log on")); + purple_connection_update_progress(na->pc, _("Joining public chat"), 5, 5); + purple_connection_set_state(na->pc, PURPLE_CONNECTED); + g_free(na->chat_token); + na->chat_token = g_strdup(json_node_get_string(json_object_get_member(obj, "token"))); + roomId = json_node_get_string(json_object_get_member(obj, "roomId")); + ning_join_chat_by_name(na, roomId); + json_object_unref(obj); +void ning_chat_redir_cb(NingAccount *na, gchar *data, gsize data_len, gpointer userdata) + gchar *postdata, *encoded_app, *encoded_id; + gchar *user_json, *user_encoded; + purple_debug_info("ning", "ning_chat_redir_cb: %s\n", data?data:"(null)"); + //We get a randomly generated chat domain to use + // eg {"domain": "3841.chat07.ningim.com"} + obj = ning_json_parse(data, data_len); + g_free(na->chat_domain); + na->chat_domain = g_strdup(json_node_get_string(json_object_get_member(obj, "domain"))); + json_object_unref(obj); + //Use our new domain to log into the chat servers + purple_connection_update_progress(na->pc, _("Logging into chat"), 4, 5); + encoded_app = g_strdup(purple_url_encode(na->ning_app)); + encoded_id = g_strdup(purple_url_encode(na->ning_id)); + user_json = build_user_json(na); + user_encoded = g_strdup(purple_url_encode(user_json)); + postdata = g_strdup_printf("a=%s&t=%s%s&i=%s&user=%s", encoded_app, encoded_app, encoded_id, encoded_id, user_encoded); + ning_post_or_get(na, NING_METHOD_POST, na->chat_domain, + "/xn/presence/login", postdata, ning_chat_login_cb, NULL, FALSE); +void ning_login_home_cb(NingAccount *na, gchar *data, gsize data_len, gpointer userdata) + //<script>window.bzplcm.add({"app":"thoughtleaders","user":"37lfxean70eqh" + //xg.token = 'b1a7f3ce1719481334cdcc5fe8eabcaa'; + const gchar *start_string = "\nning = "; + const gchar *mid_string = "}};\n"; + const gchar *xgtoken_start = "xg.token = '"; + gchar *tmp, *ning_json_string, *xg_token; + JsonObject *obj, *profile; + tmp = g_strstr_len(data, data_len, start_string); + purple_connection_error(na->pc, _("NingID not found")); + tmp += strlen(start_string); + ning_json_string = g_strndup(tmp, strstr(tmp, mid_string) - tmp + 2); + purple_debug_info("ning", "ning_json_string: %s\n", ning_json_string); + obj = ning_json_parse(ning_json_string, strlen(ning_json_string)); + profile = json_node_get_object(json_object_get_member(obj, "CurrentProfile")); + na->ning_id = g_strdup(json_node_get_string(json_object_get_member(profile, "id"))); + na->name = g_strdup(json_node_get_string(json_object_get_member(profile, "fullName"))); + na->icon_url = g_strdup_printf("%s&width=16&height=16", json_node_get_string(json_object_get_member(profile, "photoUrl"))); + tmp = g_strstr_len(data, data_len, xgtoken_start); + purple_connection_error(na->pc, _("xgToken not found")); + tmp += strlen(xgtoken_start); + xg_token = g_strndup(tmp, strchr(tmp, '\'') - tmp); + na->xg_token = xg_token; + //Now we should have everything we need to sign into chat + purple_connection_update_progress(na->pc, _("Fetching chat server"), 3, 5); + url = g_strdup_printf("/xn/redirector/redirect?a=%s", purple_url_encode(na->ning_app)); + ning_post_or_get(na, NING_METHOD_GET, "chat01.ningim.com", + url, NULL, ning_chat_redir_cb, NULL, FALSE); +void ning_scan_cookies_for_id(gchar *key, gchar *value, NingAccount *na) + if (g_str_has_prefix(key, "xn_id_")) + na->ning_app = g_strdup(&key[6]); +static void ning_login_cb(NingAccount *na, gchar *response, gsize len, + purple_connection_update_progress(na->pc, _("Fetching token"), 2, 4); + // ok, we're logged into the host website now + // Pull the host's Ning account id from the cookie + g_hash_table_foreach(na->cookie_table, (GHFunc)ning_scan_cookies_for_id, na); + //Load the homepage to grab the interesting info + ning_post_or_get(na, NING_METHOD_GET, purple_account_get_string(na->account, "host", NULL), + "/", NULL, ning_login_home_cb, NULL, FALSE); +static void ning_login(PurpleAccount *account) + gchar *postdata, *encoded_username, *encoded_password; + gchar *encoded_host, *url; + purple_debug_info("ning", "login\n"); + /* Create account and initialize state */ + na = g_new0(NingAccount, 1); + na->pc = purple_account_get_connection(account); + na->last_messages_download_time = time(NULL) - 60; /* 60 secs is a safe buffer */ + na->cookie_table = g_hash_table_new_full(g_str_hash, g_str_equal, + na->hostname_ip_cache = g_hash_table_new_full(g_str_hash, g_str_equal, + g_hash_table_replace(na->cookie_table, g_strdup("xg_cookie_check"), + account->gc->proto_data = na; + purple_connection_set_state(na->pc, PURPLE_CONNECTING); + purple_connection_update_progress(na->pc, _("Logging in"), 1, 4); + encoded_username = g_strdup(purple_url_encode(purple_account_get_username(account))); + encoded_password = g_strdup(purple_url_encode(purple_account_get_password(account))); + postdata = g_strdup_printf("xg_token=&emailAddress=%s&password=%s", + encoded_username, encoded_password); + g_free(encoded_username); + g_free(encoded_password); + host = purple_account_get_string(account, "host", NULL); + if (host == NULL || host[0] == '\0') + purple_connection_error(na->pc, _("Host not set")); + encoded_host = g_strdup(purple_url_encode(host)); + url = g_strdup_printf("/main/authorization/doSignIn?target=http%%3A%%2F%%2F%s", host); + ning_post_or_get(na, NING_METHOD_POST | NING_METHOD_SSL, host, + url, postdata, ning_login_cb, NULL, FALSE); +static void ning_close(PurpleConnection *pc) + gchar *xg_token_encoded; + PurpleDnsQueryData *dns_query; + purple_debug_info("ning", "disconnecting account\n"); + host_encoded = g_strdup(purple_url_encode(purple_account_get_string(na->account, "host", ""))); + xg_token_encoded = g_strdup(purple_url_encode(na->xg_token)); + postdata = g_strdup_printf("target=%s&xg_token=%s", host_encoded, xg_token_encoded); + ning_post_or_get(na, NING_METHOD_POST, purple_account_get_string(na->account, "host", NULL), + "/main/authorization/signOut", postdata, NULL, NULL, FALSE); + g_free(xg_token_encoded); + purple_debug_info("ning", "destroying %d incomplete connections\n", + g_slist_length(na->conns)); + while (na->conns != NULL) + ning_connection_destroy(na->conns->data); + while (na->dns_queries != NULL) { + dns_query = na->dns_queries->data; + purple_debug_info("ning", "canceling dns query for %s\n", + purple_dnsquery_get_host(dns_query)); + na->dns_queries = g_slist_remove(na->dns_queries, dns_query); + purple_dnsquery_destroy(dns_query); + g_hash_table_destroy(na->cookie_table); + g_hash_table_destroy(na->hostname_ip_cache); + while (na->chats != NULL) + NingChat *chat = na->chats->data; + na->chats = g_list_remove(na->chats, chat); + purple_timeout_remove(chat->userlist_timer); + purple_timeout_remove(chat->message_poll_timer); + purple_conv_chat_left(PURPLE_CONV_CHAT(purple_find_chat(pc, chat->purple_id))); + g_free(chat->ning_hash); +#if PURPLE_MAJOR_VERSION >= 2 && PURPLE_MINOR_VERSION >= 5 +static GHashTable *ning_get_account_text_table(PurpleAccount *account) + table = g_hash_table_new(g_str_hash, g_str_equal); + g_hash_table_insert(table, "login_label", (gpointer)_("Email Address...")); +ning_change_passwd(PurpleConnection *pc, const char *old_pass, const char *new_pass) + PurpleAccount *account; + gchar *encoded_username; + gchar *encoded_password; + if (na == NULL || na->xg_token == NULL) + encoded_username = g_strdup(purple_url_encode(purple_account_get_username(account))); + encoded_password = g_strdup(purple_url_encode(new_pass)); + encoded_token = g_strdup(purple_url_encode(na->xg_token)); + postdata = g_strdup_printf("emailAddress=%s&password=%s&xg_token=%s", + encoded_username, encoded_password, encoded_token); + ning_post_or_get(na, NING_METHOD_POST, purple_account_get_string(na->account, "host", NULL), + "/profiles/settings/updateEmailAddress", postdata, NULL, NULL, FALSE); + g_free(encoded_password); + g_free(encoded_username); +/******************************************************************************/ +/******************************************************************************/ +static gboolean plugin_load(PurplePlugin *plugin) +static gboolean plugin_unload(PurplePlugin *plugin) +static void plugin_init(PurplePlugin *plugin) + PurpleAccountOption *option; + PurplePluginInfo *info = plugin->info; + PurplePluginProtocolInfo *prpl_info = info->extra_info; + option = purple_account_option_string_new("Host", "host", ""); + prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option); +static PurplePluginProtocolInfo prpl_info = { + NULL, /* user_splits */ + NULL, /* protocol_options */ + NO_BUDDY_ICONS /* icon_spec */ + /*{"jpg", 0, 0, 50, 50, -1, PURPLE_ICON_SCALE_SEND}*/, /* icon_spec */ + ning_list_icon, /* list_icon */ + NULL, /* list_emblems */ + NULL, /* status_text */ + NULL, /* tooltip_text */ + ning_statuses, /* status_types */ + NULL, /* blist_node_menu */ + NULL, /* chat_info_defaults */ + ning_login, /* login */ + ning_close, /* close */ + ning_send_im, /* send_im */ + NULL, /* send_typing */ + ning_change_passwd, /* change_passwd */ + NULL, /* add_buddies */ + NULL, /* remove_buddy */ + NULL, /* remove_buddies */ + NULL, /* set_permit_deny */ + ning_join_chat, /* join_chat */ + NULL, /* reject chat invite */ + NULL, /* get_chat_name */ + NULL, /* chat_invite */ + ning_chat_whisper, /* chat_whisper */ + ning_chat_send, /* chat_send */ + NULL, /* register_user */ + NULL, /* get_cb_info */ + NULL, /* get_cb_away */ + NULL, /* alias_buddy */ + NULL, /* group_buddy */ + NULL, /* rename_group */ + NULL, /* convo_closed */ + purple_normalize_nocase,/* normalize */ + NULL, /* set_buddy_icon */ + NULL, /* remove_group */ + NULL, /* get_cb_real_name */ + NULL, /* set_chat_topic */ + NULL, /* find_blist_chat */ + NULL, /* roomlist_get_list */ + NULL, /* roomlist_cancel */ + NULL, /* roomlist_expand_category */ + NULL, /* can_receive_file */ + NULL, /* offline_message */ + NULL, /* whiteboard_prpl_ops */ + NULL, /* roomlist_room_serialize */ + NULL, /* unregister_user */ + NULL, /* send_attention */ + NULL, /* attention_types */ +#if PURPLE_MAJOR_VERSION >= 2 && PURPLE_MINOR_VERSION >= 5 + sizeof(PurplePluginProtocolInfo), /* struct_size */ + ning_get_account_text_table, /* get_account_text_table */ + (gpointer) sizeof(PurplePluginProtocolInfo) +static PurplePluginInfo info = { + PURPLE_PLUGIN_PROTOCOL, /* type */ + NULL, /* ui_requirement */ + NULL, /* dependencies */ + PURPLE_PRIORITY_DEFAULT, /* priority */ + "prpl-bigbrownchunx-ning", /* id */ + NING_PLUGIN_VERSION, /* version */ + N_("Ning Protocol Plugin"), /* summary */ + N_("Ning Protocol Plugin"), /* description */ + "Eion Robb <eionrobb@gmail.com>", /* author */ + plugin_load, /* load */ + plugin_unload, /* unload */ + &prpl_info, /* extra_info */ +PURPLE_INIT_PLUGIN(ning, plugin_init, info); --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ning/ning.h Mon Jul 04 23:23:31 2011 -0400
@@ -0,0 +1,100 @@
+ * libning is the property of its developers. See the COPYRIGHT file + * 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 3 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, see <http://www.gnu.org/licenses/>. +#define NING_PLUGIN_VERSION "0.01" +#define NING_TEMP_GROUP_NAME "Ning Temp" +#include <json-glib/json-glib.h> +#ifndef G_GNUC_NULL_TERMINATED +# define G_GNUC_NULL_TERMINATED __attribute__((__sentinel__)) +# define G_GNUC_NULL_TERMINATED +# endif /* __GNUC__ >= 4 */ +#endif /* G_GNUC_NULL_TERMINATED */ +# define dlopen(a,b) LoadLibrary(a) +# define dlsym(a,b) GetProcAddress(a,b) +# define dlclose(a) FreeLibrary(a) +# include <netinet/in.h> +# include <sys/socket.h> +typedef struct _NingAccount NingAccount; + PurpleAccount *account; + GHashTable *hostname_ip_cache; + GSList *conns; /**< A list of all active connections */ + GHashTable *cookie_table; + time_t last_messages_download_time; +JsonObject *ning_json_parse(const gchar *data, gssize data_len); +gchar *build_user_json(NingAccount *na); --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ning/plugins.cfg Mon Jul 04 23:23:31 2011 -0400
@@ -0,0 +1,9 @@
+depends=purple json-glib +summary=Protocol plugin for the Ning social networking site framework +description=Protocol plugin for the Ning social networking site framework