comparison mcabber/src/roster.c @ 447:03bb57383cea

Initial Multi-User Chat support This patch adds basic MUC support. We now can: - join an existing room; - create and unlock a room using the /rawxml command; - set our nickname; - send/receive chatgroup messages; - see the members of the room; - leave the room. Chatroom logging is currently disabled, as it could do some unexpected things.
author Mikael Berthe <mikael@lilotux.net>
date Sun, 25 Sep 2005 01:01:44 +0200
parents 63562fd409a1
children 644b8bf9ca4d
comparison
equal deleted inserted replaced
446:9f4e9e9aaf08 447:03bb57383cea
42 gchar *name; 42 gchar *name;
43 gchar *jid; 43 gchar *jid;
44 guint type; 44 guint type;
45 enum subscr subscription; 45 enum subscr subscription;
46 GSList *resource; 46 GSList *resource;
47 res *cur_res; 47 gchar *nickname; // For groupchats
48 guint flags; 48 guint flags;
49 // list: user -> points to his group; group -> points to its users list 49 // list: user -> points to his group; group -> points to its users list
50 GSList *list; 50 GSList *list;
51 } roster; 51 } roster;
52 52
195 GCompareFunc comp; 195 GCompareFunc comp;
196 196
197 if (!jidname) return NULL; 197 if (!jidname) return NULL;
198 198
199 if (!roster_type) 199 if (!roster_type)
200 roster_type = ROSTER_TYPE_USER|ROSTER_TYPE_AGENT|ROSTER_TYPE_GROUP; 200 roster_type = ROSTER_TYPE_USER | ROSTER_TYPE_ROOM |
201 ROSTER_TYPE_AGENT | ROSTER_TYPE_GROUP;
201 202
202 sample.type = roster_type; 203 sample.type = roster_type;
203 if (type == jidsearch) { 204 if (type == jidsearch) {
204 sample.jid = (gchar*)jidname; 205 sample.jid = (gchar*)jidname;
205 comp = (GCompareFunc)&roster_compare_jid_type; 206 comp = (GCompareFunc)&roster_compare_jid_type;
247 { 248 {
248 roster *roster_usr; 249 roster *roster_usr;
249 roster *my_group; 250 roster *my_group;
250 GSList *slist; 251 GSList *slist;
251 252
252 if ((type != ROSTER_TYPE_USER) && (type != ROSTER_TYPE_AGENT)) { 253 if ((type != ROSTER_TYPE_USER) &&
254 (type != ROSTER_TYPE_ROOM) &&
255 (type != ROSTER_TYPE_AGENT)) {
253 // XXX Error message? 256 // XXX Error message?
254 return NULL; 257 return NULL;
255 } 258 }
256 259
257 // Let's be arbitrary: default group has an empty name (""). 260 // Let's be arbitrary: default group has an empty name ("").
258 if (!group) group = ""; 261 if (!group) group = "";
259 262
260 // #1 Check this user doesn't already exist 263 // #1 Check this user doesn't already exist
261 slist = roster_find(jid, jidsearch, ROSTER_TYPE_USER|ROSTER_TYPE_AGENT); 264 slist = roster_find(jid, jidsearch, type|ROSTER_TYPE_AGENT);
262 if (slist) return slist; 265 if (slist) return slist;
263 // #2 add group if necessary 266 // #2 add group if necessary
264 slist = roster_add_group(group); 267 slist = roster_add_group(group);
265 if (!slist) return NULL; 268 if (!slist) return NULL;
266 my_group = (roster*)slist->data; 269 my_group = (roster*)slist->data;
274 p = strstr(str, "/"); 277 p = strstr(str, "/");
275 if (p) *p = '\0'; 278 if (p) *p = '\0';
276 roster_usr->name = g_strdup(str); 279 roster_usr->name = g_strdup(str);
277 g_free(str); 280 g_free(str);
278 } 281 }
279 roster_usr->type = type; //ROSTER_TYPE_USER; 282 roster_usr->type = type;
280 roster_usr->list = slist; // (my_group SList element) 283 roster_usr->list = slist; // (my_group SList element)
281 // #4 Insert node (sorted) 284 // #4 Insert node (sorted)
282 my_group->list = g_slist_insert_sorted(my_group->list, roster_usr, 285 my_group->list = g_slist_insert_sorted(my_group->list, roster_usr,
283 (GCompareFunc)&roster_compare_name); 286 (GCompareFunc)&roster_compare_name);
284 return roster_find(jid, jidsearch, type); 287 return roster_find(jid, jidsearch, type);
290 GSList *sl_user, *sl_group; 293 GSList *sl_user, *sl_group;
291 GSList **sl_group_listptr; 294 GSList **sl_group_listptr;
292 roster *roster_usr; 295 roster *roster_usr;
293 GSList *node; 296 GSList *node;
294 297
295 sl_user = roster_find(jid, jidsearch, ROSTER_TYPE_USER|ROSTER_TYPE_AGENT); 298 sl_user = roster_find(jid, jidsearch,
299 ROSTER_TYPE_USER|ROSTER_TYPE_AGENT|ROSTER_TYPE_ROOM);
296 if (sl_user == NULL) 300 if (sl_user == NULL)
297 return; 301 return;
298 roster_usr = (roster*)sl_user->data; 302 roster_usr = (roster*)sl_user->data;
299 303
300 // Remove (if present) from unread messages list 304 // Remove (if present) from unread messages list
302 if (node) unread_list = g_slist_delete_link(unread_list, node); 306 if (node) unread_list = g_slist_delete_link(unread_list, node);
303 307
304 // Let's free memory (jid, name, status message) 308 // Let's free memory (jid, name, status message)
305 if (roster_usr->jid) g_free((gchar*)roster_usr->jid); 309 if (roster_usr->jid) g_free((gchar*)roster_usr->jid);
306 if (roster_usr->name) g_free((gchar*)roster_usr->name); 310 if (roster_usr->name) g_free((gchar*)roster_usr->name);
311 if (roster_usr->nickname) g_free((gchar*)roster_usr->nickname);
307 free_all_resources(&roster_usr->resource); 312 free_all_resources(&roster_usr->resource);
308 g_free(roster_usr); 313 g_free(roster_usr);
309 314
310 // That's a little complex, we need to dereference twice 315 // That's a little complex, we need to dereference twice
311 sl_group = ((roster*)sl_user->data)->list; 316 sl_group = ((roster*)sl_user->data)->list;
339 while (sl_usr) { 344 while (sl_usr) {
340 roster *roster_usr = (roster*)sl_usr->data; 345 roster *roster_usr = (roster*)sl_usr->data;
341 // Free name and jid 346 // Free name and jid
342 if (roster_usr->jid) g_free((gchar*)roster_usr->jid); 347 if (roster_usr->jid) g_free((gchar*)roster_usr->jid);
343 if (roster_usr->name) g_free((gchar*)roster_usr->name); 348 if (roster_usr->name) g_free((gchar*)roster_usr->name);
349 if (roster_usr->nickname) g_free((gchar*)roster_usr->nickname);
344 free_all_resources(&roster_usr->resource); 350 free_all_resources(&roster_usr->resource);
345 g_free(roster_usr); 351 g_free(roster_usr);
346 sl_usr = g_slist_next(sl_usr); 352 sl_usr = g_slist_next(sl_usr);
347 } 353 }
348 // Free group's users list 354 // Free group's users list
369 { 375 {
370 GSList *sl_user; 376 GSList *sl_user;
371 roster *roster_usr; 377 roster *roster_usr;
372 res *p_res; 378 res *p_res;
373 379
374 sl_user = roster_find(jid, jidsearch, ROSTER_TYPE_USER|ROSTER_TYPE_AGENT); 380 sl_user = roster_find(jid, jidsearch,
381 ROSTER_TYPE_USER|ROSTER_TYPE_ROOM|ROSTER_TYPE_AGENT);
375 // If we can't find it, we add it 382 // If we can't find it, we add it
376 if (sl_user == NULL) 383 if (sl_user == NULL)
377 sl_user = roster_add_user(jid, NULL, NULL, ROSTER_TYPE_USER); 384 sl_user = roster_add_user(jid, NULL, NULL, ROSTER_TYPE_USER);
378 385
379 // If there is no resource name, we can leave now 386 // If there is no resource name, we can leave now
403 void roster_setflags(const char *jid, guint flags, guint value) 410 void roster_setflags(const char *jid, guint flags, guint value)
404 { 411 {
405 GSList *sl_user; 412 GSList *sl_user;
406 roster *roster_usr; 413 roster *roster_usr;
407 414
408 sl_user = roster_find(jid, jidsearch, ROSTER_TYPE_USER|ROSTER_TYPE_AGENT); 415 sl_user = roster_find(jid, jidsearch,
416 ROSTER_TYPE_USER|ROSTER_TYPE_ROOM|ROSTER_TYPE_AGENT);
409 if (sl_user == NULL) 417 if (sl_user == NULL)
410 return; 418 return;
411 419
412 roster_usr = (roster*)sl_user->data; 420 roster_usr = (roster*)sl_user->data;
413 if (value) 421 if (value)
423 void roster_msg_setflag(const char *jid, guint value) 431 void roster_msg_setflag(const char *jid, guint value)
424 { 432 {
425 GSList *sl_user; 433 GSList *sl_user;
426 roster *roster_usr, *roster_grp; 434 roster *roster_usr, *roster_grp;
427 435
428 sl_user = roster_find(jid, jidsearch, ROSTER_TYPE_USER|ROSTER_TYPE_AGENT); 436 sl_user = roster_find(jid, jidsearch,
437 ROSTER_TYPE_USER|ROSTER_TYPE_ROOM|ROSTER_TYPE_AGENT);
429 if (sl_user == NULL) 438 if (sl_user == NULL)
430 return; 439 return;
431 440
432 roster_usr = (roster*)sl_user->data; 441 roster_usr = (roster*)sl_user->data;
433 roster_grp = (roster*)roster_usr->list->data; 442 roster_grp = (roster*)roster_usr->list->data;
525 534
526 roster_usr = (roster*)sl_user->data; 535 roster_usr = (roster*)sl_user->data;
527 return roster_usr->type; 536 return roster_usr->type;
528 } 537 }
529 538
530 inline guint roster_exists(const char *jidname, enum findwhat type,
531 guint roster_type)
532 {
533 if (roster_find(jidname, type, roster_type))
534 return TRUE;
535 return FALSE;
536 }
537
538 539
539 /* ### BuddyList functions ### */ 540 /* ### BuddyList functions ### */
540 541
541 // buddylist_set_hide_offline_buddies(hide) 542 // buddylist_set_hide_offline_buddies(hide)
542 // "hide" values: 1=hide 0=show_all -1=invert 543 // "hide" values: 1=hide 0=show_all -1=invert
691 roster_usr->resource = NULL; 692 roster_usr->resource = NULL;
692 693
693 // Free old buddy 694 // Free old buddy
694 if (roster_usr->jid) g_free((gchar*)roster_usr->jid); 695 if (roster_usr->jid) g_free((gchar*)roster_usr->jid);
695 if (roster_usr->name) g_free((gchar*)roster_usr->name); 696 if (roster_usr->name) g_free((gchar*)roster_usr->name);
697 if (roster_usr->nickname) g_free((gchar*)roster_usr->nickname);
696 free_all_resources(&roster_usr->resource); 698 free_all_resources(&roster_usr->resource);
697 g_free(roster_usr); 699 g_free(roster_usr);
698 700
699 // If new new group is folded, the curren_buddy will be lost, and the 701 // If new new group is folded, the curren_buddy will be lost, and the
700 // chat window won't be correctly refreshed. So we make sure it isn't... 702 // chat window won't be correctly refreshed. So we make sure it isn't...
738 { 740 {
739 roster *roster_usr = rosterdata; 741 roster *roster_usr = rosterdata;
740 return roster_usr->name; 742 return roster_usr->name;
741 } 743 }
742 744
745 void buddy_setnickname(gpointer rosterdata, char *newname)
746 {
747 roster *roster_usr = rosterdata;
748
749 if (!roster_usr->type & ROSTER_TYPE_ROOM) return;
750
751 if (roster_usr->nickname) {
752 g_free((gchar*)roster_usr->nickname);
753 roster_usr->nickname = NULL;
754 }
755 if (newname)
756 roster_usr->nickname = g_strdup(newname);
757 }
758
759 const char *buddy_getnickname(gpointer rosterdata)
760 {
761 roster *roster_usr = rosterdata;
762 return roster_usr->nickname;
763 }
764
743 // buddy_getgroupname() 765 // buddy_getgroupname()
744 // Returns a pointer on buddy's group name. 766 // Returns a pointer on buddy's group name.
745 const char *buddy_getgroupname(gpointer rosterdata) 767 const char *buddy_getgroupname(gpointer rosterdata)
746 { 768 {
747 roster *roster_usr = rosterdata; 769 roster *roster_usr = rosterdata;
809 831
810 for (lp = roster_usr->resource; lp; lp = g_slist_next(lp)) 832 for (lp = roster_usr->resource; lp; lp = g_slist_next(lp))
811 reslist = g_slist_append(reslist, g_strdup(((res*)lp->data)->name)); 833 reslist = g_slist_append(reslist, g_strdup(((res*)lp->data)->name));
812 834
813 return reslist; 835 return reslist;
836 }
837
838 // buddy_del_all_resources()
839 // Remove all resources from the specified buddy
840 void buddy_del_all_resources(gpointer rosterdata)
841 {
842 roster *roster_usr = rosterdata;
843
844 while (roster_usr->resource) {
845 res *r = roster_usr->resource->data;
846 del_resource(roster_usr, r->name);
847 }
814 } 848 }
815 849
816 // buddy_setflags() 850 // buddy_setflags()
817 // Set one or several flags to value (TRUE/FALSE) 851 // Set one or several flags to value (TRUE/FALSE)
818 void buddy_setflags(gpointer rosterdata, guint flags, guint value) 852 void buddy_setflags(gpointer rosterdata, guint flags, guint value)
871 if (btype == ROSTER_TYPE_GROUP) { 905 if (btype == ROSTER_TYPE_GROUP) {
872 const char *bname = buddy_getname(BUDDATA(buddy)); 906 const char *bname = buddy_getname(BUDDATA(buddy));
873 if ((bname) && (*bname)) 907 if ((bname) && (*bname))
874 list = g_slist_append(list, g_strdup(bname)); 908 list = g_slist_append(list, g_strdup(bname));
875 } 909 }
876 } else { // ROSTER_TYPE_USER (jid) 910 } else { // ROSTER_TYPE_USER (jid) (or agent, or chatroom...)
877 const char *bjid = buddy_getjid(BUDDATA(buddy)); 911 const char *bjid = buddy_getjid(BUDDATA(buddy));
878 if (bjid) 912 if (bjid)
879 list = g_slist_append(list, g_strdup(bjid)); 913 list = g_slist_append(list, g_strdup(bjid));
880 } 914 }
881 } 915 }