summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Aurich <darkrain42@pidgin.im>2009-03-27 07:59:37 +0000
committerPaul Aurich <darkrain42@pidgin.im>2009-03-27 07:59:37 +0000
commit3b1e1301b3a2e37d9a656bca15189002e6649c08 (patch)
tree5d829659f723da7ce2a2183adb3e7c393b01e720
parentf167e7ea38df8bfc30b43e48ee9b78ceae94eb62 (diff)
parent93bfe3564c57266737808d671d44db83d6677879 (diff)
downloadpidgin-3b1e1301b3a2e37d9a656bca15189002e6649c08.tar.gz
propagate from branch 'im.pidgin.pidgin' (head a1417d5cdedbe39c829e0342c2ededed83ce1720)
to branch 'im.pidgin.cpw.darkrain42.xmpp.iq-handlers' (head 796a92f8e640c92f1f274a265f6036033a0049ff)
-rw-r--r--libpurple/protocols/jabber/adhoccommands.c35
-rw-r--r--libpurple/protocols/jabber/adhoccommands.h4
-rw-r--r--libpurple/protocols/jabber/auth.c27
-rw-r--r--libpurple/protocols/jabber/buddy.c152
-rw-r--r--libpurple/protocols/jabber/buddy.h2
-rw-r--r--libpurple/protocols/jabber/caps.c10
-rw-r--r--libpurple/protocols/jabber/chat.c61
-rw-r--r--libpurple/protocols/jabber/data.c19
-rw-r--r--libpurple/protocols/jabber/data.h3
-rw-r--r--libpurple/protocols/jabber/disco.c90
-rw-r--r--libpurple/protocols/jabber/disco.h6
-rw-r--r--libpurple/protocols/jabber/google.c25
-rw-r--r--libpurple/protocols/jabber/google.h3
-rw-r--r--libpurple/protocols/jabber/ibb.c13
-rw-r--r--libpurple/protocols/jabber/iq.c245
-rw-r--r--libpurple/protocols/jabber/iq.h19
-rw-r--r--libpurple/protocols/jabber/jabber.c100
-rw-r--r--libpurple/protocols/jabber/jabber.h4
-rw-r--r--libpurple/protocols/jabber/message.c4
-rw-r--r--libpurple/protocols/jabber/oob.c15
-rw-r--r--libpurple/protocols/jabber/oob.h5
-rw-r--r--libpurple/protocols/jabber/pep.c7
-rw-r--r--libpurple/protocols/jabber/ping.c57
-rw-r--r--libpurple/protocols/jabber/ping.h12
-rw-r--r--libpurple/protocols/jabber/presence.c6
-rw-r--r--libpurple/protocols/jabber/roster.c10
-rw-r--r--libpurple/protocols/jabber/roster.h3
-rw-r--r--libpurple/protocols/jabber/si.c89
-rw-r--r--libpurple/protocols/jabber/si.h6
29 files changed, 574 insertions, 458 deletions
diff --git a/libpurple/protocols/jabber/adhoccommands.c b/libpurple/protocols/jabber/adhoccommands.c
index 0781822eeb..3d64b6b07a 100644
--- a/libpurple/protocols/jabber/adhoccommands.c
+++ b/libpurple/protocols/jabber/adhoccommands.c
@@ -39,16 +39,17 @@ typedef struct _JabberAdHocActionInfo {
GList *actionslist;
} JabberAdHocActionInfo;
-void jabber_adhoc_disco_result_cb(JabberStream *js, xmlnode *packet, gpointer data) {
- const char *from = xmlnode_get_attrib(packet, "from");
- const char *type = xmlnode_get_attrib(packet, "type");
+void jabber_adhoc_disco_result_cb(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *packet, gpointer data)
+{
const char *node;
xmlnode *query, *item;
JabberID *jabberid;
JabberBuddy *jb;
JabberBuddyResource *jbr = NULL;
- if(strcmp(type, "result"))
+ if (type == JABBER_IQ_ERROR)
return;
query = xmlnode_get_child_with_namespace(packet,"query","http://jabber.org/protocol/disco#items");
@@ -95,7 +96,10 @@ void jabber_adhoc_disco_result_cb(JabberStream *js, xmlnode *packet, gpointer da
}
}
-static void jabber_adhoc_parse(JabberStream *js, xmlnode *packet, gpointer data);
+static void jabber_adhoc_parse(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *packet, gpointer data);
+
static void do_adhoc_action_cb(JabberStream *js, xmlnode *result, const char *actionhandle, gpointer user_data) {
xmlnode *command;
@@ -131,13 +135,16 @@ static void do_adhoc_action_cb(JabberStream *js, xmlnode *result, const char *ac
jabber_iq_send(iq);
}
-static void jabber_adhoc_parse(JabberStream *js, xmlnode *packet, gpointer data) {
+static void
+jabber_adhoc_parse(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *packet, gpointer data)
+{
xmlnode *command = xmlnode_get_child_with_namespace(packet, "command", "http://jabber.org/protocol/commands");
const char *status = xmlnode_get_attrib(command,"status");
xmlnode *xdata = xmlnode_get_child_with_namespace(command,"x","jabber:x:data");
- const char *type = xmlnode_get_attrib(packet,"type");
- if(type && !strcmp(type,"error")) {
+ if (type == JABBER_IQ_ERROR) {
char *msg = jabber_parse_error(js, packet, NULL);
if(!msg)
msg = g_strdup(_("Unknown Error"));
@@ -147,8 +154,6 @@ static void jabber_adhoc_parse(JabberStream *js, xmlnode *packet, gpointer data)
g_free(msg);
return;
}
- if(!type || strcmp(type,"result"))
- return;
if(!status)
return;
@@ -159,7 +164,7 @@ static void jabber_adhoc_parse(JabberStream *js, xmlnode *packet, gpointer data)
if(note) {
char *data = xmlnode_get_data(note);
- purple_notify_info(NULL, xmlnode_get_attrib(packet, "from"), data, NULL);
+ purple_notify_info(NULL, from, data, NULL);
g_free(data);
}
@@ -199,7 +204,7 @@ static void jabber_adhoc_parse(JabberStream *js, xmlnode *packet, gpointer data)
actionInfo = g_new0(JabberAdHocActionInfo, 1);
actionInfo->sessionid = g_strdup(xmlnode_get_attrib(command,"sessionid"));
- actionInfo->who = g_strdup(xmlnode_get_attrib(packet,"from"));
+ actionInfo->who = g_strdup(from);
actionInfo->node = g_strdup(xmlnode_get_attrib(command,"node"));
actionInfo->actionslist = actionslist;
@@ -218,7 +223,11 @@ void jabber_adhoc_execute_action(PurpleBlistNode *node, gpointer data) {
}
}
-static void jabber_adhoc_server_got_list_cb(JabberStream *js, xmlnode *packet, gpointer data) {
+static void
+jabber_adhoc_server_got_list_cb(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *packet, gpointer data)
+{
xmlnode *query = xmlnode_get_child_with_namespace(packet, "query", "http://jabber.org/protocol/disco#items");
xmlnode *item;
diff --git a/libpurple/protocols/jabber/adhoccommands.h b/libpurple/protocols/jabber/adhoccommands.h
index 46559ee249..59f5d1e905 100644
--- a/libpurple/protocols/jabber/adhoccommands.h
+++ b/libpurple/protocols/jabber/adhoccommands.h
@@ -26,7 +26,9 @@
/* Implementation of XEP-0050 */
-void jabber_adhoc_disco_result_cb(JabberStream *js, xmlnode *packet, gpointer data);
+void jabber_adhoc_disco_result_cb(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *packet, gpointer data);
void jabber_adhoc_execute(JabberStream *js, JabberAdHocCommands *cmd);
diff --git a/libpurple/protocols/jabber/auth.c b/libpurple/protocols/jabber/auth.c
index ae8320f871..d00cdaa811 100644
--- a/libpurple/protocols/jabber/auth.c
+++ b/libpurple/protocols/jabber/auth.c
@@ -36,8 +36,9 @@
#include "iq.h"
#include "notify.h"
-static void auth_old_result_cb(JabberStream *js, xmlnode *packet,
- gpointer data);
+static void auth_old_result_cb(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *packet, gpointer data);
gboolean
jabber_process_starttls(JabberStream *js, xmlnode *packet)
@@ -566,11 +567,11 @@ jabber_auth_start(JabberStream *js, xmlnode *packet)
#endif
}
-static void auth_old_result_cb(JabberStream *js, xmlnode *packet, gpointer data)
+static void auth_old_result_cb(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *packet, gpointer data)
{
- const char *type = xmlnode_get_attrib(packet, "type");
-
- if(type && !strcmp(type, "result")) {
+ if (type == JABBER_IQ_RESULT) {
jabber_stream_set_state(js, JABBER_STREAM_CONNECTED);
} else {
PurpleConnectionError reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
@@ -593,24 +594,20 @@ static void auth_old_result_cb(JabberStream *js, xmlnode *packet, gpointer data)
}
}
-static void auth_old_cb(JabberStream *js, xmlnode *packet, gpointer data)
+static void auth_old_cb(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *packet, gpointer data)
{
JabberIq *iq;
xmlnode *query, *x;
- const char *type = xmlnode_get_attrib(packet, "type");
const char *pw = purple_connection_get_password(js->gc);
- if(!type) {
- purple_connection_error_reason (js->gc,
- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
- _("Invalid response from server."));
- return;
- } else if(!strcmp(type, "error")) {
+ if (type == JABBER_IQ_ERROR) {
PurpleConnectionError reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
char *msg = jabber_parse_error(js, packet, &reason);
purple_connection_error_reason (js->gc, reason, msg);
g_free(msg);
- } else if(!strcmp(type, "result")) {
+ } else if (type == JABBER_IQ_RESULT) {
query = xmlnode_get_child(packet, "query");
if(js->stream_id && xmlnode_get_child(query, "digest")) {
char *s, *hash;
diff --git a/libpurple/protocols/jabber/buddy.c b/libpurple/protocols/jabber/buddy.c
index 31f20c7e45..280a69c741 100644
--- a/libpurple/protocols/jabber/buddy.c
+++ b/libpurple/protocols/jabber/buddy.c
@@ -155,6 +155,7 @@ JabberBuddyResource *jabber_buddy_track_resource(JabberBuddy *jb, const char *re
jbr->jb = jb;
jbr->name = g_strdup(resource);
jbr->capabilities = JABBER_CAP_XHTML;
+ jbr->tz_off = PURPLE_NO_TZ_OFF;
jb->resources = g_list_append(jb->resources, jbr);
}
jbr->priority = priority;
@@ -801,6 +802,21 @@ static void jabber_buddy_info_show_if_ready(JabberBuddyInfo *jbi)
purple_notify_user_info_prepend_pair(user_info, _("Operating System"), jbr->client.os);
}
}
+ if (jbr && jbr->tz_off != PURPLE_NO_TZ_OFF) {
+ time_t now_t;
+ struct tm *now;
+ char *timestamp;
+ time(&now_t);
+ now_t += jbr->tz_off;
+ now = gmtime(&now_t);
+
+ timestamp = g_strdup_printf("%s %c%02d%02d", purple_time_format(now),
+ jbr->tz_off < 0 ? '-' : '+',
+ abs(jbr->tz_off / (60*60)),
+ abs((jbr->tz_off % (60*60)) / 60));
+ purple_notify_user_info_prepend_pair(user_info, _("Local Time"), timestamp);
+ g_free(timestamp);
+ }
if(jbir) {
if(jbir->idle_seconds > 0) {
char *idle = purple_str_seconds_to_string(jbir->idle_seconds);
@@ -919,7 +935,7 @@ static void jabber_buddy_info_show_if_ready(JabberBuddyInfo *jbi)
feature = _("User Gaming");
else if(!strcmp(feature, "http://jabber.org/protocol/viewing"))
feature = _("User Viewing");
- else if(!strcmp(feature, "urn:xmpp:ping") || !strcmp(feature, "http://www.xmpp.org/extensions/xep-0199.html#ns"))
+ else if(!strcmp(feature, "urn:xmpp:ping"))
feature = _("Ping");
else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0200.html#ns"))
feature = _("Stanza Encryption");
@@ -971,6 +987,22 @@ static void jabber_buddy_info_show_if_ready(JabberBuddyInfo *jbi)
}
}
+ if (jbr->tz_off != PURPLE_NO_TZ_OFF) {
+ time_t now_t;
+ struct tm *now;
+ char *timestamp;
+ time(&now_t);
+ now_t += jbr->tz_off;
+ now = gmtime(&now_t);
+
+ timestamp = g_strdup_printf("%s %c%02d%02d", purple_time_format(now),
+ jbr->tz_off < 0 ? '-' : '+',
+ abs(jbr->tz_off / (60*60)),
+ abs((jbr->tz_off % (60*60)) / 60));
+ purple_notify_user_info_prepend_pair(user_info, _("Local Time"), timestamp);
+ g_free(timestamp);
+ }
+
if(jbr->name && (jbir = g_hash_table_lookup(jbi->resources, jbr->name))) {
if(jbir->idle_seconds > 0) {
char *idle = purple_str_seconds_to_string(jbir->idle_seconds);
@@ -1089,7 +1121,7 @@ static void jabber_buddy_info_show_if_ready(JabberBuddyInfo *jbi)
feature = _("User Gaming");
else if(!strcmp(feature, "http://jabber.org/protocol/viewing"))
feature = _("User Viewing");
- else if(!strcmp(feature, "urn:xmpp:ping") || !strcmp(feature, "http://www.xmpp.org/extensions/xep-0199.html#ns"))
+ else if(!strcmp(feature, "urn:xmpp:ping"))
feature = _("Ping");
else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0200.html#ns"))
feature = _("Stanza Encryption");
@@ -1155,12 +1187,19 @@ static void jabber_buddy_info_remove_id(JabberBuddyInfo *jbi, const char *id)
}
}
-static void jabber_vcard_save_mine(JabberStream *js, xmlnode *packet, gpointer data)
+static void jabber_vcard_save_mine(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *packet, gpointer data)
{
xmlnode *vcard;
char *txt;
PurpleStoredImage *img;
+ if (type == JABBER_IQ_ERROR) {
+ purple_debug_warning("jabber", "Server returned error while retrieving vCard");
+ return;
+ }
+
if((vcard = xmlnode_get_child(packet, "vCard")) ||
(vcard = xmlnode_get_child_with_namespace(packet, "query", "vcard-temp")))
{
@@ -1191,9 +1230,10 @@ void jabber_vcard_fetch_mine(JabberStream *js)
jabber_iq_send(iq);
}
-static void jabber_vcard_parse(JabberStream *js, xmlnode *packet, gpointer data)
+static void jabber_vcard_parse(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *packet, gpointer data)
{
- const char *id, *from;
char *bare_jid;
char *text;
char *serverside_alias = NULL;
@@ -1202,9 +1242,6 @@ static void jabber_vcard_parse(JabberStream *js, xmlnode *packet, gpointer data)
JabberBuddyInfo *jbi = data;
PurpleNotifyUserInfo *user_info;
- from = xmlnode_get_attrib(packet, "from");
- id = xmlnode_get_attrib(packet, "id");
-
if(!jbi)
return;
@@ -1554,19 +1591,16 @@ static void jabber_buddy_info_resource_free(gpointer data)
g_free(jbri);
}
-static void jabber_version_parse(JabberStream *js, xmlnode *packet, gpointer data)
+static void jabber_version_parse(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *packet, gpointer data)
{
JabberBuddyInfo *jbi = data;
- const char *type, *id, *from;
xmlnode *query;
char *resource_name;
g_return_if_fail(jbi != NULL);
- type = xmlnode_get_attrib(packet, "type");
- id = xmlnode_get_attrib(packet, "id");
- from = xmlnode_get_attrib(packet, "from");
-
jabber_buddy_info_remove_id(jbi, id);
if(!from)
@@ -1575,7 +1609,7 @@ static void jabber_version_parse(JabberStream *js, xmlnode *packet, gpointer dat
resource_name = jabber_get_resource(from);
if(resource_name) {
- if(type && !strcmp(type, "result")) {
+ if (type == JABBER_IQ_RESULT) {
if((query = xmlnode_get_child(packet, "query"))) {
JabberBuddyResource *jbr = jabber_buddy_find_resource(jbi->jb, resource_name);
if(jbr) {
@@ -1598,19 +1632,17 @@ static void jabber_version_parse(JabberStream *js, xmlnode *packet, gpointer dat
jabber_buddy_info_show_if_ready(jbi);
}
-static void jabber_last_parse(JabberStream *js, xmlnode *packet, gpointer data)
+static void jabber_last_parse(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *packet, gpointer data)
{
JabberBuddyInfo *jbi = data;
xmlnode *query;
char *resource_name;
- const char *type, *id, *from, *seconds;
+ const char *seconds;
g_return_if_fail(jbi != NULL);
- type = xmlnode_get_attrib(packet, "type");
- id = xmlnode_get_attrib(packet, "id");
- from = xmlnode_get_attrib(packet, "from");
-
jabber_buddy_info_remove_id(jbi, id);
if(!from)
@@ -1619,7 +1651,7 @@ static void jabber_last_parse(JabberStream *js, xmlnode *packet, gpointer data)
resource_name = jabber_get_resource(from);
if(resource_name) {
- if(type && !strcmp(type, "result")) {
+ if (type == JABBER_IQ_RESULT) {
if((query = xmlnode_get_child(packet, "query"))) {
seconds = xmlnode_get_attrib(query, "seconds");
if(seconds) {
@@ -1640,6 +1672,56 @@ static void jabber_last_parse(JabberStream *js, xmlnode *packet, gpointer data)
jabber_buddy_info_show_if_ready(jbi);
}
+static void jabber_time_parse(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *packet, gpointer data)
+{
+ JabberBuddyInfo *jbi = data;
+ JabberBuddyResource *jbr;
+ char *resource_name;
+
+ g_return_if_fail(jbi != NULL);
+
+ jabber_buddy_info_remove_id(jbi, id);
+
+ if (!from)
+ return;
+
+ resource_name = jabber_get_resource(from);
+ jbr = resource_name ? jabber_buddy_find_resource(jbi->jb, resource_name) : NULL;
+ g_free(resource_name);
+ if (jbr) {
+ if (type == JABBER_IQ_RESULT) {
+ xmlnode *time = xmlnode_get_child(packet, "time");
+ xmlnode *tzo = time ? xmlnode_get_child(time, "tzo") : NULL;
+ char *tzo_data = tzo ? xmlnode_get_data(tzo) : NULL;
+ if (tzo_data) {
+ char *c = tzo_data;
+ int hours, minutes;
+ if (tzo_data[0] == 'Z' && tzo_data[1] == '\0') {
+ jbr->tz_off = 0;
+ } else {
+ gboolean offset_positive = (tzo_data[0] == '+');
+ /* [+-]HH:MM */
+ if (((*c == '+' || *c == '-') && (c = c + 1)) &&
+ sscanf(c, "%02d:%02d", &hours, &minutes) == 2) {
+ jbr->tz_off = 60*60*hours + 60*minutes;
+ if (!offset_positive)
+ jbr->tz_off *= -1;
+ } else {
+ purple_debug_info("jabber", "Ignoring malformed timezone %s",
+ tzo_data);
+ }
+ }
+
+ g_free(tzo_data);
+ }
+ }
+ }
+
+ jabber_buddy_info_show_if_ready(jbi);
+}
+
void jabber_buddy_remove_all_pending_buddy_info_requests(JabberStream *js)
{
if (js->pending_buddy_info_requests)
@@ -1771,6 +1853,19 @@ static void jabber_buddy_get_info_for_jid(JabberStream *js, const char *jid)
jabber_iq_send(iq);
}
+ if (jbr->tz_off == PURPLE_NO_TZ_OFF &&
+ (!jbr->caps ||
+ jabber_resource_has_capability(jbr, "urn:xmpp:time"))) {
+ xmlnode *child;
+ iq = jabber_iq_new(js, JABBER_IQ_GET);
+ xmlnode_set_attrib(iq->node, "to", full_jid);
+ child = xmlnode_new_child(iq->node, "time");
+ xmlnode_set_namespace(child, "urn:xmpp:time");
+ jabber_iq_set_callback(iq, jabber_time_parse, jbi);
+ jbi->ids = g_slist_prepend(jbi->ids, g_strdup(iq->id));
+ jabber_iq_send(iq);
+ }
+
g_free(full_jid);
}
@@ -2167,7 +2262,9 @@ static void user_search_result_add_buddy_cb(PurpleConnection *gc, GList *row, vo
g_list_nth_data(row, 0), NULL, NULL);
}
-static void user_search_result_cb(JabberStream *js, xmlnode *packet, gpointer data)
+static void user_search_result_cb(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *packet, gpointer data)
{
PurpleNotifySearchResults *results;
PurpleNotifySearchColumn *column;
@@ -2363,15 +2460,16 @@ static const char * jabber_user_dir_comments [] = {
};
#endif
-static void user_search_fields_result_cb(JabberStream *js, xmlnode *packet, gpointer data)
+static void user_search_fields_result_cb(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *packet, gpointer data)
{
xmlnode *query, *x;
- const char *from, *type;
- if(!(from = xmlnode_get_attrib(packet, "from")))
+ if (!from)
return;
- if(!(type = xmlnode_get_attrib(packet, "type")) || !strcmp(type, "error")) {
+ if (type == JABBER_IQ_ERROR) {
char *msg = jabber_parse_error(js, packet, NULL);
if(!msg)
diff --git a/libpurple/protocols/jabber/buddy.h b/libpurple/protocols/jabber/buddy.h
index 0eb49b7c50..3844e29ae9 100644
--- a/libpurple/protocols/jabber/buddy.h
+++ b/libpurple/protocols/jabber/buddy.h
@@ -81,6 +81,8 @@ typedef struct _JabberBuddyResource {
char *name;
char *os;
} client;
+ /* tz_off == PURPLE_NO_TZ_OFF when unset */
+ long tz_off;
JabberCapsClientInfo *caps;
GList *commands;
} JabberBuddyResource;
diff --git a/libpurple/protocols/jabber/caps.c b/libpurple/protocols/jabber/caps.c
index 99213b3ea6..755e709a3b 100644
--- a/libpurple/protocols/jabber/caps.c
+++ b/libpurple/protocols/jabber/caps.c
@@ -369,7 +369,10 @@ static void jabber_caps_get_info_check_completion(jabber_caps_cbplususerdata *us
}
}
-static void jabber_caps_ext_iqcb(JabberStream *js, xmlnode *packet, gpointer data) {
+static void jabber_caps_ext_iqcb(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *packet, gpointer data)
+{
/* collect data and fetch all exts */
xmlnode *query = xmlnode_get_child_with_namespace(packet, "query", "http://jabber.org/protocol/disco#info");
jabber_ext_userdata *extuserdata = data;
@@ -433,7 +436,10 @@ static void jabber_caps_ext_iqcb(JabberStream *js, xmlnode *packet, gpointer dat
jabber_caps_get_info_check_completion(userdata);
}
-static void jabber_caps_client_iqcb(JabberStream *js, xmlnode *packet, gpointer data) {
+static void jabber_caps_client_iqcb(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *packet, gpointer data)
+{
/* collect data and fetch all exts */
xmlnode *query = xmlnode_get_child_with_namespace(packet, "query",
"http://jabber.org/protocol/disco#info");
diff --git a/libpurple/protocols/jabber/chat.c b/libpurple/protocols/jabber/chat.c
index 4c2a644b02..0bbaad7efc 100644
--- a/libpurple/protocols/jabber/chat.c
+++ b/libpurple/protocols/jabber/chat.c
@@ -376,21 +376,19 @@ static void jabber_chat_room_configure_x_data_cb(JabberStream *js, xmlnode *resu
jabber_iq_send(iq);
}
-static void jabber_chat_room_configure_cb(JabberStream *js, xmlnode *packet, gpointer data)
+static void jabber_chat_room_configure_cb(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *packet, gpointer data)
{
xmlnode *query, *x;
- const char *type = xmlnode_get_attrib(packet, "type");
- const char *from = xmlnode_get_attrib(packet, "from");
char *msg;
JabberChat *chat;
JabberID *jid;
- if(!type || !from)
+ if (!from)
return;
-
-
- if(!strcmp(type, "result")) {
+ if (type == JABBER_IQ_RESULT) {
jid = jabber_id_new(from);
if(!jid)
@@ -416,7 +414,7 @@ static void jabber_chat_room_configure_cb(JabberStream *js, xmlnode *packet, gpo
return;
}
}
- } else if(!strcmp(type, "error")) {
+ } else if (type == JABBER_IQ_ERROR) {
char *msg = jabber_parse_error(js, packet, NULL);
purple_notify_error(js->gc, _("Configuration error"), _("Configuration error"), msg);
@@ -486,11 +484,12 @@ void jabber_chat_create_instant_room(JabberChat *chat) {
g_free(room_jid);
}
-static void jabber_chat_register_x_data_result_cb(JabberStream *js, xmlnode *packet, gpointer data)
+static void
+jabber_chat_register_x_data_result_cb(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *packet, gpointer data)
{
- const char *type = xmlnode_get_attrib(packet, "type");
-
- if(type && !strcmp(type, "error")) {
+ if (type == JABBER_IQ_ERROR) {
char *msg = jabber_parse_error(js, packet, NULL);
purple_notify_error(js->gc, _("Registration error"), _("Registration error"), msg);
@@ -521,19 +520,19 @@ static void jabber_chat_register_x_data_cb(JabberStream *js, xmlnode *result, gp
jabber_iq_send(iq);
}
-static void jabber_chat_register_cb(JabberStream *js, xmlnode *packet, gpointer data)
+static void jabber_chat_register_cb(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *packet, gpointer data)
{
xmlnode *query, *x;
- const char *type = xmlnode_get_attrib(packet, "type");
- const char *from = xmlnode_get_attrib(packet, "from");
char *msg;
JabberChat *chat;
JabberID *jid;
- if(!type || !from)
+ if (!from)
return;
- if(!strcmp(type, "result")) {
+ if (type == JABBER_IQ_RESULT) {
jid = jabber_id_new(from);
if(!jid)
@@ -559,7 +558,7 @@ static void jabber_chat_register_cb(JabberStream *js, xmlnode *packet, gpointer
return;
}
}
- } else if(!strcmp(type, "error")) {
+ } else if (type == JABBER_IQ_ERROR) {
char *msg = jabber_parse_error(js, packet, NULL);
purple_notify_error(js->gc, _("Registration error"), _("Registration error"), msg);
@@ -690,16 +689,17 @@ void jabber_chat_part(JabberChat *chat, const char *msg)
g_free(room_jid);
}
-static void roomlist_disco_result_cb(JabberStream *js, xmlnode *packet, gpointer data)
+static void roomlist_disco_result_cb(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *packet, gpointer data)
{
xmlnode *query;
xmlnode *item;
- const char *type;
if(!js->roomlist)
return;
- if(!(type = xmlnode_get_attrib(packet, "type")) || strcmp(type, "result")) {
+ if (type == JABBER_IQ_ERROR) {
char *err = jabber_parse_error(js, packet, NULL);
purple_notify_error(js->gc, _("Error"),
_("Error retrieving room list"), err);
@@ -988,13 +988,17 @@ gboolean jabber_chat_kick_user(JabberChat *chat, const char *who, const char *wh
return TRUE;
}
-static void jabber_chat_disco_traffic_cb(JabberStream *js, xmlnode *packet, gpointer data)
+static void jabber_chat_disco_traffic_cb(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *packet, gpointer data)
{
JabberChat *chat;
- /*xmlnode *query;*/
- int id = GPOINTER_TO_INT(data);
+#if 0
+ xmlnode *query, *x;
+#endif
+ int chat_id = GPOINTER_TO_INT(data);
- if(!(chat = jabber_chat_find_by_id(js, id)))
+ if(!(chat = jabber_chat_find_by_id(js, chat_id)))
return;
/* defaults, in case the conference server doesn't
@@ -1002,8 +1006,9 @@ static void jabber_chat_disco_traffic_cb(JabberStream *js, xmlnode *packet, gpoi
chat->xhtml = TRUE;
/* disabling this until more MUC servers support
- * announcing this
- if(xmlnode_get_child(packet, "error")) {
+ * announcing this */
+#if 0
+ if (type == JABBER_IQ_ERROR) {
return;
}
@@ -1019,7 +1024,7 @@ static void jabber_chat_disco_traffic_cb(JabberStream *js, xmlnode *packet, gpoi
chat->xhtml = TRUE;
}
}
- */
+#endif
}
void jabber_chat_disco_traffic(JabberChat *chat)
diff --git a/libpurple/protocols/jabber/data.c b/libpurple/protocols/jabber/data.c
index ba1d91ba33..bddafb18f9 100644
--- a/libpurple/protocols/jabber/data.c
+++ b/libpurple/protocols/jabber/data.c
@@ -200,25 +200,26 @@ jabber_data_associate_remote(JabberData *data)
}
void
-jabber_data_parse(JabberStream *js, xmlnode *packet)
+jabber_data_parse(JabberStream *js, const char *who, JabberIqType type,
+ const char *id, xmlnode *data_node)
{
JabberIq *result = NULL;
- const char *who = xmlnode_get_attrib(packet, "from");
- xmlnode *data_node = xmlnode_get_child(packet, "data");
- const JabberData *data =
- jabber_data_find_local_by_cid(xmlnode_get_attrib(data_node, "cid"));
+ const char *cid = xmlnode_get_attrib(data_node, "cid");
+ const JabberData *data = cid ? jabber_data_find_local_by_cid(cid) : NULL;
if (!data) {
xmlnode *item_not_found = xmlnode_new("item-not-found");
result = jabber_iq_new(js, JABBER_IQ_ERROR);
- xmlnode_set_attrib(result->node, "to", who);
- xmlnode_set_attrib(result->node, "id", xmlnode_get_attrib(packet, "id"));
+ if (who)
+ xmlnode_set_attrib(result->node, "to", who);
+ xmlnode_set_attrib(result->node, "id", id);
xmlnode_insert_child(result->node, item_not_found);
} else {
result = jabber_iq_new(js, JABBER_IQ_RESULT);
- xmlnode_set_attrib(result->node, "to", who);
- xmlnode_set_attrib(result->node, "id", xmlnode_get_attrib(packet, "id"));
+ if (who)
+ xmlnode_set_attrib(result->node, "to", who);
+ xmlnode_set_attrib(result->node, "id", id);
xmlnode_insert_child(result->node,
jabber_data_get_xml_definition(data));
}
diff --git a/libpurple/protocols/jabber/data.h b/libpurple/protocols/jabber/data.h
index 5134de2777..802ded7132 100644
--- a/libpurple/protocols/jabber/data.h
+++ b/libpurple/protocols/jabber/data.h
@@ -65,7 +65,8 @@ void jabber_data_associate_local(JabberData *data, const gchar *alt);
void jabber_data_associate_remote(JabberData *data);
/* handles iq requests */
-void jabber_data_parse(JabberStream *js, xmlnode *packet);
+void jabber_data_parse(JabberStream *js, const char *who, JabberIqType type,
+ const char *id, xmlnode *data_node);
void jabber_data_init(void);
void jabber_data_uninit(void);
diff --git a/libpurple/protocols/jabber/disco.c b/libpurple/protocols/jabber/disco.c
index 85e8524d67..bbe4511424 100644
--- a/libpurple/protocols/jabber/disco.c
+++ b/libpurple/protocols/jabber/disco.c
@@ -45,9 +45,11 @@ struct _jabber_disco_info_cb_data {
}
static void
-jabber_disco_bytestream_server_cb(JabberStream *js, xmlnode *packet, gpointer data) {
+jabber_disco_bytestream_server_cb(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *packet, gpointer data)
+{
JabberBytestreamsStreamhost *sh = data;
- const char *from = xmlnode_get_attrib(packet, "from");
xmlnode *query = xmlnode_get_child_with_namespace(packet, "query",
"http://jabber.org/protocol/bytestreams");
@@ -85,29 +87,22 @@ jabber_disco_bytestream_server_cb(JabberStream *js, xmlnode *packet, gpointer da
}
-void jabber_disco_info_parse(JabberStream *js, xmlnode *packet) {
- const char *from = xmlnode_get_attrib(packet, "from");
- const char *type = xmlnode_get_attrib(packet, "type");
+void jabber_disco_info_parse(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *in_query) {
- if(!from || !type)
+ if(!from)
return;
- if(!strcmp(type, "get")) {
+ if(type == JABBER_IQ_GET) {
xmlnode *query, *identity, *feature;
JabberIq *iq;
-
- xmlnode *in_query;
- const char *node = NULL;
-
- if((in_query = xmlnode_get_child(packet, "query"))) {
- node = xmlnode_get_attrib(in_query, "node");
- }
-
+ const char *node = xmlnode_get_attrib(in_query, "node");
iq = jabber_iq_new_query(js, JABBER_IQ_RESULT,
"http://jabber.org/protocol/disco#info");
- jabber_iq_set_id(iq, xmlnode_get_attrib(packet, "id"));
+ jabber_iq_set_id(iq, id);
xmlnode_set_attrib(iq->node, "to", from);
query = xmlnode_get_child(iq->node, "query");
@@ -126,7 +121,7 @@ void jabber_disco_info_parse(JabberStream *js, xmlnode *packet) {
SUPPORT_FEATURE("jabber:iq:last")
SUPPORT_FEATURE("jabber:iq:oob")
SUPPORT_FEATURE("jabber:iq:time")
- SUPPORT_FEATURE("xmpp:urn:time")
+ SUPPORT_FEATURE("urn:xmpp:time")
SUPPORT_FEATURE("jabber:iq:version")
SUPPORT_FEATURE("jabber:x:conference")
SUPPORT_FEATURE("http://jabber.org/protocol/bytestreams")
@@ -139,7 +134,6 @@ void jabber_disco_info_parse(JabberStream *js, xmlnode *packet) {
SUPPORT_FEATURE("http://jabber.org/protocol/si/profile/file-transfer")
SUPPORT_FEATURE("http://jabber.org/protocol/xhtml-im")
SUPPORT_FEATURE("urn:xmpp:ping")
- SUPPORT_FEATURE("http://www.xmpp.org/extensions/xep-0199.html#ns")
if(!node) { /* non-caps disco#info, add all enabled extensions */
GList *features;
@@ -198,8 +192,7 @@ void jabber_disco_info_parse(JabberStream *js, xmlnode *packet) {
}
jabber_iq_send(iq);
- } else if(!strcmp(type, "result")) {
- xmlnode *query = xmlnode_get_child(packet, "query");
+ } else if(type == JABBER_IQ_RESULT) {
xmlnode *child;
JabberID *jid;
JabberBuddy *jb;
@@ -216,7 +209,7 @@ void jabber_disco_info_parse(JabberStream *js, xmlnode *packet) {
if(jbr)
capabilities = jbr->capabilities;
- for(child = query->child; child; child = child->next) {
+ for(child = in_query->child; child; child = child->next) {
if(child->type != XMLNODE_TYPE_TAG)
continue;
@@ -266,7 +259,7 @@ void jabber_disco_info_parse(JabberStream *js, xmlnode *packet) {
capabilities |= JABBER_CAP_IQ_SEARCH;
else if(!strcmp(var, "jabber:iq:register"))
capabilities |= JABBER_CAP_IQ_REGISTER;
- else if(!strcmp(var, "http://www.xmpp.org/extensions/xep-0199.html#ns"))
+ else if(!strcmp(var, "urn:xmpp:ping"))
capabilities |= JABBER_CAP_PING;
else if(!strcmp(var, "http://jabber.org/protocol/commands")) {
capabilities |= JABBER_CAP_ADHOC;
@@ -287,7 +280,7 @@ void jabber_disco_info_parse(JabberStream *js, xmlnode *packet) {
jdicd->callback(js, from, capabilities, jdicd->data);
g_hash_table_remove(js->disco_callbacks, from);
}
- } else if(!strcmp(type, "error")) {
+ } else if(type == JABBER_IQ_ERROR) {
JabberID *jid;
JabberBuddy *jb;
JabberBuddyResource *jbr = NULL;
@@ -311,28 +304,23 @@ void jabber_disco_info_parse(JabberStream *js, xmlnode *packet) {
}
}
-void jabber_disco_items_parse(JabberStream *js, xmlnode *packet) {
- const char *from = xmlnode_get_attrib(packet, "from");
- const char *type = xmlnode_get_attrib(packet, "type");
-
- if(type && !strcmp(type, "get")) {
+void jabber_disco_items_parse(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *query) {
+ if(type == JABBER_IQ_GET) {
JabberIq *iq = jabber_iq_new_query(js, JABBER_IQ_RESULT,
"http://jabber.org/protocol/disco#items");
/* preserve node */
- xmlnode *iq_query = xmlnode_get_child_with_namespace(iq->node,"query","http://jabber.org/protocol/disco#items");
- if(iq_query) {
- xmlnode *query = xmlnode_get_child_with_namespace(packet,"query","http://jabber.org/protocol/disco#items");
- if(query) {
- const char *node = xmlnode_get_attrib(query,"node");
- if(node)
- xmlnode_set_attrib(iq_query,"node",node);
- }
- }
+ xmlnode *iq_query = xmlnode_get_child(iq->node, "query");
+ const char *node = xmlnode_get_attrib(query, "node");
+ if(node)
+ xmlnode_set_attrib(iq_query,"node",node);
- jabber_iq_set_id(iq, xmlnode_get_attrib(packet, "id"));
+ jabber_iq_set_id(iq, id);
- xmlnode_set_attrib(iq->node, "to", from);
+ if (from)
+ xmlnode_set_attrib(iq->node, "to", from);
jabber_iq_send(iq);
}
}
@@ -397,19 +385,18 @@ jabber_disco_finish_server_info_result_cb(JabberStream *js)
}
static void
-jabber_disco_server_info_result_cb(JabberStream *js, xmlnode *packet, gpointer data)
+jabber_disco_server_info_result_cb(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *packet, gpointer data)
{
xmlnode *query, *child;
- const char *from = xmlnode_get_attrib(packet, "from");
- const char *type = xmlnode_get_attrib(packet, "type");
- if((!from || !type) ||
- (strcmp(from, js->user->domain))) {
+ if (!from || strcmp(from, js->user->domain)) {
jabber_disco_finish_server_info_result_cb(js);
return;
}
- if(strcmp(type, "result")) {
+ if (type == JABBER_IQ_ERROR) {
/* A common way to get here is for the server not to support xmlns http://jabber.org/protocol/disco#info */
jabber_disco_finish_server_info_result_cb(js);
return;
@@ -470,19 +457,16 @@ jabber_disco_server_info_result_cb(JabberStream *js, xmlnode *packet, gpointer d
}
static void
-jabber_disco_server_items_result_cb(JabberStream *js, xmlnode *packet, gpointer data)
+jabber_disco_server_items_result_cb(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *packet, gpointer data)
{
xmlnode *query, *child;
- const char *from = xmlnode_get_attrib(packet, "from");
- const char *type = xmlnode_get_attrib(packet, "type");
-
- if(!from || !type)
- return;
- if(strcmp(from, js->user->domain))
+ if (!from || strcmp(from, js->user->domain) != 0)
return;
- if(strcmp(type, "result"))
+ if (type == JABBER_IQ_ERROR)
return;
while(js->chat_servers) {
diff --git a/libpurple/protocols/jabber/disco.h b/libpurple/protocols/jabber/disco.h
index 04e17853bd..f317079f1f 100644
--- a/libpurple/protocols/jabber/disco.h
+++ b/libpurple/protocols/jabber/disco.h
@@ -27,8 +27,10 @@
typedef void (JabberDiscoInfoCallback)(JabberStream *js, const char *who,
JabberCapabilities capabilities, gpointer data);
-void jabber_disco_info_parse(JabberStream *js, xmlnode *packet);
-void jabber_disco_items_parse(JabberStream *js, xmlnode *packet);
+void jabber_disco_info_parse(JabberStream *js, const char *from,
+ JabberIqType type, const char *id, xmlnode *in_query);
+void jabber_disco_items_parse(JabberStream *js, const char *from,
+ JabberIqType type, const char *id, xmlnode *query);
void jabber_disco_items_server(JabberStream *js);
diff --git a/libpurple/protocols/jabber/google.c b/libpurple/protocols/jabber/google.c
index 70c184fa8b..171333ca05 100644
--- a/libpurple/protocols/jabber/google.c
+++ b/libpurple/protocols/jabber/google.c
@@ -30,13 +30,13 @@
#include "iq.h"
static void
-jabber_gmail_parse(JabberStream *js, xmlnode *packet, gpointer nul)
+jabber_gmail_parse(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *packet, gpointer nul)
{
- const char *type = xmlnode_get_attrib(packet, "type");
xmlnode *child;
- xmlnode *message, *sender_node, *subject_node;
- const char *from, *to, *url, *tid;
- char *subject;
+ xmlnode *message;
+ const char *to, *url;
const char *in_str;
char *to_name;
char *default_tos[1];
@@ -46,7 +46,7 @@ jabber_gmail_parse(JabberStream *js, xmlnode *packet, gpointer nul)
const char **tos, **froms, **urls;
char **subjects;
- if (strcmp(type, "result"))
+ if (type == JABBER_IQ_ERROR)
return;
child = xmlnode_get_child(packet, "mailbox");
@@ -87,6 +87,10 @@ jabber_gmail_parse(JabberStream *js, xmlnode *packet, gpointer nul)
message= xmlnode_get_child(child, "mail-thread-info");
for (i=0; message; message = xmlnode_get_next_twin(message), i++) {
+ xmlnode *sender_node, *subject_node;
+ const char *from, *tid;
+ char *subject;
+
subject_node = xmlnode_get_child(message, "subject");
sender_node = xmlnode_get_child(message, "senders");
sender_node = xmlnode_get_child(sender_node, "sender");
@@ -144,9 +148,9 @@ jabber_gmail_parse(JabberStream *js, xmlnode *packet, gpointer nul)
}
void
-jabber_gmail_poke(JabberStream *js, xmlnode *packet)
+jabber_gmail_poke(JabberStream *js, const char *from, JabberIqType type,
+ const char *id, xmlnode *new_mail)
{
- const char *type;
xmlnode *query;
JabberIq *iq;
@@ -154,11 +158,8 @@ jabber_gmail_poke(JabberStream *js, xmlnode *packet)
if (!purple_account_get_check_mail(js->gc->account))
return;
- type = xmlnode_get_attrib(packet, "type");
-
-
/* Is this an initial incoming mail notification? If so, send a request for more info */
- if (strcmp(type, "set") || !xmlnode_get_child(packet, "new-mail"))
+ if (type != JABBER_IQ_SET)
return;
purple_debug(PURPLE_DEBUG_MISC, "jabber",
diff --git a/libpurple/protocols/jabber/google.h b/libpurple/protocols/jabber/google.h
index c1b6e0d0c2..8845a2a699 100644
--- a/libpurple/protocols/jabber/google.h
+++ b/libpurple/protocols/jabber/google.h
@@ -27,7 +27,8 @@
#include "jabber.h"
void jabber_gmail_init(JabberStream *js);
-void jabber_gmail_poke(JabberStream *js, xmlnode *node);
+void jabber_gmail_poke(JabberStream *js, const char *from, JabberIqType type,
+ const char *id, xmlnode *new_mail);
void jabber_google_roster_init(JabberStream *js);
void jabber_google_roster_outgoing(JabberStream *js, xmlnode *query, xmlnode *item);
diff --git a/libpurple/protocols/jabber/ibb.c b/libpurple/protocols/jabber/ibb.c
index 2efebeda8c..f555cdd118 100644
--- a/libpurple/protocols/jabber/ibb.c
+++ b/libpurple/protocols/jabber/ibb.c
@@ -198,11 +198,13 @@ jabber_ibb_session_set_error_callback(JabberIBBSession *sess,
}
static void
-jabber_ibb_session_opened_cb(JabberStream *js, xmlnode *packet, gpointer data)
+jabber_ibb_session_opened_cb(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *packet, gpointer data)
{
JabberIBBSession *sess = (JabberIBBSession *) data;
- if (strcmp(xmlnode_get_attrib(packet, "type"), "error") == 0) {
+ if (type == JABBER_IQ_ERROR) {
sess->state = JABBER_IBB_SESSION_ERROR;
} else {
sess->state = JABBER_IBB_SESSION_OPENED;
@@ -274,10 +276,11 @@ jabber_ibb_session_accept(JabberIBBSession *sess)
}
static void
-jabber_ibb_session_send_acknowledge_cb(JabberStream *js, xmlnode *packet, gpointer data)
+jabber_ibb_session_send_acknowledge_cb(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *packet, gpointer data)
{
JabberIBBSession *sess = (JabberIBBSession *) data;
- xmlnode *error = xmlnode_get_child(packet, "error");
if (sess) {
/* reset callback */
@@ -286,7 +289,7 @@ jabber_ibb_session_send_acknowledge_cb(JabberStream *js, xmlnode *packet, gpoint
sess->last_iq_id = NULL;
}
- if (error) {
+ if (type == JABBER_IQ_ERROR) {
jabber_ibb_session_close(sess);
sess->state = JABBER_IBB_SESSION_ERROR;
diff --git a/libpurple/protocols/jabber/iq.c b/libpurple/protocols/jabber/iq.c
index 33126a41ed..b193bb108e 100644
--- a/libpurple/protocols/jabber/iq.c
+++ b/libpurple/protocols/jabber/iq.c
@@ -143,23 +143,19 @@ void jabber_iq_free(JabberIq *iq)
g_free(iq);
}
-static void jabber_iq_last_parse(JabberStream *js, xmlnode *packet)
+static void jabber_iq_last_parse(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *packet)
{
JabberIq *iq;
- const char *type;
- const char *from;
- const char *id;
xmlnode *query;
char *idle_time;
- type = xmlnode_get_attrib(packet, "type");
- from = xmlnode_get_attrib(packet, "from");
- id = xmlnode_get_attrib(packet, "id");
-
- if(type && !strcmp(type, "get")) {
+ if(type == JABBER_IQ_GET) {
iq = jabber_iq_new_query(js, JABBER_IQ_RESULT, "jabber:iq:last");
jabber_iq_set_id(iq, id);
- xmlnode_set_attrib(iq->node, "to", from);
+ if (from)
+ xmlnode_set_attrib(iq->node, "to", from);
query = xmlnode_get_child(iq->node, "query");
@@ -171,88 +167,67 @@ static void jabber_iq_last_parse(JabberStream *js, xmlnode *packet)
}
}
-static void jabber_iq_time_parse(JabberStream *js, xmlnode *packet)
+static void jabber_iq_time_parse(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *child)
{
- const char *type, *from, *id, *xmlns;
+ const char *xmlns;
JabberIq *iq;
- xmlnode *query;
time_t now_t;
+ struct tm now_local;
+ struct tm now_utc;
struct tm *now;
time(&now_t);
now = localtime(&now_t);
+ memcpy(&now_local, now, sizeof(struct tm));
+ now = gmtime(&now_t);
+ memcpy(&now_utc, now, sizeof(struct tm));
- type = xmlnode_get_attrib(packet, "type");
- from = xmlnode_get_attrib(packet, "from");
- id = xmlnode_get_attrib(packet, "id");
+ xmlns = xmlnode_get_namespace(child);
- /* we're gonna throw this away in a moment, but we need it
- * to get the xmlns, so we can figure out if this is
- * jabber:iq:time or urn:xmpp:time */
- query = xmlnode_get_child(packet, "query");
- xmlns = xmlnode_get_namespace(query);
-
- if(type && !strcmp(type, "get")) {
+ if(type == JABBER_IQ_GET) {
xmlnode *utc;
- const char *date;
+ const char *date, *tz, *display;
- iq = jabber_iq_new_query(js, JABBER_IQ_RESULT, xmlns);
+ iq = jabber_iq_new(js, JABBER_IQ_RESULT);
jabber_iq_set_id(iq, id);
- xmlnode_set_attrib(iq->node, "to", from);
-
- query = xmlnode_get_child(iq->node, "query");
+ if (from)
+ xmlnode_set_attrib(iq->node, "to", from);
- date = purple_utf8_strftime("%Y%m%dT%T", now);
- utc = xmlnode_new_child(query, "utc");
- xmlnode_insert_data(utc, date, -1);
+ child = xmlnode_new_child(iq->node, child->name);
+ xmlnode_set_namespace(child, xmlns);
+ utc = xmlnode_new_child(child, "utc");
if(!strcmp("urn:xmpp:time", xmlns)) {
- xmlnode_insert_data(utc, "Z", 1); /* of COURSE the thing that is the same is different */
+ tz = purple_get_tzoff_str(&now_local, TRUE);
+ xmlnode_insert_data(xmlnode_new_child(child, "tzo"), tz, -1);
- date = purple_get_tzoff_str(now, TRUE);
- xmlnode_insert_data(xmlnode_new_child(query, "tzo"), date, -1);
+ date = purple_utf8_strftime("%FT%TZ", &now_utc);
+ xmlnode_insert_data(utc, date, -1);
} else { /* jabber:iq:time */
- date = purple_utf8_strftime("%Z", now);
- xmlnode_insert_data(xmlnode_new_child(query, "tz"), date, -1);
+ tz = purple_utf8_strftime("%Z", &now_local);
+ xmlnode_insert_data(xmlnode_new_child(child, "tz"), tz, -1);
- date = purple_utf8_strftime("%d %b %Y %T", now);
- xmlnode_insert_data(xmlnode_new_child(query, "display"), date, -1);
- }
+ date = purple_utf8_strftime("%Y%m%dT%T", &now_utc);
+ xmlnode_insert_data(utc, date, -1);
- jabber_iq_send(iq);
- }
-}
-
-static void urn_xmpp_ping_parse(JabberStream *js, xmlnode *packet)
-{
- const char *type, *id, *from;
- JabberIq *iq;
-
- type = xmlnode_get_attrib(packet, "type");
- from = xmlnode_get_attrib(packet, "from");
- id = xmlnode_get_attrib(packet, "id");
-
- if(type && !strcmp(type, "get")) {
- iq = jabber_iq_new_query(js, JABBER_IQ_RESULT, "urn:xmpp:ping");
-
- jabber_iq_set_id(iq, id);
- xmlnode_set_attrib(iq->node, "to", from);
+ display = purple_utf8_strftime("%d %b %Y %T", &now_local);
+ xmlnode_insert_data(xmlnode_new_child(child, "display"), display, -1);
+ }
jabber_iq_send(iq);
- } else {
- /* XXX: error */
}
}
-static void jabber_iq_version_parse(JabberStream *js, xmlnode *packet)
+static void jabber_iq_version_parse(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *packet)
{
JabberIq *iq;
- const char *type, *from, *id;
xmlnode *query;
- type = xmlnode_get_attrib(packet, "type");
-
- if(type && !strcmp(type, "get")) {
+ if(type == JABBER_IQ_GET) {
GHashTable *ui_info;
const char *ui_name = NULL, *ui_version = NULL;
#if 0
@@ -265,11 +240,10 @@ static void jabber_iq_version_parse(JabberStream *js, xmlnode *packet)
osinfo.machine);
}
#endif
- from = xmlnode_get_attrib(packet, "from");
- id = xmlnode_get_attrib(packet, "id");
iq = jabber_iq_new_query(js, JABBER_IQ_RESULT, "jabber:iq:version");
- xmlnode_set_attrib(iq->node, "to", from);
+ if (from)
+ xmlnode_set_attrib(iq->node, "to", from);
jabber_iq_set_id(iq, id);
query = xmlnode_get_child(iq->node, "query");
@@ -310,33 +284,56 @@ void jabber_iq_remove_callback_by_id(JabberStream *js, const char *id)
void jabber_iq_parse(JabberStream *js, xmlnode *packet)
{
JabberCallbackData *jcd;
- xmlnode *query, *error, *x;
+ xmlnode *child, *error, *x;
const char *xmlns;
- const char *type, *id, *from;
- JabberIqHandler *jih;
+ const char *iq_type, *id, *from;
+ JabberIqType type = JABBER_IQ_NONE;
+
+ /*
+ * child will be either the first tag child or NULL if there is no child.
+ * Historically, we used just the 'query' subchild, but newer XEPs use
+ * differently named children. Grabbing the first child is (for the time
+ * being) sufficient.
+ */
+ for (child = packet->child; child; child = child->next) {
+ if (child->type == XMLNODE_TYPE_TAG)
+ break;
+ }
- query = xmlnode_get_child(packet, "query");
- type = xmlnode_get_attrib(packet, "type");
+ iq_type = xmlnode_get_attrib(packet, "type");
from = xmlnode_get_attrib(packet, "from");
id = xmlnode_get_attrib(packet, "id");
- if(type == NULL || !(!strcmp(type, "get") || !strcmp(type, "set")
- || !strcmp(type, "result") || !strcmp(type, "error"))) {
+ if (iq_type) {
+ if (!strcmp(iq_type, "get"))
+ type = JABBER_IQ_GET;
+ else if (!strcmp(iq_type, "set"))
+ type = JABBER_IQ_SET;
+ else if (!strcmp(iq_type, "result"))
+ type = JABBER_IQ_RESULT;
+ else if (!strcmp(iq_type, "error"))
+ type = JABBER_IQ_ERROR;
+ }
+
+ if (type == JABBER_IQ_NONE) {
purple_debug_error("jabber", "IQ with invalid type ('%s') - ignoring.\n",
- type ? type : "(null)");
+ iq_type ? iq_type : "(null)");
return;
}
/* All IQs must have an ID, so send an error for a set/get that doesn't */
if(!id || !*id) {
- if(!strcmp(type, "set") || !strcmp(type, "get")) {
+ if(type == JABBER_IQ_SET || type == JABBER_IQ_GET) {
JabberIq *iq = jabber_iq_new(js, JABBER_IQ_ERROR);
xmlnode_free(iq->node);
iq->node = xmlnode_copy(packet);
- xmlnode_set_attrib(iq->node, "to", from);
- xmlnode_remove_attrib(iq->node, "from");
+ if (from) {
+ xmlnode_set_attrib(iq->node, "to", from);
+ xmlnode_remove_attrib(iq->node, "from");
+ }
+
xmlnode_set_attrib(iq->node, "type", "error");
/* This id is clearly not useful, but we must put something there for a valid stanza */
iq->id = jabber_get_next_id(js);
@@ -348,67 +345,46 @@ void jabber_iq_parse(JabberStream *js, xmlnode *packet)
jabber_iq_send(iq);
} else
- purple_debug_error("jabber", "IQ of type '%s' missing id - ignoring.\n", type);
+ purple_debug_error("jabber", "IQ of type '%s' missing id - ignoring.\n",
+ iq_type);
return;
}
/* First, lets see if a special callback got registered */
-
- if(!strcmp(type, "result") || !strcmp(type, "error")) {
- if(id && *id && (jcd = g_hash_table_lookup(js->iq_callbacks, id))) {
- jcd->callback(js, packet, jcd->data);
+ if(type == JABBER_IQ_RESULT || type == JABBER_IQ_ERROR) {
+ if((jcd = g_hash_table_lookup(js->iq_callbacks, id))) {
+ jcd->callback(js, from, type, id, packet, jcd->data);
jabber_iq_remove_callback_by_id(js, id);
return;
}
}
/* Apparently not, so lets see if we have a pre-defined handler */
+ if(child && (xmlns = xmlnode_get_namespace(child))) {
+ char *key = g_strdup_printf("%s %s", child->name, xmlns);
+ JabberIqHandler *jih = g_hash_table_lookup(iq_handlers, key);
+ g_free(key);
- if(query && (xmlns = xmlnode_get_namespace(query))) {
- if((jih = g_hash_table_lookup(iq_handlers, xmlns))) {
- jih(js, packet);
+ if(jih) {
+ jih(js, from, type, id, child);
return;
}
}
- if(xmlnode_get_child_with_namespace(packet, "si", "http://jabber.org/protocol/si")) {
- jabber_si_parse(js, packet);
- return;
- }
-
- if(xmlnode_get_child_with_namespace(packet, "new-mail", "google:mail:notify")) {
- jabber_gmail_poke(js, packet);
- return;
- }
-
purple_debug_info("jabber", "jabber_iq_parse\n");
- if(xmlnode_get_child_with_namespace(packet, "ping", "urn:xmpp:ping")) {
- jabber_ping_parse(js, packet);
- return;
- }
-
- if (xmlnode_get_child_with_namespace(packet, "data", XEP_0231_NAMESPACE)) {
- jabber_data_parse(js, packet);
- return;
- }
-
- if (xmlnode_get_child_with_namespace(packet, "data", XEP_0047_NAMESPACE)
- || xmlnode_get_child_with_namespace(packet, "close", XEP_0047_NAMESPACE)
- || xmlnode_get_child_with_namespace(packet, "open", XEP_0047_NAMESPACE)) {
- jabber_ibb_parse(js, packet);
- return;
- }
-
/* If we get here, send the default error reply mandated by XMPP-CORE */
- if(!strcmp(type, "set") || !strcmp(type, "get")) {
+ if(type == JABBER_IQ_SET || type == JABBER_IQ_GET) {
JabberIq *iq = jabber_iq_new(js, JABBER_IQ_ERROR);
xmlnode_free(iq->node);
iq->node = xmlnode_copy(packet);
- xmlnode_set_attrib(iq->node, "to", from);
- xmlnode_remove_attrib(iq->node, "from");
+ if (from) {
+ xmlnode_set_attrib(iq->node, "to", from);
+ xmlnode_remove_attrib(iq->node, "from");
+ }
+
xmlnode_set_attrib(iq->node, "type", "error");
error = xmlnode_new_child(iq->node, "error");
xmlnode_set_attrib(error, "type", "cancel");
@@ -420,26 +396,36 @@ void jabber_iq_parse(JabberStream *js, xmlnode *packet)
}
}
-void jabber_iq_register_handler(const char *xmlns, JabberIqHandler *handlerfunc)
+void jabber_iq_register_handler(const char *node, const char *xmlns, JabberIqHandler *handlerfunc)
{
- g_hash_table_replace(iq_handlers, g_strdup(xmlns), handlerfunc);
+ /*
+ * This is valid because nodes nor namespaces cannot have spaces in them
+ * (see http://www.w3.org/TR/2006/REC-xml-20060816/ and
+ * http://www.w3.org/TR/REC-xml-names/)
+ */
+ char *key = g_strdup_printf("%s %s", node, xmlns);
+ g_hash_table_replace(iq_handlers, key, handlerfunc);
}
void jabber_iq_init(void)
{
iq_handlers = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
- jabber_iq_register_handler("jabber:iq:roster", jabber_roster_parse);
- jabber_iq_register_handler("jabber:iq:oob", jabber_oob_parse);
- jabber_iq_register_handler("http://jabber.org/protocol/bytestreams", jabber_bytestreams_parse);
- jabber_iq_register_handler("jabber:iq:last", jabber_iq_last_parse);
- jabber_iq_register_handler("jabber:iq:time", jabber_iq_time_parse);
- jabber_iq_register_handler("urn:xmpp:time", jabber_iq_time_parse);
- jabber_iq_register_handler("jabber:iq:version", jabber_iq_version_parse);
- jabber_iq_register_handler("http://jabber.org/protocol/disco#info", jabber_disco_info_parse);
- jabber_iq_register_handler("http://jabber.org/protocol/disco#items", jabber_disco_items_parse);
- jabber_iq_register_handler("jabber:iq:register", jabber_register_parse);
- jabber_iq_register_handler("urn:xmpp:ping", urn_xmpp_ping_parse);
+ jabber_iq_register_handler("mailbox", "google:mail:notify", jabber_gmail_poke);
+ jabber_iq_register_handler("new-mail", "google:mail:notify", jabber_gmail_poke);
+ jabber_iq_register_handler("query", "http://jabber.org/protocol/bytestreams", jabber_bytestreams_parse);
+ jabber_iq_register_handler("query", "http://jabber.org/protocol/disco#info", jabber_disco_info_parse);
+ jabber_iq_register_handler("query", "http://jabber.org/protocol/disco#items", jabber_disco_items_parse);
+ jabber_iq_register_handler("si", "http://jabber.org/protocol/si", jabber_si_parse);
+ jabber_iq_register_handler("query", "jabber:iq:last", jabber_iq_last_parse);
+ jabber_iq_register_handler("query", "jabber:iq:oob", jabber_oob_parse);
+ jabber_iq_register_handler("query", "jabber:iq:register", jabber_register_parse);
+ jabber_iq_register_handler("query", "jabber:iq:roster", jabber_roster_parse);
+ jabber_iq_register_handler("query", "jabber:iq:time", jabber_iq_time_parse);
+ jabber_iq_register_handler("query", "jabber:iq:version", jabber_iq_version_parse);
+ jabber_iq_register_handler("data", XEP_0231_NAMESPACE, jabber_data_parse);
+ jabber_iq_register_handler("ping", "urn:xmpp:ping", jabber_ping_parse);
+ jabber_iq_register_handler("time", "urn:xmpp:time", jabber_iq_time_parse);
}
void jabber_iq_uninit(void)
@@ -447,4 +433,3 @@ void jabber_iq_uninit(void)
g_hash_table_destroy(iq_handlers);
iq_handlers = NULL;
}
-
diff --git a/libpurple/protocols/jabber/iq.h b/libpurple/protocols/jabber/iq.h
index a8743350cd..4b9f5d2394 100644
--- a/libpurple/protocols/jabber/iq.h
+++ b/libpurple/protocols/jabber/iq.h
@@ -22,10 +22,6 @@
#ifndef _PURPLE_JABBER_IQ_H_
#define _PURPLE_JABBER_IQ_H_
-#include "jabber.h"
-
-typedef struct _JabberIq JabberIq;
-
typedef enum {
JABBER_IQ_SET,
JABBER_IQ_GET,
@@ -34,9 +30,17 @@ typedef enum {
JABBER_IQ_NONE
} JabberIqType;
-typedef void (JabberIqHandler)(JabberStream *js, xmlnode *packet);
+#include "jabber.h"
+
+typedef struct _JabberIq JabberIq;
+
+typedef void (JabberIqHandler)(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *child);
-typedef void (JabberIqCallback)(JabberStream *js, xmlnode *packet, gpointer data);
+typedef void (JabberIqCallback)(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *packet, gpointer data);
struct _JabberIq {
JabberIqType type;
@@ -65,6 +69,7 @@ void jabber_iq_free(JabberIq *iq);
void jabber_iq_init(void);
void jabber_iq_uninit(void);
-void jabber_iq_register_handler(const char *xmlns, JabberIqHandler *func);
+void jabber_iq_register_handler(const char *node, const char *xmlns,
+ JabberIqHandler *func);
#endif /* _PURPLE_JABBER_IQ_H_ */
diff --git a/libpurple/protocols/jabber/jabber.c b/libpurple/protocols/jabber/jabber.c
index 14b4a82287..8a3269a243 100644
--- a/libpurple/protocols/jabber/jabber.c
+++ b/libpurple/protocols/jabber/jabber.c
@@ -85,10 +85,11 @@ static void jabber_stream_init(JabberStream *js)
}
static void
-jabber_session_initialized_cb(JabberStream *js, xmlnode *packet, gpointer data)
+jabber_session_initialized_cb(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *packet, gpointer data)
{
- const char *type = xmlnode_get_attrib(packet, "type");
- if(type && !strcmp(type, "result")) {
+ if (type == JABBER_IQ_RESULT) {
jabber_stream_set_state(js, JABBER_STREAM_CONNECTED);
if(js->unregistration)
jabber_unregister_account_cb(js);
@@ -112,13 +113,13 @@ static void jabber_session_init(JabberStream *js)
jabber_iq_send(iq);
}
-static void jabber_bind_result_cb(JabberStream *js, xmlnode *packet,
- gpointer data)
+static void jabber_bind_result_cb(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *packet, gpointer data)
{
- const char *type = xmlnode_get_attrib(packet, "type");
xmlnode *bind;
- if(type && !strcmp(type, "result") &&
+ if (type == JABBER_IQ_RESULT &&
(bind = xmlnode_get_child_with_namespace(packet, "bind", "urn:ietf:params:xml:ns:xmpp-bind"))) {
xmlnode *jid;
char *full_jid;
@@ -446,13 +447,7 @@ void jabber_send(JabberStream *js, xmlnode *packet)
g_free(txt);
}
-static void jabber_pong_cb(JabberStream *js, xmlnode *packet, gpointer unused)
-{
- purple_timeout_remove(js->keepalive_timeout);
- js->keepalive_timeout = -1;
-}
-
-static gboolean jabber_pong_timeout(PurpleConnection *gc)
+static gboolean jabber_keepalive_timeout(PurpleConnection *gc)
{
JabberStream *js = gc->proto_data;
purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
@@ -466,14 +461,9 @@ void jabber_keepalive(PurpleConnection *gc)
JabberStream *js = gc->proto_data;
if (js->keepalive_timeout == -1) {
- JabberIq *iq = jabber_iq_new(js, JABBER_IQ_GET);
-
- xmlnode *ping = xmlnode_new_child(iq->node, "ping");
- xmlnode_set_namespace(ping, "urn:xmpp:ping");
-
- js->keepalive_timeout = purple_timeout_add_seconds(120, (GSourceFunc)(jabber_pong_timeout), gc);
- jabber_iq_set_callback(iq, jabber_pong_cb, NULL);
- jabber_iq_send(iq);
+ jabber_ping_jid(js, NULL);
+ js->keepalive_timeout = purple_timeout_add_seconds(120,
+ (GSourceFunc)(jabber_keepalive_timeout), gc);
}
}
@@ -796,14 +786,15 @@ jabber_connection_schedule_close(JabberStream *js)
}
static void
-jabber_registration_result_cb(JabberStream *js, xmlnode *packet, gpointer data)
+jabber_registration_result_cb(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *packet, gpointer data)
{
PurpleAccount *account = purple_connection_get_account(js->gc);
- const char *type = xmlnode_get_attrib(packet, "type");
char *buf;
char *to = data;
- if(!strcmp(type, "result")) {
+ if (type == JABBER_IQ_RESULT) {
if(js->registration) {
buf = g_strdup_printf(_("Registration of %s@%s successful"),
js->user->node, js->user->domain);
@@ -831,13 +822,14 @@ jabber_registration_result_cb(JabberStream *js, xmlnode *packet, gpointer data)
}
g_free(to);
if(js->registration)
- jabber_connection_schedule_close(js);
+ jabber_connection_schedule_close(js);
}
static void
-jabber_unregistration_result_cb(JabberStream *js, xmlnode *packet, gpointer data)
+jabber_unregistration_result_cb(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *packet, gpointer data)
{
- const char *type = xmlnode_get_attrib(packet, "type");
char *buf;
char *to = data;
@@ -845,7 +837,7 @@ jabber_unregistration_result_cb(JabberStream *js, xmlnode *packet, gpointer data
* the server, so there should always be a 'to' address. */
g_return_if_fail(to != NULL);
- if(!strcmp(type, "result")) {
+ if (type == JABBER_IQ_RESULT) {
buf = g_strdup_printf(_("Registration from %s successfully removed"),
to);
purple_notify_info(NULL, _("Unregistration Successful"),
@@ -994,31 +986,30 @@ static void jabber_register_x_data_cb(JabberStream *js, xmlnode *result, gpointe
jabber_iq_send(iq);
}
-void jabber_register_parse(JabberStream *js, xmlnode *packet)
+void jabber_register_parse(JabberStream *js, const char *from, JabberIqType type,
+ const char *id, xmlnode *query)
{
PurpleAccount *account = purple_connection_get_account(js->gc);
- const char *type;
- const char *from;
PurpleRequestFields *fields;
PurpleRequestFieldGroup *group;
PurpleRequestField *field;
- xmlnode *query, *x, *y;
+ xmlnode *x, *y;
char *instructions;
JabberRegisterCBData *cbdata;
gboolean registered = FALSE;
- if(!(type = xmlnode_get_attrib(packet, "type")) || strcmp(type, "result"))
+ if (type != JABBER_IQ_RESULT)
return;
- from = xmlnode_get_attrib(packet, "from");
+ if (!from)
+ from = js->serverFQDN;
+ g_return_if_fail(from != NULL);
if(js->registration) {
/* get rid of the login thingy */
purple_connection_set_state(js->gc, PURPLE_CONNECTED);
}
- query = xmlnode_get_child(packet, "query");
-
if(xmlnode_get_child(query, "registered")) {
registered = TRUE;
@@ -1252,10 +1243,14 @@ void jabber_register_account(PurpleAccount *account)
}
}
-static void jabber_unregister_account_iq_cb(JabberStream *js, xmlnode *packet, gpointer data) {
+static void
+jabber_unregister_account_iq_cb(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *packet, gpointer data)
+{
PurpleAccount *account = purple_connection_get_account(js->gc);
- const char *type = xmlnode_get_attrib(packet,"type");
- if(!strcmp(type,"error")) {
+
+ if (type == JABBER_IQ_ERROR) {
char *msg = jabber_parse_error(js, packet, NULL);
purple_notify_error(js->gc, _("Error unregistering account"),
@@ -1263,7 +1258,7 @@ static void jabber_unregister_account_iq_cb(JabberStream *js, xmlnode *packet, g
g_free(msg);
if(js->unregistration_cb)
js->unregistration_cb(account, FALSE, js->unregistration_user_data);
- } else if(!strcmp(type,"result")) {
+ } else {
purple_notify_info(js->gc, _("Account successfully unregistered"),
_("Account successfully unregistered"), NULL);
if(js->unregistration_cb)
@@ -1492,7 +1487,9 @@ void jabber_idle_set(PurpleConnection *gc, int idle)
js->idle = idle ? time(NULL) - idle : idle;
}
-static void jabber_blocklist_parse(JabberStream *js, xmlnode *packet, gpointer data)
+static void jabber_blocklist_parse(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *packet, gpointer data)
{
xmlnode *blocklist, *item;
PurpleAccount *account;
@@ -1916,14 +1913,11 @@ GList *jabber_status_types(PurpleAccount *account)
}
static void
-jabber_password_change_result_cb(JabberStream *js, xmlnode *packet,
- gpointer data)
+jabber_password_change_result_cb(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *packet, gpointer data)
{
- const char *type;
-
- type = xmlnode_get_attrib(packet, "type");
-
- if(type && !strcmp(type, "result")) {
+ if (type == JABBER_IQ_RESULT) {
purple_notify_info(js->gc, _("Password Changed"), _("Password Changed"),
_("Your password has been changed."));
@@ -2455,10 +2449,16 @@ static PurpleCmdRet jabber_cmd_chat_msg(PurpleConversation *conv,
static PurpleCmdRet jabber_cmd_ping(PurpleConversation *conv,
const char *cmd, char **args, char **error, void *data)
{
+ PurpleAccount *account;
+ PurpleConnection *pc;
+
if(!args || !args[0])
return PURPLE_CMD_RET_FAILED;
- if(!jabber_ping_jid(conv, args[0])) {
+ account = purple_conversation_get_account(conv);
+ pc = purple_account_get_connection(account);
+
+ if(!jabber_ping_jid(purple_connection_get_protocol_data(pc), args[0])) {
*error = g_strdup_printf(_("Unable to ping user %s"), args[0]);
return PURPLE_CMD_RET_FAILED;
}
diff --git a/libpurple/protocols/jabber/jabber.h b/libpurple/protocols/jabber/jabber.h
index d616119631..f154c9dc95 100644
--- a/libpurple/protocols/jabber/jabber.h
+++ b/libpurple/protocols/jabber/jabber.h
@@ -57,6 +57,7 @@ typedef struct _JabberStream JabberStream;
#include "roomlist.h"
#include "sslconn.h"
+#include "iq.h"
#include "jutil.h"
#include "xmlnode.h"
#include "buddy.h"
@@ -269,7 +270,8 @@ void jabber_send_raw(JabberStream *js, const char *data, int len);
void jabber_stream_set_state(JabberStream *js, JabberStreamState state);
-void jabber_register_parse(JabberStream *js, xmlnode *packet);
+void jabber_register_parse(JabberStream *js, const char *from,
+ JabberIqType type, const char *id, xmlnode *query);
void jabber_register_start(JabberStream *js);
char *jabber_get_next_id(JabberStream *js);
diff --git a/libpurple/protocols/jabber/message.c b/libpurple/protocols/jabber/message.c
index ed7fdc9eec..adc5feac85 100644
--- a/libpurple/protocols/jabber/message.c
+++ b/libpurple/protocols/jabber/message.c
@@ -477,7 +477,9 @@ typedef struct {
} JabberDataRef;
static void
-jabber_message_get_data_cb(JabberStream *js, xmlnode *packet, gpointer data)
+jabber_message_get_data_cb(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *packet, gpointer data)
{
JabberDataRef *ref = (JabberDataRef *) data;
PurpleConversation *conv = ref->conv;
diff --git a/libpurple/protocols/jabber/oob.c b/libpurple/protocols/jabber/oob.c
index e43bf5c3ec..73b18fb030 100644
--- a/libpurple/protocols/jabber/oob.c
+++ b/libpurple/protocols/jabber/oob.c
@@ -187,18 +187,18 @@ static void jabber_oob_xfer_recv_canceled(PurpleXfer *xfer) {
jabber_oob_xfer_recv_error(xfer, "404");
}
-void jabber_oob_parse(JabberStream *js, xmlnode *packet) {
+void jabber_oob_parse(JabberStream *js, const char *from, JabberIqType type,
+ const char *id, xmlnode *querynode) {
JabberOOBXfer *jox;
PurpleXfer *xfer;
char *filename;
char *url;
- const char *type;
- xmlnode *querynode, *urlnode;
+ xmlnode *urlnode;
- if(!(type = xmlnode_get_attrib(packet, "type")) || strcmp(type, "set"))
+ if(type != JABBER_IQ_SET)
return;
- if(!(querynode = xmlnode_get_child(packet, "query")))
+ if(!from)
return;
if(!(urlnode = xmlnode_get_child(querynode, "url")))
@@ -211,10 +211,9 @@ void jabber_oob_parse(JabberStream *js, xmlnode *packet) {
g_free(url);
jox->js = js;
jox->headers = g_string_new("");
- jox->iq_id = g_strdup(xmlnode_get_attrib(packet, "id"));
+ jox->iq_id = g_strdup(id);
- xfer = purple_xfer_new(js->gc->account, PURPLE_XFER_RECEIVE,
- xmlnode_get_attrib(packet, "from"));
+ xfer = purple_xfer_new(js->gc->account, PURPLE_XFER_RECEIVE, from);
if (xfer)
{
xfer->data = jox;
diff --git a/libpurple/protocols/jabber/oob.h b/libpurple/protocols/jabber/oob.h
index 3a669003dd..6fe67461f9 100644
--- a/libpurple/protocols/jabber/oob.h
+++ b/libpurple/protocols/jabber/oob.h
@@ -22,6 +22,9 @@
#ifndef _PURPLE_JABBER_OOB_H_
#define _PURPLE_JABBER_OOB_H_
-void jabber_oob_parse(JabberStream *js, xmlnode *packet);
+#include "jabber.h"
+
+void jabber_oob_parse(JabberStream *js, const char *from, JabberIqType type,
+ const char *id, xmlnode *querynode);
#endif /* _PURPLE_JABBER_OOB_H_ */
diff --git a/libpurple/protocols/jabber/pep.c b/libpurple/protocols/jabber/pep.c
index 843e69b427..514c1f86d3 100644
--- a/libpurple/protocols/jabber/pep.c
+++ b/libpurple/protocols/jabber/pep.c
@@ -52,8 +52,11 @@ void jabber_pep_register_handler(const char *shortname, const char *xmlns, Jabbe
g_hash_table_replace(pep_handlers, g_strdup(xmlns), handlerfunc);
}
-static void do_pep_iq_request_item_callback(JabberStream *js, xmlnode *packet, gpointer data) {
- const char *from = xmlnode_get_attrib(packet,"from");
+static void
+do_pep_iq_request_item_callback(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *packet, gpointer data)
+{
xmlnode *pubsub = xmlnode_get_child_with_namespace(packet,"pubsub","http://jabber.org/protocol/pubsub");
xmlnode *items = NULL;
JabberPEPHandler *cb = data;
diff --git a/libpurple/protocols/jabber/ping.c b/libpurple/protocols/jabber/ping.c
index 4339c27dd1..058f9bcdbd 100644
--- a/libpurple/protocols/jabber/ping.c
+++ b/libpurple/protocols/jabber/ping.c
@@ -23,50 +23,63 @@
#include "internal.h"
#include "debug.h"
-#include "xmlnode.h"
#include "jabber.h"
#include "ping.h"
#include "iq.h"
-void
-jabber_ping_parse(JabberStream *js, xmlnode *packet)
+static void jabber_keepalive_pong_cb(JabberStream *js)
{
- JabberIq *iq;
-
- purple_debug_info("jabber", "jabber_ping_parse\n");
-
- iq = jabber_iq_new(js, JABBER_IQ_RESULT);
+ purple_timeout_remove(js->keepalive_timeout);
+ js->keepalive_timeout = -1;
+}
- xmlnode_set_attrib(iq->node, "to", xmlnode_get_attrib(packet, "from") );
+void
+jabber_ping_parse(JabberStream *js, const char *from,
+ JabberIqType type, const char *id, xmlnode *ping)
+{
+ if (type == JABBER_IQ_GET) {
+ JabberIq *iq = jabber_iq_new(js, JABBER_IQ_RESULT);
- jabber_iq_set_id(iq, xmlnode_get_attrib(packet, "id"));
+ if (from)
+ xmlnode_set_attrib(iq->node, "to", from);
+ xmlnode_set_attrib(iq->node, "id", id);
- jabber_iq_send(iq);
+ jabber_iq_send(iq);
+ } else if (type == JABBER_IQ_SET) {
+ /* XXX: error */
+ }
}
-static void jabber_ping_result_cb(JabberStream *js, xmlnode *packet,
- gpointer data)
+static void jabber_ping_result_cb(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *packet, gpointer data)
{
- const char *type = xmlnode_get_attrib(packet, "type");
+ char *own_bare_jid = g_strdup_printf("%s@%s", js->user->node,
+ js->user->domain);
+
+ if (!from || !strcmp(from, own_bare_jid)) {
+ /* If the pong is from our bare JID, treat it as a return from the
+ * keepalive functions */
+ jabber_keepalive_pong_cb(js);
+ }
+ g_free(own_bare_jid);
- purple_debug_info("jabber", "jabber_ping_result_cb\n");
- if(type && !strcmp(type, "result")) {
+ if (type == JABBER_IQ_RESULT) {
purple_debug_info("jabber", "PONG!\n");
} else {
purple_debug_info("jabber", "(not supported)\n");
}
}
-gboolean jabber_ping_jid(PurpleConversation *conv, const char *jid)
+gboolean jabber_ping_jid(JabberStream *js, const char *jid)
{
JabberIq *iq;
xmlnode *ping;
- purple_debug_info("jabber", "jabber_ping_jid\n");
-
- iq = jabber_iq_new(conv->account->gc->proto_data, JABBER_IQ_GET);
- xmlnode_set_attrib(iq->node, "to", jid);
+ iq = jabber_iq_new(js, JABBER_IQ_GET);
+ if (jid)
+ xmlnode_set_attrib(iq->node, "to", jid);
ping = xmlnode_new_child(iq->node, "ping");
xmlnode_set_namespace(ping, "urn:xmpp:ping");
@@ -74,7 +87,5 @@ gboolean jabber_ping_jid(PurpleConversation *conv, const char *jid)
jabber_iq_set_callback(iq, jabber_ping_result_cb, NULL);
jabber_iq_send(iq);
-
-
return TRUE;
}
diff --git a/libpurple/protocols/jabber/ping.h b/libpurple/protocols/jabber/ping.h
index 377452f56c..fd906384b0 100644
--- a/libpurple/protocols/jabber/ping.h
+++ b/libpurple/protocols/jabber/ping.h
@@ -23,13 +23,11 @@
#define _PURPLE_JABBER_PING_H_
#include "jabber.h"
-#include "conversation.h"
-
-void jabber_ping_parse(JabberStream *js,
- xmlnode *packet);
-
-
-gboolean jabber_ping_jid(PurpleConversation *conv, const char *jid);
+#include "iq.h"
+#include "xmlnode.h"
+void jabber_ping_parse(JabberStream *js, const char *from,
+ JabberIqType, const char *id, xmlnode *child);
+gboolean jabber_ping_jid(JabberStream *js, const char *jid);
#endif /* _PURPLE_JABBER_PING_H_ */
diff --git a/libpurple/protocols/jabber/presence.c b/libpurple/protocols/jabber/presence.c
index d22e6a0726..90a80ae39d 100644
--- a/libpurple/protocols/jabber/presence.c
+++ b/libpurple/protocols/jabber/presence.c
@@ -326,14 +326,16 @@ static void deny_add_cb(gpointer data)
g_free(jap);
}
-static void jabber_vcard_parse_avatar(JabberStream *js, xmlnode *packet, gpointer blah)
+static void
+jabber_vcard_parse_avatar(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *packet, gpointer blah)
{
JabberBuddy *jb = NULL;
xmlnode *vcard, *photo, *binval;
char *text;
guchar *data;
gsize size;
- const char *from = xmlnode_get_attrib(packet, "from");
if(!from)
return;
diff --git a/libpurple/protocols/jabber/roster.c b/libpurple/protocols/jabber/roster.c
index 9febc1e729..e051fbc65c 100644
--- a/libpurple/protocols/jabber/roster.c
+++ b/libpurple/protocols/jabber/roster.c
@@ -145,10 +145,10 @@ static void add_purple_buddies_to_groups(JabberStream *js, const char *jid,
g_slist_free(buddies);
}
-void jabber_roster_parse(JabberStream *js, xmlnode *packet)
+void jabber_roster_parse(JabberStream *js, const char *from,
+ JabberIqType type, const char *id, xmlnode *query)
{
- xmlnode *query, *item, *group;
- const char *from = xmlnode_get_attrib(packet, "from");
+ xmlnode *item, *group;
if(from) {
char *from_norm;
@@ -169,10 +169,6 @@ void jabber_roster_parse(JabberStream *js, xmlnode *packet)
return;
}
- query = xmlnode_get_child(packet, "query");
- if(!query)
- return;
-
js->currently_parsing_roster_push = TRUE;
for(item = xmlnode_get_child(query, "item"); item; item = xmlnode_get_next_twin(item))
diff --git a/libpurple/protocols/jabber/roster.h b/libpurple/protocols/jabber/roster.h
index a20ac309ee..227abdfffa 100644
--- a/libpurple/protocols/jabber/roster.h
+++ b/libpurple/protocols/jabber/roster.h
@@ -26,7 +26,8 @@
void jabber_roster_request(JabberStream *js);
-void jabber_roster_parse(JabberStream *js, xmlnode *packet);
+void jabber_roster_parse(JabberStream *js, const char *from,
+ JabberIqType type, const char *id, xmlnode *query);
void jabber_roster_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy,
PurpleGroup *group);
diff --git a/libpurple/protocols/jabber/si.c b/libpurple/protocols/jabber/si.c
index fe3f490c22..ae8ef41f12 100644
--- a/libpurple/protocols/jabber/si.c
+++ b/libpurple/protocols/jabber/si.c
@@ -311,20 +311,18 @@ static void jabber_si_bytestreams_attempt_connect(PurpleXfer *xfer)
}
}
-void jabber_bytestreams_parse(JabberStream *js, xmlnode *packet)
+void jabber_bytestreams_parse(JabberStream *js, const char *from,
+ JabberIqType type, const char *id, xmlnode *query)
{
PurpleXfer *xfer;
JabberSIXfer *jsx;
- xmlnode *query, *streamhost;
- const char *sid, *from, *type;
-
- if(!(type = xmlnode_get_attrib(packet, "type")) || strcmp(type, "set"))
- return;
+ xmlnode *streamhost;
+ const char *sid;
- if(!(from = xmlnode_get_attrib(packet, "from")))
+ if(type != JABBER_IQ_SET)
return;
- if(!(query = xmlnode_get_child(packet, "query")))
+ if(!from)
return;
if(!(sid = xmlnode_get_attrib(query, "sid")))
@@ -340,7 +338,7 @@ void jabber_bytestreams_parse(JabberStream *js, xmlnode *packet)
if(jsx->iq_id)
g_free(jsx->iq_id);
- jsx->iq_id = g_strdup(xmlnode_get_attrib(packet, "id"));
+ jsx->iq_id = g_strdup(id);
for(streamhost = xmlnode_get_child(query, "streamhost"); streamhost;
streamhost = xmlnode_get_next_twin(streamhost)) {
@@ -685,13 +683,14 @@ jabber_si_xfer_bytestreams_send_connected_cb(gpointer data, gint source,
}
static void
-jabber_si_connect_proxy_cb(JabberStream *js, xmlnode *packet,
- gpointer data)
+jabber_si_connect_proxy_cb(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *packet, gpointer data)
{
PurpleXfer *xfer = data;
JabberSIXfer *jsx;
xmlnode *query, *streamhost_used;
- const char *from, *type, *jid;
+ const char *jid;
GList *matched;
/* TODO: This need to send errors if we don't see what we're looking for */
@@ -708,37 +707,34 @@ jabber_si_connect_proxy_cb(JabberStream *js, xmlnode *packet,
jsx = xfer->data;
- if(!(type = xmlnode_get_attrib(packet, "type")) || strcmp(type, "result")) {
- purple_debug_info("jabber",
- "jabber_si_xfer_connect_proxy_cb: type = %s\n",
- type);
- if (type && !strcmp(type, "error")) {
- /* if IBB is available, open IBB session */
- purple_debug_info("jabber",
- "jabber_si_xfer_connect_proxy_cb: got error, method: %d\n",
- jsx->stream_method);
- if (jsx->stream_method & STREAM_METHOD_IBB) {
- purple_debug_info("jabber", "IBB is possible, try it\n");
- /* if we are the sender and haven't already opened an IBB
- session, do so now (we might already have failed to open
- the bytestream proxy ourselves when receiving this <iq/> */
- if (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND
- && !jsx->ibb_session) {
- jabber_si_xfer_ibb_send_init(js, xfer);
- } else {
- jsx->ibb_timeout_handle = purple_timeout_add_seconds(30,
- jabber_si_bytestreams_ibb_timeout_cb, xfer);
- }
- /* if we are receiver, just wait for IBB open stanza, callback
- is already set up */
+ if(type != JABBER_IQ_RESULT) {
+ purple_debug_info("jabber",
+ "jabber_si_xfer_connect_proxy_cb: type = error\n");
+ /* if IBB is available, open IBB session */
+ purple_debug_info("jabber",
+ "jabber_si_xfer_connect_proxy_cb: got error, method: %d\n",
+ jsx->stream_method);
+ if (jsx->stream_method & STREAM_METHOD_IBB) {
+ purple_debug_info("jabber", "IBB is possible, try it\n");
+ /* if we are the sender and haven't already opened an IBB
+ session, do so now (we might already have failed to open
+ the bytestream proxy ourselves when receiving this <iq/> */
+ if (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND
+ && !jsx->ibb_session) {
+ jabber_si_xfer_ibb_send_init(js, xfer);
} else {
- purple_xfer_cancel_remote(xfer);
+ jsx->ibb_timeout_handle = purple_timeout_add_seconds(30,
+ jabber_si_bytestreams_ibb_timeout_cb, xfer);
}
+ /* if we are receiver, just wait for IBB open stanza, callback
+ is already set up */
+ } else {
+ purple_xfer_cancel_remote(xfer);
}
return;
}
- if(!(from = xmlnode_get_attrib(packet, "from")))
+ if (!from)
return;
if(!(query = xmlnode_get_child(packet, "query")))
@@ -1183,8 +1179,9 @@ jabber_si_xfer_ibb_send_init(JabberStream *js, PurpleXfer *xfer)
}
}
-static void jabber_si_xfer_send_method_cb(JabberStream *js, xmlnode *packet,
- gpointer data)
+static void jabber_si_xfer_send_method_cb(JabberStream *js, const char *from,
+ JabberIqType type, const char *id,
+ xmlnode *packet, gpointer data)
{
PurpleXfer *xfer = data;
xmlnode *si, *feature, *x, *field, *value;
@@ -1585,17 +1582,15 @@ void jabber_si_xfer_send(PurpleConnection *gc, const char *who, const char *file
purple_xfer_request(xfer);
}
-void jabber_si_parse(JabberStream *js, xmlnode *packet)
+void jabber_si_parse(JabberStream *js, const char *from, JabberIqType type,
+ const char *id, xmlnode *si)
{
JabberSIXfer *jsx;
PurpleXfer *xfer;
- xmlnode *si, *file, *feature, *x, *field, *option, *value;
- const char *stream_id, *filename, *filesize_c, *profile, *from;
+ xmlnode *file, *feature, *x, *field, *option, *value;
+ const char *stream_id, *filename, *filesize_c, *profile;
size_t filesize = 0;
- if(!(si = xmlnode_get_child(packet, "si")))
- return;
-
if(!(profile = xmlnode_get_attrib(si, "profile")) ||
strcmp(profile, "http://jabber.org/protocol/si/profile/file-transfer"))
return;
@@ -1618,7 +1613,7 @@ void jabber_si_parse(JabberStream *js, xmlnode *packet)
if(!(x = xmlnode_get_child_with_namespace(feature, "x", "jabber:x:data")))
return;
- if(!(from = xmlnode_get_attrib(packet, "from")))
+ if(!from)
return;
/* if they've already sent us this file transfer with the same damn id
@@ -1659,7 +1654,7 @@ void jabber_si_parse(JabberStream *js, xmlnode *packet)
jsx->js = js;
jsx->stream_id = g_strdup(stream_id);
- jsx->iq_id = g_strdup(xmlnode_get_attrib(packet, "id"));
+ jsx->iq_id = g_strdup(id);
xfer = purple_xfer_new(js->gc->account, PURPLE_XFER_RECEIVE, from);
if (xfer)
diff --git a/libpurple/protocols/jabber/si.h b/libpurple/protocols/jabber/si.h
index 120046fc59..a54b072d85 100644
--- a/libpurple/protocols/jabber/si.h
+++ b/libpurple/protocols/jabber/si.h
@@ -26,8 +26,10 @@
#include "jabber.h"
-void jabber_bytestreams_parse(JabberStream *js, xmlnode *packet);
-void jabber_si_parse(JabberStream *js, xmlnode *packet);
+void jabber_bytestreams_parse(JabberStream *js, const char *from,
+ JabberIqType type, const char *id, xmlnode *query);
+void jabber_si_parse(JabberStream *js, const char *from, JabberIqType type,
+ const char *id, xmlnode *si);
PurpleXfer *jabber_si_new_xfer(PurpleConnection *gc, const char *who);
void jabber_si_xfer_send(PurpleConnection *gc, const char *who, const char *file);
void jabber_si_init(void);