const char *jabber_normalize(const GaimAccount *account, const char *in) { GaimConnection *gc = account ? account->gc : NULL; JabberStream *js = gc ? gc->proto_data : NULL; static char buf[3072]; /* maximum legal length of a jabber jid */ JabberID *jid; char *node, *domain; jid = jabber_id_new(in); if(!jid) return NULL; node = jid->node ? g_utf8_strdown(jid->node, -1) : NULL; domain = g_utf8_strdown(jid->domain, -1); if(js && node && jid->resource && jabber_chat_find(js, node, domain)) g_snprintf(buf, sizeof(buf), "%s@%s/%s", node, domain, jid->resource); else g_snprintf(buf, sizeof(buf), "%s%s%s", node ? node : "", node ? "@" : "", domain); jabber_id_free(jid); g_free(node); g_free(domain); return buf; }
static void jabber_chat_room_configure_cb(JabberStream *js, xmlnode *packet, gpointer data) { xmlnode *query, *x; const char *type = xmlnode_get_attrib(packet, "type"); const char *from = xmlnode_get_attrib(packet, "from"); char *msg; JabberChat *chat; JabberID *jid; if(!type || !from) return; if(!strcmp(type, "result")) { jid = jabber_id_new(from); if(!jid) return; chat = jabber_chat_find(js, jid->node, jid->domain); jabber_id_free(jid); if(!chat) return; if(!(query = xmlnode_get_child(packet, "query"))) return; for(x = xmlnode_get_child(query, "x"); x; x = xmlnode_get_next_twin(x)) { const char *xmlns; if(!(xmlns = xmlnode_get_namespace(x))) continue; if(!strcmp(xmlns, "jabber:x:data")) { chat->config_dialog_type = PURPLE_REQUEST_FIELDS; chat->config_dialog_handle = jabber_x_data_request(js, x, jabber_chat_room_configure_x_data_cb, chat); return; } } } else if(!strcmp(type, "error")) { char *msg = jabber_parse_error(js, packet); purple_notify_error(js->gc, _("Configuration error"), _("Configuration error"), msg); if(msg) g_free(msg); return; } msg = g_strdup_printf("Unable to configure room %s", from); purple_notify_info(js->gc, _("Unable to configure"), _("Unable to configure"), msg); g_free(msg); }
static void jabber_chat_register_cb(JabberStream *js, const char *from, JabberIqType type, const char *id, xmlnode *packet, gpointer data) { xmlnode *query, *x; char *msg; JabberChat *chat; JabberID *jid; if (!from) return; if (type == JABBER_IQ_RESULT) { jid = jabber_id_new(from); if(!jid) return; chat = jabber_chat_find(js, jid->node, jid->domain); jabber_id_free(jid); if(!chat) return; if(!(query = xmlnode_get_child(packet, "query"))) return; for(x = xmlnode_get_child(query, "x"); x; x = xmlnode_get_next_twin(x)) { const char *xmlns; if(!(xmlns = xmlnode_get_namespace(x))) continue; if(!strcmp(xmlns, "jabber:x:data")) { jabber_x_data_request(js, x, jabber_chat_register_x_data_cb, chat); return; } } } else if (type == JABBER_IQ_ERROR) { char *msg = jabber_parse_error(js, packet, NULL); purple_notify_error(js->gc, _("Registration error"), _("Registration error"), msg); if(msg) g_free(msg); return; } msg = g_strdup_printf("Unable to configure room %s", from); purple_notify_info(js->gc, _("Unable to configure"), _("Unable to configure"), msg); g_free(msg); }
static JabberChat *jabber_chat_new(JabberStream *js, const char *room, const char *server, const char *handle, const char *password, GHashTable *data) { JabberChat *chat; char *jid; if (jabber_chat_find(js, room, server) != NULL) return NULL; chat = g_new0(JabberChat, 1); chat->js = js; chat->joined = 0; chat->room = g_strdup(room); chat->server = g_strdup(server); chat->handle = g_strdup(handle); /* Copy the data hash table to chat->components */ chat->components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); if (data == NULL) { g_hash_table_insert(chat->components, g_strdup("handle"), g_strdup(handle)); g_hash_table_insert(chat->components, g_strdup("room"), g_strdup(room)); g_hash_table_insert(chat->components, g_strdup("server"), g_strdup(server)); /* g_hash_table_insert(chat->components, g_strdup("password"), g_strdup(server)); */ } else { g_hash_table_foreach(data, insert_in_hash_table, chat->components); } chat->members = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, (GDestroyNotify)jabber_chat_member_free); jid = g_strdup_printf("%s@%s", room, server); g_hash_table_insert(js->chats, jid, chat); return chat; }
const char *jabber_normalize(const PurpleAccount *account, const char *in) { PurpleConnection *gc = account ? account->gc : NULL; JabberStream *js = gc ? gc->proto_data : NULL; static char buf[3072]; /* maximum legal length of a jabber jid */ JabberID *jid; jid = jabber_id_new_internal(in, TRUE); if(!jid) return NULL; if(js && jid->node && jid->resource && jabber_chat_find(js, jid->node, jid->domain)) g_snprintf(buf, sizeof(buf), "%s@%s/%s", jid->node, jid->domain, jid->resource); else g_snprintf(buf, sizeof(buf), "%s%s%s", jid->node ? jid->node : "", jid->node ? "@" : "", jid->domain); jabber_id_free(jid); return buf; }
void jabber_roster_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) { JabberStream *js = gc->proto_data; char *who; JabberID *jid; JabberBuddy *jb; JabberBuddyResource *jbr; const char *name; /* If we haven't received the roster yet, ignore any adds */ if (js->state != JABBER_STREAM_CONNECTED) return; name = purple_buddy_get_name(buddy); jid = jabber_id_new(name); if (jid == NULL) { /* TODO: Remove the buddy from the list? */ return; } /* Adding a chat room or a chat buddy to the roster is *not* supported. */ if (jid->node && jabber_chat_find(js, jid->node, jid->domain) != NULL) { /* * This is the same thing Bonjour does. If it causes problems, move * it to an idle callback. */ purple_debug_warning("jabber", "Cowardly refusing to add a MUC user " "to your buddy list and removing the buddy. " "Buddies can only be added by real (non-MUC) " "JID\n"); purple_blist_remove_buddy(buddy); jabber_id_free(jid); return; } who = jabber_id_get_bare_jid(jid); if (jid->resource != NULL) { /* * If the buddy name added contains a resource, strip that off and * rename the buddy. */ purple_blist_rename_buddy(buddy, who); } jb = jabber_buddy_find(js, who, FALSE); purple_debug_info("jabber", "jabber_roster_add_buddy(): Adding %s\n", who); jabber_roster_update(js, who, NULL); if (jb == js->user_jb) { jabber_presence_fake_to_self(js, NULL); } else if(!jb || !(jb->subscription & JABBER_SUB_TO)) { jabber_presence_subscription_set(js, who, "subscribe"); } else if((jbr =jabber_buddy_find_resource(jb, NULL))) { purple_prpl_got_user_status(gc->account, who, jabber_buddy_state_get_status_id(jbr->state), "priority", jbr->priority, jbr->status ? "message" : NULL, jbr->status, NULL); } g_free(who); }
void jabber_presence_parse(JabberStream *js, xmlnode *packet) { const char *type; JabberBuddyResource *jbr = NULL; gboolean signal_return, ret; JabberPresence presence; xmlnode *child; memset(&presence, 0, sizeof(presence)); /* defaults */ presence.state = JABBER_BUDDY_STATE_UNKNOWN; presence.sent = time(NULL); /* interesting values */ presence.from = xmlnode_get_attrib(packet, "from"); presence.to = xmlnode_get_attrib(packet, "to"); type = xmlnode_get_attrib(packet, "type"); presence.type = str_to_presence_type(type); presence.jb = jabber_buddy_find(js, presence.from, TRUE); g_return_if_fail(presence.jb != NULL); presence.jid_from = jabber_id_new(presence.from); if (presence.jid_from == NULL) { purple_debug_error("jabber", "Ignoring presence with malformed 'from' " "JID: %s\n", presence.from); return; } signal_return = GPOINTER_TO_INT(purple_signal_emit_return_1(purple_connection_get_prpl(js->gc), "jabber-receiving-presence", js->gc, type, presence.from, packet)); if (signal_return) { goto out; } if (presence.jid_from->node) presence.chat = jabber_chat_find(js, presence.jid_from->node, presence.jid_from->domain); if(presence.jb->error_msg) { g_free(presence.jb->error_msg); presence.jb->error_msg = NULL; } if (presence.type == JABBER_PRESENCE_AVAILABLE) { presence.state = JABBER_BUDDY_STATE_ONLINE; } else if (presence.type == JABBER_PRESENCE_ERROR) { /* TODO: Is this handled properly? Should it be treated as per-jbr? */ char *msg = jabber_parse_error(js, packet, NULL); presence.state = JABBER_BUDDY_STATE_ERROR; presence.jb->error_msg = msg ? msg : g_strdup(_("Unknown Error in presence")); } else if (presence.type == JABBER_PRESENCE_SUBSCRIBE) { /* TODO: Move to handle_subscribe() (so nick is extracted by the * PresenceHandler */ struct _jabber_add_permit *jap = g_new0(struct _jabber_add_permit, 1); gboolean onlist = FALSE; PurpleAccount *account; PurpleBuddy *buddy; xmlnode *nick; account = purple_connection_get_account(js->gc); buddy = purple_find_buddy(account, presence.from); nick = xmlnode_get_child_with_namespace(packet, "nick", "http://jabber.org/protocol/nick"); if (nick) presence.nickname = xmlnode_get_data(nick); if (buddy) { if ((presence.jb->subscription & (JABBER_SUB_TO | JABBER_SUB_PENDING))) onlist = TRUE; } jap->gc = js->gc; jap->who = g_strdup(presence.from); jap->js = js; purple_account_request_authorization(account, presence.from, NULL, presence.nickname, NULL, onlist, authorize_add_cb, deny_add_cb, jap); goto out; } else if (presence.type == JABBER_PRESENCE_SUBSCRIBED) {
void jabber_chat_join(PurpleConnection *gc, GHashTable *data) { JabberChat *chat; char *room, *server, *handle, *passwd; xmlnode *presence, *x; char *tmp, *room_jid, *full_jid; JabberStream *js = gc->proto_data; PurplePresence *gpresence; PurpleStatus *status; JabberBuddyState state; char *msg; int priority; room = g_hash_table_lookup(data, "room"); server = g_hash_table_lookup(data, "server"); handle = g_hash_table_lookup(data, "handle"); passwd = g_hash_table_lookup(data, "password"); if(!room || !server) return; if(!handle) handle = js->user->node; if(!jabber_nodeprep_validate(room)) { char *buf = g_strdup_printf(_("%s is not a valid room name"), room); purple_notify_error(gc, _("Invalid Room Name"), _("Invalid Room Name"), buf); g_free(buf); return; } else if(!jabber_nameprep_validate(server)) { char *buf = g_strdup_printf(_("%s is not a valid server name"), server); purple_notify_error(gc, _("Invalid Server Name"), _("Invalid Server Name"), buf); g_free(buf); return; } else if(!jabber_resourceprep_validate(handle)) { char *buf = g_strdup_printf(_("%s is not a valid room handle"), handle); purple_notify_error(gc, _("Invalid Room Handle"), _("Invalid Room Handle"), buf); } if(jabber_chat_find(js, room, server)) return; tmp = g_strdup_printf("%s@%s", room, server); room_jid = g_strdup(jabber_normalize(NULL, tmp)); g_free(tmp); chat = g_new0(JabberChat, 1); chat->js = gc->proto_data; chat->room = g_strdup(room); chat->server = g_strdup(server); chat->handle = g_strdup(handle); chat->members = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, (GDestroyNotify)jabber_chat_member_free); g_hash_table_insert(js->chats, room_jid, chat); gpresence = purple_account_get_presence(gc->account); status = purple_presence_get_active_status(gpresence); purple_status_to_jabber(status, &state, &msg, &priority); presence = jabber_presence_create(state, msg, priority); full_jid = g_strdup_printf("%s/%s", room_jid, handle); xmlnode_set_attrib(presence, "to", full_jid); g_free(full_jid); g_free(msg); x = xmlnode_new_child(presence, "x"); xmlnode_set_namespace(x, "http://jabber.org/protocol/muc"); if(passwd && *passwd) { xmlnode *password = xmlnode_new_child(x, "password"); xmlnode_insert_data(password, passwd, -1); } jabber_send(js, presence); xmlnode_free(presence); }