home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AmigActive 13
/
AACD13.ISO
/
AACD
/
Online
/
StrICQ
/
Src
/
ICQ.c
< prev
next >
Wrap
C/C++ Source or Header
|
2000-02-16
|
37KB
|
1,625 lines
/*
STRICQ - An Amiga, MUI Based, ICQ Clone.
Copyright (C) 1998-2000 Douglas F. McLaughlin
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Douglas F. McLaughlin - stricq@owlnet.net
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <exec/memory.h>
#include <exec/types.h>
#include <libraries/icq.h>
#include <proto/dos.h>
#include <proto/exec.h>
#include "STRICQMUI.h"
#define BCOPY_L(b) L = BREV_L(b); memcpy(Buf+Len,&L,4); Len += 4
#define BCOPY_W(b) W = BREV_W(b); memcpy(Buf+Len,&W,2); Len += 2
#define BCOPY_B(b) memcpy(Buf+Len,&b,1); Len++
#define BCOPY_S(s) S = strlen(s)+1; BCOPY_W(S); strcpy(Buf+Len,(s)); Len += S
#define BCOPY_M(b,l) memcpy(Buf+Len,(b),(l)); Len += (l);
#define ACOPY_L(b) memcpy(&L,Buf+Len,4); b = BREV_L(L); Len += 4
#define ACOPY_W(b) memcpy(&W,Buf+Len,2); b = BREV_W(W); Len += 2
#define ACOPY_B(b) memcpy(&b,Buf+Len,1); Len++
#define ACOPY_S(s) ACOPY_W(S); strcpy((s),Buf+Len); Len += S
#define ACOPY_P(s) ACOPY_W(S); (s) = Buf+Len; Len += S
#define FCOPY_L(b) memcpy(Buf+Len,&b,4); Len += 4;
#define FCOPY_W(b) memcpy(Buf+Len,&b,2); Len += 2;
#define ECOPY_L(b) memcpy(&b,Buf+Len,4); Len += 4;
#define ECOPY_W(b) memcpy(&b,Buf+Len,2); Len += 2;
void MSG_ParseMessage(UWORD, UBYTE *, APTR);
UWORD TCP_ParseTCPInit(struct TCP_Init *, UBYTE *);
UWORD TCP_CreateMsgPacket(struct TCP_Message *, UBYTE **, ULONG *, UWORD *);
void TCP_FreeMsgPacket(UBYTE *Buf);
void TCP_ParseMsgPacket(struct TCP_Message *, UBYTE *, ULONG *);
UWORD TCP_CreateFilePacket(UBYTE, APTR, UBYTE *, UWORD *);
UWORD TCP_CreateChatPacket(UBYTE, APTR, UBYTE *, UWORD *);
UBYTE TCP_ParseChatPacket(void **, UBYTE *);
UWORD TCP_CreateChatCmd(UBYTE, APTR, UBYTE *);
UWORD UDP_CreateHeader(struct UDP_Header *, UBYTE *);
void UDP_ParseHeader(UBYTE *, struct UDP_Header *);
UWORD UDP_CreatePacket(struct UDP_Header *, APTR, UBYTE *);
BOOL UDP_EncryptPacket(UBYTE *, UBYTE *, UWORD);
void UDP_ParsePacket(APTR, UBYTE *, UWORD, struct UDP_Header *);
void UDP_ParseMeta(APTR, struct S_Meta *);
void UDP_NextMulti(struct S_Multi *);
char *ICQ_CmdToText(UWORD);
ULONG CalcCheckCode(UBYTE *Buf, UWORD Len);
ULONG ScrambleCheckCode(ULONG CheckCode);
void PrintHex(UBYTE, char *, UBYTE *, UWORD);
extern void HandleError(UBYTE, char *, ...);
/*
** The following data constitutes fair use for compatibility.
*/
UBYTE UDP_Table[] = {
0x59, 0x60, 0x37 , 0x6B , 0x65 , 0x62 , 0x46 , 0x48 , 0x53 , 0x61 , 0x4C , 0x59 , 0x60 , 0x57 , 0x5B , 0x3D,
0x5E, 0x34, 0x6D , 0x36 , 0x50 , 0x3F , 0x6F , 0x67 , 0x53 , 0x61 , 0x4C , 0x59 , 0x40 , 0x47 , 0x63 , 0x39,
0x50, 0x5F, 0x5F , 0x3F , 0x6F , 0x47 , 0x43 , 0x69 , 0x48 , 0x33 , 0x31 , 0x64 , 0x35 , 0x5A , 0x4A , 0x42,
0x56, 0x40, 0x67 , 0x53 , 0x41 , 0x07 , 0x6C , 0x49 , 0x58 , 0x3B , 0x4D , 0x46 , 0x68 , 0x43 , 0x69 , 0x48,
0x33, 0x31, 0x44 , 0x65 , 0x62 , 0x46 , 0x48 , 0x53 , 0x41 , 0x07 , 0x6C , 0x69 , 0x48 , 0x33 , 0x51 , 0x54,
0x5D, 0x4E, 0x6C , 0x49 , 0x38 , 0x4B , 0x55 , 0x4A , 0x62 , 0x46 , 0x48 , 0x33 , 0x51 , 0x34 , 0x6D , 0x36,
0x50, 0x5F, 0x5F , 0x5F , 0x3F , 0x6F , 0x47 , 0x63 , 0x59 , 0x40 , 0x67 , 0x33 , 0x31 , 0x64 , 0x35 , 0x5A,
0x6A, 0x52, 0x6E , 0x3C , 0x51 , 0x34 , 0x6D , 0x36 , 0x50 , 0x5F , 0x5F , 0x3F , 0x4F , 0x37 , 0x4B , 0x35,
0x5A, 0x4A, 0x62 , 0x66 , 0x58 , 0x3B , 0x4D , 0x66 , 0x58 , 0x5B , 0x5D , 0x4E , 0x6C , 0x49 , 0x58 , 0x3B,
0x4D, 0x66, 0x58 , 0x3B , 0x4D , 0x46 , 0x48 , 0x53 , 0x61 , 0x4C , 0x59 , 0x40 , 0x67 , 0x33 , 0x31 , 0x64,
0x55, 0x6A, 0x32 , 0x3E , 0x44 , 0x45 , 0x52 , 0x6E , 0x3C , 0x31 , 0x64 , 0x55 , 0x6A , 0x52 , 0x4E , 0x6C,
0x69, 0x48, 0x53 , 0x61 , 0x4C , 0x39 , 0x30 , 0x6F , 0x47 , 0x63 , 0x59 , 0x60 , 0x57 , 0x5B , 0x3D , 0x3E,
0x64, 0x35, 0x3A , 0x3A , 0x5A , 0x6A , 0x52 , 0x4E , 0x6C , 0x69 , 0x48 , 0x53 , 0x61 , 0x6C , 0x49 , 0x58,
0x3B, 0x4D, 0x46 , 0x68 , 0x63 , 0x39 , 0x50 , 0x5F , 0x5F , 0x3F , 0x6F , 0x67 , 0x53 , 0x41 , 0x25 , 0x41,
0x3C, 0x51, 0x54 , 0x3D , 0x5E , 0x54 , 0x5D , 0x4E , 0x4C , 0x39 , 0x50 , 0x5F , 0x5F , 0x5F , 0x3F , 0x6F,
0x47, 0x43, 0x69 , 0x48 , 0x33 , 0x51 , 0x54 , 0x5D , 0x6E , 0x3C , 0x31 , 0x64 , 0x35 , 0x5A , 0x00 , 0x00,
};
char version_icq[] = "$VER: icq.c 0.36 (06.12.99)\n\nCopyright © 1998-2000 Douglas F. McLaughlin\nICQ Protocol Copyright © 1996 Mirabilis LTD.\n\nAll Rights Reserved.";
extern char err_buf[];
UBYTE TCP_Flag = TCP_FLAG_CAPABLE;
ULONG L, TCP_Sequence = 0xFFFFFFFE;
UWORD W, S, Len, Sequence, Sequence2, TCP_Version = TCP_VERSION_CURRENT;
void MSG_ParseMessage(UWORD Type, UBYTE *Msg, APTR Data)
{
char *c, *d;
switch(Type) {
case MSG_MSG:
case MSG_CHAT:
case MSG_FILE:
case MSG_DENY_AUTH:
case MSG_GIVE_AUTH: {
struct MSG_Message *Message = Data;
Message->Message = Msg;
break;
}
case MSG_URL: {
struct MSG_URLDesc *URL = Data;
URL->Desc = c = Msg;
d = strchr(c,'\xFE');
*d = '\0';
URL->URL = d+1;
break;
}
case MSG_REQ_AUTH:
case MSG_ADDED:
case MSG_WEB_PAGER:
case MSG_EMAIL_PAGER: {
struct MSG_Common *Common = Data;
Common->Nick = c = Msg;
d = strchr(c,'\xFE');
*d = '\0';
Common->First = c = d+1;
d = strchr(c,'\xFE');
*d = '\0';
Common->Last = c = d+1;
d = strchr(c,'\xFE');
*d = '\0';
Common->EMail = c = d+1;
d = strchr(c,'\xFE');
*d = '\0';
Common->Authorize = (UBYTE)(*(d+1))&0x0F;
c = d+1;
d = strchr(c,'\xFE');
if (!d) Common->Message = c+1;
else Common->Message = d+1;
break;
}
case MSG_ADDUIN: {
struct MSG_AddUIN *AddUIN = Data;
c = Msg;
if (AddUIN->Total == 0) {
d = strchr(c,'\xFE');
*d = '\0';
StrToLong(c,(LONG *)&AddUIN->Total);
c = d+1;
}
d = strchr(c,'\xFE');
*d = '\0';
StrToLong(c,(LONG *)&AddUIN->UIN);
AddUIN->Nick = c = d+1;
d = strchr(c,'\xFE');
*d = '\0';
AddUIN->Next = d+1;
break;
}
}
return;
}
UWORD TCP_ParseTCPInit(struct TCP_Init *Init, UBYTE *Buf)
{
UBYTE Ident;
UWORD PktLen;
Len = 0;
ACOPY_W(PktLen);
ACOPY_B(Ident);
ACOPY_W(Init->Version);
if (Ident != TCP_INIT_IDENT || Init->Version > TCP_VERSION_MAX) return(0);
ACOPY_W(Init->X1); // This is probably a revision indicator...?
ACOPY_L(Init->TCP_Chat_File_Port);
ACOPY_L(Init->UIN);
ECOPY_L(Init->TCP_MsgIP);
ECOPY_L(Init->TCP_RealIP);
ACOPY_B(Init->TCP_Flag);
ACOPY_L(Init->TCP_MsgPort);
if (PktLen != Len-2) HandleError(DBG_TCP_ERRS,"TCP Init Packet passed with wrong size, received %d, expected %d",PktLen,Len-2);
return(PktLen);
}
UWORD TCP_CreateMsgPacket(struct TCP_Message *TCPMsg, UBYTE **Buffer, ULONG *Sequence, UWORD *RevLen)
{
UBYTE *Buf;
ULONG pkt_size;
pkt_size = 4+2+2+2+4+2+2+strlen(TCPMsg->Message)+1+4+4+4+1+2+2+4;
switch(TCPMsg->Type) {
case MSG_CHAT:
pkt_size += 2+strlen(TCPMsg->Chat_Session)+1+2+2+4;
break;
case MSG_FILE:
pkt_size += 2+2+2+strlen(TCPMsg->File_Name)+1+4+4;
break;
}
//HandleError(DBG_TCP_DBUG,"Created a TCP_Buf of %ld bytes.",pkt_size);
if (!(Buf = AllocVec(pkt_size,MEMF_CLEAR))) {
HandleError(DBG_OTH_FATL,"Out of memory creating a TCP Message packet.");
return(0);
}
Len = 0;
BCOPY_L(TCPMsg->UIN);
BCOPY_W(TCP_Version);
BCOPY_W(TCPMsg->Command);
BCOPY_W(TCPMsg->X1);
BCOPY_L(TCPMsg->UIN);
BCOPY_W(TCPMsg->Type);
BCOPY_S(TCPMsg->Message);
FCOPY_L(TCPMsg->TCP_MsgIP);
FCOPY_L(TCPMsg->TCP_RealIP);
BCOPY_L(TCPMsg->TCP_MsgPort);
BCOPY_B(TCP_Flag);
BCOPY_W(TCPMsg->TCP_Status);
BCOPY_W(TCPMsg->MsgCommand);
switch(TCPMsg->Type) {
case MSG_CHAT:
BCOPY_S(TCPMsg->Chat_Session);
FCOPY_W(TCPMsg->Chat_RevPort);
BCOPY_W(TCPMsg->Chat_X2);
BCOPY_L(TCPMsg->Chat_Port);
break;
case MSG_FILE:
FCOPY_W(TCPMsg->File_RevPort);
BCOPY_W(TCPMsg->File_X3);
BCOPY_S(TCPMsg->File_Name);
BCOPY_L(TCPMsg->File_Size);
BCOPY_L(TCPMsg->File_Port);
break;
}
BCOPY_L(TCP_Sequence);
PrintHex(DBG_TCP_PKTS,"TCP Message Packet",Buf,Len);
*Sequence = TCP_Sequence--;
*RevLen = BREV_W(Len);
*Buffer = Buf;
return(Len);
}
void TCP_FreeMsgPacket(UBYTE *Buf)
{
FreeVec(Buf);
return;
}
void TCP_ParseMsgPacket(struct TCP_Message *tcpmsg, UBYTE *Buf, ULONG *Sequence)
{
ULONG Seq = 0;
UWORD slen = 0;
Len = 0;
BCOPY_L(tcpmsg->UIN);
BCOPY_W(tcpmsg->Command);
BCOPY_W(tcpmsg->X1);
BCOPY_W(tcpmsg->Type);
BCOPY_W(slen);
tcpmsg->Message = Buf+Len; Len += slen;
FCOPY_L(tcpmsg->TCP_MsgIP);
FCOPY_L(tcpmsg->TCP_RealIP);
BCOPY_L(tcpmsg->TCP_MsgPort);
BCOPY_W(tcpmsg->TCP_Status);
BCOPY_W(tcpmsg->MsgCommand);
switch(tcpmsg->Type) {
case MSG_CHAT:
BCOPY_W(slen);
tcpmsg->Chat_Session = Buf+Len; Len += slen;
FCOPY_W(tcpmsg->Chat_RevPort);
BCOPY_W(tcpmsg->Chat_X2);
BCOPY_L(tcpmsg->Chat_Port);
break;
case MSG_FILE:
FCOPY_W(tcpmsg->File_RevPort);
BCOPY_W(tcpmsg->File_X3);
BCOPY_W(slen);
tcpmsg->File_Name = Buf+Len; Len += slen;
BCOPY_L(tcpmsg->File_Size);
BCOPY_L(tcpmsg->File_Port);
break;
}
BCOPY_L(Seq);
*Sequence = Seq;
return;
}
UWORD TCP_CreateFilePacket(UBYTE Cmd, APTR Data, UBYTE *Buf, UWORD *RevLen)
{
Len = 0;
switch(Cmd) {
case TCP_FILE_BEGIN: {
struct TCP_FileBegin *Begin = Data;
BCOPY_B(Cmd);
BCOPY_L(Begin->X1);
BCOPY_L(Begin->TotalFiles);
BCOPY_L(Begin->TotalSize);
BCOPY_L(Begin->Speed);
BCOPY_S(Begin->Nick);
break;
}
case TCP_FILE_READY: {
struct TCP_FileReady *Ready = Data;
BCOPY_B(Cmd);
BCOPY_B(Ready->X2);
BCOPY_S(Ready->Filename);
BCOPY_S(Ready->Text);
BCOPY_L(Ready->Filesize);
BCOPY_L(Ready->X2);
BCOPY_L(Ready->Speed);
break;
}
case TCP_FILE_SPEED: {
struct TCP_FileSpeed *Speed = Data;
BCOPY_B(Cmd);
BCOPY_L(Speed->Speed);
break;
}
case TCP_FILE_DATA: {
struct TCP_FileData *DataPkt = Data;
UWORD PktSize;
PktSize = DataPkt->DataLen + 1;
BCOPY_W(PktSize);
BCOPY_B(Cmd);
BCOPY_M(DataPkt->Data,DataPkt->DataLen);
Len -= 2;
break;
}
}
*RevLen = BREV_W(Len);
if (Cmd != TCP_FILE_DATA) PrintHex(DBG_TCP_PKTS,"File Packet",Buf,(Cmd==TCP_FILE_DATA?32:Len));
return(Len);
}
UWORD TCP_CreateChatPacket(UBYTE Cmd, APTR Data, UBYTE *Buf, UWORD *RevLen)
{
Len = 0;
switch(Cmd) {
case TCP_CHAT_1: {
struct TCP_ChatInit *Init = Data;
HandleError(DBG_TCP_DBUG,"Creating TCP_CHAT_1");
BCOPY_L(Init->HandShake);
BCOPY_L(Init->HiVersion);
BCOPY_L(Init->UIN);
BCOPY_S(Init->Nick);
FCOPY_W(Init->RevPort);
BCOPY_L(Init->TextColor);
BCOPY_L(Init->BackColor);
BCOPY_B(Init->X1);
break;
}
case TCP_CHAT_2: {
struct TCP_ChatTwo *Two = Data;
struct TCP_ChatTwo_Ext *ext_p1;
HandleError(DBG_TCP_DBUG,"Creating TCP_CHAT_2");
BCOPY_L(Two->HandShake);
BCOPY_L(Two->UIN);
BCOPY_S(Two->Nick);
BCOPY_L(Two->TextColor);
BCOPY_L(Two->BackColor);
BCOPY_W(Two->Version);
BCOPY_W(Two->X1);
BCOPY_L(Two->Port);
FCOPY_L(Two->IP);
FCOPY_L(Two->RealIP);
BCOPY_B(Two->TCP_Flag);
BCOPY_W(Two->X2);
BCOPY_L(Two->FontSize);
BCOPY_L(Two->FontFamily);
BCOPY_S(Two->FontName);
BCOPY_B(Two->X3);
BCOPY_B(Two->X4);
BCOPY_B(Two->Count);
ext_p1 = Two->Ext.Next;
while(ext_p1) {
BCOPY_W(ext_p1->Version);
BCOPY_W(ext_p1->X1);
BCOPY_L(ext_p1->Port);
BCOPY_L(ext_p1->UIN);
FCOPY_L(ext_p1->IP);
FCOPY_L(ext_p1->RealIP);
BCOPY_B(ext_p1->TCP_Flag);
BCOPY_W(ext_p1->RevPort);
BCOPY_W(ext_p1->X2);
BCOPY_L(ext_p1->HandShake);
ext_p1 = ext_p1->Next;
}
HandleError(DBG_TCP_DBUG,"TCP_CHAT_2");
break;
}
case TCP_CHAT_3: {
struct TCP_ChatThree *Three = Data;
HandleError(DBG_TCP_DBUG,"Creating TCP_CHAT_3");
BCOPY_W(Three->Version);
BCOPY_W(Three->X1);
BCOPY_L(Three->Port);
FCOPY_L(Three->IP);
FCOPY_L(Three->RealIP);
BCOPY_B(Three->TCP_Flag);
BCOPY_W(Three->X2);
BCOPY_L(Three->FontSize);
BCOPY_L(Three->FontFamily);
BCOPY_S(Three->FontName);
BCOPY_W(Three->X3);
break;
}
}
*RevLen = BREV_W(Len);
PrintHex(DBG_TCP_PKTS,"Chat Initialization Packet",Buf,Len);
return(Len);
}
UBYTE TCP_ParseChatPacket(void **Data, UBYTE *Buf)
{
UBYTE Cmd = TCP_CHAT_ERROR;
ULONG HandShake, HiVersion;
UWORD PktLen;
Len = 0;
ACOPY_W(PktLen);
ACOPY_L(HandShake);
ACOPY_L(HiVersion);
HandleError(DBG_TCP_DBUG,"HandShake %ld, HiVersion %ld",HandShake,HiVersion);
if (HandShake != TCP_CHAT_HANDSHAKE && HandShake != TCP_CHAT_HANDSHAKE2) Cmd = TCP_CHAT_3;
else {
if (HiVersion >= TCP_CHAT_VERSION) Cmd = TCP_CHAT_1;
else Cmd = TCP_CHAT_2;
}
Len = 0;
ACOPY_W(PktLen);
switch(Cmd) {
case TCP_CHAT_1: {
struct TCP_ChatInit *Init;
if (!(Init = (struct TCP_ChatInit *)AllocVec(sizeof(struct TCP_ChatInit),MEMF_CLEAR))) return(TCP_CHAT_ERROR);
ACOPY_L(Init->HandShake);
ACOPY_L(Init->HiVersion);
ACOPY_L(Init->UIN);
ACOPY_S(Init->Nick);
ECOPY_W(Init->RevPort);
ACOPY_L(Init->TextColor);
ACOPY_L(Init->BackColor);
ACOPY_B(Init->X1);
*Data = Init;
break;
}
case TCP_CHAT_2: {
struct TCP_ChatTwo *Two;
struct TCP_ChatTwo_Ext *ext_p1, *ext_p2;
if (!(Two = (struct TCP_ChatTwo *)AllocVec(sizeof(struct TCP_ChatTwo),MEMF_CLEAR))) return(TCP_CHAT_ERROR);
ACOPY_L(Two->HandShake);
ACOPY_L(Two->UIN);
ACOPY_S(Two->Nick);
ACOPY_L(Two->TextColor);
ACOPY_L(Two->BackColor);
ACOPY_W(Two->Version);
ACOPY_W(Two->X1);
ACOPY_L(Two->Port);
ECOPY_L(Two->IP);
ECOPY_L(Two->RealIP);
ACOPY_B(Two->TCP_Flag);
ACOPY_W(Two->X2);
ACOPY_L(Two->FontSize);
ACOPY_L(Two->FontFamily);
ACOPY_S(Two->FontName);
ACOPY_B(Two->X3);
ACOPY_B(Two->X4);
ACOPY_B(Two->Count);
ext_p2 = &Two->Ext;
ext_p2->Next = NULL;
while(PktLen > Len-2) {
if (!(ext_p1 = (struct TCP_ChatTwo_Ext *)AllocVec(sizeof(struct TCP_ChatTwo_Ext),MEMF_CLEAR))) break;
ext_p2->Next = ext_p1;
ext_p1->Next = NULL;
ACOPY_W(ext_p1->Version);
ACOPY_W(ext_p1->X1);
ACOPY_L(ext_p1->Port);
ACOPY_L(ext_p1->UIN);
ECOPY_L(ext_p1->IP);
ECOPY_L(ext_p1->RealIP);
ACOPY_B(ext_p1->TCP_Flag);
ACOPY_W(ext_p1->RevPort);
ACOPY_W(ext_p1->X2);
ACOPY_L(ext_p1->HandShake);
ext_p2 = ext_p1;
}
*Data = Two;
break;
}
case TCP_CHAT_3: {
struct TCP_ChatThree *Three;
if (!(Three = (struct TCP_ChatThree *)AllocVec(sizeof(struct TCP_ChatThree),MEMF_CLEAR))) return(TCP_CHAT_ERROR);
ACOPY_W(Three->Version);
ACOPY_W(Three->X1);
ACOPY_L(Three->Port);
ECOPY_L(Three->IP);
ECOPY_L(Three->RealIP);
ACOPY_B(Three->TCP_Flag);
ACOPY_W(Three->X2);
ACOPY_L(Three->FontSize);
ACOPY_L(Three->FontFamily);
ACOPY_S(Three->FontName);
ACOPY_W(Three->X3);
*Data = Three;
break;
}
}
HandleError(DBG_TCP_DBUG,"Cmd is %d",Cmd);
return(Cmd);
}
UWORD TCP_CreateChatCmd(UBYTE Cmd, APTR Data, UBYTE *Buf)
{
ULONG tmp;
Len = 0;
switch(Cmd) {
case TCP_CHAT_CMD_FCOLOR: {
struct TCP_ChatColor *Color = Data;
UBYTE Alpha = 0x00;
BCOPY_B(Cmd);
BCOPY_B(Color->Red);
BCOPY_B(Color->Green);
BCOPY_B(Color->Blue);
BCOPY_B(Alpha);
break;
}
case TCP_CHAT_CMD_STYLE: {
struct TCP_ChatCmdStyle *Style = Data;
BCOPY_B(Cmd);
tmp = (Style->Bold?TCP_CHATF_BOLD:TCP_CHATF_NONE) | (Style->Italic?TCP_CHATF_ITALIC:TCP_CHATF_NONE) | (Style->Underline?TCP_CHATF_UNDERLINE:TCP_CHATF_NONE);
BCOPY_L(tmp);
break;
}
}
return(Len);
}
UWORD UDP_CreatePacket(struct UDP_Header *Header, APTR Data, UBYTE *Buf)
{
if (Header->Command == C_LOGIN || Header->Command == C_NEW_USER_1) {
switch(Header->Version) {
case 0x0002:
Sequence = 0x0000;
break;
case 0x0005:
srand(time(NULL));
Header->SessionID = rand();
Sequence2 = rand() & 0x3FFF;
Sequence = 0x0000;
Header->CheckCode = 0x00000000;
break;
}
}
Len = UDP_CreateHeader(Header,Buf);
switch(Header->Command) {
case C_ACK: {
ULONG Random = rand();
switch(Header->Version) {
case 0x0005:
BCOPY_L(Random);
break;
}
break;
}
case C_SEND_MESSAGE: {
struct C_SendMessage *Msg = Data;
BCOPY_L(Msg->ToUIN);
BCOPY_W(Msg->Type);
BCOPY_S(Msg->Message);
break;
}
case C_LOGIN: {
struct C_LogOn *LogOn = Data;
switch(Header->Version) {
case 0x0005:
BCOPY_L(LogOn->Time);
break;
}
BCOPY_L(LogOn->TCP_MsgPort);
BCOPY_S(LogOn->Password);
BCOPY_L(LogOn->X1);
FCOPY_L(LogOn->TCP_MsgIP);
BCOPY_B(LogOn->TCP_Flag);
BCOPY_L(LogOn->Status);
BCOPY_L(LogOn->X3);
switch(Header->Version) {
case 0x0002:
BCOPY_W(LogOn->Seq_Login);
break;
}
BCOPY_L(LogOn->X4);
BCOPY_L(LogOn->X5);
switch(Header->Version) {
case 0x0005:
BCOPY_L(LogOn->X6);
BCOPY_L(LogOn->X7);
BCOPY_L(LogOn->X8);
break;
}
TCP_Flag = LogOn->TCP_Flag;
break;
}
case C_NEW_USER_REG: {
struct C_NewUser *NewUIN = Data;
switch(Header->Version) {
case 0x0002:
BCOPY_W(NewUIN->X1);
break;
}
BCOPY_S(NewUIN->Password);
BCOPY_L(NewUIN->X2);
BCOPY_W(NewUIN->Random);
BCOPY_W(NewUIN->Pad);
switch(Header->Version) {
case 0x0005:
BCOPY_L(NewUIN->X3);
BCOPY_L(NewUIN->X4);
break;
}
break;
}
case C_INVIS_LIST:
case C_VIS_LIST:
case C_CONTACT_LIST: {
int i;
struct C_ContactList *ContactList = Data;
BCOPY_B(ContactList->UIN_Count);
for(i = 0; i<ContactList->UIN_Count; i++) {
BCOPY_L(ContactList->UIN[i]);
}
break;
}
case C_SEARCH_USER: {
struct C_Search_User *Search = Data;
BCOPY_W(Search->Sequence);
BCOPY_S(Search->Nick);
BCOPY_S(Search->First);
BCOPY_S(Search->Last);
BCOPY_S(Search->EMail);
break;
}
case C_KEEP_ALIVE: {
ULONG Random = rand();
switch(Header->Version) {
case 0x0005:
BCOPY_L(Random);
break;
}
break;
}
case C_SEND_TEXT_CODE: {
struct C_LogOff *LogOff = Data;
BCOPY_S(LogOff->Text);
BCOPY_W(LogOff->X1);
break;
}
case C_ACK_MSG: {
ULONG Random = rand();
switch(Header->Version) {
case 0x0005:
BCOPY_L(Random);
break;
}
break;
}
case C_LOGIN_1: {
ULONG Random = rand();
switch(Header->Version) {
case 0x0005:
BCOPY_L(Random);
break;
}
break;
}
case C_INFO_REQ:
case C_EXT_INFO_REQ:{
struct C_Info_Req *Info = Data;
switch(Header->Version) {
case 0x0002:
BCOPY_W(Info->Sequence);
Info->Sequence++;
break;
}
BCOPY_L(Info->UIN);
break;
}
case C_CHANGE_PASSWORD: {
struct C_ChangePassword *Pass = Data;
switch(Header->Version) {
case 0x0002:
BCOPY_W(Pass->Sequence);
break;
}
BCOPY_S(Pass->Password);
break;
}
case C_UPDATE_INFO:
case C_NEW_USER_INFO: {
struct C_Update_Basic_Info *Basic = Data;
switch(Header->Version) {
case 0x0002:
BCOPY_W(Basic->Sequence);
break;
}
BCOPY_S(Basic->Nick);
BCOPY_S(Basic->First);
BCOPY_S(Basic->Last);
BCOPY_S(Basic->EMail);
BCOPY_B(Basic->Authorize);
break;
}
case C_UPDATE_EXT_INFO: {
struct C_Update_Ext_Info *Extended = Data;
switch(Header->Version) {
case 0x0002:
BCOPY_W(Extended->Sequence);
break;
}
BCOPY_S(Extended->City);
BCOPY_W(Extended->Country);
BCOPY_B(Extended->Timezone);
BCOPY_S(Extended->State);
BCOPY_W(Extended->Age);
BCOPY_B(Extended->Sex);
BCOPY_S(Extended->Phone);
BCOPY_S(Extended->URL);
BCOPY_S(Extended->About);
break;
}
case C_QUERY_STATUS: {
struct C_ServerStat *SrvrStat = Data;
BCOPY_L(SrvrStat->Index);
break;
}
case C_LOGIN_3: {
struct C_LogOn_3 *LogOn3 = Data;
BCOPY_L(LogOn3->X1);
break;
}
case C_STATUS_CHANGE: {
struct C_StatusChange *Status = Data;
BCOPY_L(Status->Status);
break;
}
case C_SEND_URL_MESSAGE: {
struct C_SendURLMsg *URLMsg = Data;
BCOPY_L(URLMsg->Index);
break;
}
case C_UPDATE_AUTH: {
struct C_UpdateAuth *Auth = Data;
BCOPY_W(Auth->Sequence);
BCOPY_B(Auth->Authorize);
break;
}
case C_LOGIN_2: {
struct C_LogOn_2 *LogOn2 = Data;
BCOPY_B(LogOn2->X1);
break;
}
case C_NEW_USER_1:
break;
case C_META: {
struct C_Meta *Meta = Data;
BCOPY_W(Meta->Subcommand);
BCOPY_L(Meta->UIN);
break;
}
}
return(Len);
}
BOOL UDP_EncryptPacket(UBYTE *Buf, UBYTE *OldBuf, UWORD Len)
{
ULONG code, data1, checkcode;
UWORD pos;
if (Len < 0x19) {
HandleError(DBG_UDP_ERRS,"UDP_EncryptPacket() - Packet has no data!");
return(FALSE);
}
memcpy(Buf,OldBuf,Len);
checkcode = CalcCheckCode(Buf,Len);
code = Len * 0x68656c6c + checkcode;
for(pos = 0x0a; pos < Len; pos += 4) {
memcpy(&L,Buf + pos,4); data1 = BREV_L(L);
data1 ^= code + UDP_Table[pos & 0xFF];
L = BREV_L(data1); memcpy(Buf + pos,&L,4);
}
checkcode = ScrambleCheckCode(checkcode);
L = BREV_L(checkcode); memcpy(Buf + 0x14,&L,4);
return(TRUE);
}
ULONG CalcCheckCode(UBYTE *Buf, UWORD Len)
{
ULONG Number1, Number2, CheckCode;
UBYTE r1, r2;
Number1 = Buf[8];
Number1 <<= 8;
Number1 += Buf[4];
Number1 <<= 8;
Number1 += Buf[2];
Number1 <<= 8;
Number1 += Buf[6];
r1 = (rand() % (Len - 0x18)) + 0x18;
r2 = rand() & 0xFF;
Number2 = r1;
Number2 <<= 8;
Number2 += Buf[r1];
Number2 <<= 8;
Number2 += r2;
Number2 <<= 8;
Number2 += UDP_Table[r2];
Number2 ^= 0xFF00FF;
CheckCode = Number1 ^ Number2;
//HandleError(DBG_UDP_DBUG,"n1 = %08lx, r1 = %02x, r2 = %02x, Buf[r1] = %02x, Table[r2] = %02x, n2 = %08lx, CheckCode = %08x",Number1,r1,r2,Buf[r1],UDP_Table[r2],Number2,CheckCode);
return(CheckCode);
}
ULONG ScrambleCheckCode(ULONG CheckCode)
{
ULONG a[6];
a[1] = CheckCode & 0x0000001F;
a[2] = CheckCode & 0x03E003E0;
a[3] = CheckCode & 0xF8000400;
a[4] = CheckCode & 0x0000F800;
a[5] = CheckCode & 0x041F0000;
a[1] <<= 0x0C;
a[2] <<= 0x01;
a[3] >>= 0x0A;
a[4] <<= 0x10;
a[5] >>= 0x0F;
return(a[1] + a[2] + a[3] + a[4] + a[5]);
}
void UDP_ParsePacket(APTR Data, UBYTE *Buf, UWORD PktLen, struct UDP_Header *Header)
{
switch(Header->Version) {
case 0x0002:
Len = 6;
break;
case 0x0005:
Len = 21;
break;
}
switch(Header->Command) {
case S_ACK:
break;
case S_GO_AWAY:
PrintHex(DBG_UDP_ERRS,"S_GO_AWAY",Buf,PktLen);
break;
case S_NEW_USER_UIN:
switch(Header->Version) {
case 0x0002: {
struct S_New_User_UIN *NewUIN = Data;
ACOPY_W(NewUIN->X1);
ACOPY_L(NewUIN->UIN);
ACOPY_L(NewUIN->Random);
break;
}
case 0x0005:
PrintHex(DBG_UDP_ERRS,"S_NEW_USER_UIN",Buf,PktLen);
break;
}
break;
case S_LOGIN_REPLY: {
struct S_Login_Reply *Login = Data;
switch(Header->Version) {
case 0x0002:
ECOPY_L(Login->IP);
// ACOPY_W(Login->X1);
// ACOPY_W(Login->X2);
// ACOPY_W(Login->X3);
// ACOPY_L(Login->X4);
// ACOPY_L(Login->X5);
// ACOPY_W(Login->X6);
// ACOPY_W(Login->X7);
// ACOPY_W(Login->X8);
// ACOPY_W(Login->X9);
// ACOPY_W(Login->X10);
// ACOPY_W(Login->X11);
// ACOPY_L(Login->X12);
break;
case 0x0005:
ACOPY_L(Login->X5);
ACOPY_W(Login->X6);
ACOPY_W(Login->X7);
ACOPY_W(Login->X8);
ACOPY_W(Login->X9);
ECOPY_L(Login->IP);
// ACOPY_L(Login->X12);
break;
}
break;
}
case S_BAD_PASSWORD:
PrintHex(DBG_UDP_ERRS,"S_BAD_PASSWORD",Buf,PktLen);
break;
case S_USER_ONLINE: {
struct S_User_Online *Online = Data;
ACOPY_L(Online->UIN);
ECOPY_L(Online->IP);
ACOPY_L(Online->TCP_MsgPort);
ECOPY_L(Online->RealIP);
ACOPY_B(Online->TCP_Flag);
ACOPY_L(Online->Status);
ACOPY_W(Online->TCP_Version);
ACOPY_W(Online->TCP_Revision);
break;
}
case S_USER_OFFLINE: {
struct S_User_Offline *Offline = Data;
ACOPY_L(Offline->UIN);
break;
}
case S_QUERY_REPLY:
break;
case S_USER_FOUND:
case S_INFO_REPLY: {
struct S_Basic_Info *Basic = Data;
switch(Header->Version) {
case 0x0002:
ACOPY_W(Basic->Sequence);
break;
}
ACOPY_L(Basic->UIN);
ACOPY_S(Basic->Nick);
ACOPY_S(Basic->First);
ACOPY_S(Basic->Last);
ACOPY_S(Basic->EMail);
ACOPY_B(Basic->Authorize);
break;
}
case S_END_OF_SEARCH: {
struct S_End_Of_Search *Search = Data;
switch(Header->Version) {
case 0x0002:
ACOPY_W(Search->Sequence);
break;
}
ACOPY_B(Search->TooMany);
break;
}
case S_NEW_USER_REPLY:
case S_UPDATE_EXT_REPLY:
break;
case S_RECEIVE_MESSAGE: {
struct S_Receive_Message *Msg = Data;
ACOPY_L(Msg->UIN);
ACOPY_W(Msg->Year);
ACOPY_B(Msg->Month);
ACOPY_B(Msg->Day);
ACOPY_B(Msg->Hour);
ACOPY_B(Msg->Minute);
ACOPY_W(Msg->Type);
ACOPY_W(Msg->Length);
Msg->MessageBuf = Buf+Len;
break;
}
case S_END_OFFLINE_MSGS:
case S_TOO_BUSY:
break;
case S_GET_MESSAGE: {
struct S_Get_Message *Msg = Data;
ACOPY_L(Msg->UIN);
ACOPY_W(Msg->Type);
ACOPY_W(Msg->Length);
Msg->MessageBuf = Buf+Len;
break;
}
case S_EXT_INFO_REPLY: {
struct S_Ext_Info *Ext = Data;
switch(Header->Version) {
case 0x0002:
ACOPY_W(Ext->Sequence);
break;
}
ACOPY_L(Ext->UIN);
ACOPY_S(Ext->City);
ACOPY_W(Ext->Country);
ACOPY_B(Ext->Timezone);
ACOPY_S(Ext->State);
ACOPY_W(Ext->Age);
ACOPY_B(Ext->Sex);
ACOPY_S(Ext->Phone);
ACOPY_S(Ext->URL);
ACOPY_S(Ext->About);
break;
}
case S_INFO_NOT_FOUND:
case S_EXT_INFO_NOT_FOUND:
break;
case S_TCP_REQUEST: {
struct S_TCP_Request *Req = Data;
switch(Header->Version) {
case 0x0002:
ACOPY_L(Req->Local_UIN);
break;
}
ACOPY_L(Req->Remote_UIN);
ECOPY_L(Req->IP);
ACOPY_L(Req->Port);
ACOPY_B(Req->TCP_Flag);
ACOPY_L(Req->Port2);
ACOPY_L(Req->Port3);
ACOPY_W(Req->TCP_Version);
// ACOPY_L(Req->X1);
// ACOPY_L(Req->X2);
break;
}
case S_STATUS_UPDATE : {
struct S_Status_Update *Status = Data;
ACOPY_L(Status->UIN);
ACOPY_L(Status->Status);
break;
}
case S_SYSTEM_MESSAGE: {
struct S_System_Message *Sys = Data;
switch(Header->Version) {
case 0x0002:
ACOPY_L(Sys->Index);
ACOPY_S(Sys->Ad);
ACOPY_S(Sys->URL);
ACOPY_S(Sys->Button);
break;
case 0x0005:
PrintHex(DBG_UDP_ERRS,"S_SYSTEM_MESSAGE",Buf,PktLen);
break;
}
break;
}
case S_UPDATE_REPLY:
case S_UPDATE_FAIL:
case S_UPDATE_AUTH_REPLY:
break;
case S_META: {
struct S_Meta *Meta = Data;
ACOPY_W(Meta->Subcommand);
ACOPY_B(Meta->Success);
Meta->Packet = Buf + Len;
break;
}
case S_REPLY_X1:
PrintHex(DBG_UDP_ERRS,"S_REPLY_X1",Buf,PktLen);
break;
case S_MULTI: {
struct S_Multi *Multi = Data;
ACOPY_B(Multi->Count);
ACOPY_W(Multi->Size);
Multi->Packet = Buf + Len;
break;
}
}
return;
}
void UDP_NextMulti(struct S_Multi *Multi)
{
UBYTE *Buf;
UWORD Len = 0;
if ((--Multi->Count) == 0) {
Multi->Size = 0;
Multi->Packet = NULL;
return;
}
Buf = Multi->Packet + Multi->Size;
ACOPY_W(Multi->Size);
Multi->Packet = Buf + Len;
return;
}
void UDP_ParseMeta(APTR Data, struct S_Meta *Meta)
{
UBYTE *Buf = Meta->Packet;
Len = 0;
switch(Meta->Subcommand) {
case META_INFO_HOME: {
struct Meta_Info_Home *Home = Data;
ACOPY_S(Home->Nick);
ACOPY_S(Home->First);
ACOPY_S(Home->Last);
ACOPY_S(Home->EMail_Primary);
ACOPY_S(Home->EMail_Secondary);
ACOPY_S(Home->EMail_Old);
ACOPY_S(Home->City);
ACOPY_S(Home->State);
ACOPY_S(Home->Phone);
ACOPY_S(Home->FAX);
ACOPY_S(Home->Street);
ACOPY_S(Home->Cellular);
ACOPY_S(Home->ZipCode);
ACOPY_W(Home->Country);
ACOPY_B(Home->Timezone);
ACOPY_B(Home->Flag1);
ACOPY_B(Home->Flag2); /* Depending on the circumstance, these last three flags may not actually */
ACOPY_B(Home->Flag3); /* have been sent by the server. No harm in always copying them as the */
ACOPY_B(Home->Flag4); /* calling program should always know which flags were actually sent. */
break;
}
case META_INFO_WORK: {
struct Meta_Info_Work *Work = Data;
ACOPY_S(Work->City);
ACOPY_S(Work->State);
ACOPY_S(Work->Phone);
ACOPY_S(Work->FAX);
ACOPY_S(Work->Address);
ACOPY_S(Work->ZipCode);
ACOPY_W(Work->Country);
ACOPY_S(Work->Company);
ACOPY_S(Work->Department);
ACOPY_S(Work->Position);
ACOPY_W(Work->Occupation);
ACOPY_S(Work->URL);
break;
}
case META_INFO_MORE: {
struct Meta_Info_More *More = Data;
ACOPY_W(More->Age);
ACOPY_B(More->Sex);
ACOPY_S(More->URL);
ACOPY_W(More->BDay_Year);
ACOPY_B(More->BDay_Month);
ACOPY_B(More->BDay_Day);
ACOPY_B(More->Language1);
ACOPY_B(More->Language2);
ACOPY_B(More->Language3);
break;
}
case META_INFO_ABOUT: {
struct Meta_Info_About *About = Data;
ACOPY_S(About->About);
break;
}
case META_INFO_INTERESTS: {
struct Meta_Info_Interests *Interest = Data;
ACOPY_B(Interest->Total_Categories);
ACOPY_W(Interest->Topic);
ACOPY_P(Interest->TopicText);
Interest->Next_Category = Buf + Len;
break;
}
case META_INFO_AFFILIATIONS: {
struct Meta_Info_Affiliations *Affiliation = Data;
ACOPY_B(Affiliation->Total_Backgrounds);
if (Affiliation->Total_Backgrounds) {
ACOPY_W(Affiliation->Background);
ACOPY_P(Affiliation->BackgroundText);
Affiliation->Next_Background = Buf + Len;
break;
}
ACOPY_B(Affiliation->Total_Affiliations);
if (Affiliation->Total_Affiliations) {
ACOPY_W(Affiliation->Affiliation);
ACOPY_P(Affiliation->AffiliationText);
Affiliation->Next_Affiliation = Buf + Len;
}
break;
}
case META_INFO_URLCATEGORY: {
struct Meta_Info_URLCategory *URLCat = Data;
ACOPY_B(URLCat->Total_Categories);
ACOPY_W(URLCat->Category);
ACOPY_P(URLCat->AboutText);
URLCat->Next_Category = Buf + Len;
break;
}
}
return;
}
UWORD UDP_CreateHeader(struct UDP_Header *Header, UBYTE *Buf)
{
UWORD Zero = 0;
Len = 0;
switch(Header->Version) {
case 0x0002:
if (Header->Command != C_ACK) Header->Sequence = ++Sequence;
BCOPY_W(Header->Version);
BCOPY_W(Header->Command);
BCOPY_W(Header->Sequence);
if (Header->Command != C_NEW_USER_1 && Header->Command != C_NEW_USER_REG) {
BCOPY_L(Header->UIN);
}
break;
case 0x0005:
switch(Header->Command) {
case C_ACK:
break;
case C_KEEP_ALIVE:
Header->Sequence = 0;
Header->Sequence2 = ++Sequence2;
break;
default:
Header->Sequence = ++Sequence;
Header->Sequence2 = ++Sequence2;
}
BCOPY_W(Header->Version);
BCOPY_L(Zero);
BCOPY_L(Header->UIN);
BCOPY_L(Header->SessionID);
BCOPY_W(Header->Command);
BCOPY_W(Header->Sequence2);
BCOPY_W(Header->Sequence);
BCOPY_L(Header->CheckCode);
break;
}
return(Len);
}
void UDP_ParseHeader(UBYTE *Buf, struct UDP_Header *Header)
{
UBYTE X1;
Len = 0;
ACOPY_W(Header->Version);
switch(Header->Version) {
case 0x0002:
ACOPY_W(Header->Command);
ACOPY_W(Header->Sequence);
break;
case 0x0005:
ACOPY_B(X1);
ACOPY_L(Header->SessionID);
ACOPY_W(Header->Command);
ACOPY_W(Header->Sequence2);
ACOPY_W(Header->Sequence);
ACOPY_L(Header->UIN);
ACOPY_L(Header->CheckCode);
break;
}
return;
}
void PrintHex(UBYTE type, char *txt, UBYTE *buf, UWORD len)
{
char line[80], tmp[5];
int i, j;
UBYTE c;
if (txt) HandleError(type,txt);
for(i = 0; i<len; i += 8) {
line[0] = '\0';
for(j = 0; j<8; j++) {
if (i+j >= len) strcat(line," ");
else {
c = (unsigned char)buf[i+j];
sprintf(tmp,"%02x ",c);
strcat(line,tmp);
}
}
for(j = 0; j<8; j++) {
if (i+j >= len) break;
c = (unsigned char)buf[i+j];
// if (c >= ' ' && c <= 'z') sprintf(tmp,"%c",c);
if (c >= ' ') sprintf(tmp,"%c",c);
else sprintf(tmp,".");
strcat(line,tmp);
}
HandleError(type,line);
if (j < 8) break;
}
return;
}
char *ICQ_CmdToText(UWORD cmd)
{
static char txt[50];
switch(cmd) {
case TCP_MESSAGE:
strcpy(txt,"TCP Message");
break;
case C_ACK:
strcpy(txt,"ACK");
break;
case C_ACK_MSG:
strcpy(txt,"Del Offline Msgs");
break;
case C_SEND_MESSAGE:
strcpy(txt,"Send Message");
break;
case C_LOGIN:
strcpy(txt,"Login");
break;
case C_CONTACT_LIST:
strcpy(txt,"Contact List");
break;
case C_SEND_TEXT_CODE:
strcpy(txt,"Client Logout");
break;
case C_LOGIN_1:
strcpy(txt,"Unknown (Login 1)");
break;
case C_LOGIN_2:
strcpy(txt,"Unknown (Login 2)");
break;
case C_INFO_REQ:
strcpy(txt,"Info Request");
break;
case C_SEARCH_USER:
strcpy(txt,"User Search");
break;
case C_CHANGE_PASSWORD:
strcpy(txt,"Change Password");
break;
case C_STATUS_CHANGE:
strcpy(txt,"Status Change");
break;
case C_QUERY_STATUS:
strcpy(txt,"Query Servers");
break;
case C_SEND_URL_MESSAGE:
strcpy(txt,"Request URL Message");
break;
case C_EXT_INFO_REQ:
strcpy(txt,"Ext. Info Request");
break;
case C_META:
strcpy(txt,"Meta Command");
break;
case C_UPDATE_INFO:
strcpy(txt,"Update Basic Info");
break;
case C_NEW_USER_INFO:
strcpy(txt,"New User Info");
break;
case C_UPDATE_EXT_INFO:
strcpy(txt,"Update Ext. Info");
break;
case C_NEW_USER_1:
strcpy(txt,"Request New User");
break;
case C_NEW_USER_REG:
strcpy(txt,"Register New User");
break;
case C_UPDATE_AUTH:
strcpy(txt,"Update Authorize");
break;
case C_VIS_LIST:
strcpy(txt,"Visible List");
break;
case C_INVIS_LIST:
strcpy(txt,"Invisible List");
break;
case C_KEEP_ALIVE:
strcpy(txt,"Ping Server");
break;
case S_LOGIN_REPLY:
strcpy(txt,"Login Reply");
break;
case S_USER_ONLINE:
strcpy(txt,"User Online");
break;
case S_USER_OFFLINE:
strcpy(txt,"User Offline");
break;
case S_RECEIVE_MESSAGE:
strcpy(txt,"Receive Offline Message");
break;
case S_GET_MESSAGE:
strcpy(txt,"Receive Online Message");
break;
case S_STATUS_UPDATE :
strcpy(txt,"Status Update");
break;
case S_GO_AWAY:
strcpy(txt,"Server Logout");
break;
case S_REPLY_X1:
strcpy(txt,"End Online User List");
break;
case S_END_OFFLINE_MSGS:
strcpy(txt,"No More Messages");
break;
case S_INFO_REPLY:
strcpy(txt,"Reply User Info");
break;
case S_USER_FOUND:
strcpy(txt,"User Found");
break;
case S_END_OF_SEARCH:
strcpy(txt,"End Of Search");
break;
case S_QUERY_REPLY:
strcpy(txt,"Query Reply");
break;
case S_EXT_INFO_REPLY:
strcpy(txt,"Ext. Info Reply");
break;
case S_UPDATE_REPLY:
strcpy(txt,"Update Info Reply");
break;
case S_UPDATE_EXT_REPLY:
strcpy(txt,"Update Ext. Reply");
break;
case S_NEW_USER_REPLY:
strcpy(txt,"New User Info Reply");
break;
case S_BAD_PASSWORD:
strcpy(txt,"Bad Password");
break;
case S_NEW_USER_UIN:
strcpy(txt,"New User UIN");
break;
case S_UPDATE_AUTH_REPLY:
strcpy(txt,"Update Auth. Reply");
break;
case S_TOO_BUSY:
strcpy(txt,"Server is Busy");
break;
case S_TCP_REQUEST:
strcpy(txt,"TCP Information");
break;
case S_INFO_NOT_FOUND:
strcpy(txt,"Info Not Found");
break;
case S_EXT_INFO_NOT_FOUND:
strcpy(txt,"Ext. Info Not Found");
break;
case S_MULTI:
strcpy(txt,"Multi-Packet");
break;
case S_META:
strcpy(txt,"Meta Command Reply");
break;
default:
sprintf(txt,"0x%04x",cmd);
}
return(txt);
}