comparison mcabber/mcabber/xmpp.c @ 2165:db6ca1e1e082

Remove support for obsolete XEP 22
author franky
date Fri, 17 Oct 2014 22:33:19 +0200
parents 28ee843ddc02
children f51c341a9da5
comparison
equal deleted inserted replaced
2164:038c4d601011 2165:db6ca1e1e082
309 LmMessageSubType subtype; 309 LmMessageSubType subtype;
310 #ifdef HAVE_LIBOTR 310 #ifdef HAVE_LIBOTR
311 int otr_msg = 0; 311 int otr_msg = 0;
312 #endif 312 #endif
313 char *barejid; 313 char *barejid;
314 #if defined HAVE_GPGME || defined XEP0022 || defined XEP0085 314 #if defined HAVE_GPGME || defined XEP0085
315 char *rname; 315 char *rname;
316 GSList *sl_buddy; 316 GSList *sl_buddy;
317 #endif 317 #endif
318 #if defined XEP0022 || defined XEP0085 318 #ifdef XEP0085
319 LmMessageNode *event; 319 LmMessageNode *event;
320 struct xep0085 *xep85 = NULL; 320 struct xep0085 *xep85 = NULL;
321 #if defined XEP0022
322 guint use_xep85 = 0;
323 #endif
324 #endif 321 #endif
325 gchar *enc = NULL; 322 gchar *enc = NULL;
326 323
327 if (encrypted) 324 if (encrypted)
328 *encrypted = 0; 325 *encrypted = 0;
341 else 338 else
342 subtype = LM_MESSAGE_SUB_TYPE_CHAT; 339 subtype = LM_MESSAGE_SUB_TYPE_CHAT;
343 } 340 }
344 341
345 barejid = jidtodisp(fjid); 342 barejid = jidtodisp(fjid);
346 #if defined HAVE_GPGME || defined HAVE_LIBOTR || \ 343 #if defined HAVE_GPGME || defined HAVE_LIBOTR || defined XEP0085
347 defined XEP0022 || defined XEP0085
348 rname = strchr(fjid, JID_RESOURCE_SEPARATOR); 344 rname = strchr(fjid, JID_RESOURCE_SEPARATOR);
349 sl_buddy = roster_find(barejid, jidsearch, ROSTER_TYPE_USER); 345 sl_buddy = roster_find(barejid, jidsearch, ROSTER_TYPE_USER);
350 346
351 // If we can get a resource name, we use it. Else we use NULL, 347 // If we can get a resource name, we use it. Else we use NULL,
352 // which hopefully will give us the most likely resource. 348 // which hopefully will give us the most likely resource.
397 } 393 }
398 } 394 }
399 } 395 }
400 #endif // HAVE_GPGME 396 #endif // HAVE_GPGME
401 397
402 #endif // HAVE_GPGME || defined XEP0022 || defined XEP0085 398 #endif // HAVE_GPGME || defined XEP0085
403 399
404 x = lm_message_new_with_sub_type(fjid, LM_MESSAGE_TYPE_MESSAGE, subtype); 400 x = lm_message_new_with_sub_type(fjid, LM_MESSAGE_TYPE_MESSAGE, subtype);
405 lm_message_node_add_child(x->node, "body", 401 lm_message_node_add_child(x->node, "body",
406 enc ? "This message is PGP-encrypted." : text); 402 enc ? "This message is PGP-encrypted." : text);
407 403
431 "xmlns", NS_RECEIPTS); 427 "xmlns", NS_RECEIPTS);
432 *xep184 = g_strdup(lm_message_get_id(x)); 428 *xep184 = g_strdup(lm_message_get_id(x));
433 } 429 }
434 g_free(barejid); 430 g_free(barejid);
435 431
436 #if defined XEP0022 || defined XEP0085 432 #ifdef XEP0085
437 // If typing notifications are disabled, we can skip all this stuff... 433 // If typing notifications are disabled, we can skip all this stuff...
438 if (chatstates_disabled || type == ROSTER_TYPE_ROOM) 434 if (chatstates_disabled || type == ROSTER_TYPE_ROOM)
439 goto xmpp_send_msg_no_chatstates; 435 goto xmpp_send_msg_no_chatstates;
440 436
441 if (sl_buddy) 437 if (sl_buddy)
442 xep85 = buddy_resource_xep85(sl_buddy->data, rname); 438 xep85 = buddy_resource_xep85(sl_buddy->data, rname);
443 #endif 439
444
445 #ifdef XEP0085
446 /* XEP-0085 5.1 440 /* XEP-0085 5.1
447 * "Until receiving a reply to the initial content message (or a standalone 441 * "Until receiving a reply to the initial content message (or a standalone
448 * notification) from the Contact, the User MUST NOT send subsequent chat 442 * notification) from the Contact, the User MUST NOT send subsequent chat
449 * state notifications to the Contact." 443 * state notifications to the Contact."
450 * In our implementation support is initially "unknown", then it's "probed" 444 * In our implementation support is initially "unknown", then it's "probed"
454 xep85->support == CHATSTATES_SUPPORT_UNKNOWN)) { 448 xep85->support == CHATSTATES_SUPPORT_UNKNOWN)) {
455 event = lm_message_node_add_child(x->node, "active", NULL); 449 event = lm_message_node_add_child(x->node, "active", NULL);
456 lm_message_node_set_attribute(event, "xmlns", NS_CHATSTATES); 450 lm_message_node_set_attribute(event, "xmlns", NS_CHATSTATES);
457 if (xep85->support == CHATSTATES_SUPPORT_UNKNOWN) 451 if (xep85->support == CHATSTATES_SUPPORT_UNKNOWN)
458 xep85->support = CHATSTATES_SUPPORT_PROBED; 452 xep85->support = CHATSTATES_SUPPORT_PROBED;
459 #ifdef XEP0022
460 else
461 use_xep85 = 1;
462 #endif
463 xep85->last_state_sent = ROSTER_EVENT_ACTIVE; 453 xep85->last_state_sent = ROSTER_EVENT_ACTIVE;
464 }
465 #endif
466 #ifdef XEP0022
467 /* XEP-22
468 * If the Contact supports XEP-0085, we do not use XEP-0022.
469 * If not, we try to fall back to XEP-0022.
470 */
471 if (!use_xep85) {
472 struct xep0022 *xep22 = NULL;
473 event = lm_message_node_add_child(x->node, "x", NULL);
474 lm_message_node_set_attribute(event, "xmlns", NS_EVENT);
475 lm_message_node_add_child(event, "composing", NULL);
476
477 if (sl_buddy)
478 xep22 = buddy_resource_xep22(sl_buddy->data, rname);
479 if (xep22)
480 xep22->last_state_sent = ROSTER_EVENT_ACTIVE;
481
482 // An id is mandatory when using XEP-0022.
483 if (text || subject) {
484 const gchar *msgid = lm_message_get_id(x);
485 // Let's update last_msgid_sent
486 if (xep22) {
487 g_free(xep22->last_msgid_sent);
488 xep22->last_msgid_sent = g_strdup(msgid);
489 }
490 }
491 } 454 }
492 #endif 455 #endif
493 456
494 xmpp_send_msg_no_chatstates: 457 xmpp_send_msg_no_chatstates:
495 #ifdef WITH_DEPRECATED_STATUS_INVISIBLE 458 #ifdef WITH_DEPRECATED_STATUS_INVISIBLE
557 520
558 g_free(fjid); 521 g_free(fjid);
559 } 522 }
560 #endif 523 #endif
561 524
562 #ifdef XEP0022
563 // xmpp_send_xep22_event()
564 // Send a XEP-22 message event (delivered, composing...).
565 static void xmpp_send_xep22_event(const char *fjid, guint type)
566 {
567 LmMessage *x;
568 LmMessageNode *event;
569 const char *msgid;
570 char *rname, *barejid;
571 GSList *sl_buddy;
572 struct xep0022 *xep22 = NULL;
573 guint xep22_state;
574
575 if (!xmpp_is_online())
576 return;
577
578 rname = strchr(fjid, JID_RESOURCE_SEPARATOR);
579 barejid = jidtodisp(fjid);
580 sl_buddy = roster_find(barejid, jidsearch, ROSTER_TYPE_USER);
581 g_free(barejid);
582
583 // If we can get a resource name, we use it. Else we use NULL,
584 // which hopefully will give us the most likely resource.
585 if (rname)
586 rname++;
587 if (sl_buddy)
588 xep22 = buddy_resource_xep22(sl_buddy->data, rname);
589
590 if (!xep22)
591 return; // XXX Maybe we could try harder (other resources?)
592
593 msgid = xep22->last_msgid_rcvd;
594
595 // For composing events (composing, active, inactive, paused...),
596 // XEP22 only has 2 states; we'll use composing and active.
597 if (type == ROSTER_EVENT_COMPOSING)
598 xep22_state = ROSTER_EVENT_COMPOSING;
599 else if (type == ROSTER_EVENT_ACTIVE ||
600 type == ROSTER_EVENT_PAUSED)
601 xep22_state = ROSTER_EVENT_ACTIVE;
602 else
603 xep22_state = 0; // ROSTER_EVENT_NONE
604
605 if (xep22_state) {
606 // Do not re-send a same event
607 if (xep22_state == xep22->last_state_sent)
608 return;
609 xep22->last_state_sent = xep22_state;
610 }
611
612 x = lm_message_new_with_sub_type(fjid, LM_MESSAGE_TYPE_MESSAGE,
613 LM_MESSAGE_SUB_TYPE_CHAT);
614
615 event = lm_message_node_add_child(x->node, "x", NULL);
616 lm_message_node_set_attribute(event, "xmlns", NS_EVENT);
617 if (type == ROSTER_EVENT_DELIVERED)
618 lm_message_node_add_child(event, "delivered", NULL);
619 else if (type == ROSTER_EVENT_COMPOSING)
620 lm_message_node_add_child(event, "composing", NULL);
621 lm_message_node_add_child(event, "id", msgid);
622
623 lm_connection_send(lconnection, x, NULL);
624 lm_message_unref(x);
625 }
626 #endif
627
628 // xmpp_send_chatstate(buddy, state) 525 // xmpp_send_chatstate(buddy, state)
629 // Send a chatstate or event (XEP-22/85) according to the buddy's capabilities. 526 // Send a chatstate or event (XEP-22/85) according to the buddy's capabilities.
630 // The message is sent to one of the resources with the highest priority. 527 // The message is sent to one of the resources with the highest priority.
631 #if defined XEP0022 || defined XEP0085 528 #if defined XEP0085
632 void xmpp_send_chatstate(gpointer buddy, guint chatstate) 529 void xmpp_send_chatstate(gpointer buddy, guint chatstate)
633 { 530 {
634 const char *bjid; 531 const char *bjid;
635 const char *activeres; 532 const char *activeres;
636 #ifdef XEP0085
637 GSList *resources, *p_res, *p_next; 533 GSList *resources, *p_res, *p_next;
638 struct xep0085 *xep85 = NULL; 534 struct xep0085 *xep85 = NULL;
639 #endif
640 #ifdef XEP0022
641 struct xep0022 *xep22;
642 #endif
643 535
644 bjid = buddy_getjid(buddy); 536 bjid = buddy_getjid(buddy);
645 if (!bjid) return; 537 if (!bjid) return;
646 activeres = buddy_getactiveresource(buddy); 538 activeres = buddy_getactiveresource(buddy);
647 539
648 #ifdef XEP0085
649 /* Send the chatstate to the last resource (which should have the highest 540 /* Send the chatstate to the last resource (which should have the highest
650 priority). 541 priority).
651 If chatstate is "active", send an "active" state to all resources 542 If chatstate is "active", send an "active" state to all resources
652 which do not curently have this state. 543 which do not curently have this state.
653 */ 544 */
669 g_slist_free(resources); 560 g_slist_free(resources);
670 // If the last resource had chatstates support when can return now, 561 // If the last resource had chatstates support when can return now,
671 // we don't want to send a XEP22 event. 562 // we don't want to send a XEP22 event.
672 if (xep85 && xep85->support == CHATSTATES_SUPPORT_OK) 563 if (xep85 && xep85->support == CHATSTATES_SUPPORT_OK)
673 return; 564 return;
674 #endif
675 #ifdef XEP0022
676 xep22 = buddy_resource_xep22(buddy, activeres);
677 if (xep22 && xep22->support == CHATSTATES_SUPPORT_OK) {
678 xmpp_send_xep22_event(bjid, chatstate);
679 }
680 #endif
681 } 565 }
682 #endif 566 #endif
683 567
684 568
685 // chatstates_reset_probed(fulljid) 569 // chatstates_reset_probed(fulljid)
686 // If the XEP has been probed for this contact, set it back to unknown so 570 // If the XEP has been probed for this contact, set it back to unknown so
687 // that we probe it again. The parameter must be a full jid (w/ resource). 571 // that we probe it again. The parameter must be a full jid (w/ resource).
688 #if defined XEP0022 || defined XEP0085 572 #if defined XEP0085
689 static void chatstates_reset_probed(const char *fulljid) 573 static void chatstates_reset_probed(const char *fulljid)
690 { 574 {
691 char *rname, *barejid; 575 char *rname, *barejid;
692 GSList *sl_buddy; 576 GSList *sl_buddy;
693 struct xep0085 *xep85; 577 struct xep0085 *xep85;
694 struct xep0022 *xep22;
695 578
696 rname = strchr(fulljid, JID_RESOURCE_SEPARATOR); 579 rname = strchr(fulljid, JID_RESOURCE_SEPARATOR);
697 if (!rname++) 580 if (!rname++)
698 return; 581 return;
699 582
703 586
704 if (!sl_buddy) 587 if (!sl_buddy)
705 return; 588 return;
706 589
707 xep85 = buddy_resource_xep85(sl_buddy->data, rname); 590 xep85 = buddy_resource_xep85(sl_buddy->data, rname);
708 xep22 = buddy_resource_xep22(sl_buddy->data, rname);
709 591
710 if (xep85 && xep85->support == CHATSTATES_SUPPORT_PROBED) 592 if (xep85 && xep85->support == CHATSTATES_SUPPORT_PROBED)
711 xep85->support = CHATSTATES_SUPPORT_UNKNOWN; 593 xep85->support = CHATSTATES_SUPPORT_UNKNOWN;
712 if (xep22 && xep22->support == CHATSTATES_SUPPORT_PROBED)
713 xep22->support = CHATSTATES_SUPPORT_UNKNOWN;
714 } 594 }
715 #endif 595 #endif
716 596
717 #ifdef HAVE_GPGME 597 #ifdef HAVE_GPGME
718 // keys_mismatch(key, expectedkey) 598 // keys_mismatch(key, expectedkey)
972 xmpp_setstatus(offline, NULL, mystatusmsg, TRUE); 852 xmpp_setstatus(offline, NULL, mystatusmsg, TRUE);
973 } 853 }
974 854
975 static void handle_state_events(const char *from, LmMessageNode *node) 855 static void handle_state_events(const char *from, LmMessageNode *node)
976 { 856 {
977 #if defined XEP0022 || defined XEP0085 857 #if defined XEP0085
978 LmMessageNode *state_ns = NULL; 858 LmMessageNode *state_ns = NULL;
979 char *rname, *bjid; 859 char *rname, *bjid;
980 GSList *sl_buddy; 860 GSList *sl_buddy;
981 guint events;
982 struct xep0022 *xep22 = NULL;
983 struct xep0085 *xep85 = NULL; 861 struct xep0085 *xep85 = NULL;
984 enum {
985 XEP_none,
986 XEP_85,
987 XEP_22
988 } which_xep = XEP_none;
989 862
990 rname = strchr(from, JID_RESOURCE_SEPARATOR); 863 rname = strchr(from, JID_RESOURCE_SEPARATOR);
991 if (rname) 864 if (rname)
992 ++rname; 865 ++rname;
993 else 866 else
994 rname = (char *)from + strlen(from); 867 rname = (char *)from + strlen(from);
995 bjid = jidtodisp(from); 868 bjid = jidtodisp(from);
996 sl_buddy = roster_find(bjid, jidsearch, ROSTER_TYPE_USER); 869 sl_buddy = roster_find(bjid, jidsearch, ROSTER_TYPE_USER);
997 g_free(bjid); 870 g_free(bjid);
998 871
999 /* XXX Actually that's wrong, since it filters out server "offline"
1000 messages (for XEP-0022). This XEP is (almost) deprecated so
1001 we don't really care. */
1002 if (!sl_buddy) { 872 if (!sl_buddy) {
1003 return; 873 return;
1004 } 874 }
1005 875
1006 /* Let's see chich XEP the contact uses. If possible, we'll use 876 /* Let's see whether the contact supports XEP0085 */
1007 XEP-85, if not we'll look for XEP-22 support. */
1008 events = buddy_resource_getevents(sl_buddy->data, rname);
1009
1010 xep85 = buddy_resource_xep85(sl_buddy->data, rname); 877 xep85 = buddy_resource_xep85(sl_buddy->data, rname);
1011 if (xep85) { 878 if (xep85)
1012 state_ns = lm_message_node_find_xmlns(node, NS_CHATSTATES); 879 state_ns = lm_message_node_find_xmlns(node, NS_CHATSTATES);
1013 if (state_ns) 880
1014 which_xep = XEP_85; 881 if (!state_ns) { /* Sender does not use chat states */
1015 } 882 return;
1016 883 }
1017 if (which_xep != XEP_85) { /* Fall back to XEP-0022 */ 884
1018 xep22 = buddy_resource_xep22(sl_buddy->data, rname); 885 xep85->support = CHATSTATES_SUPPORT_OK;
1019 if (xep22) { 886
1020 state_ns = lm_message_node_find_xmlns(node, NS_EVENT); 887 if (!strcmp(state_ns->name, "composing")) {
1021 if (state_ns) 888 xep85->last_state_rcvd = ROSTER_EVENT_COMPOSING;
1022 which_xep = XEP_22; 889 } else if (!strcmp(state_ns->name, "active")) {
1023 } 890 xep85->last_state_rcvd = ROSTER_EVENT_ACTIVE;
1024 } 891 } else if (!strcmp(state_ns->name, "paused")) {
1025 892 xep85->last_state_rcvd = ROSTER_EVENT_PAUSED;
1026 if (!which_xep) { /* Sender does not use chat states */ 893 } else if (!strcmp(state_ns->name, "inactive")) {
1027 return; 894 xep85->last_state_rcvd = ROSTER_EVENT_INACTIVE;
1028 } 895 } else if (!strcmp(state_ns->name, "gone")) {
1029 896 xep85->last_state_rcvd = ROSTER_EVENT_GONE;
1030 if (which_xep == XEP_85) { /* XEP-0085 */ 897 }
1031 xep85->support = CHATSTATES_SUPPORT_OK; 898
1032 899 buddy_resource_setevents(sl_buddy->data, rname, xep85->last_state_rcvd);
1033 if (!strcmp(state_ns->name, "composing")) {
1034 xep85->last_state_rcvd = ROSTER_EVENT_COMPOSING;
1035 } else if (!strcmp(state_ns->name, "active")) {
1036 xep85->last_state_rcvd = ROSTER_EVENT_ACTIVE;
1037 } else if (!strcmp(state_ns->name, "paused")) {
1038 xep85->last_state_rcvd = ROSTER_EVENT_PAUSED;
1039 } else if (!strcmp(state_ns->name, "inactive")) {
1040 xep85->last_state_rcvd = ROSTER_EVENT_INACTIVE;
1041 } else if (!strcmp(state_ns->name, "gone")) {
1042 xep85->last_state_rcvd = ROSTER_EVENT_GONE;
1043 }
1044 events = xep85->last_state_rcvd;
1045 } else { /* XEP-0022 */
1046 #ifdef XEP0022
1047 const char *body = lm_message_node_get_child_value(node, "body");
1048 const char *msgid;
1049 xep22->support = CHATSTATES_SUPPORT_OK;
1050 xep22->last_state_rcvd = ROSTER_EVENT_NONE;
1051
1052 msgid = lm_message_node_get_attribute(node, "id");
1053
1054 if (lm_message_node_get_child(state_ns, "composing")) {
1055 // Clear composing if the message contains a body
1056 if (body)
1057 events &= ~ROSTER_EVENT_COMPOSING;
1058 else
1059 events |= ROSTER_EVENT_COMPOSING;
1060 xep22->last_state_rcvd |= ROSTER_EVENT_COMPOSING;
1061
1062 } else {
1063 events &= ~ROSTER_EVENT_COMPOSING;
1064 }
1065
1066 // Cache the message id
1067 g_free(xep22->last_msgid_rcvd);
1068 if (msgid)
1069 xep22->last_msgid_rcvd = g_strdup(msgid);
1070 else
1071 xep22->last_msgid_rcvd = NULL;
1072
1073 if (lm_message_node_get_child(state_ns, "delivered")) {
1074 xep22->last_state_rcvd |= ROSTER_EVENT_DELIVERED;
1075
1076 // Do we have to send back an ACK?
1077 if (body)
1078 xmpp_send_xep22_event(from, ROSTER_EVENT_DELIVERED);
1079 }
1080 #endif
1081 }
1082
1083 buddy_resource_setevents(sl_buddy->data, rname, events);
1084
1085 update_roster = TRUE; 900 update_roster = TRUE;
1086 #endif 901 #endif
1087 } 902 }
1088 903
1089 static void gotmessage(LmMessageSubType type, const char *from, 904 static void gotmessage(LmMessageSubType type, const char *from,
1273 } 1088 }
1274 1089
1275 if (mstype == LM_MESSAGE_SUB_TYPE_ERROR) { 1090 if (mstype == LM_MESSAGE_SUB_TYPE_ERROR) {
1276 x = lm_message_node_get_child(m->node, "error"); 1091 x = lm_message_node_get_child(m->node, "error");
1277 display_server_error(x, from); 1092 display_server_error(x, from);
1278 #if defined XEP0022 || defined XEP0085 1093 #ifdef XEP0085
1279 // If the XEP85/22 support is probed, set it back to unknown so that 1094 // If the XEP85/22 support is probed, set it back to unknown so that
1280 // we probe it again. 1095 // we probe it again.
1281 chatstates_reset_probed(from); 1096 chatstates_reset_probed(from);
1282 #endif 1097 #endif
1283 } else { 1098 } else {