#ifndef LIBRARIES_ICQ_H
#define LIBRARIES_ICQ_H

/* icq.library - Use to create and parse packets sent to/from an ICQ server.
** Will eventually support multiple versions and TCP.
** Written by Douglas F. McLaughlin <mclaughd@kda.attmil.ne.jp>
** Placed in the public domain.
**
** The ICQ protocol is (C) Copyright 1996, Mirabilis Ltd.
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif


extern void  MSG_ParseMessage(UWORD Type, UBYTE *Message, APTR DataStruct);

extern UWORD TCP_CreateMsgPacket(struct TCP_Message *TCPMsg, UBYTE **Buffer, ULONG *Sequence, UWORD *RevLen);
extern void  TCP_ParseMsgPacket(struct TCP_Message *TCPMsg, UBYTE *Buffer, ULONG *Sequence);
extern UWORD TCP_CreateFilePacket(UBYTE Command, APTR DataStruct, UBYTE *Buffer, UWORD *RevLen);
extern UWORD TCP_CreateChatPacket(UBYTE Command, APTR DataStruct, UBYTE *Buffer, UWORD *RevLen);
extern UBYTE TCP_ParseChatPacket(void **DataStruct, UBYTE *Buffer);
extern UWORD TCP_CreateChatCmd(UBYTE Command, APTR DataStruct, UBYTE *Buffer);
extern void  TCP_FreeMsgPacket(UBYTE *Buf);
extern UWORD TCP_ParseTCPInit(struct TCP_Init *, UBYTE *);

extern char *ICQ_CmdToText(UWORD);

extern UWORD UDP_CreatePacket(struct UDP_Header *Header, APTR DataStruct, UBYTE *Buffer);
extern BOOL  UDP_EncryptPacket(UBYTE *Buffer, UBYTE *OldBuf, UWORD Len);
extern void  UDP_ParseHeader(UBYTE *Buffer, struct UDP_Header *Header);
extern void  UDP_ParsePacket(APTR DataStruct, UBYTE *Buffer, UWORD PktLen, struct UDP_Header *Header);
extern void  UDP_ParseMeta(APTR DataStruct, struct S_Meta *Meta);

extern void  UDP_NextMulti(struct S_Multi *Multi);


extern void  PrintHex(UBYTE Type, char *Title, UBYTE *Buffer, UWORD Len);

/*
** These will convert between Big-Endian and Little-Endian, LONG and WORD values.
*/

#define BREV_L(a) (((a)>>24)|(((a)&0x00FF0000)>>8)|(((a)&0x0000FF00)<<8)|((a)<<24))
#define BREV_W(a) (((a)>>8)|((a)<<8))

/*
** Various values.
*/

#ifndef LINE
#define LINE                 "\0"        /* Empty line for sending empty messages */
#endif

#define MAX_CONTACTS_PKT     0x64        /*  100 is as large as this can go */
#define FILE_PKT_SIZE        0x0800      /* 2048 bytes per filedirect packet */

/*
** Status codes used by ICQ.
*/

/*
** -Old Method.
*/

#define STAT_ONLINE          0x00000000  /* Online */
#define STAT_AWAY            0x00000001  /* Away */
#define STAT_DND_2           0x00000003  /* Do Not Disturb */
#define STAT_NA              0x00000005  /* Not Available */
#define STAT_DND_3           0x00000010  /* Do Not Disturb */
#define STAT_OCCUPIED        0x00000011  /* Occupied */
#define STAT_DND             0x00000013  /* Do Not Disturb */
#define STAT_FREE_CHAT       0x00000020  /* Free For Chat */
#define STAT_INVISIBLE       0x00000100  /* Invisible */
#define STAT_ONLINE_99       0x00000200  /* First Online */
#define STAT_AWAY_99         0x00000201  /* First Away */
#define STAT_NA_99           0x00000204  /* First Not Available */
#define STAT_OCCUPIED_99     0x00000210  /* First Occupied */
#define STAT_FREE_CHAT_99    0x00000220  /* First Free For Chat */
#define STAT_NEWUIN          0x000000FE  /* New UIN in Contact List (STRICQ) */
#define STAT_OFFLINE         0x0000FFFF  /* Offline */

#define STAT_HIDEIP          0x00020000
#define STAT_WEBPRESENCE     0x00010000

/*
** +New Method.
*/

#define STATUS_ONLINE        0x00000000  /* Online */
#define STATUS_AWAY          0x00000001  /* Away */
#define STATUS_DND           0x00000003  /* Do Not Disturb */
#define STATUS_NA            0x00000005  /* Not Available */

#define STATUS_NEWUIN        0x000000FE  /* Not in my contact list (STRICQ) */
#define STATUS_OFFLINE       0x0000FFFF  /* Offline */

#define STATUSF_HIGH         0x00000010  /* & Online = Occupied */
#define STATUSF_CHAT         0x00000020  /* & Online = Free For Chat */
#define STATUSF_INVISIBLE    0x00000100  /* & Any mode = Invisible, but you can see me */
#define STATUSF_FIRST        0x00000200  /* & Any mode = My first login this session (ICQ99a Betas) */

#define STATUSF_WEBPRESENCE  0x00010000  /* Turn on my web page status indicator */
#define STATUSF_HIDEIP       0x00020000  /* Don't show my IP address */
#define STATUSF_BIRTHDAY     0x00080000  /* Today is my birthday */
#define STATUSF_UNK_1        0x00200000  /* Unknown */

/*
** UDP Protocol Commands sent to server.
*/

#define C_ACK                0x000A      /* 0010 acknowledgement */
#define C_SEND_MESSAGE       0x010E      /* 0270 send message through server */
#define C_LOGIN              0x03E8      /* 1000 login on to server */
#define C_NEW_USER_REG       0x03FC      /* 1020 Register a new user */
#define C_CONTACT_LIST       0x0406      /* 1030 Inform the server of contact list, addatively */
#define C_SEARCH_USER        0x0424      /* 1060 Search for user by nick/name/email */
#define C_KEEP_ALIVE         0x042E      /* 1070 keep alive */
#define C_SEND_TEXT_CODE     0x0438      /* 1080 send special message to server */
#define C_ACK_MSG            0x0442	     /* 1090 Ack all messages (delete from server) */
#define C_LOGIN_1            0x044C      /* 1100 Sent during login */
#define C_INFO_REQ           0x0460      /* 1120 Request a UINs Basic Information */
#define C_EXT_INFO_REQ       0x046A      /* 1130 Request a UINs Extended Information */
#define C_CHANGE_PASSWORD    0x049C      /* 1180 Change the user's password */
#define C_NEW_USER_INFO      0x04A6      /* 1190 Send new user's basic information */
#define C_UPDATE_EXT_INFO    0x04B0      /* 1200 Update my extended information */
#define C_QUERY_STATUS       0x04BA      /* 1210 Query about other servers */
#define C_LOGIN_3            0x04CE      /* 1230 Sent during login */
#define C_STATUS_CHANGE      0x04D8      /* 1240 Change status of user (Away etc.) */
#define C_NEW_USER_1         0x04EC      /* 1260 Ask for permission to add new user */
#define C_SEND_URL_MESSAGE   0x04F6      /* 1270 Request server advertisement */
#define C_UPDATE_INFO        0x050A      /* 1290 Update my basic information */
#define C_UPDATE_AUTH        0x0514      /* 1300 Update my authorization status */
#define C_LOGIN_2            0x0528      /* 1320 Sent during Login */
#define C_META               0x064A      /* 1610 Meta command that supports sub-commands (v5) */
#define C_INVIS_LIST         0x06A4      /* 1700 Sends the 'Invisible To User' contact list */
#define C_VIS_LIST           0x06AE      /* 1710 Sends the 'Visible To User' contact list */

/*
** UDP Protocol Commands sent by server.
*/

#define S_ACK                0x000A      /* 0010 Ack */
#define S_UNKNOWN_ERROR      0x001E      /* 0030 Unknown error message */
#define S_GO_AWAY            0x0028	     /* 0040 Been idle, logging you out */
#define S_NEW_USER_UIN       0x0046      /* 0070 Confirmation of new user with UIN */
#define S_LOGIN_REPLY        0x005A      /* 0090 Login reply */
#define S_BAD_PASSWORD       0x0064      /* 0100 Bad password sent during login */
#define S_USER_ONLINE        0x006E      /* 0110 user in clist changed status */
#define S_USER_OFFLINE       0x0078      /* 0120 user in clist has gone offline */
#define S_QUERY_REPLY        0x0082      /* 0130 Response to QUERY_SERVERS or QUERY_ADDONS */
#define S_USER_FOUND         0x008C      /* 0140 user record found matching query */
#define S_END_OF_SEARCH      0x00A0      /* 0160 No more USER_FOUND will be sent */
#define S_NEW_USER_REPLY     0x00B4      /* 0180 Confirmation of new user info */
#define S_UPDATE_EXT_REPLY   0x00C8      /* 0200 Confirmation of extended update */
#define S_RECEIVE_MESSAGE    0x00DC      /* 0220 message sent while offline */
#define S_END_OFFLINE_MSGS   0x00E6      /* 0230 The last offline message has been sent */
#define S_LOGGED_OFF         0x00F0      /* 0240 The server has logged you off */
#define S_TOO_BUSY           0x00FA      /* 0250 Server is busy try again later */
#define S_GET_MESSAGE        0x0104	     /* 0260 message from user (sent through server) */
#define S_INFO_REPLY         0x0118      /* 0280 Return basic information */
#define S_EXT_INFO_REPLY     0x0122      /* 0290 Return extended information */
#define S_INFO_NOT_FOUND     0x012C      /* 0300 User's basic information not found */
#define S_EXT_INFO_NOT_FOUND 0x0136      /* 0310 User's extended information not found */
#define S_TCP_REQUEST        0x015E      /* 0350 TCP connection request sent through server */
#define S_STATUS_UPDATE      0x01A4      /* 0420 User on contact list changed stat */
#define S_SYSTEM_MESSAGE     0x01C2      /* 0450 System message with URL button */
#define S_UPDATE_REPLY       0x01E0      /* 0480 Confirmation of basic update */
#define S_UPDATE_FAIL        0x01EA      /* 0490 Basic info update has failed */
#define S_UPDATE_AUTH_REPLY  0x01F4      /* 0500 Confirmation of Authorization update */
#define S_MULTI              0x0212      /* 0530 Multi-packet containing other packets encapsulated */
#define S_REPLY_X1           0x021C      /* 0540 Unknown, reply to C_LOGIN_1 */
#define S_META               0x03DE      /* 0990 Meta command reply that supports sub-commands (v5) */

/*
** Meta command sub-commands.
*/

#define META_RPLY_HOME         0x0064      /* 0100 Indicates the home information update succeeded/failed */
#define META_RPLY_WORK         0x006E      /* 0110 Indicates the work information update succeeded/failed */
#define META_RPLY_MORE         0x0078      /* 0120 Indicates the more information update succeeded/failed */
#define META_RPLY_ABOUT        0x0082      /* 0130 Indicates the about text update succeeded/failed */
#define META_RPLY_INTERESTS    0x008C      /* 0140 Indicates the interests update succeeded/failed */
#define META_RPLY_AFFILIATIONS 0x0096      /* 0150 Indicates the affiliations update succeeded/failed */
#define META_RPLY_FLAGS        0x00A0      /* 0160 Indicates the authorize, webaware and hideip update succeeded/failed */
#define META_RPLY_PASSWORD     0x00AA      /* 0170 Indicates the password change succeeded/failed */
#define META_RPLY_URLCATEGORY  0x00BE      /* 0190 Indicates the homepage URL category change succeeded/failed */

#define META_INFO_HOME         0x00C8      /* 0200 Returns personal contact information, including EMail, Address, Phone */
#define META_INFO_WORK         0x00D2      /* 0210 Returns work/business contact related information */
#define META_INFO_MORE         0x00DC      /* 0220 Returns more information not in META_INFO_HOME */
#define META_INFO_ABOUT        0x00E6      /* 0230 Returns only the about text */
#define META_INFO_INTERESTS    0x00F0      /* 0240 Returns interests */
#define META_INFO_AFFILIATIONS 0x00FA      /* 0250 Returns affiliations */
#define META_INFO_URLCATEGORY  0x010E      /* 0270 Returns the homepage URL category */

#define META_INFO_BASIC        0x019A      /* 0410 Returns basic information, same as S_INFO_REPLY */

#define META_UPD_HOME          0x03E8      /* 1000 Updates personal contact information */
#define META_UPD_HOME_1        0x03E9      /* 1001 Updates personal contact information (99b client) */
#define META_UPD_WORK          0x03F2      /* 1010 Updates work/business contact related information */
#define META_UPD_WORK_1        0x03F3      /* 1011 Updates work/business contact related information (99b client) */
#define META_UPD_MORE          0x03FC      /* 1020 Updates the more information */
#define META_UPD_MORE_1        0x03FD      /* 1021 Updates the more information (99b client) */
#define META_UPD_ABOUT         0x0406      /* 1030 Updates about text */
#define META_UPD_INTERESTS     0x0410      /* 1040 Updates interests */
#define META_UPD_AFFILIATIONS  0x041A      /* 1050 Updates affiliations */
#define META_UPD_FLAGS         0x0424      /* 1060 Updates authorize, webaware and hideip status' */
#define META_UPD_PASSWORD      0x042E      /* 1070 Updates the login password */
#define META_UPD_URLCATEGORY   0x0442      /* 1090 Updates the homepage URL category */

#define META_REQ_INFO          0x04B0      /* 1200 Requests META_INFO_HOME, _WORK, _MORE, _ABOUT, _INTERESTS, _AFFILIATIONS and _URLCATEGORY */
#define META_REQ_INFO_1        0x04B1      /* 1201 Requests same as META_REQ_INFO (99b client) */
#define META_REQ_GRABME        0x04CE      /* 1230 Requests all MY userinfo to synchronize with ICQ server */
#define META_REQ_GRABME_1      0x04CF      /* 1231 Requests all MY userinfo to synchronize with ICQ server (99b client) */

#define META_UNK_1             0x07D0      /* 2000 Unknown, sent during login and throughout a session by 99b clients with 0x0000 data */

#define META_SUCCESS           0x0A        /* 0010 META_REQ_* subcommand was successful and returned valid data */

/*
** TCP/UDP Message related codes.
**
** Message types.
*/

#define MSG_MSG          0x0001      /* 0001 Used to send a normal message, same for UDP and TCP  */
#define MSG_CHAT         0x0002      /* 0002 Used to initiate a Chat session */
#define MSG_FILE         0x0003      /* 0003 Used to initiate a FileDirect session */
#define MSG_URL          0x0004      /* 0004 Used to send a URL message, same for UDP and TCP */
#define MSG_REQ_AUTH     0x0006      /* 0006 Used to request authorization to add to contact list */
#define MSG_DENY_AUTH    0x0007      /* 0007 Used to deny authorization to add to contact list */
#define MSG_GIVE_AUTH    0x0008      /* 0008 Used to grant authorization to add to contact list */
#define MSG_ADDED        0x000C      /* 0012 Used to notify that your UIN was added to a contact list */
#define MSG_WEB_PAGER    0x000D      /* 0013 Used to receive a web pager message from the white page */
#define MSG_EMAIL_PAGER  0x000E      /* 0014 Used to receive an EMail message from UIN@pager.mirabilis.com */
#define MSG_ADDUIN       0x0013      /* 0019 Used to send UINs from one client to another */
#define MSG_GREETING     0x001A      /* 0026 Used to send a greeting card */

#define MSG_READAWAY     0x03E8      /* 1000 */
#define MSG_READOCCUPIED 0x03E9      /* 1001 */
#define MSG_READNA       0x03EA      /* 1002 */
#define MSG_READDND      0x03EB      /* 1003 */
#define MSG_READFFC      0x03EC      /* 1004 */

#define MSGF_MASS        0x0800      /* 2048 This message was sent to more than one UIN */

/*
** TCP Packet Constants.
*/

#define TCP_INIT_IDENT       0xFF    /* 0255 First byte is always 0xFF */

#define TCP_VERSION_CURRENT  0x0002  /* 0002 Version currently in use (STRICQ) */
#define TCP_VERSION_MAX      0x0006  /* 0006 Highest version of TCP known so far */

#define TCP_REVISION_CURRENT 0x0000  /* 0000 Revision in use */

#define TCP_FLAG_CAPABLE     0x04    /* 0004 Client is TCP capable */
#define TCP_FLAG_NOTCP       0x06    /* 0006 Client is not TCP capable */

/*
** TCP Message Commands.
*/

#define TCP_CANCEL           0x07D0  /* 2000 TCP cancel previous file/chat request */
#define TCP_ACK              0x07DA  /* 2010 TCP acknowledge message packet */
#define TCP_MESSAGE          0x07EE  /* 2030 TCP message */

/*
** TCP Message Command Types.
*/

#define TCP_MSG_AUTO         0x0000  /* TCP message ACK and Auto-Reply */
#define TCP_MSG_REAL         0x0010  /* TCP message */
#define TCP_MSG_LIST         0x0020  /* TCP message sent to the contact list */
#define TCP_MSG_URGENT       0x0040  /* TCP message sent urgently */

#define TCP_MSGF_S_INVISIBLE 0x0080  /* The message sender is Invisible */
#define TCP_MSGF_S_AWAY      0x0100  /* The message sender is Away */
#define TCP_MSGF_S_OCCUPIED  0x0200  /* The message sender is Occupied */
#define TCP_MSGF_S_NA        0x0800  /* The message sender is Not Available */
#define TCP_MSGF_S_DND       0x1000  /* The message sender is Do Not Disturb */

/*
** TCP Message Status'
*/

#define TCP_STATUS_ONLINE    0x0000
#define TCP_STATUS_REFUSE    0x0001
#define TCP_STATUS_AWAY      0x0004
#define TCP_STATUS_OCCUPIED  0x0009
#define TCP_STATUS_DND       0x000A
#define TCP_STATUS_NA        0x000E

/*
** TCP FileDirect related codes.
*/

#define TCP_FILE_BEGIN       0x00        /*   00 Start the file send process */
#define TCP_FILE_READY       0x02        /*   02 Ready to start the file transfer */
#define TCP_FILE_SPEED       0x05        /*   05 Change the sender's rate of transfer */
#define TCP_FILE_DATA        0x06        /*   06 Up to 2048 bytes of the file being sent */

/*
** TCP Chat related codes.
*/

#define TCP_CHAT_HANDSHAKE   0x00000064  /*  100 Chat initialization handshake code */
#define TCP_CHAT_HANDSHAKE2  0x00000065  /*  101 Chat initialization used in ICQ 99b */
#define TCP_CHAT_VER_CURRENT 0xFFFFFFFC  /*  -04 Current used chat version */
#define TCP_CHAT_VERSION     0xFFFFFFFA  /*  -06 Chat TCP version */

#define TCP_CHAT_1           0x00        /*   00 First chat packet sent */
#define TCP_CHAT_2           0x01        /*   01 Second chat packet sent as reply to first */
#define TCP_CHAT_3           0x02        /*   02 Third chat packet sent as reply to second */
#define TCP_CHAT_ERROR       0x80        /*  128 An error occured allocating RAM (STRICQ) */

#define TCP_CHAT_CMD_FCOLOR  0x00        /*    0 Changes the text color */
#define TCP_CHAT_CMD_STYLE   0x11        /*   17 Changes the text style Bold, Italic, Underline */

#define TCP_CHATF_NONE       0x00        /*    0 set text to normal */
#define TCP_CHATF_BOLD       0x01        /*    1 Set text style to Bold */
#define TCP_CHATF_ITALIC     0x02        /*    2 Set text style to Italic */
#define TCP_CHATF_UNDERLINE  0x04        /*    4 Set text style to Underline */

/*
** Structures used to send UDP packets to the server.
*/

struct C_SendMessage {
  ULONG ToUIN;       /* UIN of person to message to. */
  UWORD Type;        /* Message type.  See defines. */
  char *Message;     /* Actual message text. */
};

struct C_LogOn {
  ULONG Time;        /* time(NULL) (v5) */
  ULONG TCP_MsgPort; /* Port your client will accept TCP connections on. */
  char  Password[8]; /* Password, max 8 characters, case sensitive. */
  ULONG X1;          /* Unknown.  Use 0x00000000 for v2. (0x000000D5 v5) */
  ULONG TCP_MsgIP;   /* IP Address your client will accept TCP connections on. */
  UBYTE TCP_Flag;    /* Is your client TCP capable?  0x04 = Yes, 0x06 = No. */
  ULONG Status;      /* Your client's status at login.  See defines. */
  ULONG X3;          /* TCP Version.  Use 0x00000002 for v2. (0x00000006 v5) */
  UWORD Seq_Login;   /* One up for each login packet sent. (v2) */
  ULONG X4;          /* Unknown.  Use 0x00000000 for v2/5. */
  ULONG X5;          /* Unknown.  Use 0x007300D9 for v2. (0x00D60000 v5) */
  ULONG X6;          /* Unknown.  Use 0x00000050 for v5. */
  ULONG X7;          /* Unknown.  Use 0x00000003 for v5. */
  ULONG X8;          /* Unknown.  Random? (v5) */
};

struct C_NewUser {
  UWORD X1;          /* Unknown.  Use 0x000c for v2. */
  char  Password[8]; /* Password, max 8 characters, case sensitive. */
  ULONG X2;          /* Unknown.  Use 0x00000073 for v2. (0x000000A0 v5) */
  UWORD Random;      /* Unknown.  Seemingly random. */
  UWORD Pad;         /* Unknown.  Use 0x0000 for v2/5. */
  ULONG X3;          /* Unknown.  Use 0x00A00000 for v5. */
  ULONG X4;          /* Unknown.  Use 0x00000000 for v5. */
};
  
struct C_ContactList {
  UBYTE UIN_Count;             /* Count of UINs in this packet. */
  ULONG UIN[MAX_CONTACTS_PKT]; /* Each UIN one after the other. */
};

struct C_Search_User {
  UWORD Sequence;    /* Search sequence. (v2) */
  char  Nick[21];    /* Nick. */
  char  First[21];   /* First name. */
  char  Last[21];    /* Last name. */
  char  EMail[61];   /* EMail address. */
};

struct C_LogOff {
  char *Text;        /* Text code to send to the server.  Use "B_USER_DISCONNECTED" for v2. */
  UWORD X1;          /* Unknown.  Use 0x0005 for logoff. */
};

struct C_ServerStat {
  ULONG Index;       /* Index number of last Server Status message received. */
};

struct C_LogOn_3 {
  ULONG X1;          /* Unknown.  Use 0x00000000 for v2. */
};

struct C_SendURLMsg {
  ULONG Index;       /* Index number of last URL message received. */
};

struct C_LogOn_2 {
  UBYTE X1;          /* Unknown.  User 0x00 for v2. */
};

struct C_Update_Basic_Info {
  UWORD Sequence;    /* One up count for each packet sent. (v2) */
  char  Nick[21];    /* Nick. */
  char  First[21];   /* First name. */
  char  Last[21];    /* Last name. */
  char  EMail[61];   /* EMail address. */
  UBYTE Authorize;   /* Authorize flag.  NOT UPDATED WITH THIS PACKET. */
};

struct C_Update_Ext_Info {
  UWORD Sequence;    /* One up count for each packet sent. (v2) */
  char  City[51];    /* City. */
  UWORD Country;     /* Country code. */
  UBYTE Timezone;    /* Timezone +\- 24. */
  char  State[4];    /* State. */
  UWORD Age;         /* Age. */
  UBYTE Sex;         /* Sex. */
  char  Phone[21];   /* Phone number. */
  char  URL[101];    /* Homepage. */
  char  About[256];  /* About. */
};

struct C_Info_Req {
  UWORD Sequence;    /* Search sequence. (v2) */
  ULONG UIN;         /* UIN to search for. */
};

struct C_ChangePassword {
  UWORD Sequence;    /* Change password sequence. (v2) */
  char  Password[8]; /* New password. */
};

struct C_StatusChange {
  ULONG Status;      /* Change status code. */
};

struct C_UpdateAuth {
  UWORD Sequence;    /* Change authorization sequence. (v2) */
  UBYTE Authorize;   /* Authorization code. */
};

struct C_Meta {
  UWORD Subcommand;  /* Meta command subcommand. */
  ULONG UIN;         /* UIN requesting info about. */
};

/*
** Structures used for UDP receiving packets from the server.
*/

struct UDP_Header {
  UWORD Version;      /* v2/5 */
  ULONG UIN;          /* v5   */
  ULONG SessionID;    /* v5   */
  UWORD Command;      /* v2/5 */
  UWORD Sequence;     /* v2/5 */
  UWORD Sequence2;    /* v5   */
  ULONG CheckCode;    /* v5   */
  ULONG TCP_Sequence; /* STRICQ */
};

struct S_New_User_UIN {
  UWORD X1;
  ULONG UIN;
  ULONG Random;
};

struct S_Login_Reply {
  ULONG IP;
  UWORD X1, X2, X3;               /* (v2, v2, v2) */
  ULONG X4, X5;                   /* (v2, v2/5) */
  UWORD X6, X7, X8, X9, X10, X11; /* (v2/5, v2/5, v2/5, v2/5, v2) */
  ULONG X12;                      /* (v2/5) */
};

struct S_User_Online {
  ULONG UIN;
  ULONG IP;
  ULONG TCP_MsgPort;
  ULONG RealIP;
  UBYTE TCP_Flag;
  ULONG Status;
  UWORD TCP_Version;
  UWORD TCP_Revision;
//ULONG X1, X2, X3, X4, X5, X6, X7;
};

struct S_User_Offline {
  ULONG UIN;
};

struct S_End_Of_Search {
  UWORD Sequence;     /* v2   */
  UBYTE TooMany;      /* v2/5 */
};

struct S_Receive_Message {
  ULONG UIN;
  UWORD Year;
  UBYTE Month;
  UBYTE Day;
  UBYTE Hour;
  UBYTE Minute;
  UWORD Type;
  UWORD Length;
  char *MessageBuf;
};

struct S_Get_Message {
  ULONG UIN;
  UWORD Type;
  UWORD Length;
  char *MessageBuf;
};

struct S_Basic_Info { /* Also used for S_USER_FOUND. */
  UWORD Sequence;     /* Matches the sequence used in the info request. (v2) */
  ULONG UIN;          /* UIN. */
  char  Nick[21];     /* Nick. */
  char  First[21];    /* First name. */
  char  Last[21];     /* Last name. */
  char  EMail[61];    /* EMail address. */
  UBYTE Authorize;    /* Authorize flag. */
};

struct S_Ext_Info {
  UWORD Sequence;    /* One up count for each packet sent. (v2) */
  ULONG UIN;         /* UIN. */
  char  City[51];    /* City. */
  UWORD Country;     /* Country code. */
  BYTE  Timezone;    /* Timezone +\- 24. */
  char  State[4];    /* State. */
  UWORD Age;         /* Age. */
  UBYTE Sex;         /* Sex. */
  char  Phone[21];   /* Phone number. */
  char  URL[101];    /* Homepage. */
  char  About[256];  /* About. */
};

struct S_TCP_Request {
  ULONG Local_UIN;   /* Your UIN. (v2) */
  ULONG Remote_UIN;  /* Remote requester's UIN. */
  ULONG IP;          /* The IP to connect with. */
  ULONG Port;        /* The port to connect with. */
  UBYTE TCP_Flag;    /* TCP Flag of the requester. */
  ULONG Port2;       /* Another UI port. */
  ULONG Port3;       /* The UI port again. */
  UWORD TCP_Version; /* The TCP version of the requester. */
//ULONG X1;          /* Unknown.  Not sent.  Received as 0x00000000. */
//ULONG X2;          /* Unknown.  Not sent.  Received as 0x00000000. */
};

struct S_Status_Update {
  ULONG UIN;
  ULONG Status;
};

struct S_System_Message {
  ULONG Index;
  char  Ad[256];
  char  URL[256];
  char  Button[256];
};

struct S_Meta {
  UWORD Subcommand;
  UBYTE Success;
  UBYTE *Packet;
};

struct S_Multi {
  UBYTE Count;
  UWORD Size;
  UBYTE *Packet;
};

/*
** Structures used to create/parse META packets.
*/

struct Meta_Info_Home {
  char  Nick[21];
  char  First[21];
  char  Last[21];
  char  EMail_Primary[61];
  char  EMail_Secondary[61];
  char  EMail_Old[61];
  char  City[31];
  char  State[4];
  char  Phone[31];
  char  FAX[31];
  char  Street[51];
  char  Cellular[31];
  char  ZipCode[6];
  UWORD Country;
  BYTE  Timezone;
  UBYTE Flag1;         /* (Update: 0x00 = Open EMail, 0x01 = Don't publish Email) (Request/GrabMe: 0x00 = Authorize, 0x01 = Open */
  UBYTE Flag2;         /* (Update: Not sent) (Request: Unknown, usually 0x02) (GrabMe: 0x00 = WebAware off, 0x01 = On */
  UBYTE Flag3;         /* (Update: Not sent) (Request: Unknown, usually 0x00) (GrabMe: 0x00 = Open EMail, 0x01 = Don't publish EMail) */
  UBYTE Flag4;         /* (Update: Not sent) (Request: Not Sent) (GrabMe: Unknown, usually 0x00) */
};

struct Meta_Info_Work {
  char  City[31];
  char  State[4];
  char  Phone[31];
  char  FAX[31];
  char  Address[31];
  char  ZipCode[6];
  UWORD Country;
  char  Company[31];
  char  Department[41];
  char  Position[41];
  UWORD Occupation;
  char  URL[101];
};

struct Meta_Info_More {
  UWORD Age;
  UBYTE Sex;
  char  URL[101];
  UWORD BDay_Year;
  UBYTE BDay_Month;
  UBYTE BDay_Day;
  UBYTE Language1;      /* 0xFF = Undefined (i.e. blank) */
  UBYTE Language2;
  UBYTE Language3;
};

struct Meta_Info_About {
  char  About[512];
};

struct Meta_Info_Interests {
  UBYTE Total_Categories;   /* Total categories in the packet (always 0x04 for update) */
  UWORD Topic;              /* Topic index (+100?) */
  char *TopicText;          /* Text of all topics, comma seperated */
  UBYTE *Next_Category;     /* Remaining portion of packet.  Used by UDP_NextInterest() to parse the next category */
};

struct Meta_Info_Affiliations {
  UBYTE Total_Backgrounds;  /* Total categories of 'Past Background' in the packet (always 0x03 for update) */
  UWORD Background;         /* Background index */
  char *BackgroundText;     /* Text of entered names or keywords */
  UBYTE *Next_Background;   /* Remaining portion of packet.  Used by UDP_NextAffiliation() to parse the next item */
  UBYTE Total_Affiliations; /* Total categories of 'Affiliations' in the packet (always 0x03 for update) */
  UWORD Affiliation;        /* Affiliation index */
  char *AffiliationText;    /* Text of entered names or keywords */
  UBYTE *Next_Affiliation;  /* Remaining portion of packet.  Used by UDP_NextAffiliation() to parse the next item */
};

struct Meta_Info_URLCategory {
  UBYTE Total_Categories;   /* Total categories of 'Homepage URL' in the packet (always 0x01 for update) */
  UWORD Category;           /* Category index */
  char *AboutText;          /* About description of URL */
  UBYTE *Next_Category;     /* Remaining portion of packet.  Used by UDP_NextURLCategory() to parse the next item */
};

struct Meta_Update_Flags {
  UBYTE Authorize;      /* 0x00 = Authorize, 0x01 = Open */
  UBYTE Webaware;       /* 0x00 = Off, 0x01 = On */
  UBYTE HideIP;         /* 0x00 = HideIP, 0x01 = Open */
};

struct Meta_Update_Password {
  char  Password[8];
};

/*
** Structures used to send TCP packets to other clients.
*/

struct TCP_Init {
  UWORD Version;
  UWORD X1;
  ULONG TCP_Chat_File_Port;
  ULONG UIN;
  ULONG TCP_MsgIP;
  ULONG TCP_RealIP;
  UBYTE TCP_Flag;
  ULONG TCP_MsgPort;
};

struct TCP_Message {
  ULONG UIN;
  UWORD Command;
  UWORD X1;
  UWORD Type;
  char *Message;
  ULONG TCP_MsgIP;
  ULONG TCP_RealIP;
  ULONG TCP_MsgPort;
  UWORD TCP_Status;
  UWORD MsgCommand;
  char *Chat_Session;
  UWORD Chat_RevPort;
  UWORD Chat_X2;
  ULONG Chat_Port;
  UWORD File_RevPort;
  UWORD File_X3;
  char *File_Name;
  ULONG File_Size;
  ULONG File_Port;
};

/*
** Structures used during TCP File Direct.
*/

struct TCP_FileBegin { /* FileDirect packet 0x00 */
  ULONG X1;
  ULONG TotalFiles;
  ULONG TotalSize;
  ULONG Speed;
  char  Nick[21];
};

struct TCP_FileReady { /* FileDirect packet 0x02 */
  UBYTE X1;
  char *Filename;
  char *Text;
  ULONG Filesize;
  ULONG X2;
  ULONG Speed;
};

struct TCP_FileSpeed { /* FileDirect packet 0x05 */
 ULONG Speed;
};

struct TCP_FileData {  /* FileDirect packet 0x06 */
  char  Data[FILE_PKT_SIZE+3];
  UWORD DataLen;
};

/*
** Structures used during TCP Chat initialization.
*/

struct TCP_ChatInit {
  ULONG HandShake;
  ULONG HiVersion;
  ULONG UIN;
  char  Nick[21];
  UWORD RevPort;
  ULONG TextColor;
  ULONG BackColor;
  UBYTE X1;
};

struct TCP_ChatTwo_Ext {
  UWORD Version;
  UWORD X1;
  ULONG Port;
  ULONG UIN;
  ULONG IP;
  ULONG RealIP;
  UWORD RevPort;
  UBYTE TCP_Flag;
  UWORD X2;
  ULONG HandShake;
  struct TCP_ChatTwo_Ext *Next;
};

struct TCP_ChatTwo {
  ULONG HandShake;
  ULONG UIN;
  char  Nick[21];
  ULONG TextColor;
  ULONG BackColor;
  UWORD Version;
  UWORD X1;
  ULONG Port;
  ULONG IP;
  ULONG RealIP;
  UBYTE TCP_Flag;
  UWORD X2;
  ULONG FontSize;
  ULONG FontFamily;
  char  FontName[128];
  UBYTE X3;
  UBYTE X4;
  UBYTE Count;
  struct TCP_ChatTwo_Ext Ext;
};

struct TCP_ChatThree {
  UWORD Version;
  UWORD X1;
  ULONG Port;
  ULONG IP;
  ULONG RealIP;
  UBYTE TCP_Flag;
  UWORD X2;
  ULONG FontSize;
  ULONG FontFamily;
  char  FontName[128];
  UWORD X3;
};

struct TCP_ChatColor {
  UBYTE Red;
  UBYTE Green;
  UBYTE Blue;
};

struct TCP_ChatCmdStyle {
  BOOL Bold;
  BOOL Italic;
  BOOL Underline;
};

/*
** Structures used for parsing/creating the various message formats.
*/

struct MSG_Message { /* Just a plain simple message. */
  char *Message;     /*   MSG_MSG, MSG_CHAT, MSG_FILE, MSG_DENY_AUTH, MSG_GIVE_AUTH */
};

struct MSG_URLDesc { /* URL message. */
  char *Desc;        /*   MSG_URL */
  char *URL;
};

struct MSG_Common {  /* Common format used by several UDP message types.          */
  char *Nick;        /*   MSG_REQ_AUTH, MSG_ADDED, MSG_WEB_PAGER, MSG_EMAIL_PAGER */
  char *First;
  char *Last;
  char *EMail;
  UBYTE Authorize;
  char *Message;
};

struct MSG_AddUIN {  /* Used in TCP messaging to swap UINs. */
  ULONG Total;
  ULONG UIN;
  char *Nick;
  UBYTE *Next;
};

#endif  /* LIBRARIES_ICQ_H */
