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