void purple_request_field_list_set_selected(PurpleRequestField *field, GList *items) { GList *l; g_return_if_fail(field != NULL); g_return_if_fail(items != NULL); g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_LIST); purple_request_field_list_clear_selected(field); if (!purple_request_field_list_get_multi_select(field) && items && items->next) { purple_debug_warning("request", "More than one item added to non-multi-select " "field %s\n", purple_request_field_get_id(field)); return; } for (l = items; l != NULL; l = l->next) { field->u.list.selected = g_list_append(field->u.list.selected, g_strdup(l->data)); g_hash_table_insert(field->u.list.selected_table, g_strdup((char *)l->data), NULL); } }
static void cal_timeout(MsnCmdProc *cmdproc, MsnTransaction *trans) { purple_debug_warning("msn", "cal_timeout: command %s timed out\n", trans->command); cal_error_helper(trans, MSN_SB_ERROR_UNKNOWN); }
static void ycht_packet_process(YchtConn *ycht, YchtPkt *pkt) { if (pkt->data && !strncmp(pkt->data->data, "*** Danger Will Robinson!!!", strlen("*** Danger Will Robinson!!!"))) return; switch (pkt->service) { case YCHT_SERVICE_LOGIN: ycht_process_login(ycht, pkt); break; case YCHT_SERVICE_LOGOUT: ycht_process_logout(ycht, pkt); break; case YCHT_SERVICE_CHATJOIN: ycht_process_chatjoin(ycht, pkt); break; case YCHT_SERVICE_CHATPART: ycht_process_chatpart(ycht, pkt); break; case YCHT_SERVICE_CHATMSG: case YCHT_SERVICE_CHATMSG_EMOTE: ycht_progress_chatmsg(ycht, pkt); break; case YCHT_SERVICE_ONLINE_FRIENDS: ycht_progress_online_friends(ycht, pkt); break; default: purple_debug_warning("yahoo", "YCHT: warning, unhandled service 0x%02x\n", pkt->service); } }
static gboolean timeoutfunc(gpointer data) { struct stun_conn *sc = data; if(sc->retry >= 2) { purple_debug_warning("stun", "request timed out, giving up.\n"); if(sc->test == 2) nattype.type = PURPLE_STUN_NAT_TYPE_SYMMETRIC; /* set unknown */ nattype.status = PURPLE_STUN_STATUS_UNKNOWN; nattype.lookup_time = time(NULL); /* callbacks */ do_callbacks(); /* we don't need to remove the timeout (returning FALSE) */ sc->timeout = 0; close_stun_conn(sc); return FALSE; } purple_debug_info("stun", "request timed out, retrying.\n"); sc->retry++; sendto(sc->fd, sc->packet, sc->packetsize, 0, (struct sockaddr *)&(sc->addr), sizeof(struct sockaddr_in)); return TRUE; }
void qq_process_buddy_from_server(PurpleConnection *gc, int funct, gchar *from, gchar *to, guint8 *data, gint data_len) { switch (funct) { case QQ_SERVER_BUDDY_ADDED: server_buddy_added(gc, from, to, data, data_len); break; case QQ_SERVER_BUDDY_ADD_REQUEST: server_buddy_add_request(gc, from, to, data, data_len); break; case QQ_SERVER_BUDDY_ADD_REQUEST_EX: server_buddy_add_request_ex(gc, from, to, data, data_len); break; case QQ_SERVER_BUDDY_ADDED_ME: server_buddy_added_me(gc, from, to, data, data_len); break; case QQ_SERVER_BUDDY_REJECTED_ME: server_buddy_rejected_me(gc, from, to, data, data_len); break; case QQ_SERVER_BUDDY_ADDED_EX: server_buddy_added_ex(gc, from, to, data, data_len); break; case QQ_SERVER_BUDDY_ADDING_EX: case QQ_SERVER_BUDDY_ADDED_ANSWER: server_buddy_adding_ex(gc, from, to, data, data_len); break; default: purple_debug_warning("QQ", "Unknow buddy operate (%d) from server\n", funct); break; } }
/** * Takes a new incoming FLAP frame and sends it to the appropriate * handler function to be parsed. */ static void parse_flap(OscarData *od, FlapConnection *conn, FlapFrame *frame) { if (frame->channel == 0x01) { guint32 flap_version = byte_stream_get32(&frame->data); if (flap_version != 0x00000001) { /* Error! */ purple_debug_warning("oscar", "Expecting FLAP version " "0x00000001 but received FLAP version %08x. Closing connection.\n", flap_version); flap_connection_schedule_destroy(conn, OSCAR_DISCONNECT_INVALID_DATA, NULL); } else conn->connected = TRUE; } else if (frame->channel == 0x02) { parse_snac(od, conn, frame); } else if (frame->channel == 0x04) { parse_flap_ch4(od, conn, frame); } else if (frame->channel == 0x05) { /* TODO: Reset our keepalive watchdog? */ } }
void purple_plugin_pref_set_bounds(PurplePluginPref *pref, int min, int max) { int tmp; g_return_if_fail(pref != NULL); g_return_if_fail(pref->name != NULL); if (purple_prefs_get_type(pref->name) != PURPLE_PREF_INT) { purple_debug_warning("pluginpref", "purple_plugin_pref_set_bounds: %s is not an integer pref\n", pref->name); return; } if (min > max) { tmp = min; min = max; max = tmp; } pref->min = min; pref->max = max; }
static char * np_httpconn_proxy_auth(NPHttpConn *httpconn) { purple_debug_warning("np","=============> "); return "np_httpconn_proxy_auth"; }
gssize np_httpconn_write(NPHttpConn *httpconn, const char *body, size_t body_len) { purple_debug_warning("np","=============> "); return 100; }
static void action_cb (NotifyNotification *notification, gchar *action, gpointer user_data) { PurpleBuddy *buddy = NULL; PurpleConversation *conv = NULL; purple_debug_info (PLUGIN_ID, "action_cb(), " "notification: 0x%lx, action: '%s'", (unsigned long)notification, action); buddy = (PurpleBuddy *)g_object_get_data (G_OBJECT(notification), "buddy"); conv = (PurpleConversation *)g_object_get_data (G_OBJECT(notification), "conv"); if (buddy) { conv = purple_find_conversation_with_account (PURPLE_CONV_TYPE_ANY, buddy->name, buddy->account); if (!conv) { conv = purple_conversation_new (PURPLE_CONV_TYPE_IM, buddy->account, buddy->name); } } else if (!conv) { purple_debug_warning (PLUGIN_ID, "Got no buddy nor conv!"); return; } conv->ui_ops->present (conv); notify_notification_close (notification, NULL); }
static gboolean write_raw(NPHttpConn *httpconn, const char *data, size_t data_len) { purple_debug_warning("np","=============> "); return TRUE; }
/** Convert XML to something based on MSIM_XMLNODE_CONVERT. */ static gchar * msim_convert_xml(MsimSession *session, const gchar *raw, MSIM_XMLNODE_CONVERT f) { xmlnode *root; GString *str; gchar *enclosed_raw; g_return_val_if_fail(raw != NULL, NULL); /* Enclose text in one root tag, to try to make it valid XML for parsing. */ enclosed_raw = g_strconcat("<root>", raw, "</root>", NULL); root = xmlnode_from_str(enclosed_raw, -1); if (!root) { purple_debug_warning("msim", "msim_markup_to_html: couldn't parse " "%s as XML, returning raw: %s\n", enclosed_raw, raw); /* TODO: msim_unrecognized */ g_free(enclosed_raw); return g_strdup(raw); } g_free(enclosed_raw); str = g_string_new(NULL); msim_convert_xmlnode(session, str, root, f, 0); xmlnode_free(root); purple_debug_info("msim", "msim_markup_to_html: returning %s\n", str->str); return g_string_free(str, FALSE); }
/** Convert an xmlnode of msim markup or HTML to an HTML string or msim markup. * * @param f Function to convert tags. * * @return An HTML string. Caller frees. */ static void msim_convert_xmlnode(MsimSession *session, GString *out, xmlnode *root, MSIM_XMLNODE_CONVERT f, int nodes_processed) { xmlnode *node; gchar *begin, *inner, *end, *tmp; int descended = nodes_processed; if (!root || !root->name) return; purple_debug_info("msim", "msim_convert_xmlnode: got root=%s\n", root->name); begin = inner = end = NULL; if (descended == 0) /* We've not formatted this yet.. :) */ descended = f(session, root, &begin, &end); /* Get the value that our format function has already descended for us */ g_string_append(out, begin); g_free(begin); /* Loop over all child nodes. */ for (node = root->child; node != NULL; node = node->next) { switch (node->type) { case XMLNODE_TYPE_ATTRIB: /* Attributes handled above. */ break; case XMLNODE_TYPE_TAG: /* A tag or tag with attributes. Recursively descend. */ msim_convert_xmlnode(session, out, node, f, descended); purple_debug_info("msim", " ** node name=%s\n", node->name ? node->name : "(NULL)"); break; case XMLNODE_TYPE_DATA: /* Literal text. */ /* * TODO: Why is it necessary to escape here? I thought * node->data was already escaped? */ tmp = g_markup_escape_text(node->data, node->data_sz); g_string_append(out, tmp); g_free(tmp); break; default: purple_debug_warning("msim", "msim_convert_xmlnode: unknown node type\n"); } } /* TODO: Note that msim counts each piece of text enclosed by <f> as * a paragraph and will display each on its own line. You actually have * to _nest_ <f> tags to intersperse different text in one paragraph! * Comment out this line below to see. */ g_string_append(out, end); g_free(end); }
static void irc_dccsend_send_connected(gpointer data, int source, PurpleInputCondition cond) { PurpleXfer *xfer = (PurpleXfer *) data; struct irc_xfer_send_data *xd = purple_xfer_get_protocol_data(xfer); int conn; conn = accept(xd->fd, NULL, 0); if (conn == -1) { /* Accepting the connection failed. This could just be related * to the nonblocking nature of the listening socket, so we'll * just try again next time */ /* Let's print an error message anyway */ purple_debug_warning("irc", "accept: %s\n", g_strerror(errno)); return; } purple_input_remove(purple_xfer_get_watcher(xfer)); purple_xfer_set_watcher(xfer, 0); close(xd->fd); xd->fd = -1; _purple_network_set_common_socket_flags(conn); xd->inpa = purple_input_add(conn, PURPLE_INPUT_READ, irc_dccsend_send_read, xfer); /* Start the transfer */ purple_xfer_start(xfer, conn, NULL, 0); }
static void flist_get_profile_cb(FListWebRequestData *req_data, gpointer user_data, JsonObject *root, const gchar *error_message) { FListAccount *fla = user_data; FListProfiles *flp = _flist_profiles(fla); gboolean success; flp->profile_request = NULL; if(!root) { purple_debug_warning(FLIST_DEBUG, "We requested a profile from the Web API, but failed. Error Message: %s\n", error_message); success = FALSE; } else { success = flist_process_profile(fla, root); } if(success) { g_free(flp->character); flp->character = NULL; purple_notify_user_info_destroy(flp->profile_info); flp->profile_info = NULL; } else { JsonObject *json = json_object_new(); json_object_set_string_member(json, "character", flp->character); flist_request(fla->pc, "PRO", json); json_object_unref(json); } }
/* remove a buddy and send packet to QQ server accordingly */ void qq_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) { qq_data *qd; qq_buddy_data *bd; qq_buddy_opt_req *opt_req; g_return_if_fail(gc != NULL && gc->proto_data != NULL); g_return_if_fail(buddy != NULL); qd = (qq_data *) gc->proto_data; if (!qd->is_login) return; /* free it in qq_request_remove_buddy */ opt_req = g_new0(qq_buddy_opt_req, 1); opt_req->gc = gc; opt_req->uid = purple_name_to_uid(purple_buddy_get_name(buddy)); if (opt_req->uid > 0 && opt_req->uid != qd->uid) { qq_request_auth_token(gc, QQ_AUTH_INFO_BUDDY, QQ_AUTH_INFO_REMOVE_BUDDY, 0, opt_req); } if ((bd = purple_buddy_get_protocol_data(buddy)) != NULL) { qq_buddy_data_free(bd); purple_buddy_set_protocol_data(buddy, NULL); } else { purple_debug_warning("QQ", "Empty buddy data of %s\n", purple_buddy_get_name(buddy)); } }
void Poller::op_notified_invite_into_group(line::Operation &op) { // TODO: Maybe use cached objects instead of re-requesting every time parent.c_out->send_getGroup(op.param1); parent.c_out->send([this, op]{ line::Group group; parent.c_out->recv_getGroup(group); if (!group.__isset.id) { purple_debug_warning("line", "Invited into unknown group: %s\n", op.param1.c_str()); return; } parent.c_out->send_getContact(op.param2); parent.c_out->send([this, group, op]() mutable { line::Contact inviter; parent.c_out->recv_getContact(inviter); parent.c_out->send_getContact(op.param3); parent.c_out->send([this, group, inviter, op]() mutable { line::Contact invitee; parent.c_out->recv_getContact(invitee); parent.handle_group_invite(group, invitee, inviter); }); }); }); }
static void ggp_chat_left(ggp_chat_local_info *chat, uin_t uin) { uin_t me; int idx = ggp_chat_participant_find(chat, uin); if (idx < 0) { purple_debug_warning("gg", "ggp_chat_joined: " "user %u isn't present in chat %" G_GUINT64_FORMAT "\n", uin, chat->id); return; } chat->participants[idx] = chat->participants[chat->participants_count - 1]; chat->participants_count--; chat->participants = g_realloc(chat->participants, sizeof(uin) * chat->participants_count); if (chat->conv == NULL) return; me = ggp_str_to_uin(purple_account_get_username( purple_connection_get_account(chat->gc))); if (me == uin) { purple_conversation_write_system_message( PURPLE_CONVERSATION(chat->conv), _("You have left the chat"), 0); purple_serv_got_chat_left(chat->gc, chat->local_id); chat->conv = NULL; chat->left = TRUE; } purple_chat_conversation_remove_user(chat->conv, ggp_uin_to_str(uin), NULL); }
static gboolean bus_call (GstBus *bus, GstMessage *msg, gpointer data) { GstElement *play = data; GError *err = NULL; switch (GST_MESSAGE_TYPE (msg)) { case GST_MESSAGE_ERROR: gst_message_parse_error(msg, &err, NULL); purple_debug_error("gstreamer", "%s\n", err->message); g_error_free(err); /* fall-through and clean up */ case GST_MESSAGE_EOS: gst_element_set_state(play, GST_STATE_NULL); gst_object_unref(GST_OBJECT(play)); return FALSE; break; case GST_MESSAGE_WARNING: gst_message_parse_warning(msg, &err, NULL); purple_debug_warning("gstreamer", "%s\n", err->message); g_error_free(err); break; default: break; } return TRUE; }
void jabber_auth_handle_challenge(JabberStream *js, PurpleXmlNode *packet) { const char *ns = purple_xmlnode_get_namespace(packet); if (!purple_strequal(ns, NS_XMPP_SASL)) { purple_connection_error(js->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Invalid response from server")); return; } if (js->auth_mech && js->auth_mech->handle_challenge) { PurpleXmlNode *response = NULL; char *msg = NULL; JabberSaslState state = js->auth_mech->handle_challenge(js, packet, &response, &msg); if (state == JABBER_SASL_STATE_FAIL) { purple_connection_error(js->gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, msg ? msg : _("Invalid challenge from server")); } else if (response) { jabber_send(js, response); purple_xmlnode_free(response); } g_free(msg); } else purple_debug_warning("jabber", "Received unexpected (and unhandled) <challenge/>\n"); }
void qq_process_add_buddy_no_auth(PurpleConnection *gc, guint8 *data, gint data_len, guint32 uid) { qq_data *qd; gchar **segments; gchar *dest_uid, *reply; PurpleBuddy *buddy; g_return_if_fail(data != NULL && data_len != 0); g_return_if_fail(uid != 0); qd = (qq_data *) gc->proto_data; purple_debug_info("QQ", "Process buddy add for id [%u]\n", uid); qq_show_packet("buddy_add_no_auth", data, data_len); if (NULL == (segments = split_data(data, data_len, "\x1f", 2))) return; dest_uid = segments[0]; reply = segments[1]; if (strtoul(dest_uid, NULL, 10) != qd->uid) { /* should not happen */ purple_debug_error("QQ", "Add buddy reply is to [%s], not me!", dest_uid); g_strfreev(segments); return; } if (strtol(reply, NULL, 10) == 0) { /* add OK */ qq_buddy_find_or_new(gc, uid); qq_request_buddy_info(gc, uid, 0, 0); if (qd->client_version >= 2007) { qq_request_get_level_2007(gc, uid); } else { qq_request_get_level(gc, uid); } qq_request_get_buddies_online(gc, 0, 0); purple_debug_info("QQ", "Successed adding into %u's buddy list", uid); g_strfreev(segments); return; } /* need auth */ purple_debug_warning("QQ", "Failed adding buddy, need authorize\n"); buddy = qq_buddy_find(gc, uid); if (buddy == NULL) { buddy = qq_buddy_new(gc, uid); } if (buddy != NULL && buddy->proto_data != NULL) { /* Not authorized now, free buddy data */ qq_buddy_data_free(buddy->proto_data); buddy->proto_data = NULL; } add_buddy_authorize_input(gc, uid, NULL, 0); g_strfreev(segments); }
static void np_modify_buddy_memo_from_menu_cb(PurpleBlistNode *node, gpointer data) { purple_debug_warning("np","\n===>"); // PurpleBuddy *buddy; // np_buddy_data *bd; // PurpleConnection *gc; // guint32 bd_uid; // // g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); // // buddy = (PurpleBuddy *)node; // g_return_if_fail(NULL != buddy); // // gc = purple_account_get_connection(purple_buddy_get_account(buddy)); // g_return_if_fail(NULL != gc); // // bd = (np_buddy_data *)purple_buddy_get_protocol_data(buddy); // g_return_if_fail(NULL != bd); // bd_uid = bd->uid; // // /* param: gc, uid, update_class, action // * here, update_class is set to bd_uid. because some memo packages returned // * without uid, which will make us confused */ // np_request_buddy_memo(gc, bd_uid, 0, np_BUDDY_MEMO_MODIFY); }
/* As we've covered before, libpurple calls this function, if present, when it * loads the plugin. Here we're using it to show off the capabilities of the * debug API and just blindly returning TRUE to tell libpurple it's safe to * continue loading. */ static gboolean plugin_load(PurplePlugin *plugin) { /* Define these for convenience--we're just using them to show the * similarities of the debug functions to the standard printf(). */ gint i = 256; gfloat f = 512.1024; const gchar *s = "example string"; /* Introductory message */ purple_debug_info(PLUGIN_ID, "Called plugin_load. Beginning debug demonstration\n"); /* Show off the debug API a bit */ purple_debug_misc(PLUGIN_ID, "MISC level debug message. i = %d, f = %f, s = %s\n", i, f, s); purple_debug_info(PLUGIN_ID, "INFO level debug message. i = %d, f = %f, s = %s\n", i, f, s); purple_debug_warning(PLUGIN_ID, "WARNING level debug message. i = %d, f = %f, s = %s\n", i, f, s); purple_debug_error(PLUGIN_ID, "ERROR level debug message. i = %d, f = %f, s = %s\n", i, f, s); purple_debug_fatal(PLUGIN_ID, "FATAL level debug message. i = %d, f = %f, s = %s\n", i, f, s); /* Now just return TRUE to tell libpurple to finish loading. */ return TRUE; }
/* who is the nickname of buddy in np chat-room (Qun) */ static gchar *np_get_chat_buddy_real_name(PurpleConnection *gc, gint channel, const gchar *who) { purple_debug_warning("np","\n===>"); g_return_val_if_fail(who != NULL, NULL); return chat_name_to_purple_name(who); }
/* remove a buddy and send packet to QQ server accordingly */ void qq_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) { qq_data *qd; qq_buddy_data *bd; guint32 uid; g_return_if_fail(gc != NULL && gc->proto_data != NULL); g_return_if_fail(buddy != NULL); qd = (qq_data *) gc->proto_data; if (!qd->is_login) return; uid = purple_name_to_uid(purple_buddy_get_name(buddy)); if (uid > 0 && uid != qd->uid) { if (qd->client_version > 2005) { qq_request_auth_code(gc, QQ_AUTH_INFO_BUDDY, QQ_AUTH_INFO_REMOVE_BUDDY, uid); } else { request_remove_buddy(gc, uid); request_buddy_remove_me(gc, uid); } } if ((bd = purple_buddy_get_protocol_data(buddy)) != NULL) { qq_buddy_data_free(bd); purple_buddy_set_protocol_data(buddy, NULL); } else { purple_debug_warning("QQ", "Empty buddy data of %s\n", purple_buddy_get_name(buddy)); } /* Do not call purple_blist_remove_buddy, * otherwise purple segmentation fault */ }
static void np_send_im(PurpleConnection *gc, const gchar *who, const gchar *message, PurpleMessageFlags flags) { purple_debug_warning("np","\n%s",__FUNCTION__); }
static void pidgin_smiley_theme_activate_impl(PurpleSmileyTheme *theme) { PidginSmileyThemePrivate *priv = PIDGIN_SMILEY_THEME_GET_PRIVATE(theme); PidginSmileyThemeIndex *index; GHashTable *smap; GList *it, *it2, *it3; g_return_if_fail(priv != NULL); if (priv->smiley_lists_map) return; priv->smiley_lists_map = smap = g_hash_table_new_full( g_str_hash, g_str_equal, g_free, g_object_unref); index = pidgin_smiley_theme_index_parse(priv->path, TRUE); for (it = index->protocols; it; it = g_list_next(it)) { PidginSmileyThemeIndexProtocol *proto_idx = it->data; PurpleSmileyList *proto_smileys; proto_smileys = g_hash_table_lookup(smap, proto_idx->name); if (!proto_smileys) { proto_smileys = purple_smiley_list_new(); g_hash_table_insert(smap, g_strdup(proto_idx->name), proto_smileys); } for (it2 = proto_idx->smileys; it2; it2 = g_list_next(it2)) { PidginSmileyThemeIndexSmiley *smiley_idx = it2->data; gchar *smiley_path; smiley_path = g_build_filename( priv->path, smiley_idx->file, NULL); if (!g_file_test(smiley_path, G_FILE_TEST_EXISTS)) { purple_debug_warning("gtksmiley-theme", "Smiley %s is missing", smiley_path); continue; } for (it3 = smiley_idx->shortcuts; it3; it3 = g_list_next(it3)) { PurpleSmiley *smiley; gchar *shortcut = it3->data; smiley = purple_smiley_new( shortcut, smiley_path); g_object_set_data(G_OBJECT(smiley), "pidgin-smiley-hidden", GINT_TO_POINTER(smiley_idx->hidden)); purple_smiley_list_add(proto_smileys, smiley); g_object_unref(smiley); } } } pidgin_smiley_theme_index_free(index); }
/* returns the icon name for a buddy or protocol */ static const gchar *np_list_icon(PurpleAccount *a, PurpleBuddy *b) { purple_debug_warning("np","\n%s",__FUNCTION__); return "np"; }
static void _accept_socket_handler(gpointer notused, int server_socket, PurpleInputCondition condition) { /* Check that it is a read condition */ if (condition != PURPLE_INPUT_READ) return; struct sockaddr_in their_addr; /* connector's address information */ socklen_t sin_size = sizeof(struct sockaddr); int client_socket; if ((client_socket = accept(server_socket, (struct sockaddr *)&their_addr, &sin_size)) == -1) { purple_debug_warning("purple_ruby", "failed to accept %d: %d\n", client_socket, errno); return; } int flags = fcntl(client_socket, F_GETFL); fcntl(client_socket, F_SETFL, flags | O_NONBLOCK); #ifndef _WIN32 fcntl(client_socket, F_SETFD, FD_CLOEXEC); #endif purple_debug_info("purple_ruby", "new connection: %d\n", client_socket); guint purple_fd = purple_input_add(client_socket, PURPLE_INPUT_READ, _read_socket_handler, NULL); g_hash_table_insert(data_hash_table, (gpointer)client_socket, (gpointer)rb_str_new2("")); g_hash_table_insert(fd_hash_table, (gpointer)client_socket, (gpointer)purple_fd); }
void yahoo_process_chat_exit(PurpleConnection *gc, struct yahoo_packet *pkt) { char *who = NULL; char *room = NULL; GSList *l; for (l = pkt->hash; l; l = l->next) { struct yahoo_pair *pair = l->data; if (pair->key == 104) { g_free(room); room = yahoo_string_decode(gc, pair->value, TRUE); } else if (pair->key == 109) { if (g_utf8_validate(pair->value, -1, NULL)) { who = pair->value; } else { purple_debug_warning("yahoo", "yahoo_process_chat_exit " "got non-UTF-8 string for key %d\n", pair->key); } } } if (who && room) { PurpleChatConversation *c = purple_conversations_find_chat(gc, YAHOO_CHAT_ID); if (c && !purple_utf8_strcasecmp(purple_conversation_get_name( PURPLE_CONVERSATION(c)), room)) purple_chat_conversation_remove_user(c, who, NULL); } g_free(room); }