MySpaceIM

From IMFreedom Wiki
Revision as of 05:44, 6 February 2008 by Jeff (talk | contribs) (copy from http://developer.pidgin.im/wiki/MsimProtocolSpec?action=edit (to be fixed))
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

From http://developer.pidgin.im/wiki/MsimProtocolSpec

Note: may not appear correctly, conversion in progress.


TOC

Unofficial MySpaceIM Protocol Specification

Introduction

Reverse-engineered protocol specification for [wiki:MySpaceIM]. The first version of this document was created for build 673, but as of 2007-06-02 it refers to build 697.

This page is a work-in-progress to be completed by [wiki:jeff]. An older HTML version of this document is available.

Text marked

> in blockquotes

refers to [wiki:MySpaceIM msimprpl].

Servers

> msim_login

Connect to im.myspace.akadns.net, which will point you to one of several MSIM servers. All connections are made using TCP. The default port is 1863, but the client will try to connect using ports 6660,6661,6662,6665,6668,6669,0080 and 0443 in succession if 1863 fails. If successful, the port will be stored (the Win32 client uses `HKCU\Software\MySpace\IM\LastConnectedPort` in the registry) and tried first for future connections.

User Identification

Users are identified by several means:

   * User ID  (uid) - unique number; used extensively by protocol. User's web page at http://myspace.com/user_ID.
   * Email address - used to sign in, and locate buddies.
   * Username/IM Name - "Your unique name that can't be changed", shown on buddy lists, and for user's web page at http://myspace.com/username.
   * Display Name - shown on your web page, can be changed and non-unique.
   * First Name and Last Name - "private and used for search only".

Message Structure

> MsimMessage

Tokens are separated by backslashes, which alternate as name, value, name, value, etc. For example, this message:

{{{ \k1\v1\k2\v2\xxx\yyy\final\ }}}

contains the following information:

||Key||Value ||k1||v1 ||k2||v2 ||xxx||yyy

The end of a message is marked with `\final\`. Note that this marker is not a key/value pair.

Special characters are escaped with '/': ||Character||Escaped As || / || /1 || \ || /2

> msim_escape, msim_unescape

The following data types can be defined:

||Type||Description ||Integers||These are just stored as ASCII, decimal ||Text||ASCII ||Binary||Base64 encoded ||Boolean||Presence of the key indicates 'true', absense 'false' ||Dictionary||Multiple key=value's, separated by \x1c ||List||Items usually separated by '|'

> (NI) Dictionaries and lists are not yet handled by MsimMessage.

What I call here dictionaries (also known as associative arrays, hashes) are often present in a field named `body`. Keys inside a dictionary use !CamelCase and boolean values are represented as a string, `True` or `False`, instead of the absence of presence of a key.

Escape codes in dictionaries: ||Character||Escaped As || ' or ` || ' || # || # || " || "

Escape codes in '|' delimited lists: ||Character||Escaped As || | || /3

Login Sequence

> msim_login, msim_process, msim_login_challenge

Upon connection, server immediately sends a "login challenge" message to the client:

||Key||Type||Description ||lc||integer||1 ||nc||binary||0x40-byte nonce ||id||integer||1

Client sends login challenge response:

||Key||Type||Description ||login2||integer||196610 ||username||text||Email address to login using ||response||binary||Challenge response, derived using algorithm described below ||clientver||integer||673, corresponds to 1.0.673.0 in "About" dialog (679, etc.) ||reconn||integer||0 ||status||integer||100 ||id||integer||1

Server replies with:

||Key||Type||Description ||lc||integer||2 ||sesskey||integer||Session key ||proof||Same as userid? Sometimes differs. ||userid||Numeric userid ||profileid||Same as userid? ||uniquenick||Username ||id||integer||1

The session key is sent by the client in almost every future message.


Errors: ||Code||Message||Type|| ||259||The supplied email address is invalid.||Fatal ||260||The password provided is incorrect.||Fatal

Code 260 is no longer used if trying to login with an invalid email address, circa client build 404. Instead, invalid email and invalid passwords both return code 260. See MySpaceIM Info Disclosure: Silently Fixed

Challenge/Response Login Algorithm

> msim_login_challenge

`response` is computed from:

* First 0x20 bytes of `nc` field -- `nc1`
* Last 0x20 bytes of `nc` field -- `nc2`
* User's password, in UTF-16 little endian (only the first 10 characters, in lower case)
* User's ASCII email address

Compute SHA1(SHA1(`password`) + `nc2`). This will result in 0x14 bytes. Using the first 0x10 bytes (128 bits) as an RC4 key, encrypt the following concenated together:

* `nc1`
* User's ASCII email address
* Four zero bytes: 00 00 00 00
* 1 byte = number of network interfaces on this machine
* IPv4 address of interface used to connect to server in network order
* IPv4 addresses of host's network interfaces in network order

The network interface addresses are obtained using the Win32 GetIpAddrTable API call. They should be the actual interface IPs on the system, even if they are RFC1918 private addresses. The server most likely uses these addresses to determine if a connection can be directly initiated to the host, or if it must pass through some kind of NAT device.

High-level summary:

   response = encrypt(key=hash(hash(pw) + nc2), data=nc1+username+IP_list)


Buddy Messages

> msim_send_bm

Messages from client or server: ||Key||Type||Description ||bm||integer||Message type. ||sesskey||integer||Session key. ||t||integer||Userid to send message to (outgoing messages only). ||f||integer||Userid message came from (incoming messages only). ||date||integer||For offline messages, timestamp of when message was sent, Unix time ||cv||integer||Client version build number. ||msg||text||Text of message.

Known message types for `bm`: ||Value||Notes||`msg` ||1||Instant message||See markup below. ||100||Status message||List, see below. ||121||Action Message||Zap or typing notification. ||122||Media Message||Key/value pairs joined by ampersands, see below. ||124||Profile Message||Contains age, song, gender, display name, headline, etc.

Servers appear to pass all buddy messages between clients, even if the type ('bm' field) is unrecognized. The Miranda IM plugin uses bm code 200 to "send miranda + plugin version information as is done with many other protocols".

Instant Messages

> msim_incoming_im, msim_send_im

Message text is formatted using "tags", similar to HTML, and (aside from the escaped forward slashes) is valid XML. Tags and attribute names are single letters to save space. Attributes are either quoted with ' or backquote. For unknown reasons, the client uses ' but the server translates it to the backquote.

Tags end as in HTML: <tag>...</tag> (appears in protocol dumps as </1tag>, because / is encoded as /1).

Example: <f f='Times' h='16'><c v='black'>hello</1b></1c></1f></1p>

Known tags:

*

= paragraph * <a> = anchor (link) * h = href * This tag is self-closed, for example: <a h='http://google.com' /> displays http://google.com. It doesn't seem to be possible to change the text of the link. * <f> = font tag * f = font face (Arial, Arial Black, Comic Sans MS, Courier New, Tahoma, Times, Verdana, or another) * h = font height, in pixels. For displays set to 96 DPI: * 4pt = 5 (sizes must be between 4 and 72 points) * 5pt = 7 * 6pt = 8 * 7pt = 9 * 8pt = 11 * 9pt = 12 * 10pt = 13 * 11pt = 15 * 12pt = 16 * 13pt = 17 * 14pt = 19 * 15pt = 20 * 16pt = 21 * 17pt = 23 * 18pt = 24 * 72pt = 96 * Note: 1 pt = 1/72 inch, and 1 inch = 96 pixels (at 96 dpi), so height = round((96/72.)*point_size). * Note 2: At 120 DPI, 72pt is sent as h=120, and so on. Points are always 1/72 ", so the real formula is height = round((DPI/72.)*point_size). * s = bit field of text decoration; add/OR together: * 1 = bold * 2 = italic * 4 = underline * <c> = text color tag * v = color (a name like "black", "white", or "rgb(253,0,0)", "rgba(253,0,0,100)" (alpha), or "transparent") * = background color tag * v = color * = image (emoticon/smiley) * n - name: bigsmile growl mad scared tongue devil happy messed sidefrown upset frazzled heart nerd sinister wink geek laugh oops smirk worried googles mohawk pirate straight kiss Known character entities: ||Character||Entity || " || " || & || & || ' || ' || < || < || > || >

Incoming Status Message

> msim_status

Examples:

* `|s|0|ss|Offline`
* `|s|1|ss|:-)|ls||ip|0|p|0`

||Index||Type||Description || 0 || text || `s` || 1 || integer || 0 for offline (or hidden), 1 for online, 2 for idle, 5 for away || 2 || text || `ss` || 3 || text || Headline || 4 || text || `ls` || 5 || text || || 6 || integer || 0 || 7 || text || `p` || 8 || integer || 0

Action Message

> msim_incoming_action > msim_send_typing

Zaps are, in order (0-9): zap whack torch smooch hug bslap goose hi-five punk'd raspberry. Zaps are sent with this `msg`:

* `!!!ZAP_SEND!!!=RTE_BTN_ZAPS_n`, where n is a 0-based index into zap array.

For typing notifications:

* %typing%
* %stoptyping%

Group Messages

Group messages seen coming from http://myspace.com/78744676 (or http://myspace.com/myspaceim), a chatroom added to the buddy list by default:

* !!!GroupCount=25;
* !!!Offline= (someone's user ID)
* MsimMarkup-formatted messages

These messages also had:

||Field||Type||Description || f || integer || Chatroom ID, for example 78744676 || cv || integer|| Client version, build 1000 || gid || integer || Group ID? 23 || aid || integer || User ID of person talking in that chatroom, if applicable

When a user talks in a chatroom, f is set to the user ID of a user representing the chatroom, and aid is set to the user ID of the user talking. Not sure how gid fits into this. You appear to get chatroom messages if the chatroom user is on your buddy list, even if you haven't joined the chatroom. (Note: need to figure out terminology here, I've been using chatroom but MySpaceIM uses the term 'group').

Media Messages

> (NI) bm of 121 is used to send media.

Seems to be sent when someone first messages you. Example transcript:

{{{ (05:31:51 PM) someone: cmdtype=1&reqid=856000425340460813&contenttype=1& (05:32:01 PM) someone: Hello (05:32:04 PM) me: hi there (05:32:07 PM) someone: cmdtype=1&reqid=856000425340466400&contenttype=1& (conversation continues) }}}

Sending background picture:

{{{ cmdtype=3&reqid=15704865745410042&contenttype=1& }}}

Picture (less than 600K) invitation request:

{{{ cmdtype=4&reqid=15704865745421128&contenttype=4&filename=Winter.jpg }}}

If picture is not accepted, or offer canceled:

{{{ cmdtype=5&reqid=15704865745413631&contenttype=4&accept=no }}}


cmdtype ||Code||Description ||1||??? Sent initially ||3||Send background image ||4||Picture invitation request ||5||Accept/deny picture invitation request

Profile Message

This message contains information on the buddy from their profile. Sometimes it is empty, sometimes it contains the following dictionary-encoded keys:

||Name||Type||Description ||Age||integer||Age in years ||AvatarURL||string||URL of avatar ||BandName||string|| ||SongName||string|| ||ContactType||integer||2 ||DisplayName||string|| ||Gender||string||M or F ||Headline||string|| ||ImageURL||string||URL of JPEG image on MySpace Content Distribution Network ||IMName||string||Instant messaging name, blank if user doesn't have MySpaceIM ||UserName||string|| ||RoomLastLogin||integer|| ||Location||string||city, state, country ||ShowAvatar||boolean||True or False

Example:

\bm\124\f\78744676\msg\Age=27AvatarUrl=BandName=cold war kidsContactType=2DisplayName=MySpaceIMGender=FHeadline=ImageURL=http:/1/1a895.ac-images.myspacecdn.com/101111/149/186/11111986894_m.jpgIMName=MySpaceIM Chat RoomLastLogin=128287884600000000Location=SANTA MONICA, California, USShowAvatar=FalseSongName=Hang Me Up To DryTotalFriends=119814UserName=myspaceim\final\


Set Status Messages

To change your own status:

||Key||Type||Description ||status||integer||Status code. ||sesskey||integer||Session key. ||statstring||string||User-settable status message (for online or away). ||locstring||string||Location string? Sometimes "userinfo;"

Status codes: ||Code||Description ||0||Hidden/offline ||1||Online ||2||Idle ||5||Away

Unknown codes (tested 3, 4, and 6) are recognized as offline by the official client.

Same code as in incoming status messages.

Keepalives

> (NI)

From server:

||Key||Type||Description ||ka||boolean||Presence indicates this is a keepalive message.

Sent every 3 minutes to keep connection alive.

Add Buddy

> msim_add_buddy

||Key||Type||Description ||addbuddy||boolean||Presence indicates to add buddy. ||sesskey||integer||Session key. ||newprofileid||integer||Userid to add. ||reason||text||Empty

The client also sends a persist message to update the buddy list. Example sequence (after looked up userid), adding uid 6221:

* `\addbuddy\\sesskey\420159774\newprofileid\6221\reason\\final\` - add buddy
* `\blocklist\\sesskey\420159774\idlist\b-|6221|a+|6221\final` - update blocklist
* `\persist\1\sesskey\420159774\cmd\514\dsn\0\uid\180301984\lid\9\rid\31\body\ContactID=6221.GroupName=IM Friends.Position=1000.Visibility=1.NameSelect=0\final\` - update contact info

Errors: ||Code||Message||Type|| ||1539||The profile requested is already a buddy.||Non-fatal


Delete Buddy

> msim_remove_buddy

||Key||Type||Description ||delbuddy||boolean||Presence indicates to delete buddy. ||sesskey||integer||Session key. ||delprofileid||integer||Userid of buddy to delete.

The client also sends a persist message and updates the block list when deleting a buddy. Example message sequence:

   * `\delbuddy\\sesskey\97309878\delprofileid\175349942\final\` - delete buddy with numeric ID 175349942
   * `\persist\1\sesskey\97309878\cmd\515\dsn\0\uid\3656574\lid\8\rid\18\body\ContactID=175349942\final\` - delete from on-server buddy list?
   * `\blocklist\\sesskey\97309878\idlist\a-|175349942|b-|175349942\final\` - update block list; remove user (-) from accept (a) and block (b) list? 

Block List

> msim_add_buddy updates the blocklist > (NI) User-settable blocklists.

||Key||Type||Description ||blocklist||boolean||Presence indicates to change block list. ||sesskey||integer||Session key. ||idlist||list||Encoded list of buddies to block/unblock, see below.

`idlist` is constructed from one of the following format strings:

* a-|%lu|b-|%lu
* a-|%lu|b+|%lu - block userid %lu
* b-|%lu|a+|%lu - unblock userid %lu

where %lu is the userid. Current guess is that `a` is for accept list, `b` is for block lis, - removes and + adds, but this has not been proven. Example idlist, when "Who can contact me: Anyone" and "Who can see when I'm online: Anyone" is set:

* w0|c0|a-|*|b-|*|b+|blockeduser1...

Removes all users from accept list and block list, then adds blockeduser1 (userid).

If "Who can contact me: Only people on my Contact List" and "Who can see when I'm online: Anyone", then idlist is:

* w0|c1|a-|*|a+|buddy1|buddy2|...|buddyN|b-|*

where buddyN is the userid of each buddy on the contact list. |a-|*| removes all users from the accept list, |a+|...| adds only buddies to accept list, |b-|* removes all buddies from blocklist.

Opcodes:

* w# = Who can see when I'm online? 0=Anyone, 1=Only people on my contact list
* c# = Who can contact me? 0=Anyone, 1=Only people on my contact list
* a- = remove from accept list
* a+ = add to accept list
* b- = remove from block list
* b+ = add to block list
* * = all userids

Get Info

||Key||Type||Description ||getinfo||boolean||Presence indicates that this is a get info request. ||sesskey||integer||Session key. ||uid||integer||Userid to look up.

Examples:

\getinfo\\sesskey\53348262\uid\6221\final\

\getinfo\\sesskey\70517308\uid\180301984\final\

Specifics of this message's purpose are unknown.

See also the 1,0,2 persist message (they're often sent together).

Set Info

||Key||Type||Description ||setinfo||boolean||Presence indicates that this is a get info request. ||sesskey||integer||Session key. ||info||dictionary||Packed dictionary of information to set.

'info' dictionary has same fields as setinfo. Examples:

\setinfo\\sesskey\70517308\info\Age=20AvatarUrl=BandName=ContactType=1DisplayName=MySpaceIM Protocol Plugin for PidginGender=MImageURL=http:/1/1a513.ac-images.myspacecdn.com/1images01/118/1m_0ad6cfe1ae4b676622e98c6d4cb3cef0.pngLastLogin=128290072800000000Location=California, USShowAvatar=FalseSongName=TotalFriends=4UserName=msimprpl\final\

\setinfo\\sesskey\70517308\info\Age=20AvatarUrl=BandName=ContactType=1DisplayName=MySpaceIM Protocol Plugin for PidginGender=MImageURL=http:/1/1a513.ac-images.myspacecdn.com/1images01/118/1m_0ad6cfe1ae4b676622e98c6d4cb3cef0.pngLastLogin=128290072800000000Location=California, USShowAvatar=FalseSongName=TotalFriends=4UserName=msimprpl\final\

Web Challenge Request (webchlg)

||Key||Type||Description ||webchlg||boolean||Presence indicates a web challenge request. ||sesskey||integer||Session key. ||n||integer||0, unknown.

See also 1,17,26 persistance request.

Persist Messages

> msim_process_reply > msim_new_reply_callback

Persist messages allow the client to send or request information to or from the server. Thanks to Nathan Peterson for reversing the structure of these commands.

Client sends a persistance request: ||Key||Type||Description ||persist||integer||1 ||sesskey||integer||Session key. ||uid||integer||Your userid. ||cmd||integer||Command type. ||dsn||integer||Command family. ||lid||integer||Command subcode. ||rid||integer||Request/response ID. Client sends request with unique rid ||body||dictionary||Dictionary of information.

`cmd`, `dsn` and `lid` uniquely identify each command.

Known cmd/dsn/lid combinations: ||cmd||dsn||lid||Description ||1||0||1||List all contacts ||1||0||2||Get contact information by ID ||1||1||4||Lookup IM information about yourself ||1||1||7||Lookup IM information by userid ||1||2||6||List all groups ||1||4||3||Lookup MySpace information by userid ||1||4||5||Lookup MySpace information about yourself ||1||5||7||Lookup MySpace information by username/email ||1||7||18||Get mail status ||1||9||14||Your username has been changed (UserName, Code=0 for ok). Also need to call \setinfo. ||1||17||26||Web challenge ||1||21||18||Get user song ||1||101||20||Server information ||2||2||16||??? Group flags ||2||9||14||Check username availability ||2||14||21||Add all my friends from MySpace.com ||3||2||16||??? Delete something? ||514||1||10||Change user preferences ||514||0||9||Update contact information ||514||16||25||Invite to MySpaceIM ||515||0||8||Delete buddy, ContactID in buddy (see also delbuddy)

`cmd` appears to be a bitfield: ||Bit||Description ||0-7 (0-255)||Command bits, 1=get, 2=action, 3=delete ||8 (weight 256)||Set indicates reply, clear indicates request. ||9 (weight 512)||Set indicates to an action, clear indicates to get information. ||10 (weight 1024)||Set indicates an error, clear is normal.

So for example, a reply to 1,5,7 (lookup MySpace information by username/email) would have cmd,dsn,lid of 257,5,7, and a reply to 1,9,14 would be 258,9,14. These aren't listed separately in the list above because they're the same command.

Server responds with a persistance reply (persistr): ||Key||Type||Description ||persistr||boolean||Presence indicates persistr message. ||uid||integer||Your userid. ||cmd||integer||Command. This appears to the client request cmd bitwise ANDed or added with 256. ||dsn||integer||Subcommand - matches dsn of request. ||lid||integer||Subcommand - matches lid of request. ||rid||integer||Request/response ID - matches rid of request. Server sends responses back with same rid as in the client's request, allowing client to match responses to requests. ||body||dictionary||Response information.

1,0,1: List all contacts

Request:

An empty body. Example:

\\persist\1\sesskey\46543777\cmd\1\dsn\0\uid\3656574\lid\1\rid\39\body\\final\

Reply has a key for each of the contacts. Keys: ||Key||Type||Description|||Example ||ContactID||integer||Userid of contact||6221 ||Headline||text||Headline||:-) ||Position||integer||Offset on buddy list||0 ||GroupName||text||Group that buddy is located in||IM Friends ||Visibility||integer|| ||1 ||AvatarUrl||text||URL of avatar ||ShowAvatar||boolean||Show avatar? True or False ||LastLogin||integer||Login timestamp||128177889600000000 ||IMName||text||Instant messaging name, blank if user doesn't have MySpaceIM

||NickName||text|| ||NameSelect||integer||0 ||OfflineMsg||text||Offline message

Example:

ContactID=6221.Headline=:-).Position=1.GroupName=IM Friends.Visibility=1.AvatarUrl=.ShowAvatar=False.LastLogin=128182824000000000.IMName=.NickName=.NameSelect=0.OfflineMsg=.

(repeats for additional contacts)

1,0,2: Get contact information

Get information on a contact.

Request: ||Key||Values||Description ||ContactID||integer||Userid of contact.

Example, uid 180301984 looking up uid 6221:

\persist\1\sesskey\53348262\cmd\1\dsn\0\uid\180301984\lid\2\rid\7\body\ContactID=6221\final\

See also `getinfo` command.

Reply: ||Key||Values||Description ||ContactID||integer||Userid of contact (actually present twice, identically). ||Headline||text|| ||Position||integer||position in buddy list. ||!GroupName||text||"Recent Contacts" ||Visibility||integer||2 ||!AvatarUrl||text|| ||!ShowAvatar||True/False|| ||IMName||text|| ||!NickName||text|| ||!NameSelect||integer||0

1,1,4: Lookup IM Information about Yourself

Sent with an empty body.

Similar response as to 1,1,17, except also includes OfflineMessage field.

1,1,7: Lookup IM Information by UserID

> msim_lookup_user

Used for looking up MySpaceIM information on a user, as opposed to purely MySpace information.

Request body: ||Key||Values||Description ||UserID||integer||The userid to lookup.

Reply body: ||Key||Values||Description ||UserID||integer||0 ||Sound||True/False|| ||!PrivacyMode||integer||"Who can contact me?" 0=Anyone, 1=Only people on my Contact List. ||!ShowOnlyToList||True/False||"Who can see when I'm online?" False=Anyone, True=Only people on my Contact List. ||!OfflineMessageMode||integer||"When I'm offline, receive and store messages from:" 0=Everyone, 1=Only people on my Contact List, 2=No one. ||Headline||text|| ||Avatarurl||text|| ||Alert||integer|| ||!ShowAvatar||True/False|| ||IMName||text|| ||!ClientVersion||integer||Client build number. ||!AllowBrowse||True/False|| ||IMLang||???||Language. ||LangID||integer||Language ID.

1,2,6: List all groups

Request: TODO

Reply: ||Key||Type||Description||Example ||GroupID||integer||Numeric ID of group||21672248 ||GroupName||text||Textual name||IM Friends ||Position||integer||Offset in buddy list||1 ||GroupFlag||integer||Unknown||131073

1,4,3: Lookup MySpace User Info by UID

> msim_lookup_user, when called with a string of numbers

Lookup user information by userid. This command is called MySpaceUserInfo by error messages.

Request: ||Key||Values||Description ||UserID||integer||The userid to lookup.

Examples:

\persist\1\sesskey\70517308\cmd\1\dsn\4\uid\180301984\lid\3\rid\16\body\UserID=6221\final\

Reply: ||Key||Values||Description ||!UserName||text||Unique username. Present only if in request. ||Email||text||Email address. Present only if in request. Fields below only present if user exists. ||UserID||integer||Numeric user ID. ||ImageURL||text||URL to image ||!DisplayName||text||Display name, need not be unique. ||!BandName||text|| ||!SongName||text|| ||Age||integer||Age in years. ||Gender||M/F||Gender. ||Location||text||City, State, Country ||!TotalFriends||integer||Total number of friends on MySpace.

(Same as 1,5,7 reply but also has TotalFriends).

Error messages are sent with cmd=1025 (error bit set), and following body:

||Key||Type||Description ||UserID||integer||Userid of message request which had the error. ||!ErrorMessage||text||Textual description of error

Observed error messages:

* Request time elapsed configured has passed for !MessageType: Read, !DataType: !MySpaceUserInfo
* Persistence Queue Overflow

1,4,5: Lookup MySpace User Info About Yourself

Seems to be the same as 1,4,3 but looks up your information. You still need to pass UserID=xxx in the request body.

1,5,7: Lookup MySpace User Info by String

> msim_lookup_user, when called with a username

Lookup user information by username or email. Known as MySpaceUserInfoByString in error messages.

In the `body` dictionary of the request, one of these keys is present: ||Key||Values||Description ||!UserName||text||The username to lookup. ||Email||text||The email address to lookup.

Reply body: ||Key||Values||Description ||!UserName||text||Unique username. Present only if in request. ||Email||text||Email address. Present only if in request. Fields below only present if user exists. ||UserID||integer||Numeric user ID. ||ImageURL||text||URL to image, mangled an unknown way. ||!DisplayName||text||Display name, need not be unique. ||!BandName||text|| ||!SongName||text|| ||Age||integer||Age in years. ||Gender||M/F||Gender. ||Location||text||City, State, Country

Error reply, here cmd=1025 (error bit set): ||Key||Type||Description ||UserName||integer||Username of message request which had the error. ||!ErrorMessage||text||Textual description of error. Once observed: Request time elapsed configured has passed for MessageType: Read, DataType: MySpaceUserInfoByString

1,7,18: Check Mail Status

> msim_check_mail > msim_check_mail_cb

Checks for new mail, comments, or friend requests. You have to periodically poll to see if you have any.

Request: empty

Example:

\persist\1\sesskey\53348262\cmd\1\dsn\7\uid\180301984\lid\18\rid\4\body\\final\\

Reply: ||Key||Type||Description||Example ||Mail||boolean||Whether you have new mail||On ||BlogComment||boolean||Whether you have new blog comments||On ||ProfileComment||boolean||Whether you have new profile comments||On ||FriendRequest||boolean||Whether you have new friend requests||On ||PictureComment||boolean||Whether you have new picture comments||On

Example:

\persistr\\cmd\257\dsn\7\uid\180301984\lid\18\rid\4\body\Mail=On\final\\

1,17,26: Web Challenge

> (NI) Webchallenge is used to authenticate with the myspace.com website, so that links to the website (such as for mail notification) do not require logging in again through the web interface. From Scott Ellis: "I have the popup windows for my notifications opening the same web pages as the official client, but without the 'token' it will usually redirect to the myspace login page and say 'you must be logged in to do that'. Getting the web authentication sorted would be a huge bonus."

Reply: ||Key||Values||Description ||Challenge||integer||Challenge (present 3 times). ||!ChallengeData||binary||Base64 encoded 30 bytes (present 3 times).

Unknown purpose. Causes client to send an HTTP request to home.myspace.com: GET /Modules/IM/Pages/UrlRedirector.aspx, with URL-encoded parameters: ||Key||Values||Description ||challenge||X-Y-Z, 3 integers||X is as of yet unknown, Y is the uid, Z is the sesskey ||response||binary||??? base64-encoded data. Probably the result of an algorithm using the X-Y-Z above ||target||text||Several options: searchfriends, profile, comment, message, probably more... ||targetid||integer||The userid of the target profile for the target action

UrlRedirector.aspx replies with a simple HTML page that states "Object moved" followed by a hyperlink and a cookie in the HTTP header. The cookie is obviously our MySpace login validation. The client then proceeds to send an HTTP request to the page the hyperlink points to.

These messages are currently ignored by msimprpl, and are not required for basic functionality. Used for web authentication?

See also 'webchlg'.

1,21,28: Get User Song

> (NI)

If the music note icon on the buddy list in the official client is clicked, this message will be sent.

Request: ||Key||Type||Description ||UserID||integer||Userid to get song information on.

Reply: ||Key||Type||Description ||UserID||integer|| ||ProfileSong||text||URL to page with an embedded Flash media player

1,101,20: Server Information

> (NI)

This message is sent without the client asking for it, so the response bit in `cmd` is always set (cmd = 257). Sent upon connecting to the server, before logging in. It contains various timers and limits:

||Key||Type||Description ||!AdUnitRefreshInterval||integer||10 ||!AlertPollInterval||integer||180 ||!ChatRoomUserIDs||list separated by ;||Userids for chatrooms ||!CurClientVersion||integer||595, even though 673 is newer ||!EnableIMBrowse||True/False||False ||!MaxAddAllFriends||integer||100 ||!MaxContacts||integer||1000 ||!MinClientVersion||integer||529 ||!MySpaceNowTimer||integer||720 (seconds) ||!PersistanceDataTimeout||integer||900 (seconds) ||!UseWebChallenge||integer||1 ||!WebTicketGoHome||True/False||False

ChatRoomUserIDs is, as of 2007-04-15, a list of the following userids:

||UserID||Username||Display Name ||78744676 || myspaceim || hi ||142663391 || myspaceimchat || jorge ||142910130 || myspaceimchat2 || jorge ||123521495 || testbot5 || test ||138528147 || myspacejorge4 || myspacejorge4 ||140271072 || TEST4MATTCHUNG2 || tester ||163733130 || myspacecdn || jorge

None of these userids autoreply when IM'd.

2,9,14: Set username?

||Key||Type||Description ||!UserName||text||Name to use

Example request:

\persist\1\sesskey\469958979\cmd\2\dsn\9\uid\240626417\lid\14\rid\28\body\UserName=msimprpl2\final\

Example reply: \persistr\\cmd\258\dsn\9\uid\240626417\lid\14\rid\28\body\UserName=msimprpl2.Code=0\final\

Unconfirmed: does this actually set the username, or just check it? \setinfo with with a !UserName in the body is sent afterwards.

2,14,21: Add all my friends from MySpace.com

Sent when go to "Add all my friends" from File -> IM Set Up Wizard. Imports your friends from the website to IM.

Request: ||Key||Type||Description ||!GroupName||text||"IM Friends", group to add contacts to?

Example:

\persist\1\sesskey\581636623\cmd\2\dsn\14\uid\3656574\lid\21\rid\39\body\GroupName=IM Friends\final\

Reply: ||Key||Type||Description ||Completed||boolean||"True" if contacts were added

Example:

\persistr\\cmd\258\dsn\14\uid\3656574\lid\21\rid\39\body\Completed=True\final

Client then sends a 1,0,1 persistance request ("List all contacts") to get the updated list. After getting all the buddies, it removes them from the blocklist (b-) and adds to the accept list (a+, see blocklist command). After that, it sends a 514,0,9 ("Set contact information") on each contact, in body passing ContactID, GroupName, Position, Visibility, NickName, and NameSelect.

514,0,9: Set contact information

Sets the location and group of a buddy.

Request: ||Key||Type||Description ||ContactID||integer||Userid of contact. ||!GroupName||text||"Recent Contacts" ||Position||integer||0, 1000 ||Visibility||integer||1, 2 ||!NickName||text|| ||!NameSelect||integer||0

Example:

\persist\1\sesskey\70517308\cmd\514\dsn\0\uid\180301984\lid\9\rid\18\body\ContactID=6221\034GroupName=Recent Contacts\034Visibility=1NameSelect=0\final\

514,1,10: Change User Preferences

> (NI)

`body` dictionary, of settings to change: ||Key||Values||Description ||Sound||True/False||??? ||!PrivacyMode||integer||"Who can contact me?" 0=Anyone, 1=Only people on my Contact List. ||!ShowOnlyToList||True/False||"Who can see when I'm online?" False=Anyone, True=Only people on my Contact List. ||!OfflineMessageMode||integer||"When I'm offline, receive and store messages from:" 0=Everyone, 1=Only people on my Contact List, 2=No one. ||Headline||text||Your profile headline. ||Alert||integer||1 ||!ShowAvatar||True/False|| ||IMName||text||Your instant messenger name. Official client lets you change IM name capitalization and spacing.

514,16,25: Invite to MySpaceIM

> (NI)

Request: ||Key||Type||Description ||Recipient||integer||Userid to invite. ||Subject||text||"Invite to IM" ||Body||text||Entered message text.

This might be a generic command to send MySpace messages (not verified).


Client also sends this instant message: ||Key||Type||Description ||bm||integer||1 ||sesskey||integer||Session key. ||t||integer||Userid to send message to. ||cv||integer||Client version build number. ||msg||text||"Invited to MySpaceIM on hh::mm PM on mm/dd/yy"


Error Messages

> msim_error

An error notice is sent from the server in certain situations.

||Key||Type||Description ||error||boolean||Presence indicates this is an error message. ||errmsg||string||ASCII English description of error. ||err||integer||Error code. ||fatal||boolean||Presence indicates error is fatal to the connection.

Known errors: ||Code||Message||Type|| ||1||There was an error parsing an incoming request.||Fatal ||2||This request cannot be processed because you are not logged in.||Fatal ||3||This request cannot be processed because of an invalid session key.||Fatal ||6||This profile has been disconnected by another login.||Fatal ||259||The supplied email address is invalid.||Fatal ||260||The password provided is incorrect.||Fatal ||4352||Invalid user ID in persistence request.||Fatal ||4608||PM Restart||Unknown

Code 260 is no longer used if trying to login with an invalid email address, circa client build 404. Instead, invalid email and invalid passwords both return code 260. See MySpaceIM Info Disclosure: Silently Fixed

Logout

To logout:

||Key||Type||Description ||logout||boolean||Presence indicates this is a logout message. ||sesskey||integer||Session key.

Client/Executable Analysis

MySpaceIM Setup

MySpaceIM_Setup.exe, which you can download at http://myspace.com/myspaceim, is not the actual client. Instead, it fetches http://im.myspace.com/nsis/currentversion.txt , parses the key=value pairs on each line, and downloads $(SETUPURL)$(SETUPFILE) using HTTP. German, French, Italian, and Spanish clients can also be downloaded. The version described in this document is build '673.

The MySpaceIM client also occasionally checks http://im.myspace.com/nsis/currentversion.txt to see if an upgrade is available.

Libraries/Code Used by MySpaceIM.exe build 673

Interesting strings found in executable:

||String'||Comments ||@(#)$Id: TRIONAN.C,v 1.4 2005/12/08 22:03:59 rkrueger Exp $ || libxml2 ||inflate 1.1.4 Copyright 1995-2002 Mark Adler || Inflate/deflate decompression/compression, RFC1950 from zlib ||inflate 1.1.3 Copyright 1995-1998 Mark Adler || zlib, png ||deflate 1.1.4 Copyright 1995-2002 Jean-loup Gailly || zlib ||unzip 0.15 Copyright 1998 Gilles Vollant || zip archive files ||Skinux Object Runtime Error||Skinux Engine for skinning ||Copyright (C) 1998, Thomas G. Lane||JPEG library ||Copyright (c) 1992-2004 by P.J. Plauger, licensed by Dinkumware, Ltd. ALL RIGHTS RESERVED.||Standard C++ library in VC++ ||gpsp.gamespy.com||[1], for finding other gamers (not used yet?) ||\m\%d\xfer\%d %u %u||Unknown message. Near \gamename\. ||63.208.226.223||Mysterious host, blocks pings, owned by Level3

myim: URLs

MySpaceIM registers the `myim:` URL scheme to invoke `C:\Program Files\MySpace\IM\MySpaceIM.exe %1`. The URL includes a command followed by URL-encoded parameters: `myim:addContact?uID=1&cID=2`.

addContact

> msim_uri_handler_addContact_cb

Adds user to contact list. Used on http://collect.myspace.com/index.cfm?fuseaction=im.friendslist

||Name||Value ||uID||Your userid, or 0 for default ||cID||Contact userid ||auto||true if "Add all the people on this page to my IM List!" clicked, empty cID

sendIM

> msim_uri_handler_sendIM_cb

Used in JavaScript posted at http://developer.pidgin.im/attachment/ticket/194/section%20of%20code%20from%20myspaceJS032.js%20.txt

||Name||Value ||uID||Your userid, or 0 for default ||cID||Contact userid

Credits

The majority of this specification was produced from original research by [wiki:jeff Jeff Connelly].

Thanks also to Nathan Peterson for independently reverse-engineering parts of the protocol. Parts of this document were drawn from [2].

Thanks also to Scott Ellis, developer of the MySpaceIM protocol plugin for Miranda IM, for contributing to this document.

BR