├── README.md ├── random.h ├── Time.h ├── Debug.h ├── Net.h ├── Utils.h ├── random.cpp ├── Strings.h ├── List.h ├── SICQ_define.h ├── Utils.cpp ├── Time.cpp ├── SICQ.h ├── Debug.cpp ├── ICQPacket.h ├── List.cpp ├── Strings.cpp ├── Net.cpp ├── ICQPacket_define.h ├── SICQ.cpp └── ICQPacket.cpp /README.md: -------------------------------------------------------------------------------- 1 | It is a class for OSCAR(ICQ/AIM) protocol http://en.wikipedia.org/wiki/OSCAR_protocol 2 | This class was written in pure Win32 C++. 3 | 4 | -------------------------------------------------------------------------------- /random.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | //! A class represents a pseudo-random number generator 3 | class random 4 | { 5 | private: 6 | int nInit; 7 | public: 8 | random(void); 9 | ~random(void); 10 | 11 | unsigned int randomDWORD(); 12 | unsigned short randomWORD(); 13 | }; 14 | 15 | -------------------------------------------------------------------------------- /Time.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Utils.h" 4 | 5 | #define EPOCH_BIAS 116444736000000000i64 6 | 7 | //! \defgroup time_functions Time functions 8 | //! \{ 9 | int _FileTimeToUnixTime(FILETIME *pFileTeme); 10 | void _UnixTimeToFileTime(int nUnixTime,FILETIME *pFileTeme); 11 | int _SystemTimeAsUnixTime(); 12 | int _LocalTimeAsUnixTime(); 13 | int _UnixTimeAsString(int nUnixTime,PTSTR pszString,int nStringLength); 14 | //! \} -------------------------------------------------------------------------------- /Debug.h: -------------------------------------------------------------------------------- 1 | //! \file Debug.h Header for Debug.cpp 2 | #pragma once 3 | 4 | #include "Utils.h" 5 | #include "Strings.h" 6 | 7 | //! \defgroup debug_functions Debug functions 8 | //! \{ 9 | int _PrintDebugText(TCHAR *pszString); 10 | int _PrintDebugHEX(char *pData,int nDataSize); 11 | int _PrintDebugNS(); 12 | int _PrintDebugTextNS(TCHAR *pszString); 13 | int _PrintDebugHEXNS(char *pData,int nDataSize); 14 | int _PrintDebugHEXTable(char *pData,int nDataSize); 15 | //! \} -------------------------------------------------------------------------------- /Net.h: -------------------------------------------------------------------------------- 1 | //! \file Net.h Header for Net.cpp 2 | #pragma once 3 | #include 4 | #include "Strings.h" 5 | 6 | //#pragma comment(lib,"Ws2_32.lib") 7 | #pragma comment(lib,"wsock32.lib") 8 | 9 | //! \defgroup tcpconnect_functions TCPconnect functions 10 | //! \{ 11 | bool _LoadWS(); 12 | void _UnloadWS(); 13 | SOCKET _socket(); 14 | bool _connect(SOCKET sock,TCHAR *pszServerIP,int nServerPort); 15 | int _recv(SOCKET sock,char *pBuffer,int nBufferSize); 16 | int _send(SOCKET sock,char *pBuffer,int nBufferSize); 17 | void _closeconnect(SOCKET sock); 18 | //! \} -------------------------------------------------------------------------------- /Utils.h: -------------------------------------------------------------------------------- 1 | //! \file Utils.h Header for Utils.cpp 2 | 3 | #pragma once 4 | #include 5 | 6 | #ifdef _DEBUG 7 | //################################################## 8 | #include "Debug.h" 9 | //################################################## 10 | #endif 11 | 12 | //! \defgroup advanced_functions Advanced functions 13 | //! \{ 14 | void _ZeroMemory(void *pDest,int nSize); 15 | void _CopyMemory(void *pDest,void *pSource,int nSize); 16 | void *_Alloc(int nSize); 17 | void _Free(void *pMemory); 18 | int _MaxInt(int n1,int n2); 19 | int _MinInt(int n1,int n2); 20 | //! \} -------------------------------------------------------------------------------- /random.cpp: -------------------------------------------------------------------------------- 1 | #include "random.h" 2 | 3 | //! Constructor 4 | random::random(void) 5 | { 6 | unsigned int nTemp; 7 | 8 | __asm 9 | { 10 | rdtsc 11 | bswap eax 12 | 13 | mov nTemp,eax 14 | } 15 | 16 | nInit=nTemp; 17 | 18 | randomDWORD(); 19 | } 20 | //! Destructor 21 | random::~random(void) 22 | { 23 | } 24 | //! \return a random number between 0 and 4294967295 25 | unsigned int random::randomDWORD() 26 | { 27 | nInit=((400014+40692)*nInit)%2147483563; 28 | return nInit; 29 | } 30 | //! \return a random number between 0 and 65534 31 | unsigned short random::randomWORD() 32 | { 33 | return randomDWORD()>>16; 34 | } -------------------------------------------------------------------------------- /Strings.h: -------------------------------------------------------------------------------- 1 | //! \file Strings.h Header for Strings.cpp 2 | #pragma once 3 | #include 4 | #include "Utils.h" 5 | 6 | //! \defgroup strings_functions Strings functions 7 | //! \{ 8 | int _StringToChars(char *pszChars,int nCharsSize,TCHAR *pszString); 9 | int _CharsToString(TCHAR *pszString,int nStringLength,char *pszChars); 10 | int _BinToHEX(char *pData,int nDataSize,TCHAR *pszHEX); 11 | int _BinToHEXTable(char *pData,int nDataSize,TCHAR *pszHEX); 12 | int _StringToUnicode(WCHAR *pszUnicode,int nUnicodeLength,TCHAR *pszString); 13 | int _UnicodeToString(TCHAR *pszString,int nStringLength,WCHAR *pszUnicode); 14 | int _CharsToUnicode(WCHAR *pszUnicode,int nUnicodeLength,char *pszChars); 15 | int _UnicodeToChars(char *pszChars,int nCharsSize,WCHAR *pszUnicode); 16 | int _UnicodeToNet(WCHAR *pszNet,int nNetLength,WCHAR *pszUnicode); 17 | int _NetToUnicode(WCHAR *pszUnicode,int nUnicodeLength,WCHAR *pszNet); 18 | //! \} -------------------------------------------------------------------------------- /List.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Utils.h" 4 | 5 | //! \defgroup list List 6 | //! \{ 7 | struct LISTHEADER 8 | { 9 | int nSignature; //!< a Signature "List" 10 | int nNumberOfEntries; //!< a number of entries 11 | int nSize; //!< a size of list without LISTHEADER 12 | }; 13 | struct LISTENTRY 14 | { 15 | int nID; //!< a uniquely number 16 | int nEntrySize; //!< a size of entry 17 | }; 18 | 19 | #define LIST_SIGNATURE 0x7473694C //!< "List" 20 | 21 | //! A class for saving a data. 22 | class List 23 | { 24 | private: 25 | char *pData; 26 | int nDataSize; 27 | 28 | bool SetHeader(char *pData,int nDataSize); 29 | bool IsList(char *pData,int nDataSize); 30 | LISTENTRY *GetListEntryByIndex(int nIndex); 31 | LISTENTRY *GetListEntryByID(int nID); 32 | 33 | public: 34 | 35 | List(void); 36 | ~List(void); 37 | 38 | bool SetData(char *pData,int nDataSize); 39 | bool AddEntry(int nID,char *pEntry,int nEntrySize); 40 | bool RemoveEntry(int nID); 41 | char *GetEntryByIndex(int nIndex); 42 | char *GetEntryByID(int nID); 43 | }; 44 | //! \} 45 | -------------------------------------------------------------------------------- /SICQ_define.h: -------------------------------------------------------------------------------- 1 | //! \file SICQ_define.h SICQ definitions 2 | #pragma once 3 | 4 | #define SICQ_ERROR_SUCCESS 0 5 | #define SICQ_ERROR_EVENTWINDOWISEXIST 1 6 | #define SICQ_ERROR_EVENTWINDOWISNOTEXIST 2 7 | #define SICQ_ERROR_CANNOTCONNECTTOSERVER 3 8 | #define SICQ_ERROR_INCORRECTUINORPASSWORD 4 9 | #define SICQ_ERROR_RATELIMITEXCEEDED 5 10 | #define SICQ_ERROR_UNKNOWN 0xFFFF 11 | 12 | #define WM_SICQ_EVENTWND_LOGIN WM_USER+101 13 | //! \param wParam 0 14 | //! \param lParam a pointer to buffer that contains SENDTEXTSTRUCT structur 15 | #define WM_SICQ_EVENTWND_SENDMESSAGE WM_USER+102 16 | //! \param wParam status 17 | //! \param lParam 0 18 | #define WM_SICQ_EVENTWND_SETSTATUS WM_USER+103 19 | 20 | #define WM_SICQ_EVENTWND_RECVDATA WM_USER+104 21 | 22 | //! \defgroup statuses Statuses 23 | //! \{ 24 | #define SICQ_STATUS_OFFLINE 0 25 | #define SICQ_STATUS_ONLINE 1 26 | #define SICQ_STATUS_AWAY 2 27 | #define SICQ_STATUS_DND 3 28 | #define SICQ_STATUS_NA 4 29 | #define SICQ_STATUS_OCCUPIED 5 30 | #define SICQ_STATUS_FREEFORCHAT 6 31 | #define SICQ_STATUS_INVISIBLE 7 32 | //! \} 33 | 34 | 35 | //! \defgroup messages Messages 36 | //! \{ 37 | 38 | //! Login 39 | //! \param wParam true if success, false if fail 40 | //! \param lParam a pointer to SICQ class 41 | #define WM_SICQ_MAINWND_LOGIN WM_USER+200 42 | //! Status 43 | //! \param wParam Status 44 | //! \param lParam a pointer to SICQ class 45 | //! \sa statuses 46 | #define WM_SICQ_MAINWND_STATUS WM_USER+201 47 | //! MessageAck 48 | //! \param wParam MessageID 49 | //! \param lParam a pointer to SICQ class 50 | #define WM_SICQ_MAINWND_MESSAGEACK WM_USER+202 51 | //! RecvText 52 | //! \param wParam a pointer to RECVMESSAGESTRUCT 53 | //! \param lParam a pointer to SICQ class 54 | //! \sa RECVMESSAGESTRUCT 55 | #define WM_SICQ_MAINWND_RECVTEXT WM_USER+203 56 | //! \} 57 | 58 | -------------------------------------------------------------------------------- /Utils.cpp: -------------------------------------------------------------------------------- 1 | #include "Utils.h" 2 | 3 | //! Fills a block of memory with zeros 4 | //! \param pDest [in] a pointer to the starting address of the block of memory to fill with zeros 5 | //! \param nSize [in] the size of the block of memory to fill with zeros, in bytes 6 | void _ZeroMemory(void *pDest,int nSize) 7 | { 8 | 9 | if(nSize) 10 | { 11 | __asm 12 | { 13 | xor eax,eax 14 | mov ecx,nSize 15 | mov edi,pDest 16 | cld 17 | rep stosb 18 | } 19 | } 20 | } 21 | //! Copies a block of memory from one location to another 22 | //! \param pDest [in] a pointer to the starting address of the copied block's destination 23 | //! \param pSource [in] a pointer to the starting address of the block of memory to copy 24 | //! \param nSize [in] the size of the block of memory to copy, in bytes 25 | void _CopyMemory(void *pDest,void *pSource,int nSize) 26 | { 27 | if(nSize) 28 | { 29 | __asm 30 | { 31 | mov ecx,nSize 32 | mov esi,pSource 33 | mov edi,pDest 34 | cld 35 | rep movsb 36 | } 37 | } 38 | } 39 | //! Allocates the specified number of bytes from the heap 40 | //! \param nSize [in] the number of bytes to allocate 41 | //! \return a pointer to the memory 42 | void *_Alloc(int nSize) 43 | { 44 | return (void *)GlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT,nSize); 45 | } 46 | //! Frees the specified global memory object and invalidates its handle 47 | //! \param pMemory [in] a pointer to the memory 48 | void _Free(void *pMemory) 49 | { 50 | GlobalFree(pMemory); 51 | } 52 | //! Maximal of two ints 53 | //! \param n1 [in] a first int 54 | //! \param n2 [in] a second int 55 | int _MaxInt(int n1,int n2) 56 | { 57 | if(n1>n2) 58 | return n1; 59 | else 60 | return n2; 61 | } 62 | //! Minimal of two ints 63 | //! \param n1 [in] a first int 64 | //! \param n2 [in] a second int 65 | int _MinInt(int n1,int n2) 66 | { 67 | if(n1 5 | #pragma comment(lib,"shlwapi.lib") 6 | 7 | #include "Utils.h" 8 | #include "Net.h" 9 | #include "ICQPacket.h" 10 | #include "SICQ_define.h" 11 | #include "List.h" 12 | #include "random.h" 13 | #include "Time.h" 14 | 15 | //! \defgroup sicq SICQ 16 | //! \{ 17 | /*! 18 | An application or DLL is required to perform a successful WSAStartup call before it can use SICQ 19 | \code 20 | WORD wVersionRequested; 21 | WSADATA wsaData; 22 | int err; 23 | 24 | wVersionRequested = MAKEWORD(2, 2); 25 | 26 | err = WSAStartup(wVersionRequested, &wsaData); 27 | if (err != 0) { 28 | printf("WSAStartup failed with error: %d\n", err); 29 | return 1; 30 | } 31 | \endcode 32 | When it has completed the use of SICQ, the application or DLL must call WSACleanup to deregister 33 | itself from a Windows Sockets implementation and allow the implementation to free any resources 34 | allocated on behalf of the application or DLL. 35 | \code 36 | WSACleanup(); 37 | \endcode 38 | 39 | \sa _LoadWS, _UnloadWS 40 | */ 41 | //! A class for OSCAR protocol (ICQ/AIM) 42 | class SICQ: private ICQPacket 43 | { 44 | private: 45 | int nError; 46 | HWND hEventWnd; 47 | TCHAR szUIN[20]; 48 | TCHAR szPassword[20]; 49 | TCHAR szServerIP[20]; 50 | int nServerPort; 51 | SOCKET sock; 52 | int nSequence; 53 | int nStatus; 54 | static char HwndList[1000]; 55 | FOODGROUPS FoodGroups; 56 | HWND hMainWnd; 57 | 58 | void SequenceIncrement(); 59 | bool Start(); 60 | bool Stop(); 61 | bool ICQLogin(); 62 | bool ICQLoginPlain(); 63 | bool ICQLoginMD5(); 64 | void ICQBOSServerConnect(TCHAR *pszBOSServerIPAndPort,char *pCookies,int nCookiesSize); 65 | void ICQSetStatus(int nStatus); 66 | int StatusToICQ(int nStatus); 67 | void ICQSendText(SENDTEXTSTRUCT *pSts); 68 | void ICQPing(); 69 | void DefProc(); 70 | // CALLBACK function 71 | static LRESULT CALLBACK SocketProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); 72 | public: 73 | SICQ(); 74 | ~SICQ(void); 75 | 76 | void SetWindowsHandle(HWND hMainWnd); 77 | TCHAR *GetErrorString(); 78 | void Login(TCHAR *pszServerIP,int nServerPort,TCHAR *pszUIN,TCHAR *pszPassword); 79 | int SendText(TCHAR *pszUIN,TCHAR *pszText,int nTextLength); 80 | bool SetStatus(int nStatus); 81 | }; 82 | //! \} 83 | 84 | 85 | -------------------------------------------------------------------------------- /Debug.cpp: -------------------------------------------------------------------------------- 1 | #include "Debug.h" 2 | 3 | //! Writes a character string to a debug screen buffer beginning at the current cursor location. 4 | //! \param pszString [in] a pointer to a string. 5 | //! \return the number of characters written to the debug 6 | int _PrintDebugText(TCHAR *pszString) 7 | { 8 | OutputDebugString(pszString); 9 | 10 | return strlen(pszString); 11 | } 12 | //! Writes a binary data to a debug screen buffer beginning at the current cursor location. 13 | //! \param pData [in] a pointer to a binary data. 14 | //! \param nDataSize [in] a size of the binary data. 15 | //! \return the number of characters written to the debug 16 | int _PrintDebugHEX(char *pData,int nDataSize) 17 | { 18 | TCHAR *pszString=(TCHAR *)_Alloc(2*(sizeof(TCHAR))*(nDataSize+1)); 19 | 20 | _BinToHEX(pData,nDataSize,pszString); 21 | 22 | int nResult=_PrintDebugText(pszString); 23 | 24 | _Free(pszString); 25 | 26 | return nResult; 27 | } 28 | //! Writes a new string symbol("\n") to a debug screen buffer beginning at the current cursor location. 29 | //! \return the number of characters written to the debug 30 | int _PrintDebugNS() 31 | { 32 | return _PrintDebugText(TEXT("\n")); 33 | } 34 | //! Writes a character string and a new string symbol("\n") to a debug screen buffer beginning at the current cursor location. 35 | //! \param pszString [in] a pointer to a string. 36 | //! \return the number of characters written to the debug 37 | int _PrintDebugTextNS(TCHAR *pszString) 38 | { 39 | int nResult=_PrintDebugText(pszString); 40 | nResult+=_PrintDebugNS(); 41 | 42 | return nResult; 43 | } 44 | //! Writes a binary data and a new string symbol("\n") to a debug screen buffer beginning at the current cursor location. 45 | //! \param pData [in] a pointer to a binary data. 46 | //! \param nDataSize [in] a size of the binary data. 47 | //! \return the number of characters written to the debug 48 | int _PrintDebugHEXNS(char *pData,int nDataSize) 49 | { 50 | int nResult=_PrintDebugHEX(pData,nDataSize); 51 | nResult+=_PrintDebugNS(); 52 | 53 | return nResult; 54 | } 55 | //! Writes a binary data as a table to a debug screen buffer beginning at the current cursor location. 56 | //! \param pData [in] a pointer to a binary data. 57 | //! \param nDataSize [in] a size of the binary data. 58 | //! \return the number of characters written to the debug 59 | int _PrintDebugHEXTable(char *pData,int nDataSize) 60 | { 61 | TCHAR *pszString=(TCHAR *)_Alloc(3*(sizeof(TCHAR))*(nDataSize+1)); 62 | 63 | _BinToHEXTable(pData,nDataSize,pszString); 64 | 65 | int nResult=_PrintDebugText(pszString); 66 | 67 | _Free(pszString); 68 | 69 | return nResult; 70 | } -------------------------------------------------------------------------------- /ICQPacket.h: -------------------------------------------------------------------------------- 1 | //! \file ICQPacket.h Header for ICQPacket.cpp 2 | #pragma once 3 | 4 | #include "Utils.h" 5 | #include "Strings.h" 6 | #include "Net.h" 7 | #include "ICQPacket_define.h" 8 | 9 | 10 | 11 | //! \defgroup sicq SICQ 12 | //! \{ 13 | 14 | //! A class for low-level work with ICQ-packets 15 | class ICQPacket 16 | { 17 | private: 18 | char *pPacket; 19 | int nPacketSize; 20 | 21 | unsigned char GetFLAPChannel(); 22 | void SetFLAPChannel(unsigned char Channel); 23 | unsigned short GetFLAPSequence(); 24 | void SetFLAPSequence(unsigned short Sequence); 25 | unsigned short GetFLAPDataSize(); 26 | void SetFLAPDataSize(unsigned short DataSize); 27 | bool IsFLAPPacket(); 28 | void SetFLAPHeader(char Channel,short Sequence); 29 | int Add_u8(unsigned char cU8); 30 | int Add_u16_BE(unsigned short sU16); 31 | int Add_u32_BE(unsigned int nU32); 32 | int Add_blob(char *bData,int nDataSize); 33 | int Add_string(TCHAR *pszString); 34 | int Add_string08(TCHAR *pszString); 35 | int Add_TLVHeader(unsigned short Type,unsigned short Length); 36 | int Add_TLV_u16(unsigned short Type,unsigned short sU16); 37 | int Add_TLV_u32(unsigned short Type,unsigned int nU32); 38 | int Add_TLV_blob(unsigned short Type,char *bData,int nDataSize); 39 | int Add_TLV_string(unsigned short Type,TCHAR *pszString); 40 | int Add_TLV_empty(unsigned short Type); 41 | int Add_TLV_password(unsigned short Type,TCHAR *pszPassword); 42 | 43 | char *GetTLVPointer(unsigned short Type); 44 | unsigned short GetTLVTypeFromOffset(char *pOffset); 45 | unsigned short GetTLVLehgthFromOffset(char *pOffset); 46 | unsigned short GetFragmentLehgthFromOffset(char *pOffset); 47 | 48 | char *GetSNACPointer(); 49 | unsigned short GetSNACFamily(); 50 | unsigned short GetSNACSubtype(); 51 | unsigned short GetSNACFlags(); 52 | unsigned int GetSNACRequestid(); 53 | char *GetSNACDataPointer(); 54 | int GetSNACDataSize(); 55 | 56 | unsigned int Get_u32_BE_FromOffset(char *pOffset); 57 | unsigned short Get_u16_BE_FromOffset(char *pOffset); 58 | unsigned char Get_u8_FromOffset(char *pOffset); 59 | int Get_string08(char *pOffset,TCHAR *pszString,int nStringLength); 60 | 61 | int Add_SNACHeader(unsigned short family,unsigned short subtype,unsigned short flags,unsigned int requestid); 62 | 63 | int ReadNickInfoFromOffset(char *pOffset,NICKINFOSTRUCT *pNis); 64 | protected: 65 | int GetTLV_blob(unsigned short Type,char *pBuffer,int nBufferSize); 66 | int GetTLV_string(unsigned short Type,TCHAR *pszBuffer,int nBufferLength); 67 | unsigned short GetTLV_u16(unsigned short Type); 68 | bool IsHelloPacket(); 69 | bool IsSNACPresent(unsigned short family,unsigned short subtype); 70 | 71 | bool ReadFoodGroupsFamiliesPacket(FOODGROUPS *pFgs); 72 | int CreateFoodGroupsVersionsPacket(int nSequence,FOODGROUPS *pFgs); 73 | bool ReadFoodGroupsVersionsPacket(FOODGROUPS *pFgs); 74 | int CreateRequestRatesPacket(int nSequence); 75 | int CreateAcceptRatesPacket(int nSequence); 76 | int CreateRequestRosterFirstTimePacket(int nSequence); 77 | int CreateLoadRosterAfterLoginPacket(int nSequence); 78 | int CreateSetICBMParametersPacket(int nSequence); 79 | int CreateRequestBuddyParametersPacket(int nSequence); 80 | int CreateSetStatusPacket(int nSequence,int nStatus); 81 | int CreateClientReadyPacket(int nSequence); 82 | int CreateSendTextUnicodePacket(int nSequence,SENDTEXTSTRUCT *pSts); 83 | bool IsErrorChannel(); 84 | bool IsSignOffChannel(); 85 | bool IsTLVPresent(unsigned short Type); 86 | int CreatePlainLoginPacket(int nSequence,TCHAR *pszUIN,TCHAR *pszPassword); 87 | int CreateGoodByePacket(int nSequence); 88 | int CreatePingPacket(int nSequence); 89 | int CreateCookiesPacket(int nSequence,char *pCookies,int nCookiesSize); 90 | bool ReadMessageAckPacket(MESSAGEACKSTRUCT *pMas); 91 | bool ReadRecvMessagePacket(RECVMESSAGESTRUCT *pRms); 92 | public: 93 | ICQPacket(void); 94 | ~ICQPacket(void); 95 | char *GetPacketPointer(); 96 | int GetPacketSize(); 97 | int Recv(SOCKET sock); 98 | int Send(SOCKET sock); 99 | }; 100 | //! \} -------------------------------------------------------------------------------- /List.cpp: -------------------------------------------------------------------------------- 1 | #include "List.h" 2 | 3 | //! Constructor 4 | List::List(void) 5 | { 6 | 7 | } 8 | //! Destructor 9 | List::~List(void) 10 | { 11 | 12 | } 13 | //! Set Data 14 | //! \param pData [in] a pointer to a buffer that contains data 15 | //! \param nDataSize [in] a size of data 16 | //! \return true if success 17 | //! \return false if fail 18 | bool List::SetData(char *pData,int nDataSize) 19 | { 20 | if(!IsList(pData,nDataSize)) 21 | { 22 | if(!SetHeader(pData,nDataSize)) 23 | { 24 | return false; 25 | } 26 | } 27 | this->pData=pData; 28 | this->nDataSize=nDataSize; 29 | 30 | return true; 31 | } 32 | //! Add Entry 33 | //! \param nID [in] a uniquely number 34 | //! \param pEntry [in] a pointer to a buffer that contains entry 35 | //! \param nEntrySize [in] a size of entry 36 | //! \return true if success 37 | //! \return false if fail 38 | bool List::AddEntry(int nID,char *pEntry,int nEntrySize) 39 | { 40 | char *pOffset=0; 41 | 42 | if(IsList(pData,nDataSize)) 43 | { 44 | if(((((LISTHEADER *)pData)->nSize)+(int)sizeof(LISTENTRY)+nEntrySize)<=nDataSize) 45 | { 46 | pOffset=pData+sizeof(LISTHEADER)+((LISTHEADER *)pData)->nSize; 47 | 48 | ((LISTENTRY *)pOffset)->nID=nID; 49 | ((LISTENTRY *)pOffset)->nEntrySize=nEntrySize; 50 | 51 | pOffset+=sizeof(LISTENTRY); 52 | _CopyMemory(pOffset,pEntry,nEntrySize); 53 | 54 | ((LISTHEADER *)pData)->nSize+=sizeof(LISTENTRY)+nEntrySize; 55 | ((LISTHEADER *)pData)->nNumberOfEntries++; 56 | 57 | return true; 58 | } 59 | } 60 | 61 | return false; 62 | } 63 | //! Remove Entry 64 | //! \param nID [in] a uniquely number 65 | //! \return true if success 66 | //! \return false if fail 67 | bool List::RemoveEntry(int nID) 68 | { 69 | if(IsList(pData,nDataSize)) 70 | { 71 | 72 | 73 | return true; 74 | } 75 | 76 | return false; 77 | } 78 | //! \param pData [in] a pointer to a buffer that contains data 79 | //! \param nDataSize [in] a size of data 80 | //! \return true if success 81 | //! \return false if fail 82 | bool List::IsList(char *pData,int nDataSize) 83 | { 84 | if(nDataSize>=sizeof(LISTHEADER)) 85 | { 86 | if(((LISTHEADER *)pData)->nSignature==LIST_SIGNATURE) 87 | { 88 | if(((LISTHEADER *)pData)->nSize<=nDataSize-(int)sizeof(LISTHEADER)) 89 | { 90 | return true; 91 | } 92 | } 93 | } 94 | return false; 95 | } 96 | //! \Set Header 97 | //! \param pData [in] a pointer to a buffer that contains data 98 | //! \param nDataSize [in] a size of data 99 | //! \return true if success 100 | //! \return false if fail 101 | bool List::SetHeader(char *pData,int nDataSize) 102 | { 103 | if(nDataSize>=sizeof(LISTHEADER)) 104 | { 105 | ((LISTHEADER *)pData)->nSignature=LIST_SIGNATURE; 106 | ((LISTHEADER *)pData)->nNumberOfEntries=0; 107 | ((LISTHEADER *)pData)->nSize=0; 108 | return true; 109 | } 110 | return false; 111 | } 112 | LISTENTRY *List::GetListEntryByIndex(int nIndex) 113 | { 114 | char *pOffset=pData; 115 | int nSize; 116 | 117 | if(IsList(pData,nDataSize)) 118 | { 119 | if(((LISTHEADER *)pData)->nNumberOfEntries>nIndex) 120 | { 121 | pOffset+=sizeof(LISTHEADER); 122 | 123 | for(int i=0;i!=nIndex;i++) 124 | { 125 | nSize=((LISTENTRY *)pOffset)->nEntrySize+sizeof(LISTENTRY); 126 | pOffset+=nSize; 127 | } 128 | 129 | return (LISTENTRY *)pOffset; 130 | } 131 | } 132 | 133 | return 0; 134 | } 135 | LISTENTRY *List::GetListEntryByID(int nID) 136 | { 137 | int nNumberOfEntries; 138 | LISTENTRY *pListEntry=(LISTENTRY *)pData; 139 | 140 | if(IsList(pData,nDataSize)) 141 | { 142 | nNumberOfEntries=((LISTHEADER *)pData)->nNumberOfEntries; 143 | 144 | for(int i=0;inID==nID) 148 | { 149 | return pListEntry; 150 | } 151 | } 152 | } 153 | return 0; 154 | } 155 | char *List::GetEntryByIndex(int nIndex) 156 | { 157 | char *pOffset=(char *)GetListEntryByIndex(nIndex); 158 | if(pOffset) 159 | { 160 | return pOffset+sizeof(LISTENTRY); 161 | } 162 | return 0; 163 | } 164 | char *List::GetEntryByID(int nID) 165 | { 166 | char *pOffset=(char *)GetListEntryByID(nID); 167 | if(pOffset) 168 | { 169 | return pOffset+sizeof(LISTENTRY); 170 | } 171 | return 0; 172 | } -------------------------------------------------------------------------------- /Strings.cpp: -------------------------------------------------------------------------------- 1 | #include "Strings.h" 2 | 3 | //! \note Convert string(TCHAR[]) to chars. 4 | //! \param pszChars [out] a pointer to a buffer that receives the converted string. 5 | //! \param nCharsSize [in] a size, in bytes, of the buffer indicated by pszChars. 6 | //! \param pszString [in] a pointer to the string to convert. 7 | //! \return the number of bytes written to the buffer pointed to by pszChars if successful. 8 | //! \return The function returns 0 if it does not succeed. 9 | int _StringToChars(char *pszChars,int nCharsSize,TCHAR *pszString) 10 | { 11 | #ifdef UNICODE 12 | return _UnicodeToChars(pszChars,nCharsSize,pszString); 13 | #else 14 | lstrcpyn(pszChars,pszString,nCharsSize); 15 | return lstrlen(pszChars); 16 | #endif 17 | } 18 | //! \note Convert chars to string(TCHAR[]). 19 | //! \param pszString [out] a pointer to a buffer that receives the converted string. 20 | //! \param nStringLength [in] a length, in characters, of the buffer indicated by pszString. 21 | //! \param pszChars [in] a pointer to chars to convert. 22 | //! \return the number of characters written to the buffer pointed to by pszString if successful. 23 | //! \return The function returns 0 if it does not succeed. 24 | int _CharsToString(TCHAR *pszString,int nStringLength,char *pszChars) 25 | { 26 | #ifdef UNICODE 27 | return _CharsToUnicode(pszString,nStringLength,pszChars); 28 | #else 29 | lstrcpyn(pszString,pszChars,nStringLength); 30 | return lstrlen(pszString); 31 | #endif 32 | } 33 | //! \note Convert binary data to HEX. 34 | //! \param pData [in] a pointer to binary data. 35 | //! \param nDataSize [in] a size, in bytes, of binary data. 36 | //! \param pszHEX [out] a pointer to a buffer that receives the HEX string. 37 | //! \return the number of characters written to the buffer pointed to by pszHEX if successful. 38 | //! \return the function returns 0 if it does not succeed. 39 | int _BinToHEX(char *pData,int nDataSize,TCHAR *pszHEX) 40 | { 41 | TCHAR szBuffer[16]; 42 | *pszHEX=0; 43 | 44 | for(int i=0;i0;i+=1000,j-=1000) 140 | { 141 | nResult=recv(sock,&pBuffer[i],_MinInt(j,1000),0); 142 | if(nResult!=SOCKET_ERROR) 143 | { 144 | nSize+=nResult; 145 | } 146 | else if(WSAGetLastError()==WSAEWOULDBLOCK) 147 | { 148 | 149 | } 150 | else 151 | { 152 | nSize=0; 153 | j=0; 154 | #ifdef _DEBUG 155 | //################################################## 156 | wsprintf(szBuffer,TEXT("Socket Error!!!(%X code)"),WSAGetLastError()); 157 | _PrintDebugTextNS(szBuffer); 158 | LPVOID lpMsgBuf; 159 | FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | 160 | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS , 161 | NULL, WSAGetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 162 | (LPTSTR) &lpMsgBuf, 0, NULL); 163 | _PrintDebugTextNS((PTSTR)lpMsgBuf); 164 | 165 | //################################################## 166 | #endif 167 | } 168 | 169 | } 170 | 171 | #ifdef _DEBUG 172 | //################################################## 173 | 174 | wsprintf(szBuffer,TEXT("Recv %d(%X) bytes"),nSize,nSize); 175 | _PrintDebugTextNS(szBuffer); 176 | //################################################## 177 | #endif 178 | 179 | return nSize; 180 | 181 | } 182 | 183 | //! The _send function sends data on a connected socket 184 | //! \param sock [in] a descriptor identifying a connected socket 185 | //! \param pBuffer [in] A pointer to a buffer containing the data to be transmitted 186 | //! \param nBufferSize [in] the size, in bytes, of the buffer pointed to by the pBuffer parameter 187 | //! \return If no error occurs, send returns the total number of bytes sent, which can be less 188 | //! than the number requested to be sent in the nBufferSize parameter 189 | int _send(SOCKET sock,char *pBuffer,int nBufferSize) 190 | { 191 | int nSize=0; 192 | 193 | for(int i=0,j=nBufferSize;j>0;i+=1000,j-=1000) 194 | { 195 | nSize+=send(sock,&pBuffer[i],_MinInt(j,1000),0); 196 | } 197 | 198 | #ifdef _DEBUG 199 | //################################################## 200 | TCHAR szBuffer[256]; 201 | wsprintf(szBuffer,TEXT("Send %d(%X) bytes"),nSize,nSize); 202 | _PrintDebugTextNS(szBuffer); 203 | //################################################## 204 | #endif 205 | 206 | return nSize; 207 | } 208 | //! Close connection 209 | //! \param sock [in] a descriptor identifying a connected socket 210 | void _closeconnect(SOCKET sock) 211 | { 212 | #ifdef _DEBUG 213 | //################################################## 214 | _PrintDebugTextNS(TEXT("Close Socket")); 215 | //################################################## 216 | #endif 217 | 218 | shutdown(sock,2); 219 | closesocket(sock); 220 | } -------------------------------------------------------------------------------- /ICQPacket_define.h: -------------------------------------------------------------------------------- 1 | //! \file ICQPacket_define.h ICQPacket definitions 2 | #pragma once 3 | 4 | 5 | //! \defgroup oscar OSCAR protocol 6 | 7 | //! \defgroup oscar_flap FLAP 8 | //! \ingroup oscar 9 | //! \{ 10 | //! \struct FLAP_HEADER 11 | struct FLAP_HEADER 12 | { 13 | 14 | unsigned char signature; //!< FLAP signature (always 0x2a) \sa ICQ_FLAP_SIGNATURE 15 | unsigned char channel; //!< FLAP channel \sa oscar_flap_channels 16 | unsigned short sequence; //!< FLAP sequence 17 | unsigned short lenght; //!< size of FLAP data without FLAP header 18 | }; 19 | 20 | #define ICQPACKET_MAXPACKETSIZE 8192 21 | #define ICQ_FLAP_SIGNATURE 0x2a 22 | //! \} 23 | 24 | //! \defgroup oscar_flap_channels Channels 25 | //! \ingroup oscar_flap 26 | //! \{ 27 | #define ICQ_FLAP_CHANNEL_SIGNON 0x01 28 | #define ICQ_FLAP_CHANNEL_SNACDATA 0x02 29 | #define ICQ_FLAP_CHANNEL_ERROR 0x03 30 | #define ICQ_FLAP_CHANNEL_SIGNOFF 0x04 31 | #define ICQ_FLAP_CHANNEL_KEEPALIVE 0x05 32 | //! \} 33 | 34 | //! \defgroup oscar_tlv TLV 35 | //! \ingroup oscar 36 | //! \{ 37 | //! \struct TLV_HEADER 38 | struct TLV_HEADER 39 | { 40 | unsigned short type; //!< TLV type \sa oscar_tlv_types 41 | unsigned short length; //!< size of TLV data without TLV header 42 | }; 43 | //! \} 44 | 45 | //! \defgroup oscar_tlv_types Types 46 | //! \ingroup oscar_tlv 47 | //! \{ 48 | #define ICQ_TLV_UIN 0x0001 49 | #define ICQ_TLV_PASSWORD 0x0002 50 | #define ICQ_TLV_CLIENTIDSTRING 0x0003 51 | #define ICQ_TLV_DESCRIPTIONURL 0x0004 52 | #define ICQ_TLV_BOSSERVER 0x0005 53 | #define ICQ_TLV_AUTHCOOKIE 0x0006 54 | #define ICQ_TLV_USERSTATUS 0x0006 55 | #define ICQ_TLV_AUTHERRORCODE 0x0008 56 | #define ICQ_TLV_CLIENTCOUNTRY 0x000E 57 | #define ICQ_TLV_CLIENTLANG 0x000F 58 | #define ICQ_TLV_DISTRIBNUMBER 0x0014 59 | #define ICQ_TLV_CLIENTID 0x0016 60 | #define ICQ_TLV_CLIENTMAJORVER 0x0017 61 | #define ICQ_TLV_CLIENTMINORVER 0x0018 62 | #define ICQ_TLV_CLIENTLESSERVER 0x0019 63 | #define ICQ_TLV_CLIENTBUILDNUM 0x001A 64 | //! \} 65 | 66 | //! \defgroup oscar_snac SNAC 67 | //! \ingroup oscar 68 | //! \{ 69 | //! \struct SNAC_HEADER 70 | #pragma pack(push, 1) 71 | struct SNAC_HEADER 72 | { 73 | unsigned short family; //!< SNAC family 74 | unsigned short subtype; //!< SNAC subtype 75 | unsigned short flags; //!< SNAC flags 76 | unsigned int requestid; //!< SNAC requestid 77 | }; 78 | #pragma pack (pop) 79 | //! \} 80 | 81 | //! \defgroup oscar_snac_foodgroups Foodgroups 82 | //! \ingroup oscar_snac 83 | //! \{ 84 | #define ICQ_SNAC_FOODGROUP_OSERVICE 0x0001 85 | #define ICQ_SNAC_FOODGROUP_LOCATE 0x0002 86 | #define ICQ_SNAC_FOODGROUP_BUDDY 0x0003 87 | #define ICQ_SNAC_FOODGROUP_ICBM 0x0004 88 | #define ICQ_SNAC_FOODGROUP_INVITE 0x0006 89 | #define ICQ_SNAC_FOODGROUP_POPUP 0x0008 90 | #define ICQ_SNAC_FOODGROUP_PD 0x0009 91 | #define ICQ_SNAC_FOODGROUP_LOOKUP 0x000A 92 | #define ICQ_SNAC_FOODGROUP_STATS 0x000B 93 | #define ICQ_SNAC_FOODGROUP_TRANS 0x000C 94 | #define ICQ_SNAC_FOODGROUP_SSI 0x0013 95 | #define ICQ_SNAC_FOODGROUP_SPEC 0x0015 96 | #define ICQ_SNAC_FOODGROUP_UNK1 0x0022 97 | #define ICQ_SNAC_FOODGROUP_UNK2 0x0024 98 | #define ICQ_SNAC_FOODGROUP_UNK3 0x0025 99 | //! \} 100 | 101 | //! \defgroup oscar_snac_foodgroups_oservice Oservice 102 | //! \ingroup oscar_snac_foodgroups 103 | //! \{ 104 | #define ICQ_SNAC_OSERVICE_ERROR 0x0001 105 | #define ICQ_SNAC_OSERVICE_CLIENTREADY 0x0002 106 | #define ICQ_SNAC_OSERVICE_FAMILIES 0x0003 107 | #define ICQ_SNAC_OSERVICE_REQUESTRATELIMITS 0x0006 108 | #define ICQ_SNAC_OSERVICE_RATELIMITS 0x0007 109 | #define ICQ_SNAC_OSERVICE_ACCEPTRATELIMITS 0x0008 110 | #define ICQ_SNAC_OSERVICE_ONLINEINFO 0x000F 111 | #define ICQ_SNAC_OSERVICE_MESSAGEOFTHEDAY 0x0013 112 | #define ICQ_SNAC_OSERVICE_WELLKNOWNURLS 0x0015 113 | #define ICQ_SNAC_OSERVICE_REQUESTVERSIONS 0x0017 114 | #define ICQ_SNAC_OSERVICE_VERSIONS 0x0018 115 | #define ICQ_SNAC_OSERVICE_SETSTATUS 0x001E 116 | #define ICQ_SNAC_OSERVICE_EXTENDEDSTATUS 0x0021 117 | //! \} 118 | 119 | //! \defgroup oscar_snac_foodgroups_buddy Buddy 120 | //! \ingroup oscar_snac_foodgroups 121 | //! \{ 122 | #define ICQ_SNAC_BUDDY_ERROR 0x0001 123 | #define ICQ_SNAC_BUDDY_REQUESTPARAMETERS 0x0002 124 | #define ICQ_SNAC_BUDDY_PARAMETERS 0x0003 125 | #define ICQ_SNAC_BUDDY_USERONLINE 0x000B 126 | #define ICQ_SNAC_BUDDY_USEROFFLINE 0x000C 127 | //! \} 128 | 129 | //! \defgroup oscar_snac_foodgroups_icbm ICBM 130 | //! \ingroup oscar_snac_foodgroups 131 | //! \{ 132 | #define ICQ_SNAC_ICBM_ERROR 0x0001 133 | #define ICQ_SNAC_ICBM_SETPARAMETERS 0x0002 134 | #define ICQ_SNAC_ICBM_SENDMESSAGE 0x0006 135 | #define ICQ_SNAC_ICBM_RECVMESSAGE 0x0007 136 | #define ICQ_SNAC_ICBM_MESSAGEACK 0x000C 137 | //! \} 138 | 139 | //! \defgroup oscar_snac_foodgroups_stats Stats 140 | //! \ingroup oscar_snac_foodgroups 141 | //! \{ 142 | #define ICQ_SNAC_STATS_ERROR 0x0001 143 | #define ICQ_SNAC_STATS_SETMINIMUMINTERVAL 0x0002 144 | #define ICQ_SNAC_STATS_STATSREPORT 0x0003 145 | #define ICQ_SNAC_STATS_STATSREPORTACK 0x0004 146 | //! \} 147 | 148 | //! \defgroup oscar_snac_foodgroups_ssi SSI 149 | //! \ingroup oscar_snac_foodgroups 150 | //! \{ 151 | #define ICQ_SNAC_SSI_ERROR 0x0001 152 | #define ICQ_SNAC_SSI_REQUESTROSTERFIRSTTIME 0x0004 153 | #define ICQ_SNAC_SSI_ROSTER 0x0006 154 | #define ICQ_SNAC_SSI_LOADROSTERAFTERLOGIN 0x0007 155 | //! \} 156 | 157 | //! \defgroup oscar_autherrors Auth Errors 158 | //! \ingroup oscar 159 | //! \{ 160 | #define ICQ_AUTHERROR_INVALIDNICKORPASS 0x0001 161 | #define ICQ_AUTHERROR_SERVICEUNAVAILABLE 0x0002 162 | #define ICQ_AUTHERROR_OTHER 0x0003 163 | #define ICQ_AUTHERROR_INCORRECTNICKORPASS 0x0004 164 | #define ICQ_AUTHERROR_MISMATCHNICKORPASS 0x0005 165 | #define ICQ_AUTHERROR_INTERNAL 0x0006 166 | #define ICQ_AUTHERROR_INVALIDACCOUNT 0x0007 167 | #define ICQ_AUTHERROR_DELETEDACCOUNT 0x0008 168 | #define ICQ_AUTHERROR_EXPIREDACCOUNT 0x0009 169 | #define ICQ_AUTHERROR_NOACCESSTODATABASE 0x000A 170 | #define ICQ_AUTHERROR_NOACCESSTORESOLVER 0x000B 171 | #define ICQ_AUTHERROR_INVALIDDATABSEFIELDS 0x000C 172 | #define ICQ_AUTHERROR_BADDATABASESTATUS 0x000D 173 | #define ICQ_AUTHERROR_BADRESOLVERSTATUS 0x000E 174 | #define ICQ_AUTHERROR_INTERNALERROR 0x000F 175 | #define ICQ_AUTHERROR_SERVICETEMPOFFLINE 0x0010 176 | #define ICQ_AUTHERROR_SUSPENDEDACCOUNT 0x0011 177 | #define ICQ_AUTHERROR_DBSENDERROR 0x0012 178 | #define ICQ_AUTHERROR_DBLINKERROR 0x0013 179 | #define ICQ_AUTHERROR_RESERVATIONMAPERROR 0x0014 180 | #define ICQ_AUTHERROR_RESERVATIONLINKERROR 0x0015 181 | #define ICQ_AUTHERROR_MAXCONNECTFROMIP 0x0016 182 | #define ICQ_AUTHERROR_MAXCONNECTFROMIPRES 0x0017 183 | #define ICQ_AUTHERROR_RATELIMITEXCEEDEDRES 0x0018 184 | #define ICQ_AUTHERROR_TOOHEAVILYWARNED 0x0019 185 | #define ICQ_AUTHERROR_RESERVATIONTIMEOUT 0x001A 186 | #define ICQ_AUTHERROR_OLDVERSIONUPGRADEREQ 0x001B 187 | #define ICQ_AUTHERROR_OLDVERSIONUPGRADEREC 0x001C 188 | #define ICQ_AUTHERROR_RATELIMITEXCEEDED 0x001D 189 | #define ICQ_AUTHERROR_CANTREGISTERONNETWORK 0x001E 190 | #define ICQ_AUTHERROR_INVALIDSECUREID 0x0020 191 | #define ICQ_AUTHERROR_ACCOUNTSUSPENDEDAGE 0x0022 192 | //! \} 193 | 194 | //! \defgroup oscar_statuses Statuses 195 | //! \ingroup oscar 196 | //! \{ 197 | #define ICQ_STATUS_WEBAWARE 0x00010000 // Status webaware flag 198 | #define ICQ_STATUS_SHOWIP 0x00020000 // Status show ip flag 199 | #define ICQ_STATUS_BIRTHDAY 0x00080000 // User birthday flag 200 | #define ICQ_STATUS_WEBFRONT 0x00200000 // User active webfront flag 201 | #define ICQ_STATUS_DCDISABLED 0x01000000 // Direct connection not supported 202 | #define ICQ_STATUS_DCAUTH 0x10000000 // Direct connection upon authorization 203 | #define ICQ_STATUS_DCCONT 0x20000000 // DC only with contact users 204 | 205 | #define ICQ_STATUS_ONLINE 0x00000000 // Status is online 206 | #define ICQ_STATUS_AWAY 0x00000001 // Status is away 207 | #define ICQ_STATUS_DND 0x00000002 // Status is no not disturb (DND) 208 | #define ICQ_STATUS_NA 0x00000004 // Status is not available (N/A) 209 | #define ICQ_STATUS_OCCUPIED 0x00000010 // Status is occupied (BISY) 210 | #define ICQ_STATUS_FREEFORCHAT 0x00000020 // Status is free for chat 211 | #define ICQ_STATUS_INVISIBLE 0x00000100 // Status is invisible 212 | 213 | //! \} 214 | 215 | //! \defgroup advanced Advanced 216 | //! \{ 217 | struct FOODGROUP 218 | { 219 | bool Support; 220 | unsigned short Version; 221 | }; 222 | 223 | struct FOODGROUPS 224 | { 225 | FOODGROUP Oservice; 226 | FOODGROUP Locate; 227 | FOODGROUP Buddy; 228 | FOODGROUP ICBM; 229 | FOODGROUP Invite; 230 | FOODGROUP Popup; 231 | FOODGROUP PD; 232 | FOODGROUP Lookup; 233 | FOODGROUP Stats; 234 | FOODGROUP Trans; 235 | FOODGROUP SSI; 236 | FOODGROUP Spec; 237 | FOODGROUP Unk1; 238 | FOODGROUP Unk2; 239 | FOODGROUP Unk3; 240 | }; 241 | struct ICBMCOOKIESTRUCT 242 | { 243 | int nCookies1; 244 | int nCookies2; 245 | }; 246 | struct SENDTEXTSTRUCT 247 | { 248 | int MessageTime; 249 | TCHAR *pszUIN; 250 | ICBMCOOKIESTRUCT cookie; 251 | TCHAR *pszText; 252 | int nTextLength; 253 | }; 254 | struct NICKINFOSTRUCT 255 | { 256 | TCHAR szUIN[16]; 257 | short sWarningLevel; 258 | }; 259 | struct MESSAGEACKSTRUCT 260 | { 261 | ICBMCOOKIESTRUCT cookie; 262 | short sChannel; 263 | TCHAR szUIN[16]; 264 | }; 265 | struct RECVMESSAGESTRUCT 266 | { 267 | ICBMCOOKIESTRUCT cookie; 268 | short sChannel; 269 | NICKINFOSTRUCT NickInfo; 270 | TCHAR szText[1024]; 271 | }; 272 | struct FRAGMENT 273 | { 274 | unsigned char id; 275 | unsigned char version; 276 | unsigned short Length; 277 | }; 278 | //! \} -------------------------------------------------------------------------------- /SICQ.cpp: -------------------------------------------------------------------------------- 1 | #include "SICQ.h" 2 | 3 | //! Constructor 4 | 5 | SICQ::SICQ() 6 | { 7 | 8 | this->hMainWnd=hMainWnd; 9 | nError=SICQ_ERROR_SUCCESS; 10 | hEventWnd=0; 11 | nSequence=1; 12 | nStatus=SICQ_STATUS_OFFLINE; 13 | _ZeroMemory(&FoodGroups,sizeof(FoodGroups)); 14 | 15 | Start(); 16 | } 17 | 18 | //! Destructor 19 | SICQ::~SICQ(void) 20 | { 21 | Stop(); 22 | } 23 | //! SetWindowsHandle 24 | //! \param [in] hMainWnd a handle to the window whose window procedure will receive the message 25 | void SICQ::SetWindowsHandle(HWND hMainWnd) 26 | { 27 | this->hMainWnd=hMainWnd; 28 | } 29 | 30 | //! Get Last Error 31 | //! \return a pointer to a string that specifies the error message 32 | TCHAR *SICQ::GetErrorString() 33 | { 34 | TCHAR *pszErrorString; 35 | 36 | switch(nError) 37 | { 38 | case SICQ_ERROR_SUCCESS: 39 | pszErrorString=TEXT("Success"); 40 | break; 41 | case SICQ_ERROR_EVENTWINDOWISEXIST: 42 | pszErrorString=TEXT("Event Window is exist"); 43 | break; 44 | case SICQ_ERROR_EVENTWINDOWISNOTEXIST: 45 | pszErrorString=TEXT("Event Window is not exist"); 46 | break; 47 | case SICQ_ERROR_CANNOTCONNECTTOSERVER: 48 | pszErrorString=TEXT("Cannot connect to Server"); 49 | break; 50 | case SICQ_ERROR_INCORRECTUINORPASSWORD: 51 | pszErrorString=TEXT("Incorrect UIN or Password"); 52 | break; 53 | case SICQ_ERROR_RATELIMITEXCEEDED: 54 | pszErrorString=TEXT("Rate Limit Exceeded"); 55 | break; 56 | default: 57 | pszErrorString=TEXT("Unknown!!!"); 58 | } 59 | 60 | 61 | return pszErrorString; 62 | } 63 | 64 | //! Start Event Window 65 | //! 66 | //! \return true if success 67 | //! \return false if fail 68 | //! \sa GetErrorString() 69 | bool SICQ::Start() 70 | { 71 | WNDCLASS wc; 72 | HINSTANCE hInst=GetModuleHandle(0); 73 | List _list; 74 | 75 | SICQ *pThis; 76 | 77 | if(!hEventWnd) 78 | { 79 | _ZeroMemory(&wc,sizeof(wc)); 80 | 81 | wc.lpfnWndProc=SocketProc; 82 | wc.hInstance=hInst; 83 | wc.lpszClassName =TEXT("ICQ Socket"); 84 | wc.style = 0; 85 | 86 | // Register Class 87 | RegisterClass(&wc); 88 | // Create Event Window 89 | hEventWnd=CreateWindowEx(WS_EX_TOOLWINDOW,TEXT("ICQ Socket"),TEXT("ICQ Socket"),0,0,0,0,0,NULL,NULL,hInst,NULL); 90 | 91 | if(_list.SetData(HwndList,sizeof(HwndList))) 92 | { 93 | pThis=this; 94 | _list.AddEntry((int)hEventWnd,(char *)&pThis,sizeof(this)); 95 | //_list.AddEntry((int)hEventWnd,(char *)&hInst,sizeof(this)); 96 | } 97 | // Set Success 98 | nError=SICQ_ERROR_SUCCESS; 99 | 100 | return true; 101 | } 102 | else 103 | { 104 | nError=SICQ_ERROR_EVENTWINDOWISEXIST; 105 | return false; 106 | } 107 | } 108 | 109 | //! Stop Event Window 110 | //! \return true if success 111 | //! \return false if fail 112 | //! \sa GetErrorString() 113 | bool SICQ::Stop() 114 | { 115 | List _list; 116 | 117 | if(hEventWnd) 118 | { 119 | SendMessage(hEventWnd,WM_CLOSE,0,0); 120 | if(_list.SetData(HwndList,sizeof(HwndList))) 121 | { 122 | _list.RemoveEntry((int)hEventWnd); 123 | } 124 | hEventWnd=0; 125 | nError=SICQ_ERROR_SUCCESS; 126 | 127 | return true; 128 | } 129 | else 130 | { 131 | nError=SICQ_ERROR_EVENTWINDOWISNOTEXIST; 132 | 133 | return false; 134 | } 135 | 136 | } 137 | 138 | //! Login 139 | //! \param pszServerIP [in] a pointer to a buffer that contains IP of ICQ server ( for example 205.188.251.43 ) 140 | //! \param nServerPort [in] a port of ICQ server ( usually 5190 ) 141 | //! \param pszUIN [in] a pointer to a buffer that contains ICQ UIN 142 | //! \param pszPassword [in] a pointer to a buffer that contains ICQ Password 143 | //! \note main window receives #WM_SICQ_MAINWND_LOGIN event 144 | void SICQ::Login(TCHAR *pszServerIP,int nServerPort,TCHAR *pszUIN,TCHAR *pszPassword) 145 | { 146 | lstrcpyn(szServerIP,pszServerIP,16); 147 | this->nServerPort=nServerPort; 148 | lstrcpyn(szUIN,pszUIN,16); 149 | lstrcpyn(szPassword,pszPassword,16); 150 | 151 | PostMessage(hEventWnd,WM_SICQ_EVENTWND_LOGIN,0,0); 152 | } 153 | //! Send Text 154 | //! \param pszUIN [in] a pointer to a buffer that contains ICQ UIN 155 | //! \param pszText [in] a pointer to a buffer that contains a text message 156 | //! \param nTextLength [in] a length, in characters, of a text message 157 | //! \return Message ID or 0 if offline 158 | //! \note main window receives #WM_SICQ_MAINWND_SENDTEXT event 159 | int SICQ::SendText(TCHAR *pszUIN,TCHAR *pszText,int nTextLength) 160 | { 161 | random rand; 162 | SENDTEXTSTRUCT sts; 163 | 164 | if(this->nStatus!=SICQ_STATUS_OFFLINE) 165 | { 166 | int nMessageID=rand.randomDWORD(); 167 | 168 | sts.MessageTime=_LocalTimeAsUnixTime(); 169 | sts.cookie.nCookies1=nMessageID; 170 | sts.cookie.nCookies2=nMessageID; 171 | sts.pszText=pszText; 172 | sts.pszUIN=pszUIN; 173 | sts.nTextLength=nTextLength; 174 | 175 | SendMessage(hEventWnd,WM_SICQ_EVENTWND_SENDMESSAGE,0,(LPARAM)&sts); 176 | 177 | return nMessageID; 178 | } 179 | else 180 | { 181 | #ifdef _DEBUG 182 | //################################################## 183 | _PrintDebugTextNS(TEXT("Offline. Cannot send Text!!!")); 184 | //################################################## 185 | #endif 186 | return 0; 187 | } 188 | } 189 | void SICQ::ICQSendText(SENDTEXTSTRUCT *pSts) 190 | { 191 | if(this->nStatus!=SICQ_STATUS_OFFLINE) 192 | { 193 | CreateSendTextUnicodePacket(nSequence,pSts); 194 | Send(sock); 195 | SequenceIncrement(); 196 | } 197 | } 198 | void SICQ::ICQPing() 199 | { 200 | if(this->nStatus!=SICQ_STATUS_OFFLINE) 201 | { 202 | CreatePingPacket(nSequence); 203 | Send(sock); 204 | SequenceIncrement(); 205 | } 206 | } 207 | //! Set Status 208 | //! \param nStatus ICQ Status 209 | //! \return true if success 210 | //! \return false if not 211 | bool SICQ::SetStatus(int nStatus) 212 | { 213 | if(this->nStatus!=SICQ_STATUS_OFFLINE) 214 | { 215 | PostMessage(hEventWnd,WM_SICQ_EVENTWND_SETSTATUS,nStatus,0); 216 | 217 | return true; 218 | } 219 | else 220 | { 221 | #ifdef _DEBUG 222 | //################################################## 223 | _PrintDebugTextNS(TEXT("Offline. Cannot set Status!!!")); 224 | //################################################## 225 | #endif 226 | return 0; 227 | } 228 | } 229 | //! Login 230 | bool SICQ::ICQLogin() 231 | { 232 | return ICQLoginPlain(); 233 | //return ICQLoginMD5(); 234 | } 235 | bool SICQ::ICQLoginPlain() 236 | { 237 | TCHAR szBuffer[256]; 238 | char Cookies[256]; 239 | int nCookiesSize; 240 | 241 | 242 | sock=_socket(); 243 | if(_connect(sock,szServerIP,nServerPort)) 244 | { 245 | Recv(sock); 246 | 247 | if(IsHelloPacket()) 248 | { 249 | CreatePlainLoginPacket(nSequence,szUIN,szPassword); 250 | Send(sock); 251 | SequenceIncrement(); 252 | 253 | Recv(sock); 254 | 255 | if(IsSignOffChannel()) 256 | { 257 | if(IsTLVPresent(ICQ_TLV_AUTHCOOKIE)) 258 | { 259 | nCookiesSize=GetTLV_blob(ICQ_TLV_AUTHCOOKIE,Cookies,sizeof(Cookies)); 260 | GetTLV_string(ICQ_TLV_BOSSERVER,szBuffer,sizeof(szBuffer)/sizeof(TCHAR)); 261 | 262 | ICQBOSServerConnect(szBuffer,Cookies,sizeof(Cookies)); 263 | } 264 | else if(IsTLVPresent(ICQ_TLV_AUTHERRORCODE)) 265 | { 266 | #ifdef _DEBUG 267 | //################################################## 268 | _PrintDebugTextNS(TEXT("Login Error!!!")); 269 | 270 | TCHAR szBuffer[256]; 271 | wsprintf(szBuffer,TEXT("Auther Error Code %X"),GetTLV_u16(ICQ_TLV_AUTHERRORCODE)); 272 | _PrintDebugTextNS(szBuffer); 273 | //################################################## 274 | #endif 275 | 276 | switch(GetTLV_u16(ICQ_TLV_AUTHERRORCODE)) 277 | { 278 | case ICQ_AUTHERROR_INCORRECTNICKORPASS: 279 | case ICQ_AUTHERROR_MISMATCHNICKORPASS: 280 | nError=SICQ_ERROR_INCORRECTUINORPASSWORD; 281 | break; 282 | case ICQ_AUTHERROR_RATELIMITEXCEEDEDRES: 283 | nError=SICQ_ERROR_RATELIMITEXCEEDED; 284 | break; 285 | default: 286 | nError=SICQ_ERROR_UNKNOWN; 287 | } 288 | } 289 | } 290 | else 291 | { 292 | #ifdef _DEBUG 293 | //################################################## 294 | _PrintDebugTextNS(TEXT("Login Error!!!")); 295 | //################################################## 296 | #endif 297 | nError=SICQ_ERROR_UNKNOWN; 298 | } 299 | } 300 | } 301 | else 302 | { 303 | nError=SICQ_ERROR_CANNOTCONNECTTOSERVER; 304 | } 305 | 306 | if(nError==SICQ_ERROR_SUCCESS) 307 | { 308 | SendMessage(hMainWnd,WM_SICQ_MAINWND_LOGIN,1,(LPARAM)this); 309 | nStatus=SICQ_STATUS_ONLINE; 310 | return true; 311 | } 312 | else 313 | { 314 | SendMessage(hMainWnd,WM_SICQ_MAINWND_LOGIN,0,(LPARAM)this); 315 | nStatus=SICQ_STATUS_OFFLINE; 316 | return false; 317 | } 318 | 319 | } 320 | 321 | bool SICQ::ICQLoginMD5() 322 | { 323 | if(nError==SICQ_ERROR_SUCCESS) 324 | { 325 | SendMessage(hMainWnd,WM_SICQ_MAINWND_LOGIN,1,(LPARAM)this); 326 | nStatus=SICQ_STATUS_ONLINE; 327 | return true; 328 | } 329 | else 330 | { 331 | SendMessage(hMainWnd,WM_SICQ_MAINWND_LOGIN,0,(LPARAM)this); 332 | return false; 333 | } 334 | } 335 | 336 | int SICQ::StatusToICQ(int nStatus) 337 | { 338 | int nResult; 339 | 340 | switch(nStatus) 341 | { 342 | case SICQ_STATUS_ONLINE: 343 | nResult=ICQ_STATUS_ONLINE; 344 | break; 345 | case SICQ_STATUS_AWAY: 346 | nResult=ICQ_STATUS_AWAY; 347 | break; 348 | case SICQ_STATUS_DND: 349 | nResult=ICQ_STATUS_DND; 350 | break; 351 | case SICQ_STATUS_NA: 352 | nResult=ICQ_STATUS_NA; 353 | break; 354 | case SICQ_STATUS_INVISIBLE: 355 | nResult=ICQ_STATUS_INVISIBLE; 356 | break; 357 | case SICQ_STATUS_OCCUPIED: 358 | nResult=ICQ_STATUS_OCCUPIED; 359 | break; 360 | case SICQ_STATUS_FREEFORCHAT: 361 | nResult=ICQ_STATUS_FREEFORCHAT; 362 | break; 363 | 364 | } 365 | 366 | return nResult; 367 | } 368 | 369 | void SICQ::ICQSetStatus(int nStatus) 370 | { 371 | if(nStatus==SICQ_STATUS_OFFLINE) 372 | { 373 | if(this->nStatus!=SICQ_STATUS_OFFLINE) 374 | { 375 | CreateGoodByePacket(nSequence); 376 | Send(sock); 377 | SequenceIncrement(); 378 | 379 | _closeconnect(sock); 380 | } 381 | } 382 | else 383 | { 384 | if(this->nStatus==SICQ_STATUS_OFFLINE) 385 | { 386 | nStatus=SICQ_STATUS_OFFLINE; 387 | } 388 | else 389 | { 390 | CreateSetStatusPacket(nSequence,StatusToICQ(nStatus)); 391 | Send(sock); 392 | SequenceIncrement(); 393 | } 394 | } 395 | SendMessage(hMainWnd,WM_SICQ_MAINWND_STATUS,nStatus,(LPARAM)this); 396 | this->nStatus=nStatus; 397 | } 398 | 399 | void SICQ::ICQBOSServerConnect(TCHAR *pszBOSServerIPAndPort,char *pCookies,int nCookiesSize) 400 | { 401 | TCHAR szBOSServer[64],*pszOffset; 402 | int nBOSServerPort; 403 | 404 | pszOffset=StrStr(pszBOSServerIPAndPort,TEXT(":")); 405 | pszOffset++; 406 | lstrcpyn(szBOSServer,pszBOSServerIPAndPort,(pszOffset-pszBOSServerIPAndPort)); 407 | nBOSServerPort=StrToInt(pszOffset); 408 | 409 | CreateGoodByePacket(nSequence); 410 | Send(sock); 411 | SequenceIncrement(); 412 | 413 | _closeconnect(sock); 414 | 415 | // BOS Server Connection 416 | #ifdef _DEBUG 417 | //################################################## 418 | _PrintDebugTextNS(TEXT("BOS Server connection")); 419 | //################################################## 420 | #endif 421 | sock=_socket(); 422 | if(_connect(sock,szBOSServer,nBOSServerPort)) 423 | { 424 | while(true) 425 | { 426 | Recv(sock); 427 | 428 | if(IsHelloPacket()) 429 | { 430 | 431 | CreateCookiesPacket(nSequence,pCookies,nCookiesSize); 432 | Send(sock); 433 | SequenceIncrement(); 434 | } 435 | else if(IsSNACPresent(ICQ_SNAC_FOODGROUP_OSERVICE,ICQ_SNAC_OSERVICE_FAMILIES)) 436 | { 437 | 438 | ReadFoodGroupsFamiliesPacket(&FoodGroups); 439 | 440 | CreateFoodGroupsVersionsPacket(nSequence,&FoodGroups); 441 | Send(sock); 442 | SequenceIncrement(); 443 | } 444 | else if(IsSNACPresent(ICQ_SNAC_FOODGROUP_OSERVICE,ICQ_SNAC_OSERVICE_VERSIONS)) 445 | { 446 | ReadFoodGroupsVersionsPacket(&FoodGroups); 447 | } 448 | else if(IsSNACPresent(ICQ_SNAC_FOODGROUP_OSERVICE,ICQ_SNAC_OSERVICE_MESSAGEOFTHEDAY)) 449 | { 450 | CreateRequestRatesPacket(nSequence); 451 | Send(sock); 452 | SequenceIncrement(); 453 | } 454 | else if(IsSNACPresent(ICQ_SNAC_FOODGROUP_OSERVICE,ICQ_SNAC_OSERVICE_WELLKNOWNURLS)) 455 | { 456 | 457 | } 458 | else if(IsSNACPresent(ICQ_SNAC_FOODGROUP_OSERVICE,ICQ_SNAC_OSERVICE_RATELIMITS)) 459 | { 460 | CreateAcceptRatesPacket(nSequence); 461 | Send(sock); 462 | SequenceIncrement(); 463 | 464 | CreateRequestRosterFirstTimePacket(nSequence); 465 | Send(sock); 466 | SequenceIncrement(); 467 | } 468 | else if(IsSNACPresent(ICQ_SNAC_FOODGROUP_SSI,ICQ_SNAC_SSI_ROSTER)) 469 | { 470 | CreateLoadRosterAfterLoginPacket(nSequence); 471 | Send(sock); 472 | SequenceIncrement(); 473 | 474 | CreateSetICBMParametersPacket(nSequence); 475 | Send(sock); 476 | SequenceIncrement(); 477 | 478 | CreateRequestBuddyParametersPacket(nSequence); 479 | Send(sock); 480 | SequenceIncrement(); 481 | } 482 | else if(IsSNACPresent(ICQ_SNAC_FOODGROUP_OSERVICE,ICQ_SNAC_OSERVICE_ONLINEINFO)) 483 | { 484 | 485 | } 486 | else if(IsSNACPresent(ICQ_SNAC_FOODGROUP_OSERVICE,ICQ_SNAC_OSERVICE_EXTENDEDSTATUS)) 487 | { 488 | 489 | } 490 | else if(IsSNACPresent(ICQ_SNAC_FOODGROUP_BUDDY,ICQ_SNAC_BUDDY_PARAMETERS)) 491 | { 492 | CreateSetStatusPacket(nSequence,ICQ_STATUS_ONLINE); 493 | Send(sock); 494 | SequenceIncrement(); 495 | 496 | CreateClientReadyPacket(nSequence); 497 | Send(sock); 498 | SequenceIncrement(); 499 | 500 | nError=SICQ_ERROR_SUCCESS; 501 | 502 | WSAAsyncSelect(sock,hEventWnd,WM_SICQ_EVENTWND_RECVDATA,FD_READ); 503 | 504 | break; 505 | } 506 | else 507 | { 508 | #ifdef _DEBUG 509 | //################################################## 510 | _PrintDebugTextNS(TEXT("Unknown")); 511 | //################################################## 512 | #endif 513 | } 514 | } 515 | } 516 | else 517 | { 518 | nError=SICQ_ERROR_CANNOTCONNECTTOSERVER; 519 | } 520 | } 521 | void SICQ::DefProc() 522 | { 523 | MESSAGEACKSTRUCT mas; 524 | RECVMESSAGESTRUCT rms; 525 | #ifdef _DEBUG 526 | //################################################## 527 | _PrintDebugTextNS(TEXT("Recv Data")); 528 | //################################################## 529 | #endif 530 | while(Recv(sock)) 531 | { 532 | if(IsSNACPresent(ICQ_SNAC_FOODGROUP_OSERVICE,ICQ_SNAC_OSERVICE_ONLINEINFO)) 533 | { 534 | 535 | } 536 | else if(IsSNACPresent(ICQ_SNAC_FOODGROUP_STATS,ICQ_SNAC_STATS_SETMINIMUMINTERVAL)) 537 | { 538 | 539 | } 540 | else if(IsSNACPresent(ICQ_SNAC_FOODGROUP_BUDDY,ICQ_SNAC_BUDDY_USERONLINE)) 541 | { 542 | 543 | } 544 | else if(IsSNACPresent(ICQ_SNAC_FOODGROUP_BUDDY,ICQ_SNAC_BUDDY_USEROFFLINE)) 545 | { 546 | 547 | } 548 | else if(IsSNACPresent(ICQ_SNAC_FOODGROUP_ICBM,ICQ_SNAC_ICBM_RECVMESSAGE)) 549 | { 550 | ReadRecvMessagePacket(&rms); 551 | SendMessage(hMainWnd,WM_SICQ_MAINWND_RECVTEXT,(WPARAM)(&rms),(LPARAM)this); 552 | } 553 | else if(IsSNACPresent(ICQ_SNAC_FOODGROUP_ICBM,ICQ_SNAC_ICBM_MESSAGEACK)) 554 | { 555 | ReadMessageAckPacket(&mas); 556 | SendMessage(hMainWnd,WM_SICQ_MAINWND_MESSAGEACK,mas.cookie.nCookies1,(LPARAM)this); 557 | } 558 | } 559 | } 560 | //! CALLBACK function 561 | LRESULT CALLBACK SICQ::SocketProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 562 | { 563 | List _list; 564 | SICQ *pSICQ; 565 | 566 | int nResult=1; 567 | 568 | 569 | switch (message) 570 | { 571 | case WM_CREATE: 572 | 573 | SetTimer(hWnd,(int)hWnd,60000,0); 574 | 575 | break; 576 | 577 | case WM_SICQ_EVENTWND_LOGIN: 578 | 579 | _list.SetData(HwndList,sizeof(HwndList)); 580 | pSICQ=(SICQ *)(*((int *)_list.GetEntryByID((int)hWnd))); 581 | 582 | //return ((SICQ *)lParam)->ICQLogin(); 583 | nResult=pSICQ->ICQLogin(); 584 | 585 | break; 586 | 587 | case WM_SICQ_EVENTWND_SETSTATUS: 588 | 589 | _list.SetData(HwndList,sizeof(HwndList)); 590 | pSICQ=(SICQ *)(*((int *)_list.GetEntryByID((int)hWnd))); 591 | 592 | //return ((SICQ *)lParam)->ICQSetStatus(wParam); 593 | pSICQ->ICQSetStatus(wParam); 594 | nResult=1; 595 | 596 | break; 597 | 598 | case WM_SICQ_EVENTWND_RECVDATA: 599 | 600 | _list.SetData(HwndList,sizeof(HwndList)); 601 | pSICQ=(SICQ *)(*((int *)_list.GetEntryByID((int)hWnd))); 602 | 603 | //return ((SICQ *)lParam)->ICQSetStatus(wParam); 604 | pSICQ->DefProc(); 605 | 606 | break; 607 | 608 | case WM_SICQ_EVENTWND_SENDMESSAGE: 609 | 610 | _list.SetData(HwndList,sizeof(HwndList)); 611 | pSICQ=(SICQ *)(*((int *)_list.GetEntryByID((int)hWnd))); 612 | 613 | //return ((SICQ *)lParam)->ICQSetStatus(wParam); 614 | pSICQ->ICQSendText((SENDTEXTSTRUCT *)lParam); 615 | 616 | break; 617 | 618 | case WM_TIMER: 619 | 620 | _list.SetData(HwndList,sizeof(HwndList)); 621 | pSICQ=(SICQ *)(*((int *)_list.GetEntryByID((int)hWnd))); 622 | 623 | pSICQ->ICQPing(); 624 | 625 | break; 626 | case WM_DESTROY: 627 | 628 | KillTimer(hWnd,(int)hWnd); 629 | 630 | PostQuitMessage(0); 631 | break; 632 | default: 633 | 634 | DefWindowProc(hWnd,message,wParam,lParam); 635 | 636 | } 637 | return nResult; 638 | } 639 | 640 | void SICQ::SequenceIncrement() 641 | { 642 | if(nSequence<0x8000) 643 | { 644 | nSequence++; 645 | } 646 | else 647 | { 648 | nSequence=0; 649 | } 650 | } 651 | 652 | char SICQ::HwndList[1000]={0}; -------------------------------------------------------------------------------- /ICQPacket.cpp: -------------------------------------------------------------------------------- 1 | #include "ICQPacket.h" 2 | 3 | 4 | //! Constructor 5 | ICQPacket::ICQPacket(void) 6 | { 7 | pPacket=(char *)_Alloc(ICQPACKET_MAXPACKETSIZE); 8 | nPacketSize=0; 9 | } 10 | //! Destructor 11 | ICQPacket::~ICQPacket(void) 12 | { 13 | _Free(pPacket); 14 | } 15 | //! GetPacketPointer 16 | //! \return a pointer to ICQ Packet 17 | char *ICQPacket::GetPacketPointer() 18 | { 19 | return pPacket; 20 | } 21 | //! GetPacketSize 22 | //! \return a size of ICQ Packet 23 | int ICQPacket::GetPacketSize() 24 | { 25 | return nPacketSize; 26 | } 27 | //! Receives ICQ Packet from a connected socket 28 | //! \param sock [in] a descriptor identifying a connected socket 29 | //! \return If no error occurs, returns the number of bytes received 30 | int ICQPacket::Recv(SOCKET sock) 31 | { 32 | nPacketSize=0; 33 | 34 | if(_recv(sock,pPacket,sizeof(FLAP_HEADER))) 35 | { 36 | if(IsFLAPPacket()) 37 | { 38 | nPacketSize=GetFLAPDataSize(); 39 | 40 | if(_recv(sock,pPacket+sizeof(FLAP_HEADER),nPacketSize)) 41 | { 42 | nPacketSize+=sizeof(FLAP_HEADER); 43 | } 44 | else 45 | { 46 | nPacketSize=0; 47 | } 48 | } 49 | else 50 | { 51 | 52 | #ifdef _DEBUG 53 | //################################################## 54 | _PrintDebugTextNS(TEXT("It's not FLAP")); 55 | //################################################## 56 | #endif 57 | } 58 | 59 | 60 | } 61 | 62 | #ifdef _DEBUG 63 | //################################################## 64 | _PrintDebugTextNS(TEXT("----------[recv]---------------")); 65 | TCHAR szBuffer[256]; 66 | wsprintf(szBuffer,TEXT("Packet Size %d(%X) bytes"),nPacketSize,nPacketSize); 67 | _PrintDebugTextNS(szBuffer); 68 | _PrintDebugHEXTable(GetPacketPointer(),GetPacketSize()); 69 | _PrintDebugTextNS(TEXT("-------------------------------")); 70 | //################################################## 71 | #endif 72 | 73 | return nPacketSize; 74 | } 75 | //! Sends ICQ Packet on a connected socket 76 | //! \param sock [in] a descriptor identifying a connected socket 77 | //! \return If no error occurs, returns the total number of bytes sent 78 | int ICQPacket::Send(SOCKET sock) 79 | { 80 | int nResult=0; 81 | 82 | if(IsFLAPPacket()) 83 | { 84 | nResult=_send(sock,pPacket,nPacketSize); 85 | 86 | if(nResult) 87 | { 88 | #ifdef _DEBUG 89 | //################################################## 90 | _PrintDebugTextNS(TEXT("----------[send]---------------")); 91 | TCHAR szBuffer[256]; 92 | wsprintf(szBuffer,TEXT("Packet Size %d(%X) bytes"),nPacketSize,nPacketSize); 93 | _PrintDebugTextNS(szBuffer); 94 | _PrintDebugHEXTable(GetPacketPointer(),GetPacketSize()); 95 | _PrintDebugTextNS(TEXT("-------------------------------")); 96 | //################################################## 97 | #endif 98 | } 99 | } 100 | 101 | return nResult; 102 | } 103 | //! Is Packet FLAP 104 | //! \return true if success 105 | //! \return false if fail 106 | //! \sa FLAP_HEADER 107 | bool ICQPacket::IsFLAPPacket() 108 | { 109 | return *pPacket==ICQ_FLAP_SIGNATURE; 110 | } 111 | //! \return FLAP channel 112 | //! \sa FLAP_HEADER 113 | unsigned char ICQPacket::GetFLAPChannel() 114 | { 115 | return ((FLAP_HEADER *)pPacket)->channel; 116 | } 117 | //! \return FLAP sequence 118 | //! \sa FLAP_HEADER 119 | unsigned short ICQPacket::GetFLAPSequence() 120 | { 121 | return (ntohs)(((FLAP_HEADER *)pPacket)->sequence); 122 | } 123 | //! \return FLAP DataSize 124 | //! \sa FLAP_HEADER 125 | unsigned short ICQPacket::GetFLAPDataSize() 126 | { 127 | return (ntohs)(((FLAP_HEADER *)pPacket)->lenght); 128 | } 129 | //! \return true if success 130 | //! \return false if fail 131 | bool ICQPacket::IsHelloPacket() 132 | { 133 | char channel=GetFLAPChannel(); 134 | int DataSize=GetFLAPDataSize(); 135 | 136 | if((channel==ICQ_FLAP_CHANNEL_SIGNON)&&(DataSize==4)) 137 | { 138 | #ifdef _DEBUG 139 | //################################################## 140 | _PrintDebugTextNS(TEXT("It's Hello Packet")); 141 | //################################################## 142 | #endif 143 | return true; 144 | } 145 | else 146 | { 147 | #ifdef _DEBUG 148 | //################################################## 149 | _PrintDebugTextNS(TEXT("It's NOT Hello Packet")); 150 | //################################################## 151 | #endif 152 | return false; 153 | } 154 | } 155 | 156 | void ICQPacket::SetFLAPChannel(unsigned char channel) 157 | { 158 | ((FLAP_HEADER *)pPacket)->channel=channel; 159 | } 160 | void ICQPacket::SetFLAPSequence(unsigned short sequence) 161 | { 162 | ((FLAP_HEADER *)pPacket)->sequence=htons(sequence); 163 | } 164 | void ICQPacket::SetFLAPDataSize(unsigned short DataSize) 165 | { 166 | ((FLAP_HEADER *)pPacket)->lenght=htons(DataSize); 167 | } 168 | void ICQPacket::SetFLAPHeader(char Channel,short Sequence) 169 | { 170 | ((FLAP_HEADER *)pPacket)->signature=0x2A; 171 | SetFLAPChannel(Channel); 172 | SetFLAPSequence(Sequence); 173 | SetFLAPDataSize(0); 174 | 175 | nPacketSize=sizeof(FLAP_HEADER); 176 | } 177 | int ICQPacket::Add_u8(unsigned char cU8) 178 | { 179 | *(pPacket+nPacketSize)=cU8; 180 | nPacketSize++; 181 | 182 | SetFLAPDataSize(nPacketSize-sizeof(FLAP_HEADER)); 183 | 184 | return 1; 185 | } 186 | int ICQPacket::Add_u16_BE(unsigned short sU16) 187 | { 188 | *(unsigned short *)(pPacket+nPacketSize)=htons(sU16); 189 | nPacketSize+=2; 190 | 191 | SetFLAPDataSize(nPacketSize-sizeof(FLAP_HEADER)); 192 | 193 | return 2; 194 | } 195 | int ICQPacket::Add_u32_BE(unsigned int nU32) 196 | { 197 | *(unsigned int *)(pPacket+nPacketSize)=htonl(nU32); 198 | nPacketSize+=4; 199 | 200 | SetFLAPDataSize(nPacketSize-sizeof(FLAP_HEADER)); 201 | 202 | return 4; 203 | } 204 | int ICQPacket::Add_blob(char *bData,int nDataSize) 205 | { 206 | _CopyMemory(pPacket+nPacketSize,bData,nDataSize); 207 | nPacketSize+=nDataSize; 208 | 209 | SetFLAPDataSize(nPacketSize-sizeof(FLAP_HEADER)); 210 | 211 | return nDataSize; 212 | } 213 | int ICQPacket::Add_string(TCHAR *pszString) 214 | { 215 | int nStringLength=lstrlen(pszString); 216 | char *pChars=(char *)_Alloc(nStringLength+1); 217 | 218 | _StringToChars(pChars,nStringLength+1,pszString); 219 | Add_blob(pChars,nStringLength); 220 | 221 | _Free(pChars); 222 | 223 | return nStringLength; 224 | } 225 | int ICQPacket::Add_string08(TCHAR *pszString) 226 | { 227 | int nLength=lstrlen(pszString); 228 | 229 | Add_u8((char)nLength); 230 | nLength+=Add_string(pszString); 231 | 232 | return nLength; 233 | } 234 | int ICQPacket::Add_TLVHeader(unsigned short Type,unsigned short Length) 235 | { 236 | Add_u16_BE(Type); 237 | Add_u16_BE(Length); 238 | 239 | return sizeof(TLV_HEADER); 240 | } 241 | int ICQPacket::Add_TLV_u16(unsigned short Type,unsigned short sU16) 242 | { 243 | Add_TLVHeader(Type,2); 244 | Add_u16_BE(sU16); 245 | 246 | return 2+sizeof(TLV_HEADER); 247 | } 248 | int ICQPacket::Add_TLV_u32(unsigned short Type,unsigned int nU32) 249 | { 250 | Add_TLVHeader(Type,4); 251 | Add_u32_BE(nU32); 252 | 253 | return 4+sizeof(TLV_HEADER); 254 | } 255 | int ICQPacket::Add_TLV_blob(unsigned short Type,char *bData,int nDataSize) 256 | { 257 | Add_TLVHeader(Type,nDataSize); 258 | Add_blob(bData,nDataSize); 259 | 260 | return nDataSize+sizeof(TLV_HEADER); 261 | } 262 | int ICQPacket::Add_TLV_string(unsigned short Type,TCHAR *pszString) 263 | { 264 | int nStringLength=lstrlen(pszString); 265 | 266 | Add_TLVHeader(Type,nStringLength); 267 | Add_string(pszString); 268 | 269 | return nStringLength+sizeof(TLV_HEADER); 270 | } 271 | int ICQPacket::Add_TLV_empty(unsigned short Type) 272 | { 273 | Add_TLVHeader(Type,0); 274 | 275 | return 0; 276 | } 277 | int ICQPacket::Add_TLV_password(unsigned short Type,TCHAR *pszPassword) 278 | { 279 | unsigned char MagicXor[]={0xF3, 0x26, 0x81, 0xC4, 0x39, 0x86, 0xDB, 0x92, 0x71, 0xA3, 0xB9, 0xE6, 0x53, 0x7A, 0x95, 0x7C}; 280 | 281 | int nPasswordLength=lstrlen(pszPassword); 282 | char *pChars=(char *)_Alloc(nPasswordLength+1); 283 | 284 | _StringToChars(pChars,nPasswordLength+1,pszPassword); 285 | 286 | for(int i=0;i=sizeof(TLV_HEADER)) 393 | { 394 | pOffset+=sizeof(FLAP_HEADER); 395 | 396 | while(nDataSize>0) 397 | { 398 | if(GetTLVTypeFromOffset(pOffset)==Type) 399 | { 400 | return pOffset; 401 | } 402 | else 403 | { 404 | nDataSize-=sizeof(TLV_HEADER)+GetTLVLehgthFromOffset(pOffset); 405 | pOffset+=sizeof(TLV_HEADER)+GetTLVLehgthFromOffset(pOffset); 406 | } 407 | } 408 | } 409 | return 0; 410 | 411 | } 412 | unsigned short ICQPacket::GetTLVTypeFromOffset(char *pOffset) 413 | { 414 | return ntohs(((TLV_HEADER *)pOffset)->type); 415 | } 416 | unsigned short ICQPacket::GetTLVLehgthFromOffset(char *pOffset) 417 | { 418 | return ntohs(((TLV_HEADER *)pOffset)->length); 419 | } 420 | unsigned short ICQPacket::GetFragmentLehgthFromOffset(char *pOffset) 421 | { 422 | return ntohs(((FRAGMENT *)pOffset)->Length); 423 | } 424 | 425 | //! Get TLV bytes 426 | //! \param Type TLV type. 427 | //! \param pBuffer [out] a pointer to a buffer that receives TLV bytes. 428 | //! \param nBufferSize [in] a size, in characters, of the buffer indicated by pBuffer. 429 | //! \return if no error occurs, returns the number of bytes. 430 | //! \return The function returns 0 if it does not succeed. 431 | //! \sa TLV_HEADER 432 | int ICQPacket::GetTLV_blob(unsigned short Type,char *pBuffer,int nBufferSize) 433 | { 434 | char *pOffset=GetTLVPointer(Type); 435 | 436 | if(pOffset) 437 | { 438 | int nSize=GetTLVLehgthFromOffset(pOffset); 439 | 440 | if(nSize<=nBufferSize) 441 | { 442 | _CopyMemory(pBuffer,pOffset+sizeof(TLV_HEADER),nSize); 443 | return nSize; 444 | } 445 | } 446 | return 0; 447 | } 448 | //! Get TLV string 449 | //! \param Type TLV type. 450 | //! \param pszBuffer [out] a pointer to a buffer that receives TLV string. 451 | //! \param nBufferLength [in] a size, in characters, of the buffer indicated by pszBuffer. 452 | //! \return if no error occurs, returns the number of symbols. 453 | //! \return The function returns 0 if it does not succeed. 454 | //! \sa TLV_HEADER 455 | int ICQPacket::GetTLV_string(unsigned short Type,TCHAR *pszBuffer,int nBufferLength) 456 | { 457 | char *pOffset=GetTLVPointer(Type); 458 | 459 | if(pOffset) 460 | { 461 | int nSize=GetTLVLehgthFromOffset(pOffset); 462 | 463 | if(nSize<=nBufferLength-1) 464 | { 465 | char *pBuffer=(char *)_Alloc(nSize+1); 466 | _CopyMemory(pBuffer,pOffset+sizeof(TLV_HEADER),nSize); 467 | *(pBuffer+nSize)=0; 468 | _CharsToString(pszBuffer,nBufferLength,pBuffer); 469 | _Free(pBuffer); 470 | 471 | return nSize; 472 | } 473 | } 474 | return 0; 475 | } 476 | //! Get TLV short int 477 | //! \param Type TLV type. 478 | //! \return TLV short int 479 | //! \sa TLV_HEADER 480 | unsigned short ICQPacket::GetTLV_u16(unsigned short Type) 481 | { 482 | 483 | char *pOffset=GetTLVPointer(Type); 484 | 485 | if(pOffset) 486 | { 487 | if(GetTLVLehgthFromOffset(pOffset)==2) 488 | { 489 | return htons(*((unsigned short *)(pOffset+sizeof(TLV_HEADER)))); 490 | } 491 | } 492 | return 0; 493 | } 494 | 495 | char *ICQPacket::GetSNACPointer() 496 | { 497 | if(GetPacketSize()>=sizeof(FLAP_HEADER)+sizeof(SNAC_HEADER)) 498 | { 499 | return GetPacketPointer()+sizeof(FLAP_HEADER); 500 | } 501 | else 502 | { 503 | return 0; 504 | } 505 | } 506 | 507 | unsigned short ICQPacket::GetSNACFamily() 508 | { 509 | char *pOffset=GetSNACPointer(); 510 | 511 | if(pOffset) 512 | { 513 | return ntohs(((SNAC_HEADER *)pOffset)->family); 514 | } 515 | else 516 | { 517 | return 0; 518 | } 519 | } 520 | unsigned short ICQPacket::GetSNACSubtype() 521 | { 522 | char *pOffset=GetSNACPointer(); 523 | 524 | if(pOffset) 525 | { 526 | return ntohs(((SNAC_HEADER *)pOffset)->subtype); 527 | } 528 | else 529 | { 530 | return 0; 531 | } 532 | } 533 | unsigned short ICQPacket::GetSNACFlags() 534 | { 535 | char *pOffset=GetSNACPointer(); 536 | 537 | if(pOffset) 538 | { 539 | return ntohs(((SNAC_HEADER *)pOffset)->flags); 540 | } 541 | else 542 | { 543 | return 0; 544 | } 545 | } 546 | unsigned int ICQPacket::GetSNACRequestid() 547 | { 548 | char *pOffset=GetSNACPointer(); 549 | 550 | if(pOffset) 551 | { 552 | return ntohl(((SNAC_HEADER *)pOffset)->requestid); 553 | } 554 | else 555 | { 556 | return 0; 557 | } 558 | } 559 | //! IsSNACPresent 560 | //! \param family [in] a SNAC family 561 | //! \param subtype [in] a SNAC subtype 562 | //! \return true if success 563 | //! \return false if fail 564 | //! \sa FLAP_HEADER, SNAC_HEADER 565 | bool ICQPacket::IsSNACPresent(unsigned short family,unsigned short subtype) 566 | { 567 | #ifdef _DEBUG 568 | //################################################## 569 | _PrintDebugTextNS(TEXT("----------[IsSNACPresent]------")); 570 | //################################################## 571 | #endif 572 | if((GetSNACFamily()==family)&&(GetSNACSubtype()==subtype)) 573 | { 574 | #ifdef _DEBUG 575 | TCHAR szBuffer[256]; 576 | wsprintf(szBuffer,TEXT("It's SNAC(family=%X, subtype=%X)"),family,subtype); 577 | _PrintDebugTextNS(szBuffer); 578 | 579 | if(family==ICQ_SNAC_FOODGROUP_OSERVICE) 580 | { 581 | if(subtype==ICQ_SNAC_OSERVICE_CLIENTREADY) 582 | { 583 | _PrintDebugTextNS(TEXT("OService: Client Ready")); 584 | } 585 | else if(subtype==ICQ_SNAC_OSERVICE_FAMILIES) 586 | { 587 | _PrintDebugTextNS(TEXT("OService: Families")); 588 | } 589 | else if(subtype==ICQ_SNAC_OSERVICE_REQUESTRATELIMITS) 590 | { 591 | _PrintDebugTextNS(TEXT("OService: Request Rate Limits")); 592 | } 593 | else if(subtype==ICQ_SNAC_OSERVICE_RATELIMITS) 594 | { 595 | _PrintDebugTextNS(TEXT("OService: Rate Limits")); 596 | } 597 | else if(subtype==ICQ_SNAC_OSERVICE_ACCEPTRATELIMITS) 598 | { 599 | _PrintDebugTextNS(TEXT("OService: Accept Rate Limits")); 600 | } 601 | else if(subtype==ICQ_SNAC_OSERVICE_ONLINEINFO) 602 | { 603 | _PrintDebugTextNS(TEXT("OService: Online Info")); 604 | } 605 | else if(subtype==ICQ_SNAC_OSERVICE_MESSAGEOFTHEDAY) 606 | { 607 | _PrintDebugTextNS(TEXT("OService: Message Of The Day")); 608 | } 609 | else if(subtype==ICQ_SNAC_OSERVICE_WELLKNOWNURLS) 610 | { 611 | _PrintDebugTextNS(TEXT("OService: Well Known URLs")); 612 | } 613 | else if(subtype==ICQ_SNAC_OSERVICE_REQUESTVERSIONS) 614 | { 615 | _PrintDebugTextNS(TEXT("OService: Request Versions")); 616 | } 617 | else if(subtype==ICQ_SNAC_OSERVICE_VERSIONS) 618 | { 619 | _PrintDebugTextNS(TEXT("OService: Versions")); 620 | } 621 | else if(subtype==ICQ_SNAC_OSERVICE_SETSTATUS) 622 | { 623 | _PrintDebugTextNS(TEXT("OService: Set Status")); 624 | } 625 | else if(ICQ_SNAC_OSERVICE_EXTENDEDSTATUS) 626 | { 627 | _PrintDebugTextNS(TEXT("OService: Extended Status")); 628 | } 629 | } 630 | else if(family==ICQ_SNAC_FOODGROUP_BUDDY) 631 | { 632 | if(subtype==ICQ_SNAC_BUDDY_REQUESTPARAMETERS) 633 | { 634 | _PrintDebugTextNS(TEXT("Buddy: Request Parameters")); 635 | } 636 | else if(subtype==ICQ_SNAC_BUDDY_PARAMETERS) 637 | { 638 | _PrintDebugTextNS(TEXT("Buddy: Parameters")); 639 | } 640 | else if(subtype==ICQ_SNAC_BUDDY_USERONLINE) 641 | { 642 | _PrintDebugTextNS(TEXT("Buddy: User Online")); 643 | } 644 | else if(subtype==ICQ_SNAC_BUDDY_USEROFFLINE) 645 | { 646 | _PrintDebugTextNS(TEXT("Buddy: User Offline")); 647 | } 648 | } 649 | else if(family==ICQ_SNAC_FOODGROUP_ICBM) 650 | { 651 | if(subtype==ICQ_SNAC_ICBM_ERROR) 652 | { 653 | _PrintDebugTextNS(TEXT("Buddy: Error")); 654 | } 655 | else if(subtype==ICQ_SNAC_ICBM_SETPARAMETERS) 656 | { 657 | _PrintDebugTextNS(TEXT("ICBM: Set Parameters")); 658 | } 659 | else if(subtype==ICQ_SNAC_ICBM_SENDMESSAGE) 660 | { 661 | _PrintDebugTextNS(TEXT("ICBM: Send Message")); 662 | } 663 | else if(subtype==ICQ_SNAC_ICBM_RECVMESSAGE) 664 | { 665 | _PrintDebugTextNS(TEXT("ICBM: Recv Message")); 666 | } 667 | else if(subtype==ICQ_SNAC_ICBM_MESSAGEACK) 668 | { 669 | _PrintDebugTextNS(TEXT("ICBM: Message Ack")); 670 | } 671 | } 672 | else if(family==ICQ_SNAC_FOODGROUP_STATS) 673 | { 674 | if(subtype==ICQ_SNAC_STATS_SETMINIMUMINTERVAL) 675 | { 676 | _PrintDebugTextNS(TEXT("Stats: Set Minimum Interval")); 677 | } 678 | } 679 | else if(family==ICQ_SNAC_FOODGROUP_SSI) 680 | { 681 | if(subtype==ICQ_SNAC_SSI_REQUESTROSTERFIRSTTIME) 682 | { 683 | _PrintDebugTextNS(TEXT("SSI: Request Roster(First Time)")); 684 | } 685 | else if(subtype==ICQ_SNAC_SSI_ROSTER) 686 | { 687 | _PrintDebugTextNS(TEXT("SSI: Roster")); 688 | } 689 | else if(subtype==ICQ_SNAC_SSI_LOADROSTERAFTERLOGIN) 690 | { 691 | _PrintDebugTextNS(TEXT("SSI: Load Roster After Login")); 692 | } 693 | } 694 | _PrintDebugTextNS(TEXT("-------------------------------")); 695 | //################################################## 696 | #endif 697 | 698 | return true; 699 | } 700 | else 701 | { 702 | #ifdef _DEBUG 703 | //################################################## 704 | TCHAR szBuffer[256]; 705 | wsprintf(szBuffer,TEXT("It's NOT SNAC(family=%X, subtype=%X)"),family,subtype); 706 | _PrintDebugTextNS(szBuffer); 707 | _PrintDebugTextNS(TEXT("-------------------------------")); 708 | //################################################## 709 | #endif 710 | 711 | return false; 712 | } 713 | } 714 | char *ICQPacket::GetSNACDataPointer() 715 | { 716 | if(GetSNACDataSize()) 717 | { 718 | return GetSNACPointer()+sizeof(SNAC_HEADER); 719 | } 720 | else 721 | { 722 | return 0; 723 | } 724 | } 725 | int ICQPacket::GetSNACDataSize() 726 | { 727 | int nSize=GetPacketSize()-(sizeof(FLAP_HEADER)+sizeof(SNAC_HEADER)); 728 | if(nSize>0) 729 | { 730 | return nSize; 731 | } 732 | else 733 | { 734 | return 0; 735 | } 736 | } 737 | //! ReadFoodGroupsFamiliesPacket 738 | //! \param pFgs [in] a pointer to FOODGROUPS structure 739 | //! \return true if success 740 | //! \return false if fail 741 | //! \sa FLAP_HEADER, TLV_HEADER, FOODGROUPS 742 | bool ICQPacket::ReadFoodGroupsFamiliesPacket(FOODGROUPS *pFgs) 743 | { 744 | _ZeroMemory(pFgs,sizeof(FOODGROUPS)); 745 | 746 | int nSize=GetSNACDataSize(); 747 | char *pOffset=GetSNACDataPointer(); 748 | 749 | if(nSize&&IsSNACPresent(ICQ_SNAC_FOODGROUP_OSERVICE,ICQ_SNAC_OSERVICE_FAMILIES)) 750 | { 751 | while(nSize>0) 752 | { 753 | switch(Get_u16_BE_FromOffset(pOffset)) 754 | { 755 | case ICQ_SNAC_FOODGROUP_OSERVICE: 756 | pFgs->Oservice.Support=true; 757 | break; 758 | case ICQ_SNAC_FOODGROUP_LOCATE: 759 | pFgs->Locate.Support=true; 760 | break; 761 | case ICQ_SNAC_FOODGROUP_BUDDY: 762 | pFgs->Buddy.Support=true; 763 | break; 764 | case ICQ_SNAC_FOODGROUP_ICBM: 765 | pFgs->ICBM.Support=true; 766 | break; 767 | case ICQ_SNAC_FOODGROUP_INVITE: 768 | pFgs->Invite.Support=true; 769 | break; 770 | case ICQ_SNAC_FOODGROUP_POPUP: 771 | pFgs->Popup.Support=true; 772 | break; 773 | case ICQ_SNAC_FOODGROUP_PD: 774 | pFgs->PD.Support=true; 775 | break; 776 | case ICQ_SNAC_FOODGROUP_LOOKUP: 777 | pFgs->Lookup.Support=true; 778 | break; 779 | case ICQ_SNAC_FOODGROUP_STATS: 780 | pFgs->Stats.Support=true; 781 | break; 782 | case ICQ_SNAC_FOODGROUP_TRANS: 783 | pFgs->Trans.Support=true; 784 | break; 785 | case ICQ_SNAC_FOODGROUP_SSI: 786 | pFgs->SSI.Support=true; 787 | break; 788 | case ICQ_SNAC_FOODGROUP_SPEC: 789 | pFgs->Spec.Support=true; 790 | break; 791 | case ICQ_SNAC_FOODGROUP_UNK1: 792 | pFgs->Unk1.Support=true; 793 | break; 794 | case ICQ_SNAC_FOODGROUP_UNK2: 795 | pFgs->Unk2.Support=true; 796 | break; 797 | case ICQ_SNAC_FOODGROUP_UNK3: 798 | pFgs->Unk3.Support=true; 799 | break; 800 | } 801 | 802 | pOffset+=2; 803 | nSize-=2; 804 | } 805 | 806 | return true; 807 | } 808 | else 809 | { 810 | return false; 811 | } 812 | } 813 | //! CreateFoodGroupsVersionsPacket 814 | //! \param nSequence [in] a Sequence 815 | //! \param pFgs [in] a pointer to FOODGROUPS structure 816 | //! \return a size of ICQ Packet 817 | //! \sa FLAP_HEADER, TLV_HEADER, FOODGROUPS 818 | int ICQPacket::CreateFoodGroupsVersionsPacket(int nSequence,FOODGROUPS *pFgs) 819 | { 820 | SetFLAPHeader(ICQ_FLAP_CHANNEL_SNACDATA,nSequence); 821 | Add_SNACHeader(ICQ_SNAC_FOODGROUP_OSERVICE,ICQ_SNAC_OSERVICE_REQUESTVERSIONS,0,nSequence); 822 | 823 | if(pFgs->Unk1.Support) 824 | { 825 | Add_u16_BE(ICQ_SNAC_FOODGROUP_UNK1); 826 | Add_u16_BE(0x0001); // Version 827 | } 828 | if(pFgs->Oservice.Support) 829 | { 830 | Add_u16_BE(ICQ_SNAC_FOODGROUP_OSERVICE); 831 | Add_u16_BE(0x0004); // Version 832 | } 833 | if(pFgs->SSI.Support) 834 | { 835 | Add_u16_BE(ICQ_SNAC_FOODGROUP_SSI); 836 | Add_u16_BE(0x0004); // Version 837 | } 838 | if(pFgs->Locate.Support) 839 | { 840 | Add_u16_BE(ICQ_SNAC_FOODGROUP_LOCATE); 841 | Add_u16_BE(0x0001); // Version 842 | } 843 | if(pFgs->Buddy.Support) 844 | { 845 | Add_u16_BE(ICQ_SNAC_FOODGROUP_BUDDY); 846 | Add_u16_BE(0x0001); // Version 847 | } 848 | if(pFgs->Spec.Support) 849 | { 850 | Add_u16_BE(ICQ_SNAC_FOODGROUP_SPEC); 851 | Add_u16_BE(0x0001); // Version 852 | } 853 | if(pFgs->ICBM.Support) 854 | { 855 | Add_u16_BE(ICQ_SNAC_FOODGROUP_ICBM); 856 | Add_u16_BE(0x0001); // Version 857 | } 858 | if(pFgs->Invite.Support) 859 | { 860 | Add_u16_BE(ICQ_SNAC_FOODGROUP_INVITE); 861 | Add_u16_BE(0x0001); // Version 862 | } 863 | if(pFgs->PD.Support) 864 | { 865 | Add_u16_BE(ICQ_SNAC_FOODGROUP_PD); 866 | Add_u16_BE(0x0001); // Version 867 | } 868 | if(pFgs->Lookup.Support) 869 | { 870 | Add_u16_BE(ICQ_SNAC_FOODGROUP_LOOKUP); 871 | Add_u16_BE(0x0001); // Version 872 | } 873 | if(pFgs->Stats.Support) 874 | { 875 | Add_u16_BE(ICQ_SNAC_FOODGROUP_STATS); 876 | Add_u16_BE(0x0001); // Version 877 | } 878 | 879 | return nPacketSize; 880 | } 881 | 882 | unsigned int ICQPacket::Get_u32_BE_FromOffset(char *pOffset) 883 | { 884 | return ntohl(*((unsigned int *)pOffset)); 885 | } 886 | unsigned short ICQPacket::Get_u16_BE_FromOffset(char *pOffset) 887 | { 888 | return ntohs(*((unsigned short *)pOffset)); 889 | } 890 | unsigned char ICQPacket::Get_u8_FromOffset(char *pOffset) 891 | { 892 | return *pOffset; 893 | } 894 | int ICQPacket::Get_string08(char *pOffset,TCHAR *pszString,int nStringLength) 895 | { 896 | int nSize=Get_u8_FromOffset(pOffset); 897 | 898 | if(nSize0) 929 | { 930 | switch(Get_u16_BE_FromOffset(pOffset)) 931 | { 932 | case ICQ_SNAC_FOODGROUP_OSERVICE: 933 | pFgs->Oservice.Version=Get_u16_BE_FromOffset(pOffset+2); 934 | break; 935 | case ICQ_SNAC_FOODGROUP_LOCATE: 936 | pFgs->Locate.Version=Get_u16_BE_FromOffset(pOffset+2); 937 | break; 938 | case ICQ_SNAC_FOODGROUP_BUDDY: 939 | pFgs->Buddy.Version=Get_u16_BE_FromOffset(pOffset+2); 940 | break; 941 | case ICQ_SNAC_FOODGROUP_ICBM: 942 | pFgs->ICBM.Version=Get_u16_BE_FromOffset(pOffset+2); 943 | break; 944 | case ICQ_SNAC_FOODGROUP_INVITE: 945 | pFgs->Invite.Version=Get_u16_BE_FromOffset(pOffset+2); 946 | break; 947 | case ICQ_SNAC_FOODGROUP_POPUP: 948 | pFgs->Popup.Version=Get_u16_BE_FromOffset(pOffset+2); 949 | break; 950 | case ICQ_SNAC_FOODGROUP_PD: 951 | pFgs->PD.Version=Get_u16_BE_FromOffset(pOffset+2); 952 | break; 953 | case ICQ_SNAC_FOODGROUP_LOOKUP: 954 | pFgs->Lookup.Version=Get_u16_BE_FromOffset(pOffset+2); 955 | break; 956 | case ICQ_SNAC_FOODGROUP_STATS: 957 | pFgs->Stats.Version=Get_u16_BE_FromOffset(pOffset+2); 958 | break; 959 | case ICQ_SNAC_FOODGROUP_TRANS: 960 | pFgs->Trans.Version=Get_u16_BE_FromOffset(pOffset+2); 961 | break; 962 | case ICQ_SNAC_FOODGROUP_SSI: 963 | pFgs->SSI.Version=Get_u16_BE_FromOffset(pOffset+2); 964 | break; 965 | case ICQ_SNAC_FOODGROUP_SPEC: 966 | pFgs->Spec.Version=Get_u16_BE_FromOffset(pOffset+2); 967 | break; 968 | case ICQ_SNAC_FOODGROUP_UNK1: 969 | pFgs->Unk1.Version=Get_u16_BE_FromOffset(pOffset+2); 970 | break; 971 | case ICQ_SNAC_FOODGROUP_UNK2: 972 | pFgs->Unk2.Version=Get_u16_BE_FromOffset(pOffset+2); 973 | break; 974 | case ICQ_SNAC_FOODGROUP_UNK3: 975 | pFgs->Unk3.Version=Get_u16_BE_FromOffset(pOffset+2); 976 | break; 977 | } 978 | 979 | pOffset+=4; 980 | nSize-=4; 981 | } 982 | 983 | return true; 984 | } 985 | else 986 | { 987 | return false; 988 | } 989 | } 990 | //! \param nSequence [in] a Sequence 991 | //! \return a size of ICQ Packet 992 | //! \sa FLAP_HEADER, TLV_HEADER 993 | int ICQPacket::CreateRequestRatesPacket(int nSequence) 994 | { 995 | SetFLAPHeader(ICQ_FLAP_CHANNEL_SNACDATA,nSequence); 996 | Add_SNACHeader(ICQ_SNAC_FOODGROUP_OSERVICE,ICQ_SNAC_OSERVICE_REQUESTRATELIMITS,0,nSequence); 997 | 998 | #ifdef _DEBUG 999 | //################################################## 1000 | _PrintDebugTextNS(TEXT("Create Request Rates Packet")); 1001 | //################################################## 1002 | #endif 1003 | 1004 | return nPacketSize; 1005 | } 1006 | //! \param nSequence [in] a Sequence 1007 | //! \return a size of ICQ Packet 1008 | //! \sa FLAP_HEADER, TLV_HEADER 1009 | int ICQPacket::CreateAcceptRatesPacket(int nSequence) 1010 | { 1011 | SetFLAPHeader(ICQ_FLAP_CHANNEL_SNACDATA,nSequence); 1012 | Add_SNACHeader(ICQ_SNAC_FOODGROUP_OSERVICE,ICQ_SNAC_OSERVICE_ACCEPTRATELIMITS,0,nSequence); 1013 | 1014 | Add_u16_BE(0x0001); 1015 | Add_u16_BE(0x0002); 1016 | Add_u16_BE(0x0003); 1017 | Add_u16_BE(0x0004); 1018 | Add_u16_BE(0x0005); 1019 | 1020 | #ifdef _DEBUG 1021 | //################################################## 1022 | _PrintDebugTextNS(TEXT("Create Accept Rates Packet")); 1023 | //################################################## 1024 | #endif 1025 | return nPacketSize; 1026 | } 1027 | //! \param nSequence [in] a Sequence 1028 | //! \return a size of ICQ Packet 1029 | //! \sa FLAP_HEADER, TLV_HEADER 1030 | int ICQPacket::CreateRequestRosterFirstTimePacket(int nSequence) 1031 | { 1032 | SetFLAPHeader(ICQ_FLAP_CHANNEL_SNACDATA,nSequence); 1033 | Add_SNACHeader(ICQ_SNAC_FOODGROUP_SSI,ICQ_SNAC_SSI_REQUESTROSTERFIRSTTIME,0,nSequence); 1034 | 1035 | #ifdef _DEBUG 1036 | //################################################## 1037 | _PrintDebugTextNS(TEXT("Create Request Roster First Time Packet")); 1038 | //################################################## 1039 | #endif 1040 | 1041 | return nPacketSize; 1042 | } 1043 | //! \param nSequence [in] a Sequence 1044 | //! \return a size of ICQ Packet 1045 | //! \sa FLAP_HEADER, TLV_HEADER 1046 | int ICQPacket::CreateLoadRosterAfterLoginPacket(int nSequence) 1047 | { 1048 | SetFLAPHeader(ICQ_FLAP_CHANNEL_SNACDATA,nSequence); 1049 | Add_SNACHeader(ICQ_SNAC_FOODGROUP_SSI,ICQ_SNAC_SSI_LOADROSTERAFTERLOGIN,0,nSequence); 1050 | 1051 | #ifdef _DEBUG 1052 | //################################################## 1053 | _PrintDebugTextNS(TEXT("Create Load Roster After Login Packet")); 1054 | //################################################## 1055 | #endif 1056 | 1057 | return nPacketSize; 1058 | } 1059 | //! \param nSequence [in] a Sequence 1060 | //! \return a size of ICQ Packet 1061 | //! \sa FLAP_HEADER, TLV_HEADER 1062 | int ICQPacket::CreateSetICBMParametersPacket(int nSequence) 1063 | { 1064 | SetFLAPHeader(ICQ_FLAP_CHANNEL_SNACDATA,nSequence); 1065 | Add_SNACHeader(ICQ_SNAC_FOODGROUP_ICBM,ICQ_SNAC_ICBM_SETPARAMETERS,0,nSequence); 1066 | 1067 | Add_u16_BE(0x0002); 1068 | Add_u32_BE(0x00000003); // ICBM__PARAMETER_FLAGS 1069 | Add_u16_BE(0x1F40); 1070 | Add_u16_BE(0x03E7); 1071 | Add_u16_BE(0x03E7); 1072 | Add_u32_BE(0x00000000); 1073 | 1074 | #ifdef _DEBUG 1075 | //################################################## 1076 | _PrintDebugTextNS(TEXT("Create Set ICBM Parameters Packet")); 1077 | //################################################## 1078 | #endif 1079 | 1080 | return nPacketSize; 1081 | } 1082 | //! \param nSequence [in] a Sequence 1083 | //! \return a size of ICQ Packet 1084 | //! \sa FLAP_HEADER, TLV_HEADER 1085 | int ICQPacket::CreateRequestBuddyParametersPacket(int nSequence) 1086 | { 1087 | SetFLAPHeader(ICQ_FLAP_CHANNEL_SNACDATA,nSequence); 1088 | Add_SNACHeader(ICQ_SNAC_FOODGROUP_BUDDY,ICQ_SNAC_BUDDY_REQUESTPARAMETERS,0,nSequence); 1089 | 1090 | Add_u16_BE(0x0005); 1091 | Add_u16_BE(0x0002); 1092 | Add_u16_BE(0x0003); 1093 | 1094 | #ifdef _DEBUG 1095 | //################################################## 1096 | _PrintDebugTextNS(TEXT("Create Request Buddy Parameters Packet")); 1097 | //################################################## 1098 | #endif 1099 | 1100 | return nPacketSize; 1101 | } 1102 | //! \param nSequence [in] a Sequence 1103 | //! \param nStatus [in] a ICQ status 1104 | //! \return a size of ICQ Packet 1105 | //! \sa FLAP_HEADER, TLV_HEADER 1106 | int ICQPacket::CreateSetStatusPacket(int nSequence,int nStatus) 1107 | { 1108 | SetFLAPHeader(ICQ_FLAP_CHANNEL_SNACDATA,nSequence); 1109 | Add_SNACHeader(ICQ_SNAC_FOODGROUP_OSERVICE,ICQ_SNAC_OSERVICE_SETSTATUS,0,nSequence); 1110 | 1111 | Add_TLV_u32(ICQ_TLV_USERSTATUS,nStatus); 1112 | 1113 | #ifdef _DEBUG 1114 | //################################################## 1115 | _PrintDebugTextNS(TEXT("Create Set Status Packet")); 1116 | //################################################## 1117 | #endif 1118 | 1119 | return nPacketSize; 1120 | } 1121 | //! \param nSequence [in] a Sequence 1122 | //! \return a size of ICQ Packet 1123 | //! \sa FLAP_HEADER, TLV_HEADER 1124 | int ICQPacket::CreateClientReadyPacket(int nSequence) 1125 | { 1126 | SetFLAPHeader(ICQ_FLAP_CHANNEL_SNACDATA,nSequence); 1127 | Add_SNACHeader(ICQ_SNAC_FOODGROUP_OSERVICE,ICQ_SNAC_OSERVICE_CLIENTREADY,0,nSequence); 1128 | 1129 | Add_u16_BE(0x0022); 1130 | Add_u16_BE(0x0001); 1131 | Add_u16_BE(0x0110); 1132 | Add_u16_BE(0x164F); 1133 | 1134 | Add_u16_BE(0x0001); 1135 | Add_u16_BE(0x0004); 1136 | Add_u16_BE(0x0110); 1137 | Add_u16_BE(0x164F); 1138 | 1139 | Add_u16_BE(0x0013); 1140 | Add_u16_BE(0x0004); 1141 | Add_u16_BE(0x0110); 1142 | Add_u16_BE(0x164F); 1143 | 1144 | Add_u16_BE(0x0002); 1145 | Add_u16_BE(0x0001); 1146 | Add_u16_BE(0x0110); 1147 | Add_u16_BE(0x164F); 1148 | 1149 | Add_u16_BE(0x0003); 1150 | Add_u16_BE(0x0001); 1151 | Add_u16_BE(0x0110); 1152 | Add_u16_BE(0x164F); 1153 | 1154 | Add_u16_BE(0x0015); 1155 | Add_u16_BE(0x0001); 1156 | Add_u16_BE(0x0110); 1157 | Add_u16_BE(0x164F); 1158 | 1159 | Add_u16_BE(0x0004); 1160 | Add_u16_BE(0x0001); 1161 | Add_u16_BE(0x0110); 1162 | Add_u16_BE(0x164F); 1163 | 1164 | Add_u16_BE(0x0006); 1165 | Add_u16_BE(0x0001); 1166 | Add_u16_BE(0x0110); 1167 | Add_u16_BE(0x164F); 1168 | 1169 | Add_u16_BE(0x0009); 1170 | Add_u16_BE(0x0001); 1171 | Add_u16_BE(0x0110); 1172 | Add_u16_BE(0x164F); 1173 | 1174 | Add_u16_BE(0x000A); 1175 | Add_u16_BE(0x0001); 1176 | Add_u16_BE(0x0110); 1177 | Add_u16_BE(0x164F); 1178 | 1179 | Add_u16_BE(0x000B); 1180 | Add_u16_BE(0x0001); 1181 | Add_u16_BE(0x0110); 1182 | Add_u16_BE(0x164F); 1183 | 1184 | #ifdef _DEBUG 1185 | //################################################## 1186 | _PrintDebugTextNS(TEXT("Client Ready Packet")); 1187 | //################################################## 1188 | #endif 1189 | 1190 | return nPacketSize; 1191 | } 1192 | //! IsErrorChannel 1193 | //! \return true if error channel 1194 | //! \return false if not 1195 | //! \sa FLAP_HEADER 1196 | bool ICQPacket::IsErrorChannel() 1197 | { 1198 | if(GetFLAPChannel()==ICQ_FLAP_CHANNEL_ERROR) 1199 | { 1200 | #ifdef _DEBUG 1201 | //################################################## 1202 | _PrintDebugTextNS(TEXT("It's Error Channel")); 1203 | //################################################## 1204 | #endif 1205 | return true; 1206 | } 1207 | else 1208 | { 1209 | #ifdef _DEBUG 1210 | //################################################## 1211 | _PrintDebugTextNS(TEXT("It's NOT Error Channel")); 1212 | //################################################## 1213 | #endif 1214 | return false; 1215 | } 1216 | } 1217 | //! IsSignOffChannel 1218 | //! \return true if sign off channel 1219 | //! \return false if not 1220 | //! \sa FLAP_HEADER 1221 | bool ICQPacket::IsSignOffChannel() 1222 | { 1223 | if(GetFLAPChannel()==ICQ_FLAP_CHANNEL_SIGNOFF) 1224 | { 1225 | #ifdef _DEBUG 1226 | //################################################## 1227 | _PrintDebugTextNS(TEXT("It's Sigh Off Channel")); 1228 | //################################################## 1229 | #endif 1230 | return true; 1231 | } 1232 | else 1233 | { 1234 | #ifdef _DEBUG 1235 | //################################################## 1236 | _PrintDebugTextNS(TEXT("It's NOT Sigh Off Channel")); 1237 | //################################################## 1238 | #endif 1239 | return false; 1240 | } 1241 | } 1242 | //! CreateSendTextUnicodePacket 1243 | //! \param nSequence [in] a Sequence 1244 | //! \param pSts [in] a pointer to SENDTEXTSTRUCT structure 1245 | //! \return a size of ICQ Packet 1246 | //! \sa FLAP_HEADER, TLV_HEADER, SENDTEXTSTRUCT 1247 | int ICQPacket::CreateSendTextUnicodePacket(int nSequence,SENDTEXTSTRUCT *pSts) 1248 | { 1249 | char *pMemory; 1250 | int nMessageSize=pSts->nTextLength*sizeof(WCHAR); 1251 | 1252 | pMemory=(char *)_Alloc(nMessageSize); 1253 | _StringToUnicode((WCHAR *)pMemory,pSts->nTextLength,pSts->pszText); 1254 | _UnicodeToNet((WCHAR *)pMemory,pSts->nTextLength,(WCHAR *)pMemory); 1255 | 1256 | SetFLAPHeader(ICQ_FLAP_CHANNEL_SNACDATA,nSequence); 1257 | Add_SNACHeader(ICQ_SNAC_FOODGROUP_ICBM,ICQ_SNAC_ICBM_SENDMESSAGE,0,nSequence); 1258 | 1259 | Add_u32_BE(pSts->cookie.nCookies1); 1260 | Add_u32_BE(pSts->cookie.nCookies2); 1261 | Add_u16_BE(0x0001); // Channel 1262 | Add_string08(pSts->pszUIN); 1263 | Add_u16_BE(0x0002); 1264 | Add_u16_BE(0x000E+nMessageSize); 1265 | Add_u8(0x05); 1266 | Add_u8(0x01); 1267 | Add_u16_BE(0x0002); 1268 | Add_u16_BE(0x0106); 1269 | Add_u8(0x01); 1270 | Add_u8(0x01); 1271 | Add_u16_BE(0x0004+nMessageSize); 1272 | Add_u16_BE(0x0002); 1273 | Add_u16_BE(0x0000); 1274 | Add_blob(pMemory,nMessageSize); 1275 | Add_TLV_blob(ICQ_TLV_USERSTATUS,0,0); 1276 | 1277 | _Free(pMemory); 1278 | 1279 | #ifdef _DEBUG 1280 | //################################################## 1281 | _PrintDebugTextNS(TEXT("Send Text Unicode")); 1282 | _PrintDebugTextNS(pSts->pszUIN); 1283 | _PrintDebugTextNS(pSts->pszText); 1284 | //################################################## 1285 | #endif 1286 | 1287 | return nPacketSize; 1288 | } 1289 | bool ICQPacket::ReadMessageAckPacket(MESSAGEACKSTRUCT *pMas) 1290 | { 1291 | int nSize=GetSNACDataSize(); 1292 | char *pOffset=GetSNACDataPointer(); 1293 | 1294 | if(nSize&&IsSNACPresent(ICQ_SNAC_FOODGROUP_ICBM,ICQ_SNAC_ICBM_MESSAGEACK)) 1295 | { 1296 | pMas->cookie.nCookies1=Get_u32_BE_FromOffset(pOffset); 1297 | pOffset+=4; 1298 | pMas->cookie.nCookies2=Get_u32_BE_FromOffset(pOffset); 1299 | pOffset+=4; 1300 | pMas->sChannel=Get_u16_BE_FromOffset(pOffset); 1301 | pOffset+=2; 1302 | Get_string08(pOffset,pMas->szUIN,sizeof(pMas->szUIN)); 1303 | 1304 | return true; 1305 | } 1306 | else 1307 | { 1308 | return false; 1309 | } 1310 | } 1311 | bool ICQPacket::ReadRecvMessagePacket(RECVMESSAGESTRUCT *pRms) 1312 | { 1313 | short sTLVType,sTLVLength,sEncode; 1314 | int nFragmentLength=0; 1315 | char *pData=0; 1316 | char Buffer[2048]; 1317 | int nSize=GetSNACDataSize(); 1318 | char *pOffset=GetSNACDataPointer(); 1319 | 1320 | if(nSize&&IsSNACPresent(ICQ_SNAC_FOODGROUP_ICBM,ICQ_SNAC_ICBM_RECVMESSAGE)) 1321 | { 1322 | pRms->cookie.nCookies1=Get_u32_BE_FromOffset(pOffset); 1323 | pOffset+=4; 1324 | pRms->cookie.nCookies2=Get_u32_BE_FromOffset(pOffset); 1325 | pOffset+=4; 1326 | pRms->sChannel=Get_u16_BE_FromOffset(pOffset); 1327 | pOffset+=2; 1328 | pOffset+=ReadNickInfoFromOffset(pOffset,&(pRms->NickInfo)); 1329 | 1330 | nSize-=pOffset-GetSNACDataPointer(); 1331 | 1332 | while(nSize>0) 1333 | { 1334 | sTLVType=GetTLVTypeFromOffset(pOffset); 1335 | sTLVLength=GetTLVLehgthFromOffset(pOffset); 1336 | pOffset+=sizeof(TLV_HEADER); 1337 | nSize-=sizeof(TLV_HEADER); 1338 | 1339 | if(sTLVType==0x0002) 1340 | { 1341 | pData=pOffset; 1342 | nFragmentLength=GetFragmentLehgthFromOffset(pData); 1343 | 1344 | pData+=sizeof(FRAGMENT); 1345 | pData+=nFragmentLength; 1346 | 1347 | nFragmentLength=GetFragmentLehgthFromOffset(pData); 1348 | 1349 | pData+=sizeof(FRAGMENT); 1350 | sEncode=Get_u16_BE_FromOffset(pData); 1351 | pData+=4; 1352 | 1353 | switch(sEncode) 1354 | { 1355 | case 2: 1356 | _NetToUnicode((WCHAR *)Buffer,(nFragmentLength-4)/sizeof(WCHAR)+1,(WCHAR *)pData); 1357 | _UnicodeToString(pRms->szText,(nFragmentLength-4)/sizeof(WCHAR)+1,(WCHAR *)Buffer); 1358 | break; 1359 | default: 1360 | _CharsToString(pRms->szText,(nFragmentLength-4)+1,pData); 1361 | } 1362 | 1363 | } 1364 | 1365 | pOffset+=sTLVLength; 1366 | nSize-=sTLVLength; 1367 | } 1368 | 1369 | return true; 1370 | } 1371 | else 1372 | { 1373 | return false; 1374 | } 1375 | } 1376 | int ICQPacket::ReadNickInfoFromOffset(char *pOffset,NICKINFOSTRUCT *pNis) 1377 | { 1378 | int nTLVs=0; 1379 | short sTLVType,sTLVLength; 1380 | char *pData=pOffset; 1381 | 1382 | pData+=Get_string08(pData,pNis->szUIN,sizeof(pNis->szUIN)); 1383 | pData++; 1384 | pNis->sWarningLevel=Get_u16_BE_FromOffset(pData); 1385 | pData+=2; 1386 | nTLVs=Get_u16_BE_FromOffset(pData); 1387 | pData+=2; 1388 | 1389 | for(int i=0;i