59
58
struct _GabbleConnectionPresencePrivate {
60
59
InvisibilityMethod invisibility_method;
61
LmMessageHandler *iq_list_push_cb;
60
guint iq_list_push_id;
62
61
gchar *invisible_list_name;
64
63
/* Mapping between status "show" strings, and shared statuses */
126
static LmHandlerResult set_xep0186_invisible_cb (GabbleConnection *conn,
127
LmMessage *sent_msg, LmMessage *reply_msg, GObject *obj,
125
static void set_xep0186_invisible_cb (GabbleConnection *conn,
126
WockyStanza *sent_msg, WockyStanza *reply_msg, GObject *obj,
128
127
gpointer user_data);
130
static LmHandlerResult activate_current_privacy_list_cb (
131
GabbleConnection *conn, LmMessage *sent_msg, LmMessage *reply_msg,
129
static void activate_current_privacy_list_cb (
130
GabbleConnection *conn, WockyStanza *sent_msg, WockyStanza *reply_msg,
132
131
GObject *obj, gpointer user_data);
134
133
static void setup_invisible_privacy_list_async (GabbleConnection *self,
135
134
GAsyncReadyCallback callback, gpointer user_data);
137
static LmHandlerResult iq_privacy_list_push_cb (LmMessageHandler *handler,
138
LmConnection *connection, LmMessage *message, gpointer user_data);
136
static gboolean iq_privacy_list_push_cb (
138
WockyStanza *message,
140
static LmHandlerResult verify_invisible_privacy_list_cb (
141
GabbleConnection *conn, LmMessage *sent_msg, LmMessage *reply_msg,
141
static void verify_invisible_privacy_list_cb (
142
GabbleConnection *conn, WockyStanza *sent_msg, WockyStanza *reply_msg,
142
143
GObject *obj, gpointer user_data);
144
145
static void toggle_presence_visibility_async (GabbleConnection *self,
512
513
g_object_unref (result);
515
else if (!_gabble_connection_send_with_reply (self, (LmMessage *) iq,
516
else if (!_gabble_connection_send_with_reply (self, (WockyStanza *) iq,
516
517
set_xep0186_invisible_cb, NULL, result, &error))
518
519
g_simple_async_result_set_from_error (result, error);
525
526
g_object_unref (iq);
528
static LmHandlerResult
529
530
set_xep0186_invisible_cb (GabbleConnection *conn,
531
LmMessage *reply_msg,
531
WockyStanza *sent_msg,
532
WockyStanza *reply_msg,
533
534
gpointer user_data)
535
536
GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data);
536
537
GError *error = NULL;
538
if (lm_message_get_sub_type (reply_msg) == LM_MESSAGE_SUB_TYPE_ERROR)
539
if (wocky_stanza_extract_errors (reply_msg, NULL, &error, NULL, NULL))
540
541
g_simple_async_result_set_error (result,
541
542
CONN_PRESENCE_ERROR, CONN_PRESENCE_ERROR_SET_INVISIBLE,
542
"error setting XEP-0186 (in)visiblity");
543
"error setting XEP-0186 (in)visiblity: %s", error->message);
544
g_clear_error (&error);
607
607
if (base->status == TP_CONNECTION_STATUS_CONNECTED && invisible)
609
609
if (!gabble_connection_send_presence (self,
610
LM_MESSAGE_SUB_TYPE_UNAVAILABLE, NULL, NULL, &error))
610
WOCKY_STANZA_SUB_TYPE_UNAVAILABLE, NULL, NULL, &error))
613
613
/* If we're still connecting and there's no list to be set, we don't
628
_gabble_connection_send_with_reply (self, (LmMessage *) iq,
628
_gabble_connection_send_with_reply (self, (WockyStanza *) iq,
629
629
activate_current_privacy_list_cb, NULL, result, &error);
641
641
g_object_unref (iq);
644
static LmHandlerResult
645
645
activate_current_privacy_list_cb (GabbleConnection *conn,
647
LmMessage *reply_msg,
646
WockyStanza *sent_msg,
647
WockyStanza *reply_msg,
649
649
gpointer user_data)
651
651
GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data);
652
652
GError *error = NULL;
654
if (lm_message_get_sub_type (reply_msg) == LM_MESSAGE_SUB_TYPE_ERROR)
654
if (wocky_stanza_extract_errors (reply_msg, NULL, &error, NULL, NULL))
656
656
g_simple_async_result_set_error (result,
657
657
CONN_PRESENCE_ERROR, CONN_PRESENCE_ERROR_SET_PRIVACY_LIST,
658
"error setting requested privacy list");
658
"error setting requested privacy list: %s", error->message);
659
g_clear_error (&error);
699
static LmHandlerResult
700
699
create_invisible_privacy_list_reply_cb (GabbleConnection *conn,
702
LmMessage *reply_msg,
700
WockyStanza *sent_msg,
701
WockyStanza *reply_msg,
704
703
gpointer user_data)
706
705
GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data);
706
GError *error = NULL;
708
if (lm_message_get_sub_type (reply_msg) == LM_MESSAGE_SUB_TYPE_ERROR)
708
if (wocky_stanza_extract_errors (reply_msg, NULL, &error, NULL, NULL))
710
GError *error = gabble_message_get_xmpp_error (reply_msg);
712
710
g_simple_async_result_set_from_error (result, error);
717
714
g_simple_async_result_complete_in_idle (result);
719
716
g_object_unref (result);
721
return LM_HANDLER_RESULT_REMOVE_MESSAGE;
747
742
DEBUG ("Creating '%s'", self->presence_priv->invisible_list_name);
749
if (!_gabble_connection_send_with_reply (self, (LmMessage *) iq,
744
if (!_gabble_connection_send_with_reply (self, (WockyStanza *) iq,
750
745
create_invisible_privacy_list_reply_cb, NULL, result, &error))
752
747
g_simple_async_result_set_from_error (result, error);
925
920
WockyNode *query_node = wocky_node_get_child_ns (
926
921
wocky_stanza_get_top_node (stanza), "query",
927
922
NS_GOOGLE_SHARED_STATUS);
930
924
if (store_shared_statuses (self, query_node))
931
925
emit_presences_changed_for_self (self);
933
result = wocky_stanza_build_iq_result (stanza, NULL);
935
wocky_porter_send (porter, result);
937
g_object_unref (result);
927
wocky_porter_acknowledge_iq (porter, stanza, NULL);
942
static LmHandlerResult
943
iq_privacy_list_push_cb (LmMessageHandler *handler,
944
LmConnection *connection,
933
iq_privacy_list_push_cb (
935
WockyStanza *message,
946
936
gpointer user_data)
948
938
GabbleConnection *conn = GABBLE_CONNECTION (user_data);
950
LmMessageNode *list_node, *iq;
939
WockyNode *list_node, *query_node, *iq;
951
940
const gchar *list_name;
953
if (lm_message_get_sub_type (message) != LM_MESSAGE_SUB_TYPE_SET)
954
return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
956
iq = lm_message_get_node (message);
957
list_node = lm_message_node_find_child (iq, "list");
959
if (!lm_message_node_get_child_with_namespace (iq, "query", NS_PRIVACY) ||
961
return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
963
result = lm_iq_message_make_result (message);
965
wocky_porter_send (wocky_session_get_porter (conn->session), result);
967
list_name = lm_message_node_get_attribute (list_node, "name");
942
wocky_porter_acknowledge_iq (wocky_session_get_porter (conn->session),
945
iq = wocky_stanza_get_top_node (message);
946
query_node = wocky_node_get_first_child (iq);
947
list_node = wocky_node_get_child (query_node, "list");
948
list_name = wocky_node_get_attribute (list_node, "name");
969
950
if (g_strcmp0 (list_name, conn->presence_priv->invisible_list_name) == 0)
970
951
setup_invisible_privacy_list_async (conn, NULL, NULL);
972
lm_message_unref (result);
974
return LM_HANDLER_RESULT_REMOVE_MESSAGE;
977
956
/**********************************************************************
1099
1078
wocky_implement_finish_void (self, get_shared_status_async);
1102
static LmHandlerResult
1103
1082
get_existing_privacy_lists_cb (GabbleConnection *conn,
1104
LmMessage *sent_msg,
1105
LmMessage *reply_msg,
1083
WockyStanza *sent_msg,
1084
WockyStanza *reply_msg,
1107
1086
gpointer user_data)
1109
1088
GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data);
1110
1089
WockyNode *query_node = wocky_node_get_child_ns (
1111
1090
wocky_stanza_get_top_node (reply_msg), "query", NS_PRIVACY);
1112
GError *error = gabble_message_get_xmpp_error (reply_msg);
1091
GError *error = NULL;
1093
if (wocky_stanza_extract_errors (reply_msg, NULL, &error, NULL, NULL))
1116
1095
DEBUG ("Error getting privacy lists: %s", error->message);
1141
1120
wocky_node_iter_init (&iter, query_node, "list", NULL);
1142
1121
while (wocky_node_iter_next (&iter, &list_node))
1144
const gchar *list_name = lm_message_node_get_attribute (list_node,
1123
const gchar *list_name = wocky_node_get_attribute (list_node,
1146
1125
const gchar *status_name;
1186
if (!_gabble_connection_send_with_reply (self, (LmMessage *) iq,
1163
if (!_gabble_connection_send_with_reply (self, (WockyStanza *) iq,
1187
1164
get_existing_privacy_lists_cb, NULL, result, &error))
1189
1166
g_simple_async_result_set_from_error (result, error);
1232
if (!_gabble_connection_send_with_reply (self, (LmMessage *) iq,
1209
if (!_gabble_connection_send_with_reply (self, (WockyStanza *) iq,
1233
1210
verify_invisible_privacy_list_cb, NULL, result, &error))
1235
1212
g_simple_async_result_set_from_error (result, error);
1253
1230
static gboolean
1254
is_valid_invisible_list (LmMessageNode *list_node)
1231
is_valid_invisible_list (WockyNode *list_node)
1256
LmMessageNode *top_node = NULL;
1233
WockyNode *top_node = NULL;
1258
1236
guint top_order = G_MAXUINT;
1260
for (i = node_iter (list_node); i; i = node_iter_next (i))
1238
wocky_node_iter_init (&i, list_node, "item", NULL);
1239
while (wocky_node_iter_next (&i, &child))
1262
LmMessageNode *child = node_iter_data (i);
1263
1241
const gchar *order_str;
1267
if (g_strcmp0 (lm_message_node_get_name (child), "item") != 0)
1270
order_str = lm_message_node_get_attribute (child, "order");
1245
order_str = wocky_node_get_attribute (child, "order");
1272
1247
if (order_str == NULL)
1287
1262
if (top_node != NULL)
1289
const gchar *value = lm_message_node_get_attribute (top_node, "value");
1290
const gchar *action = lm_message_node_get_attribute (top_node, "action");
1291
LmMessageNode *presence_out = lm_message_node_get_child (top_node,
1264
const gchar *value = wocky_node_get_attribute (top_node, "value");
1265
const gchar *action = wocky_node_get_attribute (top_node, "action");
1266
WockyNode *presence_out = wocky_node_get_child (top_node,
1292
1267
"presence-out");
1294
1269
return (value == NULL && g_strcmp0 (action, "deny") == 0 &&
1301
static LmHandlerResult
1302
1277
verify_invisible_privacy_list_cb (GabbleConnection *conn,
1303
LmMessage *sent_msg,
1304
LmMessage *reply_msg,
1278
WockyStanza *sent_msg,
1279
WockyStanza *reply_msg,
1306
1281
gpointer user_data)
1308
1283
GabbleConnectionPresencePrivate *priv = conn->presence_priv;
1309
LmMessageNode *node = lm_message_node_find_child
1310
(wocky_stanza_get_top_node (reply_msg), "list");
1311
GError *error = gabble_message_get_xmpp_error (reply_msg);
1313
if (lm_message_get_sub_type (reply_msg) == LM_MESSAGE_SUB_TYPE_RESULT &&
1284
WockyNode *query_node, *list_node = NULL;
1285
GError *error = NULL;
1287
query_node = wocky_node_get_child_ns (wocky_stanza_get_top_node (reply_msg),
1288
"query", NS_PRIVACY);
1290
if (query_node != NULL)
1291
list_node = wocky_node_get_child (query_node, "list");
1293
if (!wocky_stanza_extract_errors (reply_msg, NULL, &error, NULL, NULL) &&
1316
if (!is_valid_invisible_list (node))
1296
if (!is_valid_invisible_list (list_node))
1318
1298
g_free (priv->invisible_list_name);
1319
1299
priv->invisible_list_name = g_strdup ("invisible-gabble");
1331
1311
toggle_presence_visibility_async (conn,
1332
1312
toggle_initial_presence_visibility_cb, user_data);
1337
else if (error != NULL)
1339
if (error->code == XMPP_ERROR_ITEM_NOT_FOUND)
1341
create_invisible_privacy_list_async (conn,
1342
create_invisible_privacy_list_cb, user_data);
1347
disable_invisible_privacy_list (conn);
1349
toggle_presence_visibility_async (conn,
1350
toggle_initial_presence_visibility_cb, user_data);
1315
else if (error->code == WOCKY_XMPP_ERROR_ITEM_NOT_FOUND)
1317
create_invisible_privacy_list_async (conn,
1318
create_invisible_privacy_list_cb, user_data);
1322
disable_invisible_privacy_list (conn);
1324
toggle_presence_visibility_async (conn,
1325
toggle_initial_presence_visibility_cb, user_data);
1353
1328
if (error != NULL)
1354
1329
g_error_free (error);
1356
return LM_HANDLER_RESULT_REMOVE_MESSAGE;
1373
1346
g_error_free (error);
1376
if (priv->invisibility_method == INVISIBILITY_METHOD_PRIVACY)
1349
if (priv->invisibility_method == INVISIBILITY_METHOD_PRIVACY &&
1350
self->session != NULL)
1378
priv->iq_list_push_cb = lm_message_handler_new (iq_privacy_list_push_cb,
1381
lm_connection_register_message_handler (self->lmconn,
1382
priv->iq_list_push_cb, LM_MESSAGE_TYPE_IQ,
1383
LM_HANDLER_PRIORITY_NORMAL);
1352
priv->iq_list_push_id = wocky_c2s_porter_register_handler_from_server (
1353
WOCKY_C2S_PORTER (wocky_session_get_porter (self->session)),
1354
WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET,
1355
WOCKY_PORTER_HANDLER_PRIORITY_NORMAL,
1356
iq_privacy_list_push_cb, self,
1357
'(', "query", ':', NS_PRIVACY,
1386
1362
g_simple_async_result_complete_in_idle (external_result);
1593
1569
GabbleConnectionPresencePrivate *priv = self->presence_priv;
1594
1570
GabblePresence *presence = self->self_presence;
1595
1571
TpBaseConnection *base = (TpBaseConnection *) self;
1596
LmMessage *message = gabble_presence_as_message (presence, to);
1572
WockyStanza *message = gabble_presence_as_message (presence, to);
1599
1575
if (presence->status == GABBLE_PRESENCE_HIDDEN && to == NULL)
1601
1577
if (priv->invisibility_method == INVISIBILITY_METHOD_PRESENCE_INVISIBLE)
1602
lm_message_node_set_attribute (lm_message_get_node (message),
1578
wocky_node_set_attribute (wocky_stanza_get_top_node (message),
1603
1579
"type", "invisible");
1604
1580
/* FIXME: or if sending directed presence, should we add
1605
1581
* <show>away</show>? */
1610
1586
ret = _gabble_connection_send (self, message, error);
1612
lm_message_unref (message);
1588
g_object_unref (message);
1614
1590
/* FIXME: if sending broadcast presence, should we echo it to everyone we
1615
1591
* previously sent directed presence to? (Perhaps also GC them after a
2021
1997
wocky_porter_unregister_handler (porter, priv->iq_shared_status_cb);
2022
1998
priv->iq_shared_status_cb = 0;
2001
if (priv->iq_list_push_id != 0)
2003
wocky_porter_unregister_handler (porter, priv->iq_list_push_id);
2004
priv->iq_list_push_id = 0;
2036
2018
if (priv->shared_statuses != NULL)
2037
2019
g_hash_table_unref (priv->shared_statuses);
2039
if (priv->iq_list_push_cb != NULL)
2040
lm_message_handler_unref (priv->iq_list_push_cb);
2042
2021
g_slice_free (GabbleConnectionPresencePrivate, priv);
2044
2023
tp_presence_mixin_finalize ((GObject *) conn);