📄 buddy.c
字号:
act = purple_menu_action_new(_("Temporarily Hide From"), PURPLE_CALLBACK(jabber_buddy_make_invisible), NULL, NULL); } m = g_list_append(m, act); } if(jb->subscription & JABBER_SUB_FROM /* && NOT ME */) { act = purple_menu_action_new(_("Cancel Presence Notification"), PURPLE_CALLBACK(jabber_buddy_cancel_presence_notification), NULL, NULL); m = g_list_append(m, act); } if(!(jb->subscription & JABBER_SUB_TO)) { act = purple_menu_action_new(_("(Re-)Request authorization"), PURPLE_CALLBACK(jabber_buddy_rerequest_auth), NULL, NULL); m = g_list_append(m, act); } else /* if(NOT ME) */{ /* shouldn't this just happen automatically when the buddy is removed? */ act = purple_menu_action_new(_("Unsubscribe"), PURPLE_CALLBACK(jabber_buddy_unsubscribe), NULL, NULL); m = g_list_append(m, act); } return m;}GList *jabber_blist_node_menu(PurpleBlistNode *node){ if(PURPLE_BLIST_NODE_IS_BUDDY(node)) { return jabber_buddy_menu((PurpleBuddy *) node); } else { return NULL; }}const char *jabber_buddy_state_get_name(JabberBuddyState state){ switch(state) { case JABBER_BUDDY_STATE_UNKNOWN: return _("Unknown"); case JABBER_BUDDY_STATE_ERROR: return _("Error"); case JABBER_BUDDY_STATE_UNAVAILABLE: return _("Offline"); case JABBER_BUDDY_STATE_ONLINE: return _("Available"); case JABBER_BUDDY_STATE_CHAT: return _("Chatty"); case JABBER_BUDDY_STATE_AWAY: return _("Away"); case JABBER_BUDDY_STATE_XA: return _("Extended Away"); case JABBER_BUDDY_STATE_DND: return _("Do Not Disturb"); } return _("Unknown");}JabberBuddyState jabber_buddy_status_id_get_state(const char *id) { if(!id) return JABBER_BUDDY_STATE_UNKNOWN; if(!strcmp(id, "available")) return JABBER_BUDDY_STATE_ONLINE; if(!strcmp(id, "freeforchat")) return JABBER_BUDDY_STATE_CHAT; if(!strcmp(id, "away")) return JABBER_BUDDY_STATE_AWAY; if(!strcmp(id, "extended_away")) return JABBER_BUDDY_STATE_XA; if(!strcmp(id, "dnd")) return JABBER_BUDDY_STATE_DND; if(!strcmp(id, "offline")) return JABBER_BUDDY_STATE_UNAVAILABLE; if(!strcmp(id, "error")) return JABBER_BUDDY_STATE_ERROR; return JABBER_BUDDY_STATE_UNKNOWN;}JabberBuddyState jabber_buddy_show_get_state(const char *id) { if(!id) return JABBER_BUDDY_STATE_UNKNOWN; if(!strcmp(id, "available")) return JABBER_BUDDY_STATE_ONLINE; if(!strcmp(id, "chat")) return JABBER_BUDDY_STATE_CHAT; if(!strcmp(id, "away")) return JABBER_BUDDY_STATE_AWAY; if(!strcmp(id, "xa")) return JABBER_BUDDY_STATE_XA; if(!strcmp(id, "dnd")) return JABBER_BUDDY_STATE_DND; if(!strcmp(id, "offline")) return JABBER_BUDDY_STATE_UNAVAILABLE; if(!strcmp(id, "error")) return JABBER_BUDDY_STATE_ERROR; return JABBER_BUDDY_STATE_UNKNOWN;}const char *jabber_buddy_state_get_show(JabberBuddyState state) { switch(state) { case JABBER_BUDDY_STATE_CHAT: return "chat"; case JABBER_BUDDY_STATE_AWAY: return "away"; case JABBER_BUDDY_STATE_XA: return "xa"; case JABBER_BUDDY_STATE_DND: return "dnd"; case JABBER_BUDDY_STATE_ONLINE: return "available"; case JABBER_BUDDY_STATE_UNKNOWN: case JABBER_BUDDY_STATE_ERROR: return NULL; case JABBER_BUDDY_STATE_UNAVAILABLE: return "offline"; } return NULL;}const char *jabber_buddy_state_get_status_id(JabberBuddyState state) { switch(state) { case JABBER_BUDDY_STATE_CHAT: return "freeforchat"; case JABBER_BUDDY_STATE_AWAY: return "away"; case JABBER_BUDDY_STATE_XA: return "extended_away"; case JABBER_BUDDY_STATE_DND: return "dnd"; case JABBER_BUDDY_STATE_ONLINE: return "available"; case JABBER_BUDDY_STATE_UNKNOWN: return "available"; case JABBER_BUDDY_STATE_ERROR: return "error"; case JABBER_BUDDY_STATE_UNAVAILABLE: return "offline"; } return NULL;}static void user_search_result_add_buddy_cb(PurpleConnection *gc, GList *row, void *user_data){ /* XXX find out the jid */ purple_blist_request_add_buddy(purple_connection_get_account(gc), g_list_nth_data(row, 0), NULL, NULL);}static void user_search_result_cb(JabberStream *js, xmlnode *packet, gpointer data){ PurpleNotifySearchResults *results; PurpleNotifySearchColumn *column; xmlnode *x, *query, *item, *field; /* XXX error checking? */ if(!(query = xmlnode_get_child(packet, "query"))) return; results = purple_notify_searchresults_new(); if((x = xmlnode_get_child_with_namespace(query, "x", "jabber:x:data"))) { xmlnode *reported; purple_debug_info("jabber", "new-skool\n"); if((reported = xmlnode_get_child(x, "reported"))) { xmlnode *field = xmlnode_get_child(reported, "field"); while(field) { /* XXX keep track of this order, use it below */ const char *var = xmlnode_get_attrib(field, "var"); const char *label = xmlnode_get_attrib(field, "label"); if(var) { column = purple_notify_searchresults_column_new(label ? label : var); purple_notify_searchresults_column_add(results, column); } field = xmlnode_get_next_twin(field); } } item = xmlnode_get_child(x, "item"); while(item) { GList *row = NULL; field = xmlnode_get_child(item, "field"); while(field) { xmlnode *valuenode = xmlnode_get_child(field, "value"); if(valuenode) { char *value = xmlnode_get_data(valuenode); row = g_list_append(row, value); } field = xmlnode_get_next_twin(field); } purple_notify_searchresults_row_add(results, row); item = xmlnode_get_next_twin(item); } } else { /* old skool */ purple_debug_info("jabber", "old-skool\n"); column = purple_notify_searchresults_column_new(_("JID")); purple_notify_searchresults_column_add(results, column); column = purple_notify_searchresults_column_new(_("First Name")); purple_notify_searchresults_column_add(results, column); column = purple_notify_searchresults_column_new(_("Last Name")); purple_notify_searchresults_column_add(results, column); column = purple_notify_searchresults_column_new(_("Nickname")); purple_notify_searchresults_column_add(results, column); column = purple_notify_searchresults_column_new(_("E-Mail")); purple_notify_searchresults_column_add(results, column); for(item = xmlnode_get_child(query, "item"); item; item = xmlnode_get_next_twin(item)) { const char *jid; xmlnode *node; GList *row = NULL; if(!(jid = xmlnode_get_attrib(item, "jid"))) continue; row = g_list_append(row, g_strdup(jid)); node = xmlnode_get_child(item, "first"); row = g_list_append(row, node ? xmlnode_get_data(node) : NULL); node = xmlnode_get_child(item, "last"); row = g_list_append(row, node ? xmlnode_get_data(node) : NULL); node = xmlnode_get_child(item, "nick"); row = g_list_append(row, node ? xmlnode_get_data(node) : NULL); node = xmlnode_get_child(item, "email"); row = g_list_append(row, node ? xmlnode_get_data(node) : NULL); purple_debug_info("jabber", "row=%d\n", row); purple_notify_searchresults_row_add(results, row); } } purple_notify_searchresults_button_add(results, PURPLE_NOTIFY_BUTTON_ADD, user_search_result_add_buddy_cb); purple_notify_searchresults(js->gc, NULL, NULL, _("The following are the results of your search"), results, NULL, NULL);}static void user_search_x_data_cb(JabberStream *js, xmlnode *result, gpointer data){ xmlnode *query; JabberIq *iq; char *dir_server = data; iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:search"); query = xmlnode_get_child(iq->node, "query"); xmlnode_insert_child(query, result); jabber_iq_set_callback(iq, user_search_result_cb, NULL); xmlnode_set_attrib(iq->node, "to", dir_server); jabber_iq_send(iq); g_free(dir_server);}struct user_search_info { JabberStream *js; char *directory_server;};static void user_search_cancel_cb(struct user_search_info *usi, PurpleRequestFields *fields){ g_free(usi->directory_server); g_free(usi);}static void user_search_cb(struct user_search_info *usi, PurpleRequestFields *fields){ JabberStream *js = usi->js; JabberIq *iq; xmlnode *query; GList *groups, *flds; iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:search"); query = xmlnode_get_child(iq->node, "query"); for(groups = purple_request_fields_get_groups(fields); groups; groups = groups->next) { for(flds = purple_request_field_group_get_fields(groups->data); flds; flds = flds->next) { PurpleRequestField *field = flds->data; const char *id = purple_request_field_get_id(field); const char *value = purple_request_field_string_get_value(field); if(value && (!strcmp(id, "first") || !strcmp(id, "last") || !strcmp(id, "nick") || !strcmp(id, "email"))) { xmlnode *y = xmlnode_new_child(query, id); xmlnode_insert_data(y, value, -1); } } } jabber_iq_set_callback(iq, user_search_result_cb, NULL); xmlnode_set_attrib(iq->node, "to", usi->directory_server); jabber_iq_send(iq); g_free(usi->directory_server); g_free(usi);}#if 0/* This is for gettext only -- it will see this even though there's an #if 0. *//* * An incomplete list of server generated original language search * comments for Jabber User Directories * * See discussion thread "Search comment for Jabber is not translatable" * in purple-i18n@lists.sourceforge.net (March 2006) */static const char * jabber_user_dir_comments [] = { /* current comment from Jabber User Directory users.jabber.org */ N_("Find a contact by entering the search criteria in the given fields. " "Note: Each field supports wild card searches (%)"), NULL};#endifstatic void user_search_fields_result_cb(JabberStream *js, xmlnode *packet, gpointer data){ xmlnode *query, *x; const char *from, *type; if(!(from = xmlnode_get_attrib(packet, "from"))) return; if(!(type = xmlnode_get_attrib(packet, "type")) || !strcmp(type, "error")) { char *msg = jabber_parse_error(js, packet); if(!msg) msg = g_strdup(_("Unknown error")); purple_notify_error(js->gc, _("Directory Query Failed"), _("Could not query the directory server."), msg); g_free(msg); return; } if(!(query = xmlnode_get_child(packet, "query"))) return; if((x = xmlnode_get_child_with_namespace(query, "x", "jabber:x:data"))) { jabber_x_data_request(js, x, user_search_x_data_cb, g_strdup(from)); return; } else { struct user_search_info *usi; xmlnode *instnode; char *instructions = NULL; PurpleRequestFields *fields; PurpleRequestFieldGroup *group; PurpleRequestField *field; /* old skool */ fields = purple_request_fields_new(); group = purple_request_field_group_new(NULL); purple_request_fields_add_group(fields, group); if((instnode = xmlnode_get_child(query, "instructions"))) { char *tmp = xmlnode_get_data(instnode); if(tmp) { /* Try to translate the message (see static message list in jabber_user_dir_comments[]) */ instructions = g_strdup_printf(_("Server Instructions: %s"), _(tmp)); g_free(tmp); } } if(!instructions) { instructions = g_strdup(_("Fill in one or more fields to search " "for any matching XMPP users.")); } if(xmlnode_get_child(query, "first")) { field = purple_request_field_string_new("first", _("First Name"), NULL, FALSE); purple_request_field_group_add_field(group, field); } if(xmlnode_get_child(query, "last")) { field = purple_request_field_string_new("last", _("Last Name"), NULL, FALSE); purple_request_field_group_add_field(group, field); } if(xmlnode_get_child(query, "nick")) { field = purple_request_field_string_new("nick", _("Nickname"), NULL, FALSE); purple_request_field_group_add_field(group, field); } if(xmlnode_get_child(query, "email")) { field = purple_request_field_string_new("email", _("E-Mail Address"), NULL, FALSE); purple_request_field_group_add_field(group, field); } usi = g_new0(struct user_search_info, 1); usi->js = js; usi->directory_server = g_strdup(from); purple_request_fields(js->gc, _("Search for XMPP users"), _("Search for XMPP users"), instructions, fields, _("Search"), G_CALLBACK(user_search_cb), _("Cancel"), G_CALLBACK(user_search_cancel_cb), NULL, NULL, NULL, usi); g_free(instructions); }}static void jabber_user_search_ok(JabberStream *js, const char *directory){ JabberIq *iq; /* XXX: should probably better validate the directory we're given */ if(!directory || !*directory) { purple_notify_error(js->gc, _("Invalid Directory"), _("Invalid Directory"), NULL); return; } iq = jabber_iq_new_query(js, JABBER_IQ_GET, "jabber:iq:search"); xmlnode_set_attrib(iq->node, "to", directory); jabber_iq_set_callback(iq, user_search_fields_result_cb, NULL); jabber_iq_send(iq);}void jabber_user_search_begin(PurplePluginAction *action){ PurpleConnection *gc = (PurpleConnection *) action->context; JabberStream *js = gc->proto_data; purple_request_input(gc, _("Enter a User Directory"), _("Enter a User Directory"), _("Select a user directory to search"), js->user_directories ? js->user_directories->data : NULL, FALSE, FALSE, NULL, _("Search Directory"), PURPLE_CALLBACK(jabber_user_search_ok), _("Cancel"), NULL, NULL, NULL, NULL, js);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -