4
0

TOC.md 43 KB

TOC Protocol Specification

Version: TOC 1.0 / TOC 2.0

This document is a reference for the TOC (Talk to OSCAR Client) protocol as implemented by Open OSCAR Server. It covers both TOC 1.0 and TOC 2.0, and contains enough detail to build a fully-functional client from scratch.

TOC is an ASCII-based protocol layered on top of FLAP (SFLAP) framing over TCP. It was originally designed by AOL to service the TiK (Tcl/Tk) and TIC (Java) AIM clients. TOC 2.0 extends the original protocol with server-side buddy lists, typing notifications, encoded messages, and richer buddy status information.


Table of Contents

  1. Transport Layer (FLAP)
  2. Connection & Authentication
  3. Client → Server Commands (TOC 1)
  4. Client → Server Commands (TOC 2)
  5. Server → Client Messages (TOC 1)
  6. Server → Client Messages (TOC 2)
  7. Error Codes
  8. Escaping & Encoding Rules
  9. Capabilities (UUIDs)
  10. Complete Session Examples

1. Transport Layer (FLAP)

All TOC communication is wrapped in FLAP frames over a single TCP connection. The default port is 9898.

1.1 FLAP Header

Every frame begins with a 6-byte binary header in network byte order (big-endian):

Offset Size Field Description
0 1 Marker Always 0x2A (ASCII *)
1 1 Frame Type See below
2 2 Sequence Number Monotonically increasing per direction
4 2 Data Length Length of the payload that follows

The payload immediately follows the header at offset 6.

1.2 Frame Types

Value Name Description
1 SIGNON Connection initialization
2 DATA Normal command/response data
3 ERROR Not used by TOC
4 SIGNOFF Client disconnect
5 KEEP_ALIVE Heartbeat (no payload)

1.3 SIGNON Frame Payload

Server → Client (after the client sends FLAPON):

Offset Size Description
0 4 FLAP version (always 0x00000001)

Client → Server (response to the server's signon frame):

Offset Size Description
0 4 FLAP version (0x00000001)
4 2 TLV tag (0x0001)
6 2 Screen name length (N)
8 N Normalized screen name (NOT null-terminated)

1.4 DATA Frame Payload

  • Client → Server: The payload is the TOC command as a null-terminated ASCII string. The Data Length includes the null terminator.
  • Server → Client: The payload is the TOC response as an ASCII string. It is NOT null-terminated. The Data Length is the exact string length.

1.5 Sequence Numbers

Each direction maintains an independent sequence counter starting at an arbitrary value (usually 0 for clients). The counter increments by 1 for each frame sent. When it reaches 65535 it wraps to 0.

1.6 Maximum Lengths

  • Client → Server: 2048 bytes maximum per command. Exceeding this drops the connection.
  • Server → Client: 8192 bytes maximum per message.

2. Connection & Authentication

2.1 Connection Handshake

Client                              Server
  |                                    |
  |  --- TCP connect (port 9898) --->  |
  |  --- "FLAPON\r\n\r\n" --------->   |
  |  <-- FLAP SIGNON frame ----------  |
  |  --- FLAP SIGNON frame --------->  |
  |  --- toc_signon/toc2_login ----->  |
  |  <-- SIGN_ON --------------------- |
  |  <-- CONFIG/CONFIG2 -------------- |
  |  <-- NICK ------------------------ |
  |  --- toc_add_buddy (optional) ---> |
  |  --- toc_add_permit (optional) --> |
  |  --- toc_init_done --------------> |
  |  <-- UPDATE_BUDDY (for each   ---  |
  |       online buddy)                |

Step by step:

  1. Open a TCP connection to the server (default port 9898).
  2. Send the string FLAPON\r\n\r\n (10 bytes).
  3. Server responds with a FLAP SIGNON frame (frame type 1) containing the 4-byte FLAP version.
  4. Client sends a FLAP SIGNON frame back containing: the 4-byte FLAP version, a TLV with tag 0x0001 holding the normalized screen name.
  5. Client sends the login command as a FLAP DATA frame (frame type 2).
  6. On success, the server sends SIGN_ON, then CONFIG/CONFIG2, then NICK. On failure, the server sends an ERROR and/or drops the connection.
  7. Client optionally sends buddy list and permit/deny setup.
  8. Client sends toc_init_done to go online. This MUST be sent within 30 seconds of the signon command.

2.2 Password Roasting

Passwords are "roasted" before transmission to prevent cleartext on the wire (this is obfuscation, not encryption).

Roasting String: Tic/Toc

Algorithm:

  1. XOR each byte of the password with the corresponding byte of the roasting string (cycling through the string).
  2. Convert the result to lowercase hexadecimal.
  3. Prepend 0x.

Example: The password password roasts to 0x2408105c23001130.

def roast_password(password):
    roast = "Tic/Toc"
    result = []
    for i, ch in enumerate(password):
        xored = ord(ch) ^ ord(roast[i % len(roast)])
        result.append(f"{xored:02x}")
    return "0x" + "".join(result)

2.3 TOC 1 Signon

toc_signon <authorizer_host> <authorizer_port> <screen_name> <roasted_password> <language> <version>
Parameter Description
authorizer_host Auth server hostname (e.g. login.oscar.aol.com). Ignored by Open OSCAR Server but required.
authorizer_port Auth server port (e.g. 5190). Ignored but required.
screen_name User screen name
roasted_password Password roasted as described above
language Language string (e.g. english)
version Client version string, max 50 characters (e.g. "TIC:MyClient")

Example:

toc_signon login.oscar.aol.com 5190 toctest1 0x2408105c23001130 english "TIC:MyClient 1.0"

On success, the server replies with:

SIGN_ON:TOC1.0
CONFIG:<config data>
NICK:<formatted screen name>

2.4 TOC 2 Signon (toc2_signon)

Same syntax as toc_signon. The server replies with SIGN_ON:TOC2.0 and CONFIG2 instead of CONFIG. TOC 2 features (server-side buddy list, UPDATE_BUDDY2, IM_IN2, etc.) are enabled.

toc2_signon login.oscar.aol.com 5190 toctest1 0x2408105c23001130 english "TIC:MyClient 1.0"

2.5 TOC 2 Login (toc2_login)

Extends toc2_signon with additional trailing parameters and enables encoded message variants (IM_IN_ENC2, CHAT_IN_ENC).

toc2_login <host> <port> <screen_name> <roasted_pw> <language> <version> 160 US "" "" 3 0 30303 -kentucky -utf8 <code>
Parameter Description
(first 6) Same as toc_signon
160 US "" "" 3 0 30303 -kentucky -utf8 Fixed parameters (send verbatim)
code Login code: 7696 * ascii(screen_name[0]) * ascii(password[0])

The version string MUST start with TIC: (e.g. "TIC:MyClient").

Code calculation example:

def login_code(screen_name, password):
    return 7696 * ord(screen_name[0]) * ord(password[0])

For screen name toctest1 (first char t = 116) and password testpass1 (first char t = 116): 7696 * 116 * 116 = 103,547,776.

Example:

toc2_login login.oscar.aol.com 5190 toctest1 0x2408105c23001130 english "TIC:MyClient" 160 US "" "" 3 0 30303 -kentucky -utf8 103547776

On success:

SIGN_ON:TOC2.0
NICK:toctest1
CONFIG2:<config data>

3. Client → Server Commands (TOC 1)

All client commands are lowercase, space-separated, and sent as FLAP DATA frames (null-terminated). Arguments containing spaces should be enclosed in quotes. Screen names must be normalized (lowercased, spaces removed). Message content must be escaped (see Escaping Rules).

toc_init_done

Tells the server the client is ready to go online. Must be sent within 30 seconds of the signon command, and only after SIGN_ON is received.

toc_init_done

toc_send_im

Send an instant message to a user. The message may contain basic HTML.

toc_send_im <destination_user> <message> [auto]
Parameter Description
destination_user Normalized screen name of the recipient
message Quoted, escaped message (may contain HTML)
auto Optional literal string auto to mark as auto-response

Examples:

toc_send_im toctest2 "Hello there!"
toc_send_im toctest2 "I am away right now" auto
toc_send_im toctest2 "Check out \$100 deals"

toc_add_buddy

Add one or more buddies to the buddy list. This subscribes to their presence updates. Does not modify saved config (TOC 1 only — use toc_set_config to persist).

toc_add_buddy <buddy1> [<buddy2> ...]

Example:

toc_add_buddy toctest2 joe mike

toc_remove_buddy

Remove one or more buddies from the buddy list. Does not modify saved config.

toc_remove_buddy <buddy1> [<buddy2> ...]

Example:

toc_remove_buddy toctest2

toc_set_config

Save the buddy list configuration on the server. The config is a line-oriented format where the first character is the item type, followed by a space, then the value. Enclose the entire config in quotes.

toc_set_config <config_string>

Config item types:

Prefix Description
g Buddy group name. All buddies until the next g or end of config belong to this group.
b Buddy screen name
p Permit list entry
d Deny list entry
m Permit/Deny mode: 1=Permit All, 2=Deny All, 3=Permit Some, 4=Deny Some

Example:

toc_set_config "m 1
g Buddies
b toctest2
b joe
g Coworkers
b mike
d spammer123
"

toc_get_status

Query the online status of a user. Returns an UPDATE_BUDDY message if online, or an ERROR if the user is not available.

toc_get_status <screen_name>

Example:

toc_get_status toctest2

toc_set_info

Set the user's profile information (HTML).

toc_set_info <info_html>

Example:

toc_set_info "<b>Hello!</b> I love AIM."

toc_get_info

Request a user's profile. The server responds with a GOTO_URL containing a URL to view the profile, or an ERROR.

toc_get_info <screen_name>

Example:

toc_get_info toctest2

toc_set_away

Set or clear the away message. If a message is provided, the user's unavailable flag is set. If omitted, the flag is cleared.

toc_set_away [<away_message>]

Examples:

toc_set_away "Gone fishing! <b>BRB</b>"
toc_set_away

toc_set_idle

Set the idle time in seconds. If 0, the user is marked as active. The server auto-increments the idle counter, so only call this once.

toc_set_idle <seconds>

Examples:

toc_set_idle 300
toc_set_idle 0

toc_set_caps

Declare the client's capabilities. All supported capabilities must be sent at once. Capabilities are represented as UUIDs (see Capabilities).

toc_set_caps [<uuid1> [<uuid2> ...]]

Example:

toc_set_caps 09461343-4C7F-11D1-8222-444553540000 09461345-4C7F-11D1-8222-444553540000

toc_evil

Warn (evil) another user. You can only warn users who have recently sent you an IM.

toc_evil <screen_name> <norm|anon>
Type Effect
norm Normal warning (+20% to target's warning level, your identity revealed)
anon Anonymous warning (+10%, your identity hidden)

Example:

toc_evil spammer123 anon

toc_add_permit

Add users to the permit list. If currently in deny mode, switches to permit mode first. With no arguments and in deny mode, switches to permit-none.

toc_add_permit [<user1> [<user2> ...]]

Example:

toc_add_permit toctest2 joe

toc_add_deny

Add users to the deny (block) list. If currently in permit mode, switches to deny mode first. With no arguments and in permit mode, switches to deny-none.

toc_add_deny [<user1> [<user2> ...]]

Example:

toc_add_deny spammer123

toc_chat_join

Join a chat room on the specified exchange. Exchange should be 4 for standard chat rooms. The server responds with CHAT_JOIN on success or ERROR on failure.

toc_chat_join <exchange> <chat_room_name>

Example:

toc_chat_join 4 "My Chat Room"

toc_chat_send

Send a message to a chat room. Use the chat room ID received in the CHAT_JOIN response. Since reflection is always on, you will receive your own message back as a CHAT_IN.

toc_chat_send <chat_room_id> <message>

Example:

toc_chat_send 0 "Hello everyone!"

toc_chat_whisper

Send a private message within a chat room directed at a specific user.

toc_chat_whisper <chat_room_id> <destination_user> <message>

Example:

toc_chat_whisper 0 toctest2 "Can you see this?"

toc_chat_invite

Invite one or more users to a chat room you are currently in.

toc_chat_invite <chat_room_id> <invite_message> <buddy1> [<buddy2> ...]

Example:

toc_chat_invite 0 "Come join us!" toctest2 joe

toc_chat_accept

Accept a chat invitation received via CHAT_INVITE. The server will respond with CHAT_JOIN.

toc_chat_accept <chat_room_id>

Example:

toc_chat_accept 5

toc_chat_leave

Leave a chat room.

toc_chat_leave <chat_room_id>

Example:

toc_chat_leave 0

toc_set_dir

Set directory information. Fields are colon-separated within a quoted string.

toc_set_dir <info_string>

Fields (colon-separated): "first_name":"middle_name":"last_name":"maiden_name":"city":"state":"country":"email":"allow_web_search"

Example:

toc_set_dir "John":"":"Doe":"":"New York":"NY":"US":"john@example.com":""

toc_get_dir

Get a user's directory information. Returns a GOTO_URL or ERROR.

toc_get_dir <screen_name>

Example:

toc_get_dir toctest2

toc_dir_search

Search the user directory by field. Returns a GOTO_URL or ERROR.

toc_dir_search <search_fields>

Fields (colon-separated): "first_name":"middle_name":"last_name":"maiden_name":"city":"state":"country":"email"

You can search by keyword by placing it in the 11th position:

toc_dir_search "::::::::":"":"search term"

Example:

toc_dir_search "John":"":"Doe":"":"":"":"":""

toc_format_nickname

Reformat the capitalization/spacing of your screen name. Returns ADMIN_NICK_STATUS and NICK on success, or ERROR on failure.

toc_format_nickname <new_format>

Example:

toc_format_nickname "TocTest1"

toc_change_passwd

Change your password. Returns ADMIN_PASSWD_STATUS on success or ERROR on failure. Passwords are sent as plaintext (not roasted). Special characters must be backslash-escaped (see Escaping Rules).

Note: Because passwords are sent in cleartext (unlike the roasted password at login), this command is not secure against network eavesdropping.

toc_change_passwd <old_password> <new_password>

Examples:

toc_change_passwd oldpass newpass
toc_change_passwd "my old pass" "my new pass"
toc_change_passwd oldpa\$\$ newpa\$\$

toc_rvous_accept

Accept a rendezvous proposal (e.g. file transfer) from another user.

toc_rvous_accept <screen_name> <cookie> <service_uuid>
Parameter Description
screen_name The user who sent the proposal
cookie Base64-encoded cookie from the RVOUS_PROPOSE message
service_uuid UUID of the service being accepted

Example:

toc_rvous_accept toctest2 fUdgNuQ6AAA= 09461343-4C7F-11D1-8222-444553540000

toc_rvous_cancel

Cancel/decline a rendezvous proposal from another user.

toc_rvous_cancel <screen_name> <cookie> <service_uuid>

Example:

toc_rvous_cancel toctest2 fUdgNuQ6AAA= 09461343-4C7F-11D1-8222-444553540000

4. Client → Server Commands (TOC 2)

TOC 2 commands use the toc2_ prefix and operate on the server-side buddy list (feedbag) directly. Changes are automatically saved.

toc2_send_im

Same syntax as toc_send_im.

toc2_send_im <destination_user> <message> [auto]

Example:

toc2_send_im toctest2 "Hey there!"

toc2_send_im_enc

Send an encoded instant message. Supports encoding and language parameters.

toc2_send_im_enc <destination_user> "F" <encoding> <language> <message> [auto]
Parameter Description
destination_user Normalized screen name
"F" Unknown flag, always F
encoding Character encoding (e.g. A for ASCII)
language Language code (e.g. en)
message Quoted, escaped message
auto Optional auto for auto-response

Example:

toc2_send_im_enc toctest2 "F" A en "Hello from TOC2!"

toc2_set_pdmode

Set the permit/deny privacy mode.

toc2_set_pdmode <mode>
Mode Description
1 Allow all (default)
2 Block all
3 Allow permit list only
4 Block deny list only
5 Allow buddy list only

Example:

toc2_set_pdmode 1

toc2_new_group

Create a new buddy list group.

toc2_new_group <group_name>

Example:

toc2_new_group "Work Friends"

toc2_del_group

Delete a buddy list group and all buddies within it.

toc2_del_group <group_name>

Example:

toc2_del_group "Work Friends"

toc2_new_buddies

Add buddies to the server-side buddy list using a config-format string. If the specified group does not exist, it will be created.

toc2_new_buddies <config_format>

Config format: {g:<group>\nb:<buddy>[:<alias>]\nb:<buddy2>\n}

Where \n is a literal linefeed character (ASCII 10, 0x0A).

Extended buddy format with alias and note: b:<buddy>:<alias>:::::note

Examples:

Add two buddies to the "Friends" group:

toc2_new_buddies "{g:Friends\nb:toctest2\nb:joe\n}"

Add a buddy with an alias:

toc2_new_buddies "{g:Friends\nb:toctest2:Test User 2\n}"

toc2_remove_buddy

Remove one or more buddies from a group. The last argument is always the group name.

toc2_remove_buddy <screen_name> [<screen_name> ...] <group>

Examples:

toc2_remove_buddy toctest2 "Friends"
toc2_remove_buddy toctest2 joe "Friends"

toc2_add_permit

Add users to the permit list (feedbag-based).

toc2_add_permit <screen_name> [<screen_name> ...]

Example:

toc2_add_permit toctest2 joe

toc2_remove_permit

Remove users from the permit list.

toc2_remove_permit <screen_name> [<screen_name> ...]

Example:

toc2_remove_permit toctest2

toc2_add_deny

Add users to the deny (block) list (feedbag-based).

toc2_add_deny <screen_name> [<screen_name> ...]

Example:

toc2_add_deny spammer

toc2_remove_deny

Remove users from the deny (block) list.

toc2_remove_deny <screen_name> [<screen_name> ...]

Example:

toc2_remove_deny spammer

toc2_client_event

Send a typing notification to another user.

toc2_client_event <screen_name> <typing_status>
Status Description
0 Idle (no activity)
1 Text entered (paused typing)
2 Currently typing

Example:

toc2_client_event toctest2 2

5. Server → Client Messages (TOC 1)

Server messages use colons as separators. Messages are NOT null-terminated. When parsing, be aware that message content (IMs, chat messages) may contain colons — split with a maximum field count appropriate to each command.

SIGN_ON

Sent after a successful login.

SIGN_ON:<protocol_version>

Example:

SIGN_ON:TOC1.0

CONFIG

The user's saved configuration (buddy list, permit/deny). Only sent for TOC 1 logins. Config may be empty if none was previously saved.

CONFIG:<config_data>

Config format uses space-separated item types (same format as toc_set_config):

CONFIG:m 1
g Buddies
b toctest2
b joe
d spammer123

Config may be empty (CONFIG:) if no configuration has been saved.

NICK

The user's properly formatted screen name.

NICK:<formatted_screen_name>

Example:

NICK:TocTest1

IM_IN

An incoming instant message.

IM_IN:<source_user>:<auto_response T/F>:<message>

Everything after the third colon is the message (may contain additional colons).

Examples:

IM_IN:TocTest2:F:Hello there!
IM_IN:TocTest2:T:I am away from my computer right now.
IM_IN:TocTest2:F:<b>Bold</b> and <i>italic</i>

UPDATE_BUDDY

Buddy presence update. Handles arrivals, departures, and status changes.

UPDATE_BUDDY:<screen_name>:<online T/F>:<warning_level>:<signon_time>:<idle_minutes>:<user_class>
Field Description
screen_name Formatted screen name
online T if online, F if offline
warning_level Warning percentage (0-100)
signon_time Unix epoch timestamp of signon
idle_minutes Minutes idle (0 = active)
user_class 2-3 character class string (see below)

User class characters:

Position Char Meaning
uc[0] ' ' Normal
uc[0] 'A' On AOL
uc[1] ' ' Normal
uc[1] 'A' Admin
uc[1] 'U' Unconfirmed
uc[1] 'O' OSCAR Free (normal AIM user)
uc[1] 'C' Mobile/wireless
uc[2] ' ' Available
uc[2] 'U' Unavailable (away)

Examples:

UPDATE_BUDDY:TocTest2:T:0:1711036800:0: O
UPDATE_BUDDY:TocTest2:T:0:1711036800:0: U
UPDATE_BUDDY:TocTest2:F:0:0:0:
UPDATE_BUDDY:TocTest2:T:20:1711036800:5: OU

ERROR

An error response. May include a screen name or sub-error code as a variable argument.

ERROR:<error_code>[:<variable>]

Example:

ERROR:901:toctest2
ERROR:980

See Error Codes for the full list.

EVILED

The user has been warned.

EVILED:<new_warning_level>:<eviler_screen_name>

If the warning was anonymous, the eviler field is empty.

Examples:

EVILED:20:TocTest2
EVILED:10:

CHAT_JOIN

Successfully joined a chat room. The chat room ID is an integer assigned by the server — store it for subsequent chat commands.

CHAT_JOIN:<chat_room_id>:<chat_room_name>

Example:

CHAT_JOIN:0:My Chat Room

CHAT_IN

A message received in a chat room.

CHAT_IN:<chat_room_id>:<source_user>:<whisper T/F>:<message>

Example:

CHAT_IN:0:TocTest2:F:Hello everyone!

CHAT_UPDATE_BUDDY

Users have joined or left a chat room. The first message of this type for a room contains the initial user list.

CHAT_UPDATE_BUDDY:<chat_room_id>:<inside T/F>:<user1>[:<user2>...]
Field Description
inside T = users arrived, F = users departed

Examples:

CHAT_UPDATE_BUDDY:0:T:TocTest1:TocTest2
CHAT_UPDATE_BUDDY:0:F:TocTest2

CHAT_INVITE

An invitation to join a chat room.

CHAT_INVITE:<chat_room_name>:<chat_room_id>:<sender>:<message>

Example:

CHAT_INVITE:My Chat Room:5:TocTest2:Come join us!

CHAT_LEFT

Confirmation that you have left a chat room.

CHAT_LEFT:<chat_room_id>

Example:

CHAT_LEFT:0

GOTO_URL

Directs the client to open a URL (for profiles, directory info, search results).

GOTO_URL:<window_name>:<url>

Example:

GOTO_URL:profile:info?cookie=abc123&user=toctest2&from=toctest1

DIR_STATUS

Result of a toc_set_dir command.

DIR_STATUS:<return_code>

Return code 0 indicates success.

ADMIN_NICK_STATUS

Result of a toc_format_nickname command.

ADMIN_NICK_STATUS:<return_code>

Return code 0 indicates success.

Example:

ADMIN_NICK_STATUS:0

ADMIN_PASSWD_STATUS

Result of a toc_change_passwd command.

ADMIN_PASSWD_STATUS:<return_code>

Return code 0 indicates success.

RVOUS_PROPOSE

Another user proposes a rendezvous (file transfer, etc.).

RVOUS_PROPOSE:<user>:<uuid>:<cookie>:<seq>:<rvous_ip>:<proposer_ip>:<verified_ip>:<port>[:<tlv_tag>:<tlv_value>...]
Field Description
user Screen name of the proposer
uuid Service UUID (e.g. file transfer)
cookie Base64-encoded session cookie
seq Sequence number
rvous_ip Rendezvous IP address
proposer_ip Proposer's IP address
verified_ip Server-verified IP address
port Port number for direct connection
tlv pairs Additional base64-encoded TLV data

Example:

RVOUS_PROPOSE:TocTest2:09461343-4C7F-11D1-8222-444553540000:fUdgNuQ6AAA=:1:192.168.1.5:192.168.1.5:203.0.113.1:5190:10001:ABIAAgAAAAEA

PAUSE

Server requests the client to pause. A new SIGN_ON will follow when the server is ready. The buddy list and permit/deny items must be resent, followed by toc_init_done.

PAUSE

6. Server → Client Messages (TOC 2)

TOC 2 extends the server messages with richer variants. When logged in via toc2_signon or toc2_login, these messages are sent instead of (or in addition to) their TOC 1 equivalents.

SIGN_ON (TOC 2)

SIGN_ON:TOC2.0

CONFIG2

Server-side buddy list configuration, sent at login. Fields are separated by linefeeds (\n, ASCII 10). Colons separate sub-fields within each line.

CONFIG2:<config_lines>

Config line types:

Prefix Format Description
g: g:<group_name> Buddy group
b: b:<screen_name>[:<alias>][:::::note] Buddy entry (with optional alias and note)
d: d:<screen_name> Deny list entry
p: p:<screen_name> Permit list entry
m: m:<mode> Privacy mode (1-5, same as toc2_set_pdmode)
done: done: End of config

Example:

CONFIG2:g:Buddies
b:toctest2:Test User
b:joe
d:spammer
m:1
done:

NICK (TOC 2)

Same as TOC 1:

NICK:<formatted_screen_name>

IM_IN2

Incoming instant message (TOC 2 variant). Adds a whisper field.

IM_IN2:<source_user>:<auto_response T/F>:<whisper T/F>:<message>

Example:

IM_IN2:TocTest2:F:F:Hello from TOC2!

IM_IN_ENC2

Incoming encoded instant message (TOC 2 with toc2_login). Includes user class and language information.

IM_IN_ENC2:<user>:<auto T/F>:<unknown1>:<unknown2>:<user_class>:<unknown3>:<unknown4>:<language>:<message>
Field Description
user Sender's screen name
auto T if auto-response, F otherwise
unknown1 Typically F
unknown2 Typically T
user_class Same as UPDATE_BUDDY user class (e.g. O, OU)
unknown3 Typically F
unknown4 Typically L
language Language code (e.g. en)
message The message content (may contain colons)

Example:

IM_IN_ENC2:TocTest2:F:F:T: O :F:L:en:Hello from TOC2!
IM_IN_ENC2:TocTest2:T:F:T: OU:F:L:en:I am away right now.

UPDATE_BUDDY2

Buddy presence update (TOC 2). Same as UPDATE_BUDDY with a trailing field.

UPDATE_BUDDY2:<screen_name>:<online T/F>:<warning_level>:<signon_time>:<idle_minutes>:<user_class>:<unknown>

The trailing unknown field is typically empty.

Examples:

UPDATE_BUDDY2:TocTest2:T:0:1711036800:0: O :
UPDATE_BUDDY2:TocTest2:F:0:0:0:   :

BUDDY_CAPS2

Sent alongside UPDATE_BUDDY2 to describe a buddy's capabilities.

BUDDY_CAPS2:<screen_name>:<cap1>,<cap2>,...

Capabilities are UUIDs (see Capabilities).

Example:

BUDDY_CAPS2:TocTest2:748f2420-6287-11d1-8222-444553540000,09461343-4c7f-11d1-8222-444553540000

CHAT_IN_ENC

Encoded chat message (TOC 2 with toc2_login).

CHAT_IN_ENC:<chat_room_id>:<source_user>:<whisper T/F>:<unknown>:<language>:<message>

The unknown field is typically A.

Example:

CHAT_IN_ENC:0:TocTest2:F:A:en:Hello everyone!

NEW_BUDDY_REPLY2

Confirmation after adding a buddy via toc2_new_buddies.

NEW_BUDDY_REPLY2:<screen_name>:<action>
Action Description
added Buddy was added successfully
auth ICQ authorization request sent

Example:

NEW_BUDDY_REPLY2:toctest2:added

CLIENT_EVENT2

Typing notification from another user.

CLIENT_EVENT2:<screen_name>:<typing_status>
Status Description
0 No activity (stopped typing)
1 Text entered (paused)
2 Currently typing

Example:

CLIENT_EVENT2:TocTest2:2

INSERTED2

Dynamic buddy list update — items added from another session.

Group added:

INSERTED2:g:<group_name>

Buddy added:

INSERTED2:b:<alias>:<screen_name>:<group>

Deny list entry added:

INSERTED2:d:<screen_name>

Permit list entry added:

INSERTED2:p:<screen_name>

Examples:

INSERTED2:g:New Group
INSERTED2:b:My Friend:toctest2:Buddies
INSERTED2:b::joe:Buddies
INSERTED2:d:spammer
INSERTED2:p:trusteduser

DELETED2

Dynamic buddy list update — items removed from another session.

Group deleted:

DELETED2:g:<group_name>

Buddy deleted:

DELETED2:b:<screen_name>:<group>

Deny list entry removed:

DELETED2:d:<screen_name>

Permit list entry removed:

DELETED2:p:<screen_name>

Examples:

DELETED2:g:Old Group
DELETED2:b:toctest2:Buddies
DELETED2:d:spammer

BART2

Buddy icon (Buddy Art) information. Structure is not fully understood.

BART2:<screen_name>:<data>

7. Error Codes

Errors are sent as ERROR:<code>[:<variable>]. The variable argument (if present) is typically a screen name or sub-error code.

General Errors

Code Description
901 $1 not currently available
902 Warning of $1 not currently available
903 Message dropped, server speed limit exceeded

Admin Errors

Code Description
911 Error validating input
912 Invalid account
913 Error encountered while processing request
914 Service unavailable

Chat Errors

Code Description
950 Chat in $1 is unavailable

IM & Info Errors

Code Description
960 Sending messages too fast to $1
961 Missed an IM from $1 because it was too big
962 Missed an IM from $1 because it was sent too fast

Directory Errors

Code Description
970 Failure
971 Too many matches
972 Need more qualifiers
973 Dir service temporarily unavailable
974 Email lookup restricted
975 Keyword ignored
976 No keywords
977 Language not supported
978 Country not supported
979 Failure unknown $1

Auth Errors

Code Description
980 Incorrect nickname or password
981 Service temporarily unavailable
982 Warning level too high to sign on
983 Connecting/disconnecting too frequently (wait 10 minutes)
989 Unknown signon error $1

Sub-error codes for 989:

Sub-code Description
0 Signed on too soon
7 Invalid screen name or password
17 Suspended account

8. Escaping & Encoding Rules

8.1 Client → Server (Encoding)

When sending commands to the server, certain characters must be backslash-escaped whether inside quotes or not:

Character Escaped
\ \\
$ \$
" \"
( \(
) \)
{ \{
} \}
[ \[
] \]

Example: To send the message He said "hello" (wow) for $5:

toc_send_im toctest2 "He said \"hello\" \(wow\) for \$5"

8.2 Screen Name Normalization

When sending screen names to the server, normalize them:

  1. Convert to lowercase.
  2. Remove all spaces.

Example: Toc Test 1toctest1

8.3 Server → Client (No Encoding)

Server messages are NOT encoded. They use colons as delimiters. When parsing, limit the number of splits to avoid breaking messages that contain colons.

8.4 Null Termination

  • Client → Server: All FLAP DATA payloads MUST end with a null byte (0x00). Include it in the FLAP data length.
  • Server → Client: FLAP DATA payloads are NOT null-terminated.

9. Capabilities (UUIDs)

Capabilities indicate which features a client supports. They are set via toc_set_caps and reported via BUDDY_CAPS2.

Standard Capabilities

Name UUID
Voice Chat 09461341-4C7F-11D1-8222-444553540000
File Send 09461343-4C7F-11D1-8222-444553540000
Image 09461345-4C7F-11D1-8222-444553540000
Buddy Icon 09461346-4C7F-11D1-8222-444553540000
Stocks 09461347-4C7F-11D1-8222-444553540000
File Get 09461348-4C7F-11D1-8222-444553540000
Games 0946134A-4C7F-11D1-8222-444553540000
Send Buddy List 0946134B-4C7F-11D1-8222-444553540000
AIM/ICQ Interop 0946134D-4C7F-11D1-8222-444553540000
Chat 748F2420-6287-11D1-8222-444553540000

Short Capability Format

Some clients send capabilities as short hex codes (1-4 hex digits). These expand to the full OSCAR capability UUID format: 0946XXYY-4C7F-11D1-8222-444553540000 where XXYY is the short code zero-padded to 4 hex digits.

Example: Short cap 134309461343-4C7F-11D1-8222-444553540000 (File Send)


10. Complete Session Examples

10.1 TOC 1 Session (Minimal)

This example shows a complete TOC 1 session: login, add a buddy, send a message, and disconnect.

Wire-level (showing FLAP framing conceptually):

→ TCP connect to server:9898
→ "FLAPON\r\n\r\n"
← [FLAP SIGNON] version=1
→ [FLAP SIGNON] version=1, TLV(1)="toctest1"
→ [FLAP DATA]   toc_signon login.oscar.aol.com 5190 toctest1 0x2408105c23001130 english "TIC:Example"
← [FLAP DATA]   SIGN_ON:TOC1.0
← [FLAP DATA]   CONFIG:m 1\ng Buddies\nb toctest2\n
← [FLAP DATA]   NICK:toctest1
→ [FLAP DATA]   toc_add_buddy toctest2
→ [FLAP DATA]   toc_init_done
← [FLAP DATA]   UPDATE_BUDDY:toctest2:T:0:1711036800:0: O
→ [FLAP DATA]   toc_send_im toctest2 "Hello!"
→ [FLAP DATA]   toc_set_away "Gone fishing"
→ [FLAP SIGNOFF]

10.2 TOC 2 Session (toc2_login)

→ TCP connect to server:9898
→ "FLAPON\r\n\r\n"
← [FLAP SIGNON] version=1
→ [FLAP SIGNON] version=1, TLV(1)="toctest1"
→ [FLAP DATA]   toc2_login login.oscar.aol.com 5190 toctest1 0x2408105c23001130 english "TIC:Example" 160 US "" "" 3 0 30303 -kentucky -utf8 103547776
← [FLAP DATA]   SIGN_ON:TOC2.0
← [FLAP DATA]   NICK:toctest1
← [FLAP DATA]   CONFIG2:g:Buddies\nb:toctest2:Test User\nm:1\ndone:\n
→ [FLAP DATA]   toc_init_done
← [FLAP DATA]   UPDATE_BUDDY2:toctest2:T:0:1711036800:0: O :
← [FLAP DATA]   BUDDY_CAPS2:toctest2:748f2420-6287-11d1-8222-444553540000
→ [FLAP DATA]   toc2_new_buddies "{g:Friends\nb:joe\n}"
← [FLAP DATA]   NEW_BUDDY_REPLY2:joe:added
→ [FLAP DATA]   toc2_send_im_enc toctest2 "F" A en "Hello from TOC2!"
→ [FLAP DATA]   toc2_client_event toctest2 2
→ [FLAP DATA]   toc2_set_pdmode 1
→ [FLAP SIGNOFF]

10.3 Chat Session

→ toc_chat_join 4 "Retro Chat"
← CHAT_JOIN:0:Retro Chat
← CHAT_UPDATE_BUDDY:0:T:toctest1
→ toc_chat_send 0 "Hello room!"
← CHAT_IN:0:toctest1:F:Hello room!
← CHAT_UPDATE_BUDDY:0:T:toctest2
→ toc_chat_invite 0 "Come chat!" joe
→ toc_chat_send 0 "Welcome toctest2!"
← CHAT_IN:0:toctest1:F:Welcome toctest2!
→ toc_chat_leave 0
← CHAT_LEFT:0

10.4 Python Client Example

A minimal Python client that connects, logs in, sends a message, and reads responses:

import socket
import struct


ROAST = "Tic/Toc"


def roast_password(password):
    result = []
    for i, ch in enumerate(password):
        xored = ord(ch) ^ ord(ROAST[i % len(ROAST)])
        result.append(f"{xored:02x}")
    return "0x" + "".join(result)


def send_flap(sock, frame_type, seq, payload):
    data = payload.encode("ascii") if isinstance(payload, str) else payload
    if frame_type == 2:
        data += b"\x00"  # null-terminate DATA frames
    header = struct.pack("!BBHH", 0x2A, frame_type, seq, len(data))
    sock.sendall(header + data)
    return seq + 1


def recv_flap(sock):
    header = b""
    while len(header) < 6:
        chunk = sock.recv(6 - len(header))
        if not chunk:
            raise ConnectionError("Connection closed")
        header += chunk
    marker, frame_type, seq, length = struct.unpack("!BBHH", header)
    payload = b""
    while len(payload) < length:
        chunk = sock.recv(length - len(payload))
        if not chunk:
            raise ConnectionError("Connection closed")
        payload += chunk
    return frame_type, seq, payload


def normalize(screen_name):
    return screen_name.lower().replace(" ", "")


def escape(text):
    for ch in r'\$"(){}[]':
        text = text.replace(ch, "\\" + ch)
    return text


def main():
    HOST = "127.0.0.1"
    PORT = 9898
    USERNAME = "toctest1"
    PASSWORD = "testpass1"

    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.connect((HOST, PORT))
    sock.settimeout(5)

    # Step 1: Send FLAPON
    sock.sendall(b"FLAPON\r\n\r\n")

    # Step 2: Receive server SIGNON frame
    frame_type, seq, payload = recv_flap(sock)
    assert frame_type == 1, f"Expected SIGNON frame, got {frame_type}"

    # Step 3: Send client SIGNON frame
    sn = normalize(USERNAME).encode("ascii")
    signon_payload = struct.pack("!IHH", 1, 1, len(sn)) + sn
    seq_out = send_flap(sock, 1, 0, signon_payload)

    # Step 4: Send toc_signon
    roasted = roast_password(PASSWORD)
    cmd = f'toc_signon login.oscar.aol.com 5190 {normalize(USERNAME)} {roasted} english "TIC:PythonTOC"'
    seq_out = send_flap(sock, 2, seq_out, cmd)

    # Step 5: Read responses
    for _ in range(10):
        try:
            frame_type, seq, payload = recv_flap(sock)
            if frame_type == 2:
                print(f"← {payload.decode('ascii', errors='replace')}")
        except socket.timeout:
            break

    # Step 6: Send init_done
    seq_out = send_flap(sock, 2, seq_out, "toc_init_done")

    # Step 7: Send a message
    msg = escape("Hello from Python!")
    seq_out = send_flap(sock, 2, seq_out, f'toc_send_im toctest2 "{msg}"')

    # Read any remaining responses
    for _ in range(10):
        try:
            frame_type, seq, payload = recv_flap(sock)
            if frame_type == 2:
                print(f"← {payload.decode('ascii', errors='replace')}")
        except socket.timeout:
            break

    # Disconnect
    send_flap(sock, 4, seq_out, b"")
    sock.close()


if __name__ == "__main__":
    main()