gboolean jabber_chat_change_nick(JabberChat *chat, const char *nick) { xmlnode *presence; char *full_jid; PurpleAccount *account; PurpleStatus *status; JabberBuddyState state; char *msg; int priority; if(!chat->muc) { purple_conv_chat_write(PURPLE_CONV_CHAT(chat->conv), "", _("Nick changing not supported in non-MUC chatrooms"), PURPLE_MESSAGE_SYSTEM, time(NULL)); return FALSE; } account = purple_connection_get_account(chat->js->gc); status = purple_account_get_active_status(account); purple_status_to_jabber(status, &state, &msg, &priority); presence = jabber_presence_create_js(chat->js, state, msg, priority); full_jid = g_strdup_printf("%s@%s/%s", chat->room, chat->server, nick); xmlnode_set_attrib(presence, "to", full_jid); g_free(full_jid); g_free(msg); jabber_send(chat->js, presence); xmlnode_free(presence); return TRUE; }
JabberChat *jabber_join_chat(JabberStream *js, const char *room, const char *server, const char *handle, const char *password, GHashTable *data) { JabberChat *chat; PurpleConnection *gc; PurpleAccount *account; PurpleStatus *status; xmlnode *presence, *x; JabberBuddyState state; char *msg; int priority; char *jid; chat = jabber_chat_new(js, room, server, handle, password, data); if (chat == NULL) return NULL; gc = js->gc; account = purple_connection_get_account(gc); status = purple_account_get_active_status(account); purple_status_to_jabber(status, &state, &msg, &priority); presence = jabber_presence_create_js(js, state, msg, priority); g_free(msg); jid = g_strdup_printf("%s@%s/%s", room, server, handle); xmlnode_set_attrib(presence, "to", jid); g_free(jid); x = xmlnode_new_child(presence, "x"); xmlnode_set_namespace(x, "http://jabber.org/protocol/muc"); if (password && *password) { xmlnode *p = xmlnode_new_child(x, "password"); xmlnode_insert_data(p, password, -1); } jabber_send(js, presence); xmlnode_free(presence); return chat; }
xmlnode *jabber_presence_create(JabberBuddyState state, const char *msg, int priority) { return jabber_presence_create_js(NULL, state, msg, priority); }
void jabber_presence_send(JabberStream *js, gboolean force) { PurpleAccount *account; xmlnode *presence, *x, *photo; char *stripped = NULL; JabberBuddyState state; int priority; const char *artist = NULL, *title = NULL, *source = NULL, *uri = NULL, *track = NULL; int length = -1; gboolean allowBuzz; PurplePresence *p; PurpleStatus *status, *tune; account = purple_connection_get_account(js->gc); p = purple_account_get_presence(account); status = purple_presence_get_active_status(p); /* we don't want to send presence before we've gotten our roster */ if (js->state != JABBER_STREAM_CONNECTED) { purple_debug_misc("jabber", "attempt to send presence before roster retrieved\n"); return; } purple_status_to_jabber(status, &state, &stripped, &priority); /* check for buzz support */ allowBuzz = purple_status_get_attr_boolean(status,"buzz"); /* changing the buzz state has to trigger a re-broadcasting of the presence for caps */ tune = purple_presence_get_status(p, "tune"); if (js->googletalk && !stripped && purple_status_is_active(tune)) { stripped = jabber_google_presence_outgoing(tune); } #define CHANGED(a,b) ((!a && b) || (a && a[0] == '\0' && b && b[0] != '\0') || \ (a && !b) || (a && a[0] != '\0' && b && b[0] == '\0') || (a && b && strcmp(a,b))) /* check if there are any differences to the <presence> and send them in that case */ if (force || allowBuzz != js->allowBuzz || js->old_state != state || CHANGED(js->old_msg, stripped) || js->old_priority != priority || CHANGED(js->old_avatarhash, js->avatar_hash) || js->old_idle != js->idle) { /* Need to update allowBuzz before creating the presence (with caps) */ js->allowBuzz = allowBuzz; presence = jabber_presence_create_js(js, state, stripped, priority); /* Per XEP-0153 4.1, we must always send the <x> */ x = xmlnode_new_child(presence, "x"); xmlnode_set_namespace(x, "vcard-temp:x:update"); /* * FIXME: Per XEP-0153 4.3.2 bullet 2, we must not publish our * image hash if another resource has logged in and updated the * vcard avatar. Requires changes in jabber_presence_parse. */ if (js->vcard_fetched) { /* Always publish a <photo>; it's empty if we have no image. */ photo = xmlnode_new_child(x, "photo"); if (js->avatar_hash) xmlnode_insert_data(photo, js->avatar_hash, -1); } jabber_send(js, presence); g_hash_table_foreach(js->chats, chats_send_presence_foreach, presence); xmlnode_free(presence); /* update old values */ if(js->old_msg) g_free(js->old_msg); if(js->old_avatarhash) g_free(js->old_avatarhash); js->old_msg = g_strdup(stripped); js->old_avatarhash = g_strdup(js->avatar_hash); js->old_state = state; js->old_priority = priority; js->old_idle = js->idle; } g_free(stripped); /* next, check if there are any changes to the tune values */ if (purple_status_is_active(tune)) { artist = purple_status_get_attr_string(tune, PURPLE_TUNE_ARTIST); title = purple_status_get_attr_string(tune, PURPLE_TUNE_TITLE); source = purple_status_get_attr_string(tune, PURPLE_TUNE_ALBUM); uri = purple_status_get_attr_string(tune, PURPLE_TUNE_URL); track = purple_status_get_attr_string(tune, PURPLE_TUNE_TRACK); length = (!purple_status_get_attr_value(tune, PURPLE_TUNE_TIME)) ? -1 : purple_status_get_attr_int(tune, PURPLE_TUNE_TIME); } if(CHANGED(artist, js->old_artist) || CHANGED(title, js->old_title) || CHANGED(source, js->old_source) || CHANGED(uri, js->old_uri) || CHANGED(track, js->old_track) || (length != js->old_length)) { PurpleJabberTuneInfo tuneinfo = { (char*)artist, (char*)title, (char*)source, (char*)track, length, (char*)uri }; jabber_tune_set(js->gc, &tuneinfo); /* update old values */ g_free(js->old_artist); g_free(js->old_title); g_free(js->old_source); g_free(js->old_uri); g_free(js->old_track); js->old_artist = g_strdup(artist); js->old_title = g_strdup(title); js->old_source = g_strdup(source); js->old_uri = g_strdup(uri); js->old_length = length; js->old_track = g_strdup(track); } #undef CHANGED jabber_presence_fake_to_self(js, status); }
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); purple_serv_got_join_chat_failed(gc, data); 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); purple_serv_got_join_chat_failed(gc, data); 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); purple_serv_got_join_chat_failed(gc, data); g_free(buf); return; } 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); /* 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); 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); 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_js(js, 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); }
JabberChat *jabber_join_chat(JabberStream *js, const char *room, const char *server, const char *handle, const char *password, GHashTable *data) { JabberChat *chat; PurpleConnection *gc; PurpleAccount *account; PurpleStatus *status; xmlnode *presence, *x; JabberBuddyState state; char *msg; int priority; char *jid; char *history_maxchars; char *history_maxstanzas; char *history_seconds; char *history_since; struct tm history_since_datetime; const char *history_since_string = NULL; chat = jabber_chat_new(js, room, server, handle, password, data); if (chat == NULL) return NULL; gc = js->gc; account = purple_connection_get_account(gc); status = purple_account_get_active_status(account); purple_status_to_jabber(status, &state, &msg, &priority); presence = jabber_presence_create_js(js, state, msg, priority); g_free(msg); jid = g_strdup_printf("%s@%s/%s", room, server, handle); xmlnode_set_attrib(presence, "to", jid); g_free(jid); history_maxchars = g_hash_table_lookup(data, "history_maxchars"); history_maxstanzas = g_hash_table_lookup(data, "history_maxstanzas"); history_seconds = g_hash_table_lookup(data, "history_seconds"); history_since = g_hash_table_lookup(data, "history_since"); if (history_since) { if (purple_str_to_time(history_since, TRUE, &history_since_datetime, NULL, NULL) != 0) { history_since_string = purple_utf8_strftime("%Y-%m-%dT%H:%M:%SZ", &history_since_datetime); } else { history_since_string = NULL; purple_debug_error("jabber", "Invalid date format for history_since" " while requesting history: %s", history_since); } } x = xmlnode_new_child(presence, "x"); xmlnode_set_namespace(x, "http://jabber.org/protocol/muc"); if (password && *password) { xmlnode *p = xmlnode_new_child(x, "password"); xmlnode_insert_data(p, password, -1); } if ((history_maxchars && *history_maxchars) || (history_maxstanzas && *history_maxstanzas) || (history_seconds && *history_seconds) || (history_since_string && *history_since_string)) { xmlnode *history = xmlnode_new_child(x, "history"); if (history_maxchars && *history_maxchars) { xmlnode_set_attrib(history, "maxchars", history_maxchars); } if (history_maxstanzas && *history_maxstanzas) { xmlnode_set_attrib(history, "maxstanzas", history_maxstanzas); } if (history_seconds && *history_seconds) { xmlnode_set_attrib(history, "seconds", history_seconds); } if (history_since_string && *history_since_string) { xmlnode_set_attrib(history, "since", history_since_string); } } jabber_send(js, presence); xmlnode_free(presence); return chat; }