comparison src/protocols/jabber/jabber.c @ 3340:f56b36347375

[gaim-migrate @ 3359] Added support for Jabber invisibility. committer: Tailor Script <tailor@pidgin.im>
author Jim Seymour <jseymour>
date Sat, 29 Jun 2002 12:13:25 +0000
parents e77fcff466a1
children 000546860da7
comparison
equal deleted inserted replaced
3339:afa68a8feee2 3340:f56b36347375
141 gboolean die; 141 gboolean die;
142 GHashTable *buddies; 142 GHashTable *buddies;
143 }; 143 };
144 144
145 /* 145 /*
146 * Used in jabber_buddy_data.invisible, below
147 */
148 #define JABBER_NOT_INVIS 0x00
149 #define JABBER_SERV_INVIS 0x01 /* Invisible set on server */
150 #define JABBER_BUD_INVIS 0x02 /* Invisible set on buddy */
151
152 /*
146 * It is *this* to which we point the buddy proto_data 153 * It is *this* to which we point the buddy proto_data
147 */ 154 */
148 struct jabber_buddy_data { 155 struct jabber_buddy_data {
149 GSList *resources; 156 GSList *resources;
150 char *error_msg; 157 char *error_msg;
158 unsigned invisible; /* We've set presence type invisible for this buddy */
151 }; 159 };
152 160
153 /* 161 /*
154 * per-resource info 162 * per-resource info
155 */ 163 */
971 gjab_send(gjc, x); 979 gjab_send(gjc, x);
972 xmlnode_free(x); 980 xmlnode_free(x);
973 } 981 }
974 } 982 }
975 983
984 /*
985 * Return pointer to jabber_buddy_data if buddy found. Create if necessary.
986 */
976 static struct jabber_buddy_data* jabber_find_buddy(struct gaim_connection *gc, char *buddy) 987 static struct jabber_buddy_data* jabber_find_buddy(struct gaim_connection *gc, char *buddy)
977 { 988 {
978 struct jabber_data *jd = gc->proto_data; 989 struct jabber_data *jd = gc->proto_data;
979 gpointer val; 990 gpointer val;
980 char *realwho; 991 char *realwho;
989 1000
990 } else { 1001 } else {
991 struct jabber_buddy_data *jbd = g_new0(struct jabber_buddy_data, 1); 1002 struct jabber_buddy_data *jbd = g_new0(struct jabber_buddy_data, 1);
992 jbd->error_msg = NULL; 1003 jbd->error_msg = NULL;
993 jbd->resources = NULL; 1004 jbd->resources = NULL;
1005 jbd->invisible = JABBER_NOT_INVIS;
994 g_hash_table_insert(jd->buddies, g_strdup(realwho), jbd); 1006 g_hash_table_insert(jd->buddies, g_strdup(realwho), jbd);
995 g_free(realwho); 1007 g_free(realwho);
996 return jbd; 1008 return jbd;
997 } 1009 }
998 } 1010 }
2394 /* 2406 /*
2395 * Remove a buddy item from the roster entirely 2407 * Remove a buddy item from the roster entirely
2396 */ 2408 */
2397 static void jabber_remove_buddy_roster_item(struct gaim_connection *gc, char *name) 2409 static void jabber_remove_buddy_roster_item(struct gaim_connection *gc, char *name)
2398 { 2410 {
2399 xmlnode x, y; 2411 gjconn gjc = ((struct jabber_data *)gc->proto_data)->gjc;
2400 char *realwho; 2412 char *realwho;
2413
2414 if((realwho = get_realwho(gjc, name, FALSE, NULL)) != NULL) {
2415 xmlnode x = jutil_iqnew(JPACKET__SET, NS_ROSTER);
2416 xmlnode y = xmlnode_insert_tag(xmlnode_get_tag(x, "query"), "item");
2417 xmlnode_put_attrib(y, "jid", realwho);
2418 xmlnode_put_attrib(y, "subscription", "remove");
2419 gjab_send(((struct jabber_data *)gc->proto_data)->gjc, x);
2420 g_free(realwho);
2421 xmlnode_free(x);
2422 }
2423 }
2424
2425 /*
2426 * Unsubscribe a buddy from our presence
2427 */
2428 static void jabber_unsubscribe_buddy_from_us(struct gaim_connection *gc, char *name)
2429 {
2401 gjconn gjc = ((struct jabber_data *)gc->proto_data)->gjc; 2430 gjconn gjc = ((struct jabber_data *)gc->proto_data)->gjc;
2402 2431 char *realwho;
2403 if(!name || (realwho = get_realwho(gjc, name, FALSE, NULL)) == NULL) 2432
2404 return; 2433 if((realwho = get_realwho(gjc, name, FALSE, NULL)) != NULL) {
2405 2434 xmlnode g = xmlnode_new_tag("presence");
2406 x = jutil_iqnew(JPACKET__SET, NS_ROSTER); 2435 xmlnode_put_attrib(g, "to", realwho);
2407 y = xmlnode_insert_tag(xmlnode_get_tag(x, "query"), "item"); 2436 xmlnode_put_attrib(g, "type", "unsubscribed");
2408 xmlnode_put_attrib(y, "jid", realwho); 2437 gjab_send(gjc, g);
2409 xmlnode_put_attrib(y, "subscription", "remove"); 2438 xmlnode_free(g);
2410 gjab_send(((struct jabber_data *)gc->proto_data)->gjc, x); 2439 }
2411 g_free(realwho); 2440 }
2412 xmlnode_free(x); 2441
2442 /*
2443 * Common code for setting ourselves invisible/visible to buddy
2444 */
2445 static void jabber_invisible_to_buddy_common(struct gaim_connection *gc, char *name, gboolean invisible)
2446 {
2447 gjconn gjc = ((struct jabber_data *)gc->proto_data)->gjc;
2448 char *realwho;
2449
2450 if((realwho = get_realwho(gjc, name, FALSE, NULL)) != NULL) {
2451 struct jabber_buddy_data *jbd = jabber_find_buddy(gc, realwho);
2452 xmlnode g = xmlnode_new_tag("presence");
2453
2454 xmlnode_put_attrib(g, "to", realwho);
2455
2456 if(invisible)
2457 xmlnode_put_attrib(g, "type", "invisible");
2458
2459 gjab_send(gjc, g);
2460
2461 g_free(realwho);
2462 xmlnode_free(g);
2463
2464 if(jbd) {
2465 if(invisible) {
2466 jbd->invisible |= JABBER_BUD_INVIS;
2467 } else {
2468 jbd->invisible &= ~JABBER_BUD_INVIS;
2469 }
2470 }
2471 }
2472 }
2473
2474 /*
2475 * Make ourselves temporarily invisible to a buddy
2476 */
2477 static void jabber_invisible_to_buddy(struct gaim_connection *gc, char *name)
2478 {
2479 jabber_invisible_to_buddy_common(gc, name, TRUE);
2480 }
2481
2482 /*
2483 * Make ourselves visible to a buddy
2484 */
2485 static void jabber_visible_to_buddy(struct gaim_connection *gc, char *name)
2486 {
2487 jabber_invisible_to_buddy_common(gc, name, FALSE);
2488 }
2489
2490 /*
2491 * Function used by the g_hash_table_foreach() in invisible_to_all_buddies() to
2492 * actually set the status.
2493 *
2494 * key is unused
2495 * value is the pointer to the jabber_buddy_data struct
2496 * data is gboolean: TRUE (invisible) or FALSE (not invisible)
2497 */
2498 static void set_invisible_to_buddy_status(gpointer key, gpointer val, gpointer data) {
2499 struct jabber_buddy_data *jbd = val;
2500 gboolean invisible = (gboolean) data;
2501
2502 if(jbd) {
2503 if(invisible) {
2504 jbd->invisible = JABBER_SERV_INVIS | JABBER_BUD_INVIS;
2505 } else {
2506 /*
2507 * If we've asserted server-level invisibility, cancelling
2508 * it removes explicit buddy invisibility settings too.
2509 */
2510 if(jbd->invisible & JABBER_SERV_INVIS)
2511 jbd->invisible = JABBER_NOT_INVIS;
2512 }
2513 }
2514 }
2515
2516 /*
2517 * Show we've set ourselves invisible/visible to all buddies on the server
2518 *
2519 * Used when we set server-wide invisibility so that individual buddy menu
2520 * entries show the proper option.
2521 */
2522 static void invisible_to_all_buddies(struct gaim_connection *gc, gboolean invisible)
2523 {
2524 struct jabber_data *jd = gc->proto_data;
2525
2526 if(jd->buddies != NULL)
2527 g_hash_table_foreach(jd->buddies, set_invisible_to_buddy_status, (gpointer) invisible);
2413 } 2528 }
2414 2529
2415 static char **jabber_list_icon(int uc) 2530 static char **jabber_list_icon(int uc)
2416 { 2531 {
2417 switch (uc) { 2532 switch (uc) {
2865 pbm->label = _("View Error Msg"); 2980 pbm->label = _("View Error Msg");
2866 pbm->callback = jabber_get_error_msg; 2981 pbm->callback = jabber_get_error_msg;
2867 pbm->gc = gc; 2982 pbm->gc = gc;
2868 m = g_list_append(m, pbm); 2983 m = g_list_append(m, pbm);
2869 } else { 2984 } else {
2985 gjconn gjc = ((struct jabber_data *)gc->proto_data)->gjc;
2986 char *realwho = get_realwho(gjc, who, FALSE, NULL);
2987 struct jabber_buddy_data *jbd = jabber_find_buddy(gc, realwho);
2988
2989 g_free(realwho);
2990
2870 pbm = g_new0(struct proto_buddy_menu, 1); 2991 pbm = g_new0(struct proto_buddy_menu, 1);
2871 pbm->label = _("Get Info"); 2992 pbm->label = _("Get Info");
2872 pbm->callback = jabber_get_info; 2993 pbm->callback = jabber_get_info;
2873 pbm->gc = gc; 2994 pbm->gc = gc;
2874 m = g_list_append(m, pbm); 2995 m = g_list_append(m, pbm);
2875 pbm = g_new0(struct proto_buddy_menu, 1); 2996 pbm = g_new0(struct proto_buddy_menu, 1);
2876 pbm->label = _("Get Away Msg"); 2997 pbm->label = _("Get Away Msg");
2877 pbm->callback = jabber_get_away_msg; 2998 pbm->callback = jabber_get_away_msg;
2878 pbm->gc = gc; 2999 pbm->gc = gc;
2879 m = g_list_append(m, pbm); 3000 m = g_list_append(m, pbm);
3001
3002 pbm = g_new0(struct proto_buddy_menu, 1);
3003 if(jbd && (jbd->invisible & JABBER_BUD_INVIS)) {
3004 pbm->label = _("Un-hide From");
3005 pbm->callback = jabber_visible_to_buddy;
3006 } else {
3007 pbm->label = _("Temporarily Hide From");
3008 pbm->callback = jabber_invisible_to_buddy;
3009 }
3010 pbm->gc = gc;
3011 m = g_list_append(m, pbm);
2880 } 3012 }
2881 3013
2882 return m; 3014 return m;
2883 } 3015 }
2884 3016
2892 pbm = g_new0(struct proto_buddy_menu, 1); 3024 pbm = g_new0(struct proto_buddy_menu, 1);
2893 pbm->label = _("Remove From Roster"); 3025 pbm->label = _("Remove From Roster");
2894 pbm->callback = jabber_remove_buddy_roster_item; 3026 pbm->callback = jabber_remove_buddy_roster_item;
2895 pbm->gc = gc; 3027 pbm->gc = gc;
2896 m = g_list_append(m, pbm); 3028 m = g_list_append(m, pbm);
3029 pbm = g_new0(struct proto_buddy_menu, 1);
3030 pbm->label = _("Cancel Presence Notification");
3031 pbm->callback = jabber_unsubscribe_buddy_from_us;
3032 pbm->gc = gc;
3033 m = g_list_append(m, pbm);
2897 3034
2898 return m; 3035 return m;
2899 } 3036 }
2900 3037
2901 static GList *jabber_away_states(struct gaim_connection *gc) { 3038 static GList *jabber_away_states(struct gaim_connection *gc) {
2904 m = g_list_append(m, "Online"); 3041 m = g_list_append(m, "Online");
2905 m = g_list_append(m, "Chatty"); 3042 m = g_list_append(m, "Chatty");
2906 m = g_list_append(m, "Away"); 3043 m = g_list_append(m, "Away");
2907 m = g_list_append(m, "Extended Away"); 3044 m = g_list_append(m, "Extended Away");
2908 m = g_list_append(m, "Do Not Disturb"); 3045 m = g_list_append(m, "Do Not Disturb");
3046 m = g_list_append(m, "Invisible");
2909 3047
2910 return m; 3048 return m;
2911 } 3049 }
2912 3050
2913 static void jabber_set_away(struct gaim_connection *gc, char *state, char *message) 3051 static void jabber_set_away(struct gaim_connection *gc, char *state, char *message)
2916 struct jabber_data *jd = gc->proto_data; 3054 struct jabber_data *jd = gc->proto_data;
2917 gjconn gjc = jd->gjc; 3055 gjconn gjc = jd->gjc;
2918 GSList *jcs; 3056 GSList *jcs;
2919 struct jabber_chat *jc; 3057 struct jabber_chat *jc;
2920 char *chatname; 3058 char *chatname;
3059 gboolean invisible = FALSE;
2921 3060
2922 gc->away = NULL; /* never send an auto-response */ 3061 gc->away = NULL; /* never send an auto-response */
2923 3062
2924 x = xmlnode_new_tag("presence"); 3063 x = xmlnode_new_tag("presence");
2925 3064
2953 gc->away = ""; 3092 gc->away = "";
2954 } else if (!strcmp(state, "Do Not Disturb")) { 3093 } else if (!strcmp(state, "Do Not Disturb")) {
2955 y = xmlnode_insert_tag(x, "show"); 3094 y = xmlnode_insert_tag(x, "show");
2956 xmlnode_insert_cdata(y, "dnd", -1); 3095 xmlnode_insert_cdata(y, "dnd", -1);
2957 gc->away = ""; 3096 gc->away = "";
3097 } else if (!strcmp(state, "Invisible")) {
3098 xmlnode_put_attrib(x, "type", "invisible");
3099 gc->away = "";
3100 invisible = TRUE;
2958 } 3101 }
2959 } 3102 }
2960 3103
2961 gjab_send(gjc, x); /* Notify "individuals" */ 3104 gjab_send(gjc, x); /* Notify "individuals" */
2962 3105
2975 g_free(chatname); 3118 g_free(chatname);
2976 } 3119 }
2977 } 3120 }
2978 3121
2979 xmlnode_free(x); 3122 xmlnode_free(x);
3123
3124 invisible_to_all_buddies(gc, invisible);
2980 } 3125 }
2981 3126
2982 static void jabber_set_idle(struct gaim_connection *gc, int idle) { 3127 static void jabber_set_idle(struct gaim_connection *gc, int idle) {
2983 struct jabber_data *jd = (struct jabber_data *)gc->proto_data; 3128 struct jabber_data *jd = (struct jabber_data *)gc->proto_data;
2984 debug_printf("jabber_set_idle: setting idle %i\n", idle); 3129 debug_printf("jabber_set_idle: setting idle %i\n", idle);