Mercurial > ~mikael > mcabber > hg
comparison mcabber/src/jabglue.c @ 987:f47e312560af
Improve JEP22 + JEP85 support
author | Mikael Berthe <mikael@lilotux.net> |
---|---|
date | Mon, 30 Oct 2006 20:18:00 +0100 |
parents | ed697234bd39 |
children | 6e2bfd1ffded |
comparison
equal
deleted
inserted
replaced
986:ed697234bd39 | 987:f47e312560af |
---|---|
414 void jb_send_msg(const char *jid, const char *text, int type, | 414 void jb_send_msg(const char *jid, const char *text, int type, |
415 const char *subject) | 415 const char *subject) |
416 { | 416 { |
417 xmlnode x; | 417 xmlnode x; |
418 gchar *strtype; | 418 gchar *strtype; |
419 #if defined JEP0022 || defined JEP0085 | |
420 xmlnode event; | |
421 char *rname, *barejid; | |
422 GSList *sl_buddy; | |
423 guint which_jep = 0; /* 0: none, 1: 85, 2: 22 */ | |
424 struct jep0085 *jep85 = NULL; | |
425 #endif | |
419 | 426 |
420 if (!online) return; | 427 if (!online) return; |
421 | 428 |
422 if (type == ROSTER_TYPE_ROOM) | 429 if (type == ROSTER_TYPE_ROOM) |
423 strtype = TMSG_GROUPCHAT; | 430 strtype = TMSG_GROUPCHAT; |
429 xmlnode y; | 436 xmlnode y; |
430 y = xmlnode_insert_tag(x, "subject"); | 437 y = xmlnode_insert_tag(x, "subject"); |
431 xmlnode_insert_cdata(y, subject, (unsigned) -1); | 438 xmlnode_insert_cdata(y, subject, (unsigned) -1); |
432 } | 439 } |
433 | 440 |
434 // TODO: insert event notifications request | 441 #if defined JEP0022 || defined JEP0085 |
435 #undef USE_JEP_85 | 442 rname = strchr(jid, JID_RESOURCE_SEPARATOR); |
436 #ifdef USE_JEP_85 | 443 barejid = jidtodisp(jid); |
437 #define NS_CHAT_STATES "http://jabber.org/features/chatstates" | 444 sl_buddy = roster_find(barejid, jidsearch, ROSTER_TYPE_USER); |
438 // JEP-85 | 445 g_free(barejid); |
439 xmlnode event = xmlnode_insert_tag(x, "composing"); | 446 |
440 xmlnode_put_attrib(event, "xmlns", NS_CHAT_STATES); | 447 // If we can get a resource name, we use it. Else we use NULL, |
441 #else | 448 // which hopefully will give us the most likely resource. |
442 // JEP-22 | 449 if (rname) |
443 xmlnode event = xmlnode_insert_tag(x, "x"); | 450 rname++; |
444 xmlnode_put_attrib(event, "xmlns", NS_EVENT); | 451 if (sl_buddy) |
445 xmlnode_insert_tag(event, "composing"); | 452 jep85 = buddy_resource_jep85(sl_buddy->data, rname); |
446 #endif | 453 #endif |
447 | 454 |
455 #ifdef JEP0085 | |
456 /* JEP-0085 5.1 | |
457 * "Until receiving a reply to the initial content message (or a standalone | |
458 * notification) from the Contact, the User MUST NOT send subsequent chat | |
459 * state notifications to the Contact." | |
460 * In our implementation support is initially "unknown", they it's "probed" | |
461 * and can become "ok". | |
462 */ | |
463 if (jep85 && (jep85->support == CHATSTATES_SUPPORT_OK || | |
464 jep85->support == CHATSTATES_SUPPORT_UNKNOWN)) { | |
465 event = xmlnode_insert_tag(x, "active"); | |
466 xmlnode_put_attrib(event, "xmlns", NS_CHATSTATES); | |
467 if (jep85->support == CHATSTATES_SUPPORT_UNKNOWN) | |
468 jep85->support = CHATSTATES_SUPPORT_PROBED; | |
469 else | |
470 which_jep = 1; | |
471 } | |
472 #endif | |
473 #ifdef JEP0022 | |
474 /* JEP-22 | |
475 * If the Contact supports JEP-0085, we do not use JEP-0022. | |
476 * If not, we try to fall back to JEP-0022. | |
477 */ | |
478 if (!which_jep) { | |
479 event = xmlnode_insert_tag(x, "x"); | |
480 xmlnode_put_attrib(event, "xmlns", NS_EVENT); | |
481 xmlnode_insert_tag(event, "composing"); | |
482 } | |
483 #endif | |
448 | 484 |
449 jab_send(jc, x); | 485 jab_send(jc, x); |
450 xmlnode_free(x); | 486 xmlnode_free(x); |
451 | 487 |
452 jb_reset_keepalive(); | 488 jb_reset_keepalive(); |
1037 xmlnode x; | 1073 xmlnode x; |
1038 char *p; | 1074 char *p; |
1039 | 1075 |
1040 x = xmlnode_get_firstchild(xmldata); | 1076 x = xmlnode_get_firstchild(xmldata); |
1041 for ( ; x; x = xmlnode_get_nextsibling(x)) { | 1077 for ( ; x; x = xmlnode_get_nextsibling(x)) { |
1042 if ((p = xmlnode_get_name(x)) && !strcmp(p, "x")) | 1078 if ((p = xmlnode_get_attrib(x, "xmlns")) && !strcmp(p, xmlns)) |
1043 if ((p = xmlnode_get_attrib(x, "xmlns")) && !strcmp(p, xmlns)) { | 1079 break; |
1044 break; | |
1045 } | |
1046 } | 1080 } |
1047 return x; | 1081 return x; |
1048 } | 1082 } |
1049 | 1083 |
1050 static time_t xml_get_timestamp(xmlnode xmldata) | 1084 static time_t xml_get_timestamp(xmlnode xmldata) |
1390 static void handle_packet_message(jconn conn, char *type, char *from, | 1424 static void handle_packet_message(jconn conn, char *type, char *from, |
1391 xmlnode xmldata) | 1425 xmlnode xmldata) |
1392 { | 1426 { |
1393 char *p, *r, *s; | 1427 char *p, *r, *s; |
1394 xmlnode x; | 1428 xmlnode x; |
1395 char *body=NULL; | 1429 char *body = NULL; |
1396 char *enc = NULL; | 1430 char *enc = NULL; |
1397 char *tmp = NULL; | 1431 char *tmp = NULL; |
1398 time_t timestamp = 0; | 1432 time_t timestamp = 0; |
1399 | 1433 |
1400 body = xmlnode_get_tag_data(xmldata, "body"); | 1434 body = xmlnode_get_tag_data(xmldata, "body"); |
1457 if (from && body) | 1491 if (from && body) |
1458 gotmessage(type, from, body, enc, timestamp); | 1492 gotmessage(type, from, body, enc, timestamp); |
1459 g_free(tmp); | 1493 g_free(tmp); |
1460 } | 1494 } |
1461 | 1495 |
1462 void handle_state_events(char* from, xmlnode xmldata) | 1496 void handle_state_events(char *from, xmlnode xmldata) |
1463 { | 1497 { |
1464 xmlnode x = NULL; | 1498 #if defined JEP0022 || defined JEP0085 |
1465 char *rname = strchr(from, JID_RESOURCE_SEPARATOR) + 1; | 1499 xmlnode state_ns; |
1466 char *jid = jidtodisp(from); | 1500 const char *body; |
1467 GSList *slist = roster_find(jid, jidsearch, ROSTER_TYPE_USER); | 1501 char *rname, *jid; |
1468 if (slist == NULL) return; | 1502 GSList *sl_buddy; |
1469 int jep85 = 0; | 1503 guint events; |
1470 | 1504 guint which_jep = 0; /* 0: none, 1: 85, 2: 22 */ |
1471 guint events = buddy_resource_getevents(slist->data, rname); | 1505 struct jep0022 *jep22; |
1472 | 1506 struct jep0085 *jep85; |
1473 x = xml_get_xmlns(xmldata, NS_EVENT); | 1507 |
1474 if (x == NULL) { | 1508 rname = strchr(from, JID_RESOURCE_SEPARATOR); |
1475 x = xmldata; | 1509 jid = jidtodisp(from); |
1476 jep85 = 1; | 1510 sl_buddy = roster_find(jid, jidsearch, ROSTER_TYPE_USER); |
1477 } | 1511 |
1478 | 1512 /* XXX Actually that's wrong, since it filters out server "offline" |
1479 xmlnode tag = xmlnode_get_tag(x, "composing"); | 1513 messages (for JEP-0022) */ |
1480 if (tag != NULL) { | 1514 if (!sl_buddy || !rname++) { |
1481 events |= ROSTER_EVENT_COMPOSING; | 1515 g_free(jid); |
1482 } else if (!jep85) { | 1516 return; |
1483 events &= ~ROSTER_EVENT_COMPOSING; | 1517 } |
1484 } | 1518 |
1485 | 1519 events = buddy_resource_getevents(sl_buddy->data, rname); |
1520 | |
1521 jep85 = buddy_resource_jep85(sl_buddy->data, rname); | |
1486 if (jep85) { | 1522 if (jep85) { |
1487 tag = xmlnode_get_tag(x, "paused"); | 1523 state_ns = xml_get_xmlns(xmldata, NS_CHATSTATES); |
1488 if (tag != NULL) { | 1524 if (state_ns) |
1525 which_jep = 1; | |
1526 } | |
1527 | |
1528 if (which_jep != 1) { /* Fall back to JEP-0022 */ | |
1529 jep22 = buddy_resource_jep22(sl_buddy->data, rname); | |
1530 if (jep22) { | |
1531 state_ns = xml_get_xmlns(xmldata, NS_EVENT); | |
1532 if (state_ns) | |
1533 which_jep = 2; | |
1534 } | |
1535 } | |
1536 | |
1537 if (!which_jep) { /* Sender does not use chat states */ | |
1538 g_free(jid); | |
1539 return; | |
1540 } | |
1541 | |
1542 body = xmlnode_get_tag_data(xmldata, "body"); | |
1543 | |
1544 if (which_jep == 1) { /* JEP-0085 */ | |
1545 const char *p; | |
1546 jep85->support = CHATSTATES_SUPPORT_OK; | |
1547 | |
1548 p = xmlnode_get_name(state_ns); | |
1549 if (!strcmp(p, "composing")) { | |
1550 jep85->last_state_rcvd = ROSTER_EVENT_COMPOSING; | |
1551 } else if (!strcmp(p, "active")) { | |
1552 jep85->last_state_rcvd = ROSTER_EVENT_ACTIVE; | |
1553 } else if (!strcmp(p, "paused")) { | |
1554 jep85->last_state_rcvd = ROSTER_EVENT_PAUSED; | |
1555 } else if (!strcmp(p, "inactive")) { | |
1556 jep85->last_state_rcvd = ROSTER_EVENT_INACTIVE; | |
1557 } else if (!strcmp(p, "gone")) { | |
1558 jep85->last_state_rcvd = ROSTER_EVENT_GONE; | |
1559 } | |
1560 | |
1561 if (jep85->last_state_rcvd == ROSTER_EVENT_COMPOSING) | |
1562 events = ROSTER_EVENT_COMPOSING; | |
1563 else | |
1564 events = ROSTER_EVENT_NONE; | |
1565 } else { /* JEP-0022 */ | |
1566 const char *msgid; | |
1567 jep22->support = CHATSTATES_SUPPORT_OK; | |
1568 jep22->last_state_rcvd = ROSTER_EVENT_NONE; | |
1569 | |
1570 msgid = xmlnode_get_attrib(xmldata, "id"); | |
1571 | |
1572 if (xmlnode_get_tag(state_ns, "composing")) { | |
1573 // Clear composing if the message contains a body | |
1574 if (body) | |
1489 events &= ~ROSTER_EVENT_COMPOSING; | 1575 events &= ~ROSTER_EVENT_COMPOSING; |
1490 } | 1576 else |
1491 } | 1577 events |= ROSTER_EVENT_COMPOSING; |
1492 | 1578 jep22->last_state_rcvd |= ROSTER_EVENT_COMPOSING; |
1493 // clear composing and set new message event | 1579 |
1494 // if message contains message body | 1580 } else { |
1495 if (xmlnode_get_tag_data(xmldata, "body") != NULL) { | 1581 events &= ~ROSTER_EVENT_COMPOSING; |
1496 events |= ROSTER_EVENT_MSG; | 1582 } |
1497 events &= ~ROSTER_EVENT_COMPOSING; | 1583 |
1498 } | 1584 if (xmlnode_get_tag(state_ns, "delivered")) |
1499 | 1585 jep22->last_state_rcvd |= ROSTER_EVENT_DELIVERED; |
1500 buddy_resource_setevents(slist->data, rname, events); | 1586 |
1501 | 1587 // Cache the message id |
1502 scr_UpdateBuddyWindow(); | 1588 g_free(jep22->last_msgid_rcvd); |
1503 scr_DrawRoster(); | 1589 if (msgid) |
1590 jep22->last_msgid_rcvd = g_strdup(msgid); | |
1591 else | |
1592 jep22->last_msgid_rcvd = NULL; | |
1593 } | |
1594 | |
1595 buddy_resource_setevents(sl_buddy->data, rname, events); | |
1596 | |
1597 update_roster = TRUE; | |
1504 | 1598 |
1505 g_free(jid); | 1599 g_free(jid); |
1600 #endif | |
1506 } | 1601 } |
1507 | 1602 |
1508 static void evscallback_subscription(eviqs *evp, guint evcontext) | 1603 static void evscallback_subscription(eviqs *evp, guint evcontext) |
1509 { | 1604 { |
1510 char *barejid; | 1605 char *barejid; |
1641 } | 1736 } |
1642 | 1737 |
1643 static void packethandler(jconn conn, jpacket packet) | 1738 static void packethandler(jconn conn, jpacket packet) |
1644 { | 1739 { |
1645 char *p; | 1740 char *p; |
1646 /* | |
1647 char *r, *s; | |
1648 const char *m; | |
1649 */ | |
1650 char *from=NULL, *type=NULL; | 1741 char *from=NULL, *type=NULL; |
1651 | 1742 |
1652 jb_reset_keepalive(); // reset keepalive timeout | 1743 jb_reset_keepalive(); // reset keepalive timeout |
1653 jpacket_reset(packet); | 1744 jpacket_reset(packet); |
1654 | 1745 |
1662 | 1753 |
1663 p = xmlnode_get_attrib(packet->x, "from"); | 1754 p = xmlnode_get_attrib(packet->x, "from"); |
1664 if (p) from = p; | 1755 if (p) from = p; |
1665 | 1756 |
1666 if (!from && packet->type != JPACKET_IQ) { | 1757 if (!from && packet->type != JPACKET_IQ) { |
1667 scr_LogPrint(LPRINT_LOGNORM, "Error in packet (could be UTF8-related)"); | 1758 scr_LogPrint(LPRINT_LOGNORM, "Error in stream packet"); |
1668 return; | 1759 return; |
1669 } | 1760 } |
1670 | 1761 |
1671 switch (packet->type) { | 1762 switch (packet->type) { |
1672 case JPACKET_MESSAGE: | 1763 case JPACKET_MESSAGE: |