changeset 13177:891be2f09b5c

[gaim-migrate @ 15540] adding support for xpidf used by windows messenger and changing Contact headers to be accepted by LCS committer: Tailor Script <tailor@pidgin.im>
author Thomas Butter <tbutter>
date Wed, 08 Feb 2006 05:53:52 +0000
parents dbe0198ced4b
children 35190e33a785
files src/protocols/simple/simple.c src/protocols/simple/simple.h
diffstat 2 files changed, 69 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/src/protocols/simple/simple.c	Wed Feb 08 05:45:03 2006 +0000
+++ b/src/protocols/simple/simple.c	Wed Feb 08 05:53:52 2006 +0000
@@ -141,12 +141,13 @@
 	return NULL;
 }
 
-static struct simple_watcher *watcher_create(struct simple_account_data *sip, gchar *name, gchar *callid, gchar *ourtag, gchar *theirtag) {
+static struct simple_watcher *watcher_create(struct simple_account_data *sip, gchar *name, gchar *callid, gchar *ourtag, gchar *theirtag, int needsxpidf) {
 	struct simple_watcher *watcher = g_new0(struct simple_watcher, 1);
 	watcher->name = g_strdup(name);
 	watcher->dialog.callid = g_strdup(callid);
 	watcher->dialog.ourtag = g_strdup(ourtag);
 	watcher->dialog.theirtag = g_strdup(theirtag);
+	watcher->needsxpidf = needsxpidf;
 	sip->watcher = g_slist_append(sip->watcher, watcher);
 	return watcher;
 }
@@ -607,10 +608,16 @@
 	g_free(buf);
 }
 
+static char *get_contact(struct simple_account_data  *sip) {
+	return g_strdup_printf("<sip:%s@%s:%d;transport=%s>;methods=\"MESSAGE, SUBSCRIBE, NOTIFY\"", sip->username, gaim_network_get_my_ip(-1), sip->listenport, sip->udp ? "udp" : "tcp");
+}
+
 static void do_register_exp(struct simple_account_data *sip, int expire) {
 	char *uri = g_strdup_printf("sip:%s",sip->servername);
 	char *to = g_strdup_printf("sip:%s@%s",sip->username,sip->servername);
-	char *contact = g_strdup_printf("Contact: <sip:%s@%s:%d;transport=%s>;methods=\"MESSAGE, SUBSCRIBE, NOTIFY\"\r\nExpires: %d\r\n", sip->username, gaim_network_get_my_ip(-1), sip->listenport, sip->udp ? "udp" : "tcp", expire);
+	char *contact = get_contact(sip);
+	char *hdr = g_strdup_printf("Contact: %s\r\nExpires: %d\r\n", contact, expire);
+	g_free(contact);
 
 	sip->registerstatus = 1;
 
@@ -619,8 +626,8 @@
 	} else {
 		sip->reregister = time(NULL) + 600;
 	}
-	send_sip_request(sip->gc,"REGISTER",uri,to, contact, "", NULL, process_register_response);
-	g_free(contact);
+	send_sip_request(sip->gc,"REGISTER",uri,to, hdr, "", NULL, process_register_response);
+	g_free(hdr);
 	g_free(uri);
 	g_free(to);
 }
@@ -674,11 +681,14 @@
 }
 
 static void simple_subscribe(struct simple_account_data *sip, struct simple_buddy *buddy) {
-	gchar *contact = "Expires: 300\r\nAccept: application/pidf+xml\r\nEvent: presence\r\n";
+	gchar *contact = "Expires: 300\r\nAccept: application/pidf+xml, application/xpidf+xml\r\nEvent: presence\r\n";
 	gchar *to;
+	gchar *tmp;
 	if(strstr(buddy->name,"sip:")) to = g_strdup(buddy->name);
 	else to = g_strdup_printf("sip:%s",buddy->name);
-	contact = g_strdup_printf("%sContact: <sip:%s@%s>\r\n", contact, sip->username, sip->servername);
+	tmp = get_contact(sip);
+	contact = g_strdup_printf("%sContact: %s\r\n", contact, tmp);
+	g_free(tmp);
 	/* subscribe to buddy presence
 	 * we dont need to know the status so we do not need a callback */
 
@@ -937,6 +947,29 @@
 	return g_strdup(tmp);
 }
 
+static gchar* gen_xpidf(struct simple_account_data *sip) {
+	gchar *doc = g_strdup_printf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+			"<presence>\n"
+			"<presentity uri=\"sip:%s@%s;method=SUBSCRIBE\"/>\n"
+			"<display name=\"sip:%s@%s\"/>\n"
+			"<atom id=\"1234\">\n"
+			"<address uri=\"sip:%s@%s\">\n"
+			"<status status=\"%s\"/>\n"
+			"</address>\n"
+			"</atom>\n"
+			"</presence>\n",
+			sip->username,
+			sip->servername,
+			sip->username,
+			sip->servername,
+			sip->username,
+			sip->servername,
+			sip->status);
+	return doc;
+}
+
+
+
 static gchar* gen_pidf(struct simple_account_data *sip) {
 	gchar *doc = g_strdup_printf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
 			"<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n"
@@ -956,8 +989,9 @@
 }
 
 static void send_notify(struct simple_account_data *sip, struct simple_watcher *watcher) {
-	gchar *doc = gen_pidf(sip);
-	send_sip_request(sip->gc, "NOTIFY", watcher->name, watcher->name, "Event: presence\r\nContent-Type: application/pidf+xml\r\n", doc, &watcher->dialog, NULL);
+	gchar *doc = watcher->needsxpidf ? gen_xpidf(sip) : gen_pidf(sip);
+	gchar *hdr = watcher->needsxpidf ? "Event: presence\r\nContent-Type: application/xpidf+xml\r\n" : "Event: presence\r\nContent-Type: application/pidf+xml\r\n";
+	send_sip_request(sip->gc, "NOTIFY", watcher->name, watcher->name, hdr, doc, &watcher->dialog, NULL);
 	g_free(doc);
 }
 
@@ -991,11 +1025,34 @@
 		ourtag = gentag();
 	}
 	if(!watcher) { /* new subscription */
+		gchar *acceptheader = sipmsg_find_header(msg, "Accept");
+		int needsxpidf = 0;
 		if(!gaim_privacy_check(sip->account, from)) {
 			send_sip_response(sip->gc, msg, 202, "Ok", NULL);
 			goto privend;
 		}
-		watcher = watcher_create(sip, from, callid, ourtag, theirtag);
+		if(acceptheader) {
+			gchar *tmp = acceptheader;
+			int foundpidf = 0;
+			int foundxpidf = 0;
+			while(tmp && tmp < acceptheader + strlen(acceptheader)) {
+				gchar *tmp2 = strchr(tmp, ',');
+				if(tmp2) *tmp2 = '\0';
+				if(!strcmp("application/pidf+xml",tmp))
+					foundpidf = 1;
+				if(!strcmp("application/xpidf+xml",tmp))
+					foundxpidf = 1;
+				if(tmp2) {
+					*tmp2 = ',';
+					tmp = tmp2;
+					while(*tmp == ' ') tmp++;
+				} else
+					tmp = 0;
+			}
+			if(!foundpidf && foundxpidf) needsxpidf = 1;
+			g_free(acceptheader);
+		}
+		watcher = watcher_create(sip, from, callid, ourtag, theirtag, needsxpidf);
 	}
 	if(tagadded) {
 		gchar *to = g_strdup_printf("%s;tag=%s", sipmsg_find_header(msg, "To"), ourtag);
@@ -1007,11 +1064,11 @@
 	else
 		watcher->expire = time(NULL) + 600;
 	sipmsg_remove_header(msg, "Contact");
-	tmp = g_strdup_printf("<sip:%s@%s>",sip->username, sip->servername);
+	tmp = get_contact(sip);
 	sipmsg_add_header(msg, "Contact", tmp);
+	g_free(tmp);
 	gaim_debug_info("simple","got subscribe: name %s ourtag %s theirtag %s callid %s\n", watcher->name, watcher->dialog.ourtag, watcher->dialog.theirtag, watcher->dialog.callid);
 	send_sip_response(sip->gc, msg, 200, "Ok", NULL);
-	g_free(tmp);
 	send_notify(sip, watcher);
 privend:
 	g_free(from);
--- a/src/protocols/simple/simple.h	Wed Feb 08 05:45:03 2006 +0000
+++ b/src/protocols/simple/simple.h	Wed Feb 08 05:53:52 2006 +0000
@@ -43,6 +43,7 @@
 	gchar *name;
 	time_t expire;
 	struct sip_dialog dialog;
+	int needsxpidf;
 };
 
 struct simple_buddy {