PyMSNt Client Developer Guide

Please visit http://delx.cjb.net/pymsnt to download the transport and see news updates

If you have any insights or comments to add to this page please let me know by email or Jabber: james@delx.cjb.net


Overview

All of this document applies to PyMSNt 0.11.

This page documents the protocols that PyMSNt understands and uses to accomplish various tasks, such as registration sending avatars, dynamic nicknames and roster pushes.

I don't have the time or inclination to submit all of these as JEPs. Anybody is welcome to write them up if they wish, and if a JEP comes along with equivalent functionality then I'll most likely depreciate these and implement the official standard.

Note that with the exception of roster pushes, these protocols are not specific to gateway interaction, and SHOULD NOT be applied specially to MSN contacts.


Required JEPs

To register with PyMSNt your client must support JEP-0077, (In-Band Registration).
It is also strongly recommended that you support:


Basic Presence

You don't need to do anything special to support this section. It's just informational for those who want to know how it works. To log in, or set your status all you need to do is send a presence packet like the following:

<presence>
	<show>dnd</show>
	<status>My Status Message</status>
</presence>

The Jabber status message and show get mapped to the MSN7 personal message and status, respectively. The show tag is mapped to the most appropriate status code that MSN has available.

This operates exactly in reverse. PyMSNt will send you presence packets with the same field mappings whenever MSN contacts change their status. So you'll get packets like:

<presence from="friend%hotmail.com@msn.host.com">
	<show>away</show>
	<status>My Friend's Status Message</status>
</presence>

Adding Contacts

To add a MSN contact you should follow the instructions given in section 6.3, (jabber:iq:gateway) of JEP-0100 (Gateway Interaction).


Typing notification

PyMSNt supports typing notification according to JEP-0022 (Message Events). Only the <composing/> tag is supported.


Request no errors

You can ask PyMSNt to not send you errors in response to a <message> packet that you send. This should only ever be used by drone programs, clients that interact with users should always give users the error message.

To tell PyMSNt you don't want to hear about any errors do this

<message to="user%hotmail.com">
	<body>
		Hi friend! If you don't get this message then I won't be
		told by my transport. It will be silently dropped.
	</body>
	<noerror xmlns="sapo:noerror"/>
</message>

Groupchat

PyMSNt only uses a subset of JEP-0045 (Multi-User Chat). This subset was originally known as "Groupchat 1.0". If you follow the instructions given in JEP-0045 to join a room with any name not containing a % (percent) character, you will be able to invite multiple MSN users to the room and chat with them.


Avatars

PyMSNt implements avatars using the vCard. See vcard-temp. To get the vCard of a MSN contact you should do this:

<iq type="get" to="friend%hotmail.com@msn.host.com" id="randomvalue" >
	<vCard xmlns="vcard-temp"/>
</iq>

<iq from="friend%hotmail.com@msn.host.com" type="result" id="randomvalue">
	<vCard xmlns="vcard-temp">
		<NICKNAME>Friend's nickname</NICKNAME>
		<PHOTO>
			<TYPE>image/png</TYPE>
			<BINVAL>
				BASE64 PNG DATA GOES HERE
			</BINVAL>
		</PHOTO>
	</vCard>
</iq>

Note the NICKNAME tag has the MSN contact's nickname in it. The BINVAL field contains the base64 image, the type is given in the TYPE field. For MSN users this type will always be "image/png", but you MUST NOT assume this!

Once again this protocol works in reverse. PyMSNt fetches your vCard once whenever a session is started. If it finds a NICKNAME tag it will set your MSN nickname to this value. If it finds a vCard then it will make that available to other MSN users.

If you want to get avatars or nicknames to dynamically update when changed then you need to implement the next section.


Dynamic vCard Updates

To signal an update of your avatar or nickname send a presence packet like below. Do this after you have updated your vCard.

<presence>
	<show>dnd</show>
	<status>My Status Message</status>
	<x xmlns="vcard-temp:x:update">
		<photo>hex SHA1 hash of avatar</photo>
		<nickname>My Nickname Goes Here</nickname>
	</x>
</presence>

In the above example the nickname tag SHOULD be identical to the nickname you specify in your vCard's nickname field.

This is because if the photo hash hasn't changed, but the nickname tag has, then PyMSNt will not fetch the vCard, it will use the value from that tag. However if the photo hash has changed, the nickname value will be taken from the vCard. Just keep these values the same and you'll never have to worry :)

The photo tag has to have the 40 byte hex hash of the avatar you have just set in your vCard. Doing the vCard update is covered in JEP-0054, (vcard-temp).

Once again, this works exactly the same in reverse. PyMSNt will send you presence packets like this for all of your MSN contacts. If the photo hash changes and you haven't cached that avatar, you should retrieve retrieve it from the MSN contact's vCard. If the nickname changes, then update your on-screen display.

Status and show fields behave exactly as described above in "Basic Presence"


Roster Pushes

The reason for this protocol is to allow users to keep their MSN and Jabber lists synchronised. That is, any users they add in MSN, using the MSN client should be automatically added and authorised in Jabber. This is especially important for their first logon, just after registration. Otherwise they have to reauthorise all of the contacts on their MSN list.

The way I've implemented it is this. Treat all subscription packets just like normal, unless they have a <x> tag qualified by the http://delx.cjb.net/protocol/roster-subsync namespace.

For more details see http://delx.cjb.net/pymsnt/jep/roster-subsync/JEP-01XX-0.4.html

If you receive one of these packets, then it will look like this.

<presence from="contact%hotmail.com@msn.host.com" to="user@host.com" type="subscribe">
        <x xmlns="http://delx.cjb.net/protocol/roster-subsync">
                <item name="Some contact" subscription="both">
                        <group>Friends</group>
                        <group>Colleagues</group>
                </item>
        </x>
</presence>

The most import bit to look it is the subscription attribute of the item tag. This tells you what the subscription is on the legacy service, so you should send whatever packets you need to in order to make it this way. The rest of the information is there if you want to use it.

The reason for doing things this way, is that older clients which do not support roster-subsync will still get the roster push. However he user will have to follow the right steps in order to get the contact added correctly.

Security Concerns

Obviously you can't just go accepting these packets without any kind of authorisation from the user. It would be very easy for a malicious Jabber contact to construct a packet like this to get themself onto your contact list if that was the case.

PyMSNt will not ever send any of these messages until after you have authorised the gateway itself. The process works like this.

If you ever receive one or more roster-subsync tag from a domain that the user has not specifically allowed or disallowed you should display exactly ONE dialog on the screen for the whole domain, asking the user if they wish to accept all of these roster pushes.


Bug reports and comments go to James Bunton

I'll gladly help you with any problems, but please look through this whole page first


Copyright James Bunton <james at delx.cjb.net>. You may freely redistribute this file.