Mercurial > ~mikael > mcabber > hg
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 } |