comparison src/protocols/jabber/buddy.c @ 11675:828802f2251b

[gaim-migrate @ 13961] Jabber User Directory searching... This works when the stars are aligned, and breaks otherwise. It hasn't been tested on any "x:data" supporting servers (because I don't know of any yet). It doesn't let you know if there was an error. Really, it doesn't do a lot of things. But you can search. You do get results. The results themselves, however, are a tad off. users.jabber.org is sending back results along the lines of: <nick>faceprint@faceprint.com</nick><email>faceprint</email> which is obviously switched. I'll ping the appropriate people to figure that out. committer: Tailor Script <tailor@pidgin.im>
author Nathan Walp <nwalp@pidgin.im>
date Mon, 17 Oct 2005 01:43:09 +0000
parents 9ddda2a86f50
children ecd471d1eeec
comparison
equal deleted inserted replaced
11674:e860157296d4 11675:828802f2251b
31 #include "buddy.h" 31 #include "buddy.h"
32 #include "chat.h" 32 #include "chat.h"
33 #include "jabber.h" 33 #include "jabber.h"
34 #include "iq.h" 34 #include "iq.h"
35 #include "presence.h" 35 #include "presence.h"
36 #include "xdata.h"
36 37
37 void jabber_buddy_free(JabberBuddy *jb) 38 void jabber_buddy_free(JabberBuddy *jb)
38 { 39 {
39 g_return_if_fail(jb != NULL); 40 g_return_if_fail(jb != NULL);
40 41
1138 case JABBER_BUDDY_STATE_UNAVAILABLE: 1139 case JABBER_BUDDY_STATE_UNAVAILABLE:
1139 return "offline"; 1140 return "offline";
1140 } 1141 }
1141 return NULL; 1142 return NULL;
1142 } 1143 }
1144
1145 static void user_search_result_add_buddy_cb(GaimConnection *gc, GList *row)
1146 {
1147 /* XXX find out the jid */
1148 gaim_blist_request_add_buddy(gaim_connection_get_account(gc),
1149 g_list_nth_data(row, 0), NULL, NULL);
1150 }
1151
1152 static void user_search_result_cb(JabberStream *js, xmlnode *packet, gpointer data)
1153 {
1154 GaimNotifySearchResults *results;
1155 GaimNotifySearchColumn *column;
1156 xmlnode *x, *query, *item, *field;
1157
1158 /* XXX error checking? */
1159 if(!(query = xmlnode_get_child(packet, "query")))
1160 return;
1161
1162 results = gaim_notify_searchresults_new();
1163 if((x = xmlnode_get_child_with_namespace(query, "x", "jabber:x:data"))) {
1164 xmlnode *reported;
1165 gaim_debug_info("jabber", "new-skool\n");
1166 if((reported = xmlnode_get_child(x, "reported"))) {
1167 xmlnode *field = xmlnode_get_child(reported, "field");
1168 while(field) {
1169 /* XXX keep track of this order, use it below */
1170 const char *var = xmlnode_get_attrib(field, "var");
1171 const char *label = xmlnode_get_attrib(field, "label");
1172 if(var) {
1173 column = gaim_notify_searchresults_column_new(label ? label : var);
1174 gaim_notify_searchresults_column_add(results, column);
1175 }
1176 field = xmlnode_get_next_twin(field);
1177 }
1178 }
1179 item = xmlnode_get_child(x, "item");
1180 while(item) {
1181 GList *row = NULL;
1182 field = xmlnode_get_child(item, "field");
1183 while(field) {
1184 xmlnode *valuenode = xmlnode_get_child(item, "value");
1185 if(valuenode) {
1186 char *value = xmlnode_get_data(valuenode);
1187 row = g_list_append(row, value);
1188 }
1189 field = xmlnode_get_next_twin(field);
1190 }
1191 gaim_notify_searchresults_row_add(results, row);
1192
1193 item = xmlnode_get_next_twin(item);
1194 }
1195 } else {
1196 /* old skool */
1197 gaim_debug_info("jabber", "old-skool\n");
1198
1199 column = gaim_notify_searchresults_column_new("JID");
1200 gaim_notify_searchresults_column_add(results, column);
1201 column = gaim_notify_searchresults_column_new("First");
1202 gaim_notify_searchresults_column_add(results, column);
1203 column = gaim_notify_searchresults_column_new("Last");
1204 gaim_notify_searchresults_column_add(results, column);
1205 column = gaim_notify_searchresults_column_new("Nickname");
1206 gaim_notify_searchresults_column_add(results, column);
1207 column = gaim_notify_searchresults_column_new("E-Mail");
1208 gaim_notify_searchresults_column_add(results, column);
1209
1210 for(item = xmlnode_get_child(query, "item"); item; item = xmlnode_get_next_twin(item)) {
1211 const char *jid;
1212 xmlnode *node;
1213 GList *row = NULL;
1214
1215 if(!(jid = xmlnode_get_attrib(item, "jid")))
1216 continue;
1217
1218 row = g_list_append(row, g_strdup(jid));
1219 node = xmlnode_get_child(item, "first");
1220 row = g_list_append(row, node ? xmlnode_get_data(node) : NULL);
1221 node = xmlnode_get_child(item, "last");
1222 row = g_list_append(row, node ? xmlnode_get_data(node) : NULL);
1223 node = xmlnode_get_child(item, "nick");
1224 row = g_list_append(row, node ? xmlnode_get_data(node) : NULL);
1225 node = xmlnode_get_child(item, "email");
1226 row = g_list_append(row, node ? xmlnode_get_data(node) : NULL);
1227 gaim_debug_info("jabber", "row=%d\n", row);
1228 gaim_notify_searchresults_row_add(results, row);
1229 }
1230 }
1231
1232 gaim_notify_searchresults_button_add(results, GAIM_NOTIFY_BUTTON_ADD_BUDDY,
1233 user_search_result_add_buddy_cb);
1234
1235 gaim_notify_searchresults(js->gc, NULL, NULL, _("The following are the results of your search"), results, NULL, NULL);
1236 }
1237
1238 static void user_search_x_data_cb(JabberStream *js, xmlnode *result, gpointer data)
1239 {
1240 xmlnode *query;
1241 JabberIq *iq;
1242
1243 iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:search");
1244 query = xmlnode_get_child(iq->node, "query");
1245
1246 xmlnode_insert_child(query, result);
1247
1248 jabber_iq_set_callback(iq, user_search_result_cb, NULL);
1249 jabber_iq_send(iq);
1250 }
1251
1252 struct user_search_info {
1253 JabberStream *js;
1254 char *directory_server;
1255 };
1256
1257 static void user_search_cancel_cb(struct user_search_info *usi, GaimRequestFields *fields)
1258 {
1259 g_free(usi->directory_server);
1260 g_free(usi);
1261 }
1262
1263 static void user_search_cb(struct user_search_info *usi, GaimRequestFields *fields)
1264 {
1265 JabberStream *js = usi->js;
1266 JabberIq *iq;
1267 xmlnode *query;
1268 GList *groups, *flds;
1269
1270 iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:search");
1271 query = xmlnode_get_child(iq->node, "query");
1272
1273 for(groups = gaim_request_fields_get_groups(fields); groups; groups = groups->next) {
1274 for(flds = gaim_request_field_group_get_fields(groups->data);
1275 flds; flds = flds->next) {
1276 GaimRequestField *field = flds->data;
1277 const char *id = gaim_request_field_get_id(field);
1278 const char *value = gaim_request_field_string_get_value(field);
1279
1280 if(value && (!strcmp(id, "first") || !strcmp(id, "last") || !strcmp(id, "nick") || !strcmp(id, "email"))) {
1281 xmlnode *y = xmlnode_new_child(query, id);
1282 xmlnode_insert_data(y, value, -1);
1283 }
1284 }
1285 }
1286
1287 jabber_iq_set_callback(iq, user_search_result_cb, NULL);
1288 xmlnode_set_attrib(iq->node, "to", usi->directory_server);
1289 jabber_iq_send(iq);
1290
1291 g_free(usi->directory_server);
1292 g_free(usi);
1293 }
1294
1295 static void user_search_fields_result_cb(JabberStream *js, xmlnode *packet, gpointer data)
1296 {
1297 xmlnode *query, *x;
1298 const char *from;
1299
1300 /* i forget, do i have to check for error? XXX */
1301 if(!(from= xmlnode_get_attrib(packet, "from")))
1302 return;
1303
1304
1305 if(!(query = xmlnode_get_child(packet, "query")))
1306 return;
1307
1308 if((x = xmlnode_get_child_with_namespace(packet, "x", "jabber:x:data"))) {
1309 jabber_x_data_request(js, x, user_search_x_data_cb, NULL);
1310 return;
1311 } else {
1312 struct user_search_info *usi;
1313 xmlnode *instnode;
1314 char *instructions;
1315 GaimRequestFields *fields;
1316 GaimRequestFieldGroup *group;
1317 GaimRequestField *field;
1318
1319 /* old skool */
1320 fields = gaim_request_fields_new();
1321 group = gaim_request_field_group_new(NULL);
1322 gaim_request_fields_add_group(fields, group);
1323
1324 if((instnode = xmlnode_get_child(query, "instructions")))
1325 instructions = xmlnode_get_data(instnode);
1326 else
1327 instructions = g_strdup(_("Fill in one or more fields to search "
1328 "for any matching Jabber users."));
1329
1330 if(xmlnode_get_child(query, "first")) {
1331 field = gaim_request_field_string_new("first", _("First Name"),
1332 NULL, FALSE);
1333 gaim_request_field_group_add_field(group, field);
1334 }
1335 if(xmlnode_get_child(query, "last")) {
1336 field = gaim_request_field_string_new("last", _("Last Name"),
1337 NULL, FALSE);
1338 gaim_request_field_group_add_field(group, field);
1339 }
1340 if(xmlnode_get_child(query, "nick")) {
1341 field = gaim_request_field_string_new("nick", _("Nickname"),
1342 NULL, FALSE);
1343 gaim_request_field_group_add_field(group, field);
1344 }
1345 if(xmlnode_get_child(query, "email")) {
1346 field = gaim_request_field_string_new("email", _("E-Mail Address"),
1347 NULL, FALSE);
1348 gaim_request_field_group_add_field(group, field);
1349 }
1350
1351 usi = g_new0(struct user_search_info, 1);
1352 usi->js = js;
1353 usi->directory_server = g_strdup(from);
1354
1355 gaim_request_fields(js->gc, _("Search for Jabber users"),
1356 _("Search for Jabber users"), instructions, fields,
1357 _("Search"), G_CALLBACK(user_search_cb),
1358 _("Cancel"), G_CALLBACK(user_search_cancel_cb), usi);
1359
1360 g_free(instructions);
1361 }
1362 }
1363
1364 static void jabber_user_search_ok(JabberStream *js, const char *directory)
1365 {
1366 JabberIq *iq;
1367
1368 /* XXX: should probably better validate the directory we're given */
1369 if(!directory || !*directory) {
1370 gaim_notify_error(js->gc, _("Invalid Directory"), _("Invalid Directory"), NULL);
1371 return;
1372 }
1373
1374 iq = jabber_iq_new_query(js, JABBER_IQ_GET, "jabber:iq:search");
1375 xmlnode_set_attrib(iq->node, "to", directory);
1376
1377 jabber_iq_set_callback(iq, user_search_fields_result_cb, NULL);
1378
1379 jabber_iq_send(iq);
1380 }
1381
1382 void jabber_user_search_begin(GaimPluginAction *action)
1383 {
1384 GaimConnection *gc = (GaimConnection *) action->context;
1385 JabberStream *js = gc->proto_data;
1386
1387 gaim_request_input(gc, _("Enter a User Directory"), _("Enter a User Directory"),
1388 _("Select a user directory to search"),
1389 js->user_directories ? js->user_directories->data : "users.jabber.org",
1390 FALSE, FALSE, NULL,
1391 _("Search Directory"), GAIM_CALLBACK(jabber_user_search_ok),
1392 _("Cancel"), NULL, js);
1393 }