Mercurial > pidgin.yaz
comparison libpurple/protocols/jabber/jabber.c @ 25987:c4fd9222dda1
propagate from branch 'im.pidgin.pidgin' (head 303af74a38e7b313d4fb0be4d4054a16cb13d819)
to branch 'im.pidgin.cpw.darkrain42.xmpp.bosh' (head 650d82b8a5f0c8860804dd8004cd54badea48e1e)
author | Paul Aurich <paul@darkrain42.org> |
---|---|
date | Sat, 07 Mar 2009 01:59:40 +0000 |
parents | 5f9a24d1c25e 97a4d71e0c3d |
children | 035ba9355361 |
comparison
equal
deleted
inserted
replaced
25464:0e93bbb7f5ca | 25987:c4fd9222dda1 |
---|---|
40 #include "version.h" | 40 #include "version.h" |
41 #include "xmlnode.h" | 41 #include "xmlnode.h" |
42 | 42 |
43 #include "auth.h" | 43 #include "auth.h" |
44 #include "buddy.h" | 44 #include "buddy.h" |
45 #include "caps.h" | |
45 #include "chat.h" | 46 #include "chat.h" |
46 #include "data.h" | 47 #include "data.h" |
47 #include "disco.h" | 48 #include "disco.h" |
48 #include "google.h" | 49 #include "google.h" |
49 #include "iq.h" | 50 #include "iq.h" |
62 | 63 |
63 #define JABBER_CONNECT_STEPS (js->gsc ? 9 : 5) | 64 #define JABBER_CONNECT_STEPS (js->gsc ? 9 : 5) |
64 | 65 |
65 static PurplePlugin *my_protocol = NULL; | 66 static PurplePlugin *my_protocol = NULL; |
66 GList *jabber_features = NULL; | 67 GList *jabber_features = NULL; |
68 GList *jabber_identities = NULL; | |
67 | 69 |
68 static void jabber_unregister_account_cb(JabberStream *js); | 70 static void jabber_unregister_account_cb(JabberStream *js); |
69 static void try_srv_connect(JabberStream *js); | 71 static void try_srv_connect(JabberStream *js); |
70 | 72 |
71 static void jabber_stream_init(JabberStream *js) | 73 static void jabber_stream_init(JabberStream *js) |
87 static void | 89 static void |
88 jabber_session_initialized_cb(JabberStream *js, xmlnode *packet, gpointer data) | 90 jabber_session_initialized_cb(JabberStream *js, xmlnode *packet, gpointer data) |
89 { | 91 { |
90 const char *type = xmlnode_get_attrib(packet, "type"); | 92 const char *type = xmlnode_get_attrib(packet, "type"); |
91 if(type && !strcmp(type, "result")) { | 93 if(type && !strcmp(type, "result")) { |
92 jabber_stream_set_state(js, JABBER_STREAM_CONNECTED); | 94 jabber_disco_items_server(js); |
93 if(js->unregistration) | 95 if(js->unregistration) |
94 jabber_unregister_account_cb(js); | 96 jabber_unregister_account_cb(js); |
95 } else { | 97 } else { |
96 purple_connection_error_reason (js->gc, | 98 purple_connection_error_reason (js->gc, |
97 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, | 99 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, |
178 dot = '\0'; | 180 dot = '\0'; |
179 | 181 |
180 return purple_strreplace(input, "__HOSTNAME__", hostname); | 182 return purple_strreplace(input, "__HOSTNAME__", hostname); |
181 } | 183 } |
182 | 184 |
183 static void jabber_stream_features_parse(JabberStream *js, xmlnode *packet) | 185 void jabber_stream_features_parse(JabberStream *js, xmlnode *packet) |
184 { | 186 { |
185 if(xmlnode_get_child(packet, "starttls")) { | 187 if(xmlnode_get_child(packet, "starttls")) { |
186 if(jabber_process_starttls(js, packet)) | 188 if(jabber_process_starttls(js, packet)) |
187 | 189 |
188 return; | 190 return; |
418 } | 420 } |
419 return; | 421 return; |
420 } | 422 } |
421 #endif | 423 #endif |
422 | 424 |
423 do_jabber_send_raw(js, data, len); | 425 if (len == -1) |
426 len = strlen(data); | |
427 | |
428 if (js->use_bosh) | |
429 jabber_bosh_connection_send_raw(js->bosh, data, len); | |
430 else | |
431 do_jabber_send_raw(js, data, len); | |
424 } | 432 } |
425 | 433 |
426 int jabber_prpl_send_raw(PurpleConnection *gc, const char *buf, int len) | 434 int jabber_prpl_send_raw(PurpleConnection *gc, const char *buf, int len) |
427 { | 435 { |
428 JabberStream *js = (JabberStream*)gc->proto_data; | 436 JabberStream *js = (JabberStream*)gc->proto_data; |
439 | 447 |
440 /* if we get NULL back, we're done processing */ | 448 /* if we get NULL back, we're done processing */ |
441 if(NULL == packet) | 449 if(NULL == packet) |
442 return; | 450 return; |
443 | 451 |
444 txt = xmlnode_to_str(packet, &len); | 452 if (js->use_bosh) |
445 jabber_send_raw(js, txt, len); | 453 jabber_bosh_connection_send(js->bosh, packet); |
446 g_free(txt); | 454 else { |
455 txt = xmlnode_to_str(packet, &len); | |
456 jabber_send_raw(js, txt, len); | |
457 g_free(txt); | |
458 } | |
447 } | 459 } |
448 | 460 |
449 static void jabber_pong_cb(JabberStream *js, xmlnode *packet, gpointer unused) | 461 static void jabber_pong_cb(JabberStream *js, xmlnode *packet, gpointer unused) |
450 { | 462 { |
451 purple_timeout_remove(js->keepalive_timeout); | 463 purple_timeout_remove(js->keepalive_timeout); |
581 | 593 |
582 /* Tell the app that we're doing encryption */ | 594 /* Tell the app that we're doing encryption */ |
583 jabber_stream_set_state(js, JABBER_STREAM_INITIALIZING_ENCRYPTION); | 595 jabber_stream_set_state(js, JABBER_STREAM_INITIALIZING_ENCRYPTION); |
584 } | 596 } |
585 | 597 |
598 static void | |
599 jabber_bosh_login_callback(PurpleBOSHConnection *conn) | |
600 { | |
601 purple_debug_info("jabber","YAY...BOSH connection established.\n"); | |
602 } | |
603 | |
604 static void | |
605 txt_resolved_cb(PurpleTxtResponse *resp, int results, gpointer data) | |
606 { | |
607 JabberStream *js = data; | |
608 int n; | |
609 | |
610 js->srv_query_data = NULL; | |
611 | |
612 if (results == 0) { | |
613 gchar *tmp; | |
614 tmp = g_strdup_printf(_("Could not find alternative XMPP connection methods after failing to connect directly.\n")); | |
615 purple_connection_error_reason (js->gc, | |
616 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); | |
617 g_free(tmp); | |
618 return; | |
619 } | |
620 | |
621 for (n = 0; n < results; n++) { | |
622 gchar **token; | |
623 token = g_strsplit(resp[n].content, "=", 2); | |
624 if (!strcmp(token[0], "_xmpp-client-xbosh")) { | |
625 purple_debug_info("jabber","Found alternative connection method using %s at %s.\n", token[0], token[1]); | |
626 js->bosh = jabber_bosh_connection_init(js, token[1]); | |
627 js->use_bosh = TRUE; | |
628 g_strfreev(token); | |
629 break; | |
630 } | |
631 g_strfreev(token); | |
632 } | |
633 if (js->bosh) { | |
634 jabber_bosh_connection_connect(js->bosh); | |
635 } else { | |
636 purple_debug_info("jabber","Didn't find an alternative connection method.\n"); | |
637 } | |
638 } | |
586 | 639 |
587 static void | 640 static void |
588 jabber_login_callback(gpointer data, gint source, const gchar *error) | 641 jabber_login_callback(gpointer data, gint source, const gchar *error) |
589 { | 642 { |
590 PurpleConnection *gc = data; | 643 PurpleConnection *gc = data; |
593 if (source < 0) { | 646 if (source < 0) { |
594 if (js->srv_rec != NULL) { | 647 if (js->srv_rec != NULL) { |
595 purple_debug_error("jabber", "Unable to connect to server: %s. Trying next SRV record.\n", error); | 648 purple_debug_error("jabber", "Unable to connect to server: %s. Trying next SRV record.\n", error); |
596 try_srv_connect(js); | 649 try_srv_connect(js); |
597 } else { | 650 } else { |
598 gchar *tmp; | 651 purple_debug_info("jabber","Couldn't connect directly to %s. Trying to find alternative connection methods, like BOSH.\n", js->user->domain); |
599 tmp = g_strdup_printf(_("Could not establish a connection with the server:\n%s"), | 652 js->srv_query_data = purple_txt_resolve("_xmppconnect", js->user->domain, txt_resolved_cb, js); |
600 error); | |
601 purple_connection_error_reason(gc, | |
602 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); | |
603 g_free(tmp); | |
604 } | 653 } |
605 return; | 654 return; |
606 } | 655 } |
607 | 656 |
608 g_free(js->srv_rec); | 657 g_free(js->srv_rec); |
726 js->user = jabber_id_new(purple_account_get_username(account)); | 775 js->user = jabber_id_new(purple_account_get_username(account)); |
727 js->next_id = g_random_int(); | 776 js->next_id = g_random_int(); |
728 js->write_buffer = purple_circ_buffer_new(512); | 777 js->write_buffer = purple_circ_buffer_new(512); |
729 js->old_length = 0; | 778 js->old_length = 0; |
730 js->keepalive_timeout = -1; | 779 js->keepalive_timeout = -1; |
731 js->certificate_CN = g_strdup(connect_server[0] ? connect_server : js->user ? js->user->domain : NULL); | |
732 | 780 |
733 if(!js->user) { | 781 if(!js->user) { |
734 purple_connection_error_reason (gc, | 782 purple_connection_error_reason (gc, |
735 PURPLE_CONNECTION_ERROR_INVALID_SETTINGS, | 783 PURPLE_CONNECTION_ERROR_INVALID_SETTINGS, |
736 _("Invalid XMPP ID")); | 784 _("Invalid XMPP ID")); |
746 | 794 |
747 if((my_jb = jabber_buddy_find(js, purple_account_get_username(account), TRUE))) | 795 if((my_jb = jabber_buddy_find(js, purple_account_get_username(account), TRUE))) |
748 my_jb->subscription |= JABBER_SUB_BOTH; | 796 my_jb->subscription |= JABBER_SUB_BOTH; |
749 | 797 |
750 jabber_stream_set_state(js, JABBER_STREAM_CONNECTING); | 798 jabber_stream_set_state(js, JABBER_STREAM_CONNECTING); |
799 | |
800 /* TODO: Just use purple_url_parse? */ | |
801 if (!g_ascii_strncasecmp(connect_server, "http://", 7) || !g_ascii_strncasecmp(connect_server, "https://", 8)) { | |
802 js->use_bosh = TRUE; | |
803 js->bosh = jabber_bosh_connection_init(js, connect_server); | |
804 if (!js->bosh) { | |
805 purple_connection_error_reason (js->gc, | |
806 PURPLE_CONNECTION_ERROR_INVALID_SETTINGS, | |
807 _("Malformed BOSH Connect Server")); | |
808 return; | |
809 } | |
810 jabber_bosh_connection_connect(js->bosh); | |
811 return; | |
812 } else { | |
813 js->certificate_CN = g_strdup(connect_server[0] ? connect_server : js->user->domain); | |
814 } | |
751 | 815 |
752 /* if they've got old-ssl mode going, we probably want to ignore SRV lookups */ | 816 /* if they've got old-ssl mode going, we probably want to ignore SRV lookups */ |
753 if(purple_account_get_bool(js->gc->account, "old_ssl", FALSE)) { | 817 if(purple_account_get_bool(js->gc->account, "old_ssl", FALSE)) { |
754 if(purple_ssl_is_supported()) { | 818 if(purple_ssl_is_supported()) { |
755 js->gsc = purple_ssl_connect(js->gc->account, | 819 js->gsc = purple_ssl_connect(js->gc->account, |
756 js->certificate_CN, | 820 js->certificate_CN, |
757 purple_account_get_int(account, "port", 5223), jabber_login_callback_ssl, | 821 purple_account_get_int(account, "port", 5223), jabber_login_callback_ssl, |
758 jabber_ssl_connect_failure, js->gc); | 822 jabber_ssl_connect_failure, js->gc); |
823 if (!js->gsc) { | |
824 purple_connection_error_reason (js->gc, | |
825 PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT, | |
826 _("Unable to establish SSL connection")); | |
827 } | |
759 } else { | 828 } else { |
760 purple_connection_error_reason (js->gc, | 829 purple_connection_error_reason (js->gc, |
761 PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT, | 830 PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT, |
762 _("SSL support unavailable")); | 831 _("SSL support unavailable")); |
763 } | 832 } |
833 | |
834 return; | |
764 } | 835 } |
765 | 836 |
766 /* no old-ssl, so if they've specified a connect server, we'll use that, otherwise we'll | 837 /* no old-ssl, so if they've specified a connect server, we'll use that, otherwise we'll |
767 * invoke the magic of SRV lookups, to figure out host and port */ | 838 * invoke the magic of SRV lookups, to figure out host and port */ |
768 if(!js->gsc) { | 839 if(connect_server[0]) { |
769 if(connect_server[0]) { | 840 jabber_login_connect(js, js->user->domain, connect_server, purple_account_get_int(account, "port", 5222), TRUE); |
770 jabber_login_connect(js, js->user->domain, connect_server, purple_account_get_int(account, "port", 5222), TRUE); | 841 } else { |
771 } else { | 842 js->srv_query_data = purple_srv_resolve("xmpp-client", |
772 js->srv_query_data = purple_srv_resolve("xmpp-client", | 843 "tcp", js->user->domain, srv_resolved_cb, js); |
773 "tcp", js->user->domain, srv_resolved_cb, js); | |
774 } | |
775 } | 844 } |
776 } | 845 } |
777 | 846 |
778 | 847 |
779 static gboolean | 848 static gboolean |
1322 | 1391 |
1323 /* Don't perform any actions on the ssl connection | 1392 /* Don't perform any actions on the ssl connection |
1324 * if we were forcibly disconnected because it will crash | 1393 * if we were forcibly disconnected because it will crash |
1325 * on some SSL backends. | 1394 * on some SSL backends. |
1326 */ | 1395 */ |
1327 if (!gc->disconnect_timeout) | 1396 if (!gc->disconnect_timeout) { |
1328 jabber_send_raw(js, "</stream:stream>", -1); | 1397 if (js->use_bosh) |
1398 jabber_bosh_connection_close(js->bosh); | |
1399 else | |
1400 jabber_send_raw(js, "</stream:stream>", -1); | |
1401 } | |
1329 | 1402 |
1330 if (js->srv_query_data) | 1403 if (js->srv_query_data) |
1331 purple_srv_cancel(js->srv_query_data); | 1404 purple_srv_cancel(js->srv_query_data); |
1332 | 1405 |
1333 if(js->gsc) { | 1406 if(js->gsc) { |
1339 if(js->gc->inpa) | 1412 if(js->gc->inpa) |
1340 purple_input_remove(js->gc->inpa); | 1413 purple_input_remove(js->gc->inpa); |
1341 close(js->fd); | 1414 close(js->fd); |
1342 } | 1415 } |
1343 | 1416 |
1417 if (js->bosh) | |
1418 jabber_bosh_connection_destroy(js->bosh); | |
1419 | |
1344 jabber_buddy_remove_all_pending_buddy_info_requests(js); | 1420 jabber_buddy_remove_all_pending_buddy_info_requests(js); |
1345 | 1421 |
1346 jabber_parser_free(js); | 1422 jabber_parser_free(js); |
1347 | 1423 |
1348 if(js->iq_callbacks) | 1424 if(js->iq_callbacks) |
1380 | 1456 |
1381 g_free(js->stream_id); | 1457 g_free(js->stream_id); |
1382 if(js->user) | 1458 if(js->user) |
1383 jabber_id_free(js->user); | 1459 jabber_id_free(js->user); |
1384 g_free(js->avatar_hash); | 1460 g_free(js->avatar_hash); |
1461 g_free(js->caps_hash); | |
1385 | 1462 |
1386 purple_circ_buffer_destroy(js->write_buffer); | 1463 purple_circ_buffer_destroy(js->write_buffer); |
1387 if(js->writeh) | 1464 if(js->writeh) |
1388 purple_input_remove(js->writeh); | 1465 purple_input_remove(js->writeh); |
1389 #ifdef HAVE_CYRUS_SASL | 1466 #ifdef HAVE_CYRUS_SASL |
1472 | 1549 |
1473 break; | 1550 break; |
1474 case JABBER_STREAM_CONNECTED: | 1551 case JABBER_STREAM_CONNECTED: |
1475 /* now we can alert the core that we're ready to send status */ | 1552 /* now we can alert the core that we're ready to send status */ |
1476 purple_connection_set_state(js->gc, PURPLE_CONNECTED); | 1553 purple_connection_set_state(js->gc, PURPLE_CONNECTED); |
1477 jabber_disco_items_server(js); | |
1478 break; | 1554 break; |
1479 } | 1555 } |
1480 } | 1556 } |
1481 | 1557 |
1482 char *jabber_get_next_id(JabberStream *js) | 1558 char *jabber_get_next_id(JabberStream *js) |
1590 xmlnode_set_attrib(item, "jid", who); | 1666 xmlnode_set_attrib(item, "jid", who); |
1591 | 1667 |
1592 jabber_iq_send(iq); | 1668 jabber_iq_send(iq); |
1593 } | 1669 } |
1594 | 1670 |
1595 void jabber_add_feature(const char *shortname, const char *namespace, JabberFeatureEnabled cb) { | 1671 void jabber_add_feature(const char *namespace, JabberFeatureEnabled cb) { |
1596 JabberFeature *feat; | 1672 JabberFeature *feat; |
1597 | 1673 |
1598 g_return_if_fail(shortname != NULL); | |
1599 g_return_if_fail(namespace != NULL); | 1674 g_return_if_fail(namespace != NULL); |
1600 | 1675 |
1601 feat = g_new0(JabberFeature,1); | 1676 feat = g_new0(JabberFeature,1); |
1602 feat->shortname = g_strdup(shortname); | |
1603 feat->namespace = g_strdup(namespace); | 1677 feat->namespace = g_strdup(namespace); |
1604 feat->is_enabled = cb; | 1678 feat->is_enabled = cb; |
1605 | 1679 |
1606 /* try to remove just in case it already exists in the list */ | 1680 /* try to remove just in case it already exists in the list */ |
1607 jabber_remove_feature(shortname); | 1681 jabber_remove_feature(namespace); |
1608 | 1682 |
1609 jabber_features = g_list_append(jabber_features, feat); | 1683 jabber_features = g_list_append(jabber_features, feat); |
1610 } | 1684 } |
1611 | 1685 |
1612 void jabber_remove_feature(const char *shortname) { | 1686 void jabber_remove_feature(const char *namespace) { |
1613 GList *feature; | 1687 GList *feature; |
1614 for(feature = jabber_features; feature; feature = feature->next) { | 1688 for(feature = jabber_features; feature; feature = feature->next) { |
1615 JabberFeature *feat = (JabberFeature*)feature->data; | 1689 JabberFeature *feat = (JabberFeature*)feature->data; |
1616 if(!strcmp(feat->shortname, shortname)) { | 1690 if(!strcmp(feat->namespace, namespace)) { |
1617 g_free(feat->shortname); | |
1618 g_free(feat->namespace); | 1691 g_free(feat->namespace); |
1619 | |
1620 g_free(feature->data); | 1692 g_free(feature->data); |
1621 jabber_features = g_list_delete_link(jabber_features, feature); | 1693 jabber_features = g_list_delete_link(jabber_features, feature); |
1622 break; | 1694 break; |
1623 } | 1695 } |
1696 } | |
1697 } | |
1698 | |
1699 static void jabber_features_destroy(void) | |
1700 { | |
1701 while (jabber_features) { | |
1702 JabberFeature *feature = jabber_features->data; | |
1703 g_free(feature->namespace); | |
1704 g_free(feature); | |
1705 jabber_features = g_list_remove_link(jabber_features, jabber_features); | |
1706 } | |
1707 } | |
1708 | |
1709 void jabber_add_identity(const gchar *category, const gchar *type, const gchar *lang, const gchar *name) { | |
1710 GList *identity; | |
1711 JabberIdentity *ident; | |
1712 /* both required according to XEP-0030 */ | |
1713 g_return_if_fail(category != NULL); | |
1714 g_return_if_fail(type != NULL); | |
1715 | |
1716 for(identity = jabber_identities; identity; identity = identity->next) { | |
1717 JabberIdentity *ident = (JabberIdentity*)identity->data; | |
1718 if (!strcmp(ident->category, category) && | |
1719 !strcmp(ident->type, type) && | |
1720 ((!ident->lang && !lang) || (ident->lang && lang && !strcmp(ident->lang, lang)))) { | |
1721 return; | |
1722 } | |
1723 } | |
1724 | |
1725 ident = g_new0(JabberIdentity, 1); | |
1726 ident->category = g_strdup(category); | |
1727 ident->type = g_strdup(type); | |
1728 ident->lang = g_strdup(lang); | |
1729 ident->name = g_strdup(name); | |
1730 jabber_identities = g_list_append(jabber_identities, ident); | |
1731 } | |
1732 | |
1733 static void jabber_identities_destroy(void) | |
1734 { | |
1735 while (jabber_identities) { | |
1736 JabberIdentity *id = jabber_identities->data; | |
1737 g_free(id->category); | |
1738 g_free(id->type); | |
1739 g_free(id->lang); | |
1740 g_free(id->name); | |
1741 g_free(id); | |
1742 jabber_identities = g_list_remove_link(jabber_identities, jabber_identities); | |
1624 } | 1743 } |
1625 } | 1744 } |
1626 | 1745 |
1627 const char *jabber_list_icon(PurpleAccount *a, PurpleBuddy *b) | 1746 const char *jabber_list_icon(PurpleAccount *a, PurpleBuddy *b) |
1628 { | 1747 { |
2673 PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, | 2792 PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, |
2674 "prpl-jabber", jabber_cmd_buzz, | 2793 "prpl-jabber", jabber_cmd_buzz, |
2675 _("buzz: Buzz a user to get their attention"), NULL); | 2794 _("buzz: Buzz a user to get their attention"), NULL); |
2676 } | 2795 } |
2677 | 2796 |
2797 /* IPC functions */ | |
2798 | |
2799 /** | |
2800 * IPC function for determining if a contact supports a certain feature. | |
2801 * | |
2802 * @param account The PurpleAccount | |
2803 * @param jid The full JID of the contact. | |
2804 * @param feature The feature's namespace. | |
2805 * | |
2806 * @return TRUE if supports feature; else FALSE. | |
2807 */ | |
2808 static gboolean | |
2809 jabber_ipc_contact_has_feature(PurpleAccount *account, const gchar *jid, | |
2810 const gchar *feature) | |
2811 { | |
2812 PurpleConnection *gc = purple_account_get_connection(account); | |
2813 JabberStream *js; | |
2814 JabberBuddy *jb; | |
2815 JabberBuddyResource *jbr; | |
2816 gchar *resource; | |
2817 | |
2818 if (!purple_account_is_connected(account)) | |
2819 return FALSE; | |
2820 js = gc->proto_data; | |
2821 | |
2822 if (!(resource = jabber_get_resource(jid)) || | |
2823 !(jb = jabber_buddy_find(js, jid, FALSE)) || | |
2824 !(jbr = jabber_buddy_find_resource(jb, resource))) { | |
2825 g_free(resource); | |
2826 return FALSE; | |
2827 } | |
2828 | |
2829 g_free(resource); | |
2830 | |
2831 return jabber_resource_has_capability(jbr, feature); | |
2832 } | |
2833 | |
2834 static void | |
2835 jabber_ipc_add_feature(const gchar *feature) | |
2836 { | |
2837 if (!feature) | |
2838 return; | |
2839 jabber_add_feature(feature, 0); | |
2840 | |
2841 /* send presence with new caps info for all connected accounts */ | |
2842 jabber_caps_broadcast_change(); | |
2843 } | |
2844 | |
2678 void | 2845 void |
2679 jabber_init_plugin(PurplePlugin *plugin) | 2846 jabber_init_plugin(PurplePlugin *plugin) |
2680 { | 2847 { |
2681 my_protocol = plugin; | 2848 my_protocol = plugin; |
2682 } | 2849 |
2850 jabber_add_identity("client", "pc", NULL, PACKAGE); | |
2851 | |
2852 /* initialize jabber_features list */ | |
2853 jabber_add_feature("jabber:iq:last", 0); | |
2854 jabber_add_feature("jabber:iq:oob", 0); | |
2855 jabber_add_feature("jabber:iq:time", 0); | |
2856 jabber_add_feature("urn:xmpp:time", 0); | |
2857 jabber_add_feature("jabber:iq:version", 0); | |
2858 jabber_add_feature("jabber:x:conference", 0); | |
2859 jabber_add_feature("http://jabber.org/protocol/bytestreams", 0); | |
2860 jabber_add_feature("http://jabber.org/protocol/caps", 0); | |
2861 jabber_add_feature("http://jabber.org/protocol/chatstates", 0); | |
2862 jabber_add_feature("http://jabber.org/protocol/disco#info", 0); | |
2863 jabber_add_feature("http://jabber.org/protocol/disco#items", 0); | |
2864 #if 0 | |
2865 jabber_add_feature("http://jabber.org/protocol/ibb", 0); | |
2866 #endif | |
2867 jabber_add_feature("http://jabber.org/protocol/muc", 0); | |
2868 jabber_add_feature("http://jabber.org/protocol/muc#user", 0); | |
2869 jabber_add_feature("http://jabber.org/protocol/si", 0); | |
2870 jabber_add_feature("http://jabber.org/protocol/si/profile/file-transfer", 0); | |
2871 jabber_add_feature("http://jabber.org/protocol/xhtml-im", 0); | |
2872 jabber_add_feature("urn:xmpp:ping", 0); | |
2873 | |
2874 /* IPC functions */ | |
2875 purple_plugin_ipc_register(plugin, "contact_has_feature", PURPLE_CALLBACK(jabber_ipc_contact_has_feature), | |
2876 purple_marshal_BOOLEAN__POINTER_POINTER_POINTER, | |
2877 purple_value_new(PURPLE_TYPE_BOOLEAN), 3, | |
2878 purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_ACCOUNT), | |
2879 purple_value_new(PURPLE_TYPE_STRING), | |
2880 purple_value_new(PURPLE_TYPE_STRING)); | |
2881 purple_plugin_ipc_register(plugin, "add_feature", PURPLE_CALLBACK(jabber_ipc_add_feature), | |
2882 purple_marshal_VOID__POINTER, | |
2883 NULL, 1, | |
2884 purple_value_new(PURPLE_TYPE_STRING)); | |
2885 } | |
2886 | |
2887 void | |
2888 jabber_uninit_plugin(void) | |
2889 { | |
2890 jabber_features_destroy(); | |
2891 jabber_identities_destroy(); | |
2892 } |