summaryrefslogtreecommitdiff
path: root/protocols/IcqOscarJ/fam_04message.cpp
diff options
context:
space:
mode:
authorVadim Dashevskiy <watcherhd@gmail.com>2012-10-12 14:53:57 +0000
committerVadim Dashevskiy <watcherhd@gmail.com>2012-10-12 14:53:57 +0000
commit3b55a62fdcb1f8222de3c2c8fbed530792c419a0 (patch)
tree5b2f628e847f61bb3e16f95ecaed6e187963362f /protocols/IcqOscarJ/fam_04message.cpp
parent1f9c986d82657f965462d289bf94aa012cf026fc (diff)
GTalkExt, ICQ, IRC, Jabber: folders restructurization
git-svn-id: http://svn.miranda-ng.org/main/trunk@1890 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'protocols/IcqOscarJ/fam_04message.cpp')
-rw-r--r--protocols/IcqOscarJ/fam_04message.cpp3043
1 files changed, 0 insertions, 3043 deletions
diff --git a/protocols/IcqOscarJ/fam_04message.cpp b/protocols/IcqOscarJ/fam_04message.cpp
deleted file mode 100644
index 7d1bc6a829..0000000000
--- a/protocols/IcqOscarJ/fam_04message.cpp
+++ /dev/null
@@ -1,3043 +0,0 @@
-// ---------------------------------------------------------------------------80
-// ICQ plugin for Miranda Instant Messenger
-// ________________________________________
-//
-// Copyright © 2000-2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
-// Copyright © 2001-2002 Jon Keating, Richard Hughes
-// Copyright © 2002-2004 Martin Öberg, Sam Kothari, Robert Rainwater
-// Copyright © 2004-2010 Joe Kucera
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-//
-// -----------------------------------------------------------------------------
-// DESCRIPTION:
-//
-// Handles packets from Family 4 ICBM Messages
-//
-// -----------------------------------------------------------------------------
-#include "icqoscar.h"
-
-
-void CIcqProto::handleMsgFam(BYTE *pBuffer, WORD wBufferLength, snac_header *pSnacHeader)
-{
- switch (pSnacHeader->wSubtype) {
-
- case ICQ_MSG_SRV_ERROR: // SNAC(4, 0x01)
- handleRecvServMsgError(pBuffer, wBufferLength, pSnacHeader->wFlags, pSnacHeader->dwRef);
- break;
-
- case ICQ_MSG_SRV_REPLYICBM: // SNAC(4, 0x05) SRV_REPLYICBM
- handleReplyICBM(pBuffer, wBufferLength, pSnacHeader->wFlags, pSnacHeader->dwRef);
- break;
-
- case ICQ_MSG_SRV_RECV: // SNAC(4, 0x07)
- handleRecvServMsg(pBuffer, wBufferLength, pSnacHeader->wFlags, pSnacHeader->dwRef);
- break;
-
- case ICQ_MSG_SRV_MISSED_MESSAGE: // SNAC(4, 0x0A)
- handleMissedMsg(pBuffer, wBufferLength, pSnacHeader->wFlags, pSnacHeader->dwRef);
- break;
-
- case ICQ_MSG_RESPONSE: // SNAC(4, 0x0B)
- handleRecvMsgResponse(pBuffer, wBufferLength, pSnacHeader->wFlags, pSnacHeader->dwRef);
- break;
-
- case ICQ_MSG_SRV_ACK: // SNAC(4, 0x0C) Server acknowledgements
- handleServerAck(pBuffer, wBufferLength, pSnacHeader->wFlags, pSnacHeader->dwRef);
- break;
-
- case ICQ_MSG_MTN: // SNAC(4, 0x14) Typing notifications
- handleTypingNotification(pBuffer, wBufferLength, pSnacHeader->wFlags, pSnacHeader->dwRef);
- break;
-
- case ICQ_MSG_SRV_OFFLINE_REPLY: // SNAC(4, 0x17) Offline Messages response
- handleOffineMessagesReply(pBuffer, wBufferLength, pSnacHeader->wFlags, pSnacHeader->dwRef);
- break;
-
- default:
- NetLog_Server("Warning: Ignoring SNAC(x%02x,x%02x) - Unknown SNAC (Flags: %u, Ref: %u)", ICQ_MSG_FAMILY, pSnacHeader->wSubtype, pSnacHeader->wFlags, pSnacHeader->dwRef);
- break;
- }
-}
-
-
-static void setMsgChannelParams(CIcqProto *ppro, WORD wChan, DWORD dwFlags)
-{
- icq_packet packet;
-
- // Set message parameters for channel wChan (CLI_SET_ICBM_PARAMS)
- serverPacketInit(&packet, 26);
- packFNACHeader(&packet, ICQ_MSG_FAMILY, ICQ_MSG_CLI_SETPARAMS);
- packWord(&packet, wChan); // Channel
- packDWord(&packet, dwFlags); // Flags
- packWord(&packet, MAX_MESSAGESNACSIZE); // Max message snac size
- packWord(&packet, 0x03E7); // Max sender warning level
- packWord(&packet, 0x03E7); // Max receiver warning level
- packWord(&packet, CLIENTRATELIMIT); // Minimum message interval in seconds
- packWord(&packet, 0x0000); // Unknown
- ppro->sendServPacket(&packet);
-}
-
-
-void CIcqProto::handleReplyICBM(BYTE *buf, WORD wLen, WORD wFlags, DWORD dwRef)
-{ // we don't care about the stuff, just change the params
- DWORD dwFlags = 0x00000303;
-
-#ifdef DBG_CAPHTML
- dwFlags |= 0x00000400;
-#endif
-#ifdef DBG_CAPMTN
- dwFlags |= 0x00000008;
-#endif
- // Set message parameters for all channels (imitate ICQ 6)
- setMsgChannelParams(this, 0x0000, dwFlags);
-}
-
-
-void CIcqProto::handleRecvServMsg(BYTE *buf, WORD wLen, WORD wFlags, DWORD dwRef)
-{
- DWORD dwUin;
- DWORD dwMsgID1;
- DWORD dwMsgID2;
- WORD wTLVCount;
- WORD wMessageFormat;
- uid_str szUID;
-
- if (wLen < 11)
- { // just do some basic packet checking
- NetLog_Server("Error: Malformed message thru server");
- return;
- }
-
- // These two values are some kind of reference, we need to save
- // them to send file request responses for example
- unpackLEDWord(&buf, &dwMsgID1); // TODO: msg cookies should be main
- wLen -= 4;
- unpackLEDWord(&buf, &dwMsgID2);
- wLen -= 4;
-
- // The message type used:
- unpackWord(&buf, &wMessageFormat); // 0x0001: Simple message format
- wLen -= 2; // 0x0002: Advanced message format
- // 0x0004: 'New' message format
- // Sender UIN
- if (!unpackUID(&buf, &wLen, &dwUin, &szUID)) return;
-
- if (dwUin && IsOnSpammerList(dwUin))
- {
- NetLog_Server("Ignored Message from known Spammer");
- return;
- }
-
- if (wLen < 4)
- { // just do some basic packet checking
- NetLog_Server("Error: Malformed message thru server");
- return;
- }
-
- // Warning level?
- buf += 2;
- wLen -= 2;
-
- // Number of following TLVs, until msg-format dependant TLVs
- unpackWord(&buf, &wTLVCount);
- wLen -= 2;
- if (wTLVCount > 0)
- {
- // Save current buffer pointer so we can calculate
- // how much data we have left after the chain read.
- BYTE *pBufStart = buf;
- oscar_tlv_chain *chain = readIntoTLVChain(&buf, wLen, wTLVCount);
-
- // This chain contains info that is filled in by the server.
- // TLV(1): unknown
- // TLV(2): date: on since
- // TLV(3): date: on since
- // TLV(4): unknown, usually 0000. Not in file-req or auto-msg-req
- // TLV(6): sender's status
- // TLV(F): a time in seconds, unknown
-
- disposeChain(&chain);
-
- // Update wLen
- wLen -= buf - pBufStart;
- }
-
-
- // This is where the format specific data begins
-
- switch (wMessageFormat) {
-
- case 1: // Simple message format
- handleRecvServMsgType1(buf, wLen, dwUin, szUID, dwMsgID1, dwMsgID2, dwRef);
- break;
-
- case 2: // Encapsulated messages
- handleRecvServMsgType2(buf, wLen, dwUin, szUID, dwMsgID1, dwMsgID2, dwRef);
- break;
-
- case 4: // Typed messages
- handleRecvServMsgType4(buf, wLen, dwUin, szUID, dwMsgID1, dwMsgID2, dwRef);
- break;
-
- default:
- NetLog_Server("Unknown format message thru server - Ref %u, Type: %u, UID: %s", dwRef, wMessageFormat, strUID(dwUin, szUID));
- break;
-
- }
-}
-
-
-char* CIcqProto::convertMsgToUserSpecificUtf(HANDLE hContact, const char *szMsg)
-{
- WORD wCP = getSettingWord(hContact, "CodePage", m_wAnsiCodepage);
- char *usMsg = NULL;
-
- if (wCP != CP_ACP)
- usMsg = ansi_to_utf8_codepage(szMsg, wCP);
-
- return usMsg;
-}
-
-
-void CIcqProto::handleRecvServMsgType1(BYTE *buf, WORD wLen, DWORD dwUin, char *szUID, DWORD dwMsgID1, DWORD dwMsgID2, DWORD dwRef)
-{
- WORD wTLVType;
- WORD wTLVLen;
- BYTE* pMsgTLV;
-
- if (wLen < 4)
- { // just perform basic structure check
- NetLog_Server("Message (format %u) - Ignoring empty message", 1);
- return;
- }
-
- // Unpack the first TLV(2)
- unpackTypedTLV(buf, wLen, 2, &wTLVType, &wTLVLen, &pMsgTLV);
- NetLog_Server("Message (format %u) - UID: %s", 1, strUID(dwUin, szUID));
-
- // It must be TLV(2)
- if (wTLVType == 2)
- {
- BYTE *pDataBuf = pMsgTLV;
- oscar_tlv_chain *pChain = readIntoTLVChain(&pDataBuf, wTLVLen, 0);
-
- // TLV(2) contains yet another TLV chain with the following TLVs:
- // TLV(1281): Capability
- // TLV(257): This TLV contains the actual message (can be fragmented)
-
- if (pChain)
- {
- oscar_tlv* pMessageTLV;
- oscar_tlv* pCapabilityTLV;
- WORD wMsgPart = 1;
-
- // Find the capability TLV
- pCapabilityTLV = pChain->getTLV(0x0501, 1);
- if (pCapabilityTLV && (pCapabilityTLV->wLen > 0))
- {
- WORD wDataLen;
- BYTE *pDataBuf;
-
- wDataLen = pCapabilityTLV->wLen;
- pDataBuf = pCapabilityTLV->pData;
-
- if (wDataLen > 0)
- NetLog_Server("Message (format 1) - Message has %d caps.", wDataLen);
- }
- else
- NetLog_Server("Message (format 1) - No message cap.");
-
- { // Parse the message parts, usually only one 0x0101 TLV containing the message,
- // but in some cases there can be more 0x0101 TLVs containing message parts in
- // different encodings (just like the new format of Offline Messages).
- DWORD dwRecvTime;
- char* szMsg = NULL;
- CCSDATA ccs;
- PROTORECVEVENT pre = {0};
- int bAdded;
-
- HANDLE hContact = HContactFromUID(dwUin, szUID, &bAdded);
-
- while (pMessageTLV = pChain->getTLV(0x0101, wMsgPart))
- { // Loop thru all message parts
- if (pMessageTLV->wLen > 4)
- {
- WORD wMsgLen;
- BYTE *pMsgBuf;
- WORD wEncoding;
- WORD wCodePage;
- char *szMsgPart = NULL;
- int bMsgPartUnicode = FALSE;
-
- // The message begins with a encoding specification
- // The first WORD is believed to have the following meaning:
- // 0x00: US-ASCII
- // 0x02: Unicode UCS-2 Big Endian encoding
- // 0x03: local 8bit encoding
- pMsgBuf = pMessageTLV->pData;
- unpackWord(&pMsgBuf, &wEncoding);
- unpackWord(&pMsgBuf, &wCodePage);
-
- wMsgLen = pMessageTLV->wLen - 4;
- NetLog_Server("Message (format 1) - Part %d: Encoding is 0x%X, page is 0x%X", wMsgPart, wEncoding, wCodePage);
-
- switch (wEncoding) {
-
- case 2: // UCS-2
- {
- WCHAR* usMsgPart = (WCHAR*)SAFE_MALLOC(wMsgLen + 2);
-
- unpackWideString(&pMsgBuf, usMsgPart, wMsgLen);
- usMsgPart[wMsgLen/sizeof(WCHAR)] = 0;
-
- szMsgPart = make_utf8_string(usMsgPart);
- if (!IsUSASCII(szMsgPart, strlennull(szMsgPart)))
- bMsgPartUnicode = TRUE;
- SAFE_FREE(&usMsgPart);
-
- break;
- }
-
- case 0: // us-ascii
- case 3: // ANSI
- default:
- {
- // Copy the message text into a new proper string.
- szMsgPart = (char*)SAFE_MALLOC(wMsgLen + 1);
- memcpy(szMsgPart, pMsgBuf, wMsgLen);
- szMsgPart[wMsgLen] = '\0';
-
- break;
- }
- }
- // Check if the new part is compatible with the message
- if (!pre.flags && bMsgPartUnicode)
- { // make the resulting message utf-8 encoded - need to append utf-8 encoded part
- if (szMsg)
- { // not necessary to convert - appending first part, only set flags
- char *szUtfMsg = ansi_to_utf8_codepage(szMsg, getSettingWord(hContact, "CodePage", m_wAnsiCodepage));
-
- SAFE_FREE(&szMsg);
- szMsg = szUtfMsg;
- }
- pre.flags = PREF_UTF;
- }
- if (!bMsgPartUnicode && pre.flags == PREF_UTF)
- { // convert message part to utf-8 and append
- char *szUtfPart = ansi_to_utf8_codepage((char*)szMsgPart, getSettingWord(hContact, "CodePage", m_wAnsiCodepage));
-
- SAFE_FREE(&szMsgPart);
- szMsgPart = szUtfPart;
- }
- // Append the new message part
- szMsg = (char*)SAFE_REALLOC(szMsg, strlennull(szMsg) + strlennull(szMsgPart) + 1);
-
- strcat(szMsg, szMsgPart);
- SAFE_FREE(&szMsgPart);
- }
- wMsgPart++;
- }
- if (strlennull(szMsg))
- {
- if (_strnicmp(szMsg, "<html>", 6) == 0)
- { // strip HTML formating from AIM message
- szMsg = EliminateHtml(szMsg, strlennull(szMsg));
- }
-
- if (!pre.flags && !IsUSASCII(szMsg, strlennull(szMsg)))
- { // message is Ansi and contains national characters, create Unicode part by codepage
- char *usMsg = convertMsgToUserSpecificUtf(hContact, szMsg);
- if (usMsg)
- {
- SAFE_FREE(&szMsg);
- szMsg = usMsg;
- pre.flags = PREF_UTF;
- }
- }
-
- dwRecvTime = (DWORD)time(NULL);
-
- { // Check if the message was received as offline
- cookie_offline_messages *cookie;
-
- if (!(dwRef & 0x80000000) && FindCookie(dwRef, NULL, (void**)&cookie))
- {
- WORD wTimeTLVType, wTimeTLVLen;
- BYTE *pTimeTLV;
-
- cookie->nMessages++;
-
- unpackTypedTLV(buf, wLen, 0x16, &wTimeTLVType, &wTimeTLVLen, &pTimeTLV);
- if (pTimeTLV && wTimeTLVType == 0x16 && wTimeTLVLen == 4)
- { // found Offline timestamp
- BYTE *pBuf = pTimeTLV;
-
- unpackDWord(&pBuf, &dwRecvTime);
- NetLog_Server("Message (format %u) - Offline timestamp is %s", 1, time2text(dwRecvTime));
- }
- SAFE_FREE((void**)&pTimeTLV);
- }
- }
- // Create and send the message event
- ccs.szProtoService = PSR_MESSAGE;
- ccs.hContact = hContact;
- ccs.wParam = 0;
- ccs.lParam = (LPARAM)&pre;
- pre.timestamp = dwRecvTime;
- pre.szMessage = (char *)szMsg;
- CallService(MS_PROTO_CHAINRECV, 0, (LPARAM)&ccs);
-
- NetLog_Server("Message (format 1) received");
-
- // Save tick value
- setSettingDword(ccs.hContact, "TickTS", time(NULL) - (dwMsgID1/1000));
- }
- else
- NetLog_Server("Message (format %u) - Ignoring empty message", 1);
-
- SAFE_FREE(&szMsg);
- }
-
- // Free the chain memory
- disposeChain(&pChain);
- }
- else
- NetLog_Server("Failed to read TLV chain in message (format 1)");
- }
- else
- NetLog_Server("Unsupported TLV (%u) in message (format %u)", wTLVType, 1);
-
- SAFE_FREE((void**)&pMsgTLV);
-}
-
-
-void CIcqProto::handleRecvServMsgType2(BYTE *buf, WORD wLen, DWORD dwUin, char *szUID, DWORD dwMsgID1, DWORD dwMsgID2, DWORD dwRef)
-{
- WORD wTLVType;
- WORD wTLVLen;
- BYTE *pDataBuf = NULL;
- BYTE *pBuf;
-
- if (wLen < 4)
- {
- NetLog_Server("Message (format %u) - Ignoring empty message", 2);
- return;
- }
-
- // Unpack the first TLV(5)
- unpackTypedTLV(buf, wLen, 5, &wTLVType, &wTLVLen, &pDataBuf);
- NetLog_Server("Message (format %u) - UID: %s", 2, strUID(dwUin, szUID));
- pBuf = pDataBuf;
-
- // It must be TLV(5)
- if (wTLVType == 5)
- {
- WORD wCommand;
- oscar_tlv_chain* chain;
- oscar_tlv* tlv;
- DWORD q1,q2,q3,q4;
-
- if (wTLVLen < 26)
- { // just check if all basic data is there
- NetLog_Server("Message (format %u) - Ignoring empty message", 2);
- SAFE_FREE((void**)&pBuf);
- return;
- }
-
- unpackWord(&pDataBuf, &wCommand);
- wTLVLen -= 2; // Command 0x0000 - Normal message/file send request
-#ifdef _DEBUG // 0x0001 - Abort request
- NetLog_Server("Command is %u", wCommand); // 0x0002 - Acknowledge request
-#endif
-
- // Some stuff we don't use
- pDataBuf += 8; // dwID1 and dwID2 again
- wTLVLen -= 8;
- unpackDWord(&pDataBuf, &q1);
- unpackDWord(&pDataBuf, &q2);
- unpackDWord(&pDataBuf, &q3);
- unpackDWord(&pDataBuf, &q4); // Message Capability
- wTLVLen -= 16;
-
- if (CompareGUIDs(q1,q2,q3,q4, MCAP_SRV_RELAY_FMT))
- { // we surely have at least 4 bytes for TLV chain
- HANDLE hContact = HContactFromUID(dwUin, szUID, NULL);
-
- if (wCommand == 1)
- {
- NetLog_Server("Cannot handle abort messages yet... :(");
- SAFE_FREE((void**)&pBuf);
- return;
- }
-
- if (wTLVLen < 4)
- { // just check if at least one tlv is there
- NetLog_Server("Message (format %u) - Ignoring empty message", 2);
- SAFE_FREE((void**)&pBuf);
- return;
- }
-
- // This TLV chain may contain the following TLVs:
- // TLV(A): Acktype 0x0000 - normal message
- // 0x0001 - file request / abort request
- // 0x0002 - file ack
- // TLV(F): Unknown
- // TLV(3): External IP
- // TLV(5): DC port (not to use for filetransfers)
- // TLV(0x2711): The next message level
-
- chain = readIntoTLVChain(&pDataBuf, wTLVLen, 0);
- if (!chain)
- { // sanity check
- NetLog_Server("Message (format %u) - Invalid data", 2);
- SAFE_FREE((void**)&pBuf);
- return;
- }
-
- WORD wAckType = chain->getWord(0x0A, 1);
-
- // Update the saved DC info (if contact already exists)
- if (hContact != INVALID_HANDLE_VALUE)
- {
- DWORD dwIP, dwExternalIP;
- WORD wPort;
-
- if (dwExternalIP = chain->getDWord(0x03, 1))
- setSettingDword(hContact, "RealIP", dwExternalIP);
- if (dwIP = chain->getDWord(0x04, 1))
- setSettingDword(hContact, "IP", dwIP);
- if (wPort = chain->getWord(0x05, 1))
- setSettingWord(hContact, "UserPort", wPort);
-
- // Save tick value
- BYTE bClientID = getSettingByte(hContact, "ClientID", 0);
- if (bClientID == CLID_GENERIC || bClientID == CLID_ICQ6)
- setSettingDword(hContact, "TickTS", time(NULL) - (dwMsgID1/1000));
- else
- setSettingDword(hContact, "TickTS", 0);
- }
-
- // Parse the next message level
- if (tlv = chain->getTLV(0x2711, 1))
- {
- parseServRelayData(tlv->pData, tlv->wLen, hContact, dwUin, szUID, dwMsgID1, dwMsgID2, wAckType);
- }
- else
- {
- NetLog_Server("Warning, no 0x2711 TLV in message (format 2)");
- }
- // Clean up
- disposeChain(&chain);
- }
- else if (CompareGUIDs(q1,q2,q3,q4, MCAP_REVERSE_DC_REQ))
- { // Handle reverse DC request
- if (wCommand == 1)
- {
- NetLog_Server("Cannot handle abort messages yet... :(");
- SAFE_FREE((void**)&pBuf);
- return;
- }
- if (wTLVLen < 4)
- { // just check if at least one tlv is there
- NetLog_Server("Message (format %u) - Ignoring empty message", 2);
- SAFE_FREE((void**)&pBuf);
- return;
- }
- if (!dwUin)
- { // AIM cannot send this, just sanity
- NetLog_Server("Error: Malformed UIN in packet");
- SAFE_FREE((void**)&pBuf);
- return;
- }
- chain = readIntoTLVChain(&pDataBuf, wTLVLen, 0);
- if (!chain)
- { // Malformed packet
- NetLog_Server("Error: Malformed data in packet");
- SAFE_FREE((void**)&pBuf);
- return;
- }
-
- WORD wAckType = chain->getWord(0x0A, 1);
- // Parse the next message level
- if (tlv = chain->getTLV(0x2711, 1))
- {
- if (tlv->wLen == 0x1B)
- {
- BYTE *buf = tlv->pData;
- DWORD dwUin;
-
- unpackLEDWord(&buf, &dwUin);
-
- HANDLE hContact = HContactFromUIN(dwUin, NULL);
- if (hContact == INVALID_HANDLE_VALUE)
- {
- NetLog_Server("Error: %s from unknown contact %u", "Reverse Connect Request", dwUin);
- }
- else
- {
- DWORD dwIp, dwPort;
- WORD wVersion;
- BYTE bMode;
-
- unpackDWord(&buf, &dwIp);
- unpackLEDWord(&buf, &dwPort);
- unpackByte(&buf, &bMode);
- buf += 4; // unknown
- if (dwPort)
- buf += 4; // port, again?
- else
- unpackLEDWord(&buf, &dwPort);
- unpackLEWord(&buf, &wVersion);
-
- setSettingDword(hContact, "IP", dwIp);
- setSettingWord(hContact, "UserPort", (WORD)dwPort);
- setSettingByte(hContact, "DCType", bMode);
- setSettingWord(hContact, "Version", wVersion);
- if (wVersion > 6)
- {
- cookie_reverse_connect *pCookie = (cookie_reverse_connect*)SAFE_MALLOC(sizeof(cookie_reverse_connect));
-
- unpackLEDWord(&buf, (DWORD*)&pCookie->ft);
- pCookie->dwMsgID1 = dwMsgID1;
- pCookie->dwMsgID2 = dwMsgID2;
-
- OpenDirectConnection(hContact, DIRECTCONN_REVERSE, (void*)pCookie);
- }
- else
- NetLog_Server("Warning: Unsupported direct protocol version in %s", "Reverse Connect Request");
- }
- }
- else
- {
- NetLog_Server("Malformed %s", "Reverse Connect Request");
- }
- }
- else
- {
- NetLog_Server("Warning, no 0x2711 TLV in message (format 2)");
- }
- // Clean up
- disposeChain(&chain);
- }
- else if (CompareGUIDs(q1,q2,q3,q4, MCAP_FILE_TRANSFER))
- { // this is an OFT packet
- handleRecvServMsgOFT(pDataBuf, wTLVLen, dwUin, szUID, dwMsgID1, dwMsgID2, wCommand);
- }
- else if (CompareGUIDs(q1,q2,q3,q4, MCAP_CONTACTS))
- { // this is Contacts Transfer
- handleRecvServMsgContacts(pDataBuf, wTLVLen, dwUin, szUID, dwMsgID1, dwMsgID2, wCommand);
- }
- else // here should be detection of extra data streams (Xtraz)
- {
- NetLog_Server("Unknown Message Format Capability");
- }
- }
- else
- {
- NetLog_Server("Unsupported TLV (%u) in message (format %u)", wTLVType, 2);
- }
-
- SAFE_FREE((void**)&pBuf);
-}
-
-
-void CIcqProto::parseServRelayData(BYTE *pDataBuf, WORD wLen, HANDLE hContact, DWORD dwUin, char *szUID, DWORD dwMsgID1, DWORD dwMsgID2, WORD wAckType)
-{
- WORD wId;
-
- if (wLen < 2)
- {
- NetLog_Server("Message (format %u) - Ignoring empty message", 2);
- return;
- }
-
- unpackLEWord(&pDataBuf, &wId); // Incorrect identification, but working
- wLen -= 2;
-
- // Only 0x1B are real messages
- if (wId == 0x001B)
- {
- WORD wVersion;
- WORD wCookie;
- DWORD dwGuid1,dwGuid2,dwGuid3,dwGuid4;
-
- if (wLen < 31)
- { // just check if we have data to work with
- NetLog_Server("Message (format %u) - Ignoring empty message", 2);
- return;
- }
-
- unpackLEWord(&pDataBuf, &wVersion);
- wLen -= 2;
-
- if (hContact != INVALID_HANDLE_VALUE)
- setSettingWord(hContact, "Version", wVersion);
-
- unpackDWord(&pDataBuf, &dwGuid1); // plugin type GUID
- unpackDWord(&pDataBuf, &dwGuid2);
- unpackDWord(&pDataBuf, &dwGuid3);
- unpackDWord(&pDataBuf, &dwGuid4);
- wLen -= 16;
-
- // Skip lots of unused stuff
- pDataBuf += 9;
- wLen -= 9;
-
- unpackLEWord(&pDataBuf, &wId);
- wLen -= 2;
-
- unpackLEWord(&pDataBuf, &wCookie);
- wLen -= 2;
-
- if (CompareGUIDs(dwGuid1, dwGuid2, dwGuid3, dwGuid4, PSIG_MESSAGE))
- { // is this a normal message ?
- BYTE bMsgType;
- BYTE bFlags;
- WORD wStatus, wPritority;
- WORD wMsgLen;
-
- if (wLen < 20)
- { // check if there is everything that should be there
- NetLog_Server("Message (format %u) - Ignoring empty message", 2);
- return;
- }
-
- pDataBuf += 12; /* all zeroes */
- wLen -= 12;
- unpackByte(&pDataBuf, &bMsgType);
- wLen -= 1;
- unpackByte(&pDataBuf, &bFlags);
- wLen -= 1;
-
- // Status
- unpackLEWord(&pDataBuf, &wStatus);
- wLen -= 2;
-
- // Priority
- unpackLEWord(&pDataBuf, &wPritority);
- wLen -= 2;
- NetLog_Server("Priority: %u", wPritority);
-
- // Message
- unpackLEWord(&pDataBuf, &wMsgLen);
- wLen -= 2;
-
- // HANDLERS
- switch (bMsgType)
- {
- // File messages, handled by the file module
- case MTYPE_FILEREQ:
- {
- if (!dwUin)
- { // AIM cannot send this, just sanity
- NetLog_Server("Error: Malformed UIN in packet");
- return;
- }
-
- char* szMsg = (char *)_alloca(wMsgLen + 1);
- memcpy(szMsg, pDataBuf, wMsgLen);
- szMsg[wMsgLen] = '\0';
- pDataBuf += wMsgLen;
- wLen -= wMsgLen;
-
- if (wAckType == 0 || wAckType == 1)
- {
- // File requests 7
- handleFileRequest(pDataBuf, wLen, dwUin, wCookie, dwMsgID1, dwMsgID2, szMsg, 7, FALSE);
- }
- else if (wAckType == 2)
- {
- // File reply 7
- handleFileAck(pDataBuf, wLen, dwUin, wCookie, wStatus, szMsg);
- }
- else
- {
- NetLog_Server("Ignored strange file message");
- }
-
- break;
- }
-
- // Chat messages, handled by the chat module
- case MTYPE_CHAT:
- { // TODO: this type is deprecated
- break;
- }
-
- // Plugin messages, need further parsing
- case MTYPE_PLUGIN:
- {
- if (wLen < wMsgLen)
- { // sanity check
- NetLog_Server("Error: Malformed server Greeting message");
- return;
- }
-
- parseServRelayPluginData(pDataBuf + wMsgLen, wLen - wMsgLen, hContact, dwUin, szUID, dwMsgID1, dwMsgID2, wAckType, bFlags, wStatus, wCookie, wVersion);
- break;
- }
-
- // Everything else
- default:
- {
- if (!dwUin)
- { // AIM cannot send this, just sanity
- NetLog_Server("Error: Malformed UIN in packet");
- return;
- }
- message_ack_params pMsgAck = {0};
-
- pMsgAck.bType = MAT_SERVER_ADVANCED;
- pMsgAck.dwUin = dwUin;
- pMsgAck.dwMsgID1 = dwMsgID1;
- pMsgAck.dwMsgID2 = dwMsgID2;
- pMsgAck.wCookie = wCookie;
- pMsgAck.msgType = bMsgType;
- pMsgAck.bFlags = bFlags;
- handleMessageTypes(dwUin, szUID, time(NULL), dwMsgID1, dwMsgID2, wCookie, wVersion, bMsgType, bFlags, wAckType, wLen, wMsgLen, (char*)pDataBuf, 0, &pMsgAck);
- break;
- }
- }
- }
- else if (CompareGUIDs(dwGuid1, dwGuid2, dwGuid3, dwGuid4, PSIG_INFO_PLUGIN))
- { // info manager plugin - obsolete
- if (!dwUin)
- { // AIM cannot send this, just sanity
- NetLog_Server("Error: Malformed UIN in packet");
- return;
- }
-
- BYTE bMsgType;
- BYTE bLevel;
-
- pDataBuf += 16; /* unused stuff */
- wLen -= 16;
- unpackByte(&pDataBuf, &bMsgType);
- wLen -= 1;
-
- pDataBuf += 3; // unknown
- wLen -= 3;
- unpackByte(&pDataBuf, &bLevel);
- if (bLevel != 0 || wLen < 16)
- {
- NetLog_Server("Invalid %s Manager Plugin message from %u", "Info", dwUin);
- return;
- }
- unpackDWord(&pDataBuf, &dwGuid1); // plugin request GUID
- unpackDWord(&pDataBuf, &dwGuid2);
- unpackDWord(&pDataBuf, &dwGuid3);
- unpackDWord(&pDataBuf, &dwGuid4);
- wLen -= 16;
-
- if (CompareGUIDs(dwGuid1, dwGuid2, dwGuid3, dwGuid4, PMSG_QUERY_INFO))
- {
- NetLog_Server("User %u requests our %s plugin list. NOT SUPPORTED", dwUin, "info");
- }
- else
- NetLog_Server("Unknown %s Manager message from %u", "Info", dwUin);
- }
- else if (CompareGUIDs(dwGuid1, dwGuid2, dwGuid3, dwGuid4, PSIG_STATUS_PLUGIN))
- { // status manager plugin - obsolete
- if (!dwUin)
- { // AIM cannot send this, just sanity
- NetLog_Server("Error: Malformed UIN in packet");
- return;
- }
-
- BYTE bMsgType;
- BYTE bLevel;
-
- pDataBuf += 16; /* unused stuff */
- wLen -= 16;
- unpackByte(&pDataBuf, &bMsgType);
- wLen -= 1;
-
- pDataBuf += 3; // unknown
- wLen -= 3;
- unpackByte(&pDataBuf, &bLevel);
- if (bLevel != 0 || wLen < 16)
- {
- NetLog_Server("Invalid %s Manager Plugin message from %u", "Status", dwUin);
- return;
- }
- unpackDWord(&pDataBuf, &dwGuid1); // plugin request GUID
- unpackDWord(&pDataBuf, &dwGuid2);
- unpackDWord(&pDataBuf, &dwGuid3);
- unpackDWord(&pDataBuf, &dwGuid4);
- wLen -= 16;
-
- if (CompareGUIDs(dwGuid1, dwGuid2, dwGuid3, dwGuid4, PMSG_QUERY_STATUS))
- NetLog_Server("User %u requests our %s plugin list. NOT SUPPORTED", dwUin, "status");
- else
- NetLog_Server("Unknown %s Manager message from %u", "Status", dwUin);
- }
- else
- NetLog_Server("Unknown signature (%08x-%08x-%08x-%08x) in message (format 2)", dwGuid1, dwGuid2, dwGuid3, dwGuid4);
- }
- else
- NetLog_Server("Unknown wId1 (%u) in message (format 2)", wId);
-}
-
-
-void CIcqProto::parseServRelayPluginData(BYTE *pDataBuf, WORD wLen, HANDLE hContact, DWORD dwUin, char *szUID, DWORD dwMsgID1, DWORD dwMsgID2, WORD wAckType, BYTE bFlags, WORD wStatus, WORD wCookie, WORD wVersion)
-{
- int nTypeId;
- WORD wFunction;
-
- NetLog_Server("Parsing Greeting message through server");
-
- // Message plugin identification
- if (!unpackPluginTypeId(&pDataBuf, &wLen, &nTypeId, &wFunction, FALSE)) return;
-
- if (wLen > 8)
- {
- DWORD dwLengthToEnd;
- DWORD dwDataLen;
-
- // Length of remaining data
- unpackLEDWord(&pDataBuf, &dwLengthToEnd);
-
- // Length of message
- unpackLEDWord(&pDataBuf, &dwDataLen);
- wLen -= 8;
-
- if (dwDataLen > wLen)
- dwDataLen = wLen;
-
- if (nTypeId == MTYPE_FILEREQ && wAckType == 2)
- {
- if (!dwUin)
- { // AIM cannot send this, just sanity
- NetLog_Server("Error: Malformed UIN in packet");
- return;
- }
- NetLog_Server("This is file ack");
-
- char *szMsg = (char *)_alloca(dwDataLen + 1);
- memcpy(szMsg, pDataBuf, dwDataLen);
- szMsg[dwDataLen] = '\0';
- pDataBuf += dwDataLen;
- wLen -= (WORD)dwDataLen;
-
- handleFileAck(pDataBuf, wLen, dwUin, wCookie, wStatus, szMsg);
- }
- else if (nTypeId == MTYPE_FILEREQ && wAckType == 1)
- {
- if (!dwUin)
- { // AIM cannot send this, just sanity
- NetLog_Server("Error: Malformed UIN in packet");
- return;
- }
- NetLog_Server("This is a file request");
-
- char *szMsg = (char *)_alloca(dwDataLen + 1);
- memcpy(szMsg, pDataBuf, dwDataLen);
- szMsg[dwDataLen] = '\0';
- pDataBuf += dwDataLen;
- wLen -= (WORD)dwDataLen;
-
- handleFileRequest(pDataBuf, wLen, dwUin, wCookie, dwMsgID1, dwMsgID2, szMsg, 8, FALSE);
- }
- else if (nTypeId == MTYPE_CHAT && wAckType == 1)
- { // TODO: this is deprecated
- if (!dwUin)
- { // AIM cannot send this, just sanity
- NetLog_Server("Error: Malformed UIN in packet");
- return;
- }
- NetLog_Server("This is a chat request");
-
- char *szMsg = (char *)_alloca(dwDataLen + 1);
- memcpy(szMsg, pDataBuf, dwDataLen);
- szMsg[dwDataLen] = '\0';
- pDataBuf += dwDataLen;
- wLen -= (WORD)dwDataLen;
-
- // handleChatRequest(pDataBuf, wLen, dwUin, wCookie, dwMsgID1, dwMsgID2, szMsg, 8);
- }
- else if (nTypeId == MTYPE_STATUSMSGEXT && wFunction >= 1 && wFunction <= 3)
- { // handle extended status message request
- int nMsgType = 0;
-
- switch (wFunction)
- {
- case 1: // Away
- if (m_iStatus == ID_STATUS_ONLINE || m_iStatus == ID_STATUS_INVISIBLE)
- nMsgType = MTYPE_AUTOONLINE;
- else if (m_iStatus == ID_STATUS_AWAY)
- nMsgType = MTYPE_AUTOAWAY;
- else if (m_iStatus == ID_STATUS_FREECHAT)
- nMsgType = MTYPE_AUTOFFC;
- break;
-
- case 2: // Busy
- if (m_iStatus == ID_STATUS_OCCUPIED)
- nMsgType = MTYPE_AUTOBUSY;
- else if (m_iStatus == ID_STATUS_DND)
- nMsgType = MTYPE_AUTODND;
- break;
-
- case 3: // N/A
- if (m_iStatus == ID_STATUS_NA)
- nMsgType = MTYPE_AUTONA;
- }
- handleMessageTypes(dwUin, szUID, time(NULL), dwMsgID1, dwMsgID2, wCookie, wVersion, nMsgType, bFlags, wAckType, dwLengthToEnd, 0, (char*)pDataBuf, MTF_PLUGIN | MTF_STATUS_EXTENDED, NULL);
- }
- else if (nTypeId)
- {
- if (!dwUin)
- { // AIM cannot send this, just sanity
- NetLog_Server("Error: Malformed UIN in packet");
- return;
- }
- message_ack_params pMsgAck = {0};
-
- pMsgAck.bType = MAT_SERVER_ADVANCED;
- pMsgAck.dwUin = dwUin;
- pMsgAck.dwMsgID1 = dwMsgID1;
- pMsgAck.dwMsgID2 = dwMsgID2;
- pMsgAck.wCookie = wCookie;
- pMsgAck.msgType = nTypeId;
- pMsgAck.bFlags = bFlags;
- handleMessageTypes(dwUin, szUID, time(NULL), dwMsgID1, dwMsgID2, wCookie, wVersion, nTypeId, bFlags, wAckType, dwLengthToEnd, (WORD)dwDataLen, (char*)pDataBuf, MTF_PLUGIN, &pMsgAck);
- }
- else
- {
- NetLog_Server("Unsupported plugin message type %d", nTypeId);
- }
- }
- else
- NetLog_Server("Error: Malformed server plugin message");
-}
-
-
-void CIcqProto::handleRecvServMsgContacts(BYTE *buf, WORD wLen, DWORD dwUin, char *szUID, DWORD dwID1, DWORD dwID2, WORD wCommand)
-{
- HANDLE hContact = HContactFromUID(dwUin, szUID, NULL);
-
- if (wCommand == 0)
- { // received contacts
- if (wLen < 4)
- { // just check if at least one tlv is there
- NetLog_Server("Message (format %u) - Ignoring empty contacts message", 2);
- return;
- }
- oscar_tlv_chain *chain = readIntoTLVChain(&buf, wLen, 0);
- if (!chain)
- { // sanity check
- NetLog_Server("Message (format %u) - Invalid data", 2);
- return;
- }
-
- WORD wAckType = chain->getWord(0x0A, 1);
-
- if (wAckType == 1)
- { // it is really message containing contacts, parse them
- oscar_tlv *tlvUins = chain->getTLV(0x2711, 1);
- oscar_tlv *tlvNames = chain->getTLV(0x2712, 1);
-
- if (!tlvUins || tlvUins->wLen < 4)
- {
- NetLog_Server("Malformed '%s' message", "contacts");
- disposeChain(&chain);
- return;
- }
- int nContacts = 0x10, iContact = 0;
- ICQSEARCHRESULT **contacts = (ICQSEARCHRESULT**)SAFE_MALLOC(nContacts * sizeof(ICQSEARCHRESULT*));
- WORD wContactsGroup = 0;
- int valid = 1;
- BYTE *pBuffer = tlvUins->pData;
- int nLen = tlvUins->wLen;
-
- while (nLen > 2)
- { // parse UIDs
- if (!wContactsGroup)
- {
- WORD wGroupLen;
-
- unpackWord(&pBuffer, &wGroupLen);
- nLen -= 2;
- if (nLen >= wGroupLen + 2)
- {
- pBuffer += wGroupLen;
- unpackWord(&pBuffer, &wContactsGroup);
- nLen -= wGroupLen + 2;
- }
- else
- break;
- }
- else
- { // group parsed, UIDs waiting
- WORD wUidLen;
-
- unpackWord(&pBuffer, &wUidLen);
- nLen -= 2;
- if (nLen >= wUidLen)
- {
- char *szUid = (char*)SAFE_MALLOC(wUidLen + 1);
- unpackString(&pBuffer, szUid, wUidLen);
- nLen -= wUidLen;
-
- if (iContact >= nContacts)
- { // the list is too small, resize it
- nContacts += 0x10;
- contacts = (ICQSEARCHRESULT**)SAFE_REALLOC(contacts, nContacts * sizeof(ICQSEARCHRESULT*));
- }
- contacts[iContact] = (ICQSEARCHRESULT*)SAFE_MALLOC(sizeof(ICQSEARCHRESULT));
- contacts[iContact]->hdr.cbSize = sizeof(ICQSEARCHRESULT);
- contacts[iContact]->hdr.flags = PSR_TCHAR;
- contacts[iContact]->hdr.nick = null_strdup(_T(""));
- contacts[iContact]->hdr.id = ansi_to_tchar(szUid);
-
- if (IsStringUIN(szUid))
- { // icq contact
- contacts[iContact]->uin = atoi(szUid);
- if (contacts[iContact]->uin == 0)
- valid = 0;
- }
- else
- { // aim contact
- if (!strlennull(szUid))
- valid = 0;
- }
- iContact++;
-
- SAFE_FREE(&szUid);
- }
- else
- {
- if (wContactsGroup) valid = 0;
- break;
- }
-
- wContactsGroup--;
- }
- }
- if (!iContact || !valid)
- {
- NetLog_Server("Malformed '%s' message", "contacts");
- disposeChain(&chain);
- for (int i = 0; i < iContact; i++)
- {
- SAFE_FREE(&contacts[i]->hdr.id);
- SAFE_FREE(&contacts[i]->hdr.nick);
- SAFE_FREE((void**)&contacts[i]);
- }
- SAFE_FREE((void**)&contacts);
- return;
- }
- nContacts = iContact;
- if (tlvNames && tlvNames->wLen >= 4)
- { // parse names, if available
- pBuffer = tlvNames->pData;
- nLen = tlvNames->wLen;
- iContact = 0;
-
- while (nLen > 2)
- { // parse Names
- if (!wContactsGroup)
- {
- WORD wGroupLen;
-
- unpackWord(&pBuffer, &wGroupLen);
- nLen -= 2;
- if (nLen >= wGroupLen + 2)
- {
- pBuffer += wGroupLen;
- unpackWord(&pBuffer, &wContactsGroup);
- nLen -= wGroupLen + 2;
- }
- else
- break;
- }
- else
- { // group parsed, Names waiting
- WORD wNickLen;
-
- unpackWord(&pBuffer, &wNickLen);
- nLen -= 2;
- if (nLen >= wNickLen)
- {
- WORD wNickTLV, wNickTLVLen;
- char *pNick = NULL;
-
- unpackTypedTLV(pBuffer, wNickLen, 0x01, &wNickTLV, &wNickTLVLen, (LPBYTE*)&pNick);
- if (wNickTLV == 0x01)
- {
- SAFE_FREE(&contacts[iContact]->hdr.nick);
- contacts[iContact]->hdr.nick = utf8_to_tchar(pNick);
- }
- else
- SAFE_FREE(&pNick);
- pBuffer += wNickLen;
- nLen -= wNickLen;
-
- iContact++;
- if (iContact >= nContacts) break;
- }
- else
- break;
-
- wContactsGroup--;
- }
- }
- }
-
- if (!valid)
- {
- NetLog_Server("Malformed '%s' message", "contacts");
- }
- else
- {
- int bAdded;
- CCSDATA ccs;
- PROTORECVEVENT pre = {0};
-
- hContact = HContactFromUID(dwUin, szUID, &bAdded);
-
- // ack the message
- icq_sendContactsAck(dwUin, szUID, dwID1, dwID2);
-
- ccs.szProtoService = PSR_CONTACTS;
- ccs.hContact = hContact;
- ccs.wParam = 0;
- ccs.lParam = (LPARAM)&pre;
- pre.timestamp = (DWORD)time(NULL);
- pre.szMessage = (char *)contacts;
- pre.lParam = nContacts;
- pre.flags = PREF_TCHAR;
- CallService(MS_PROTO_CHAINRECV, 0, (LPARAM)&ccs);
- }
-
- for (int i = 0; i < iContact; i++)
- {
- SAFE_FREE(&contacts[i]->hdr.id);
- SAFE_FREE(&contacts[i]->hdr.nick);
- SAFE_FREE((void**)&contacts[i]);
- }
- SAFE_FREE((void**)&contacts);
- }
- else
- NetLog_Server("Error: Received unknown contacts message, ignoring.");
- // Clean up
- disposeChain(&chain);
- }
- else if (wCommand == 1)
- {
- NetLog_Server("Cannot handle abort messages yet... :(");
- return;
- }
- else if (wCommand == 2)
- { // acknowledgement
- DWORD dwCookie;
- HANDLE hCookieContact;
-
- if (FindMessageCookie(dwID1, dwID2, &dwCookie, &hCookieContact, NULL))
- {
- if (hCookieContact != hContact)
- NetLog_Server("Warning: Ack Contact does not match Cookie Contact(0x%x != 0x%x)", hContact, hCookieContact);
-
- BroadcastAck(hContact, ACKTYPE_CONTACTS, ACKRESULT_SUCCESS, (HANDLE)dwCookie, 0);
-
- ReleaseCookie(dwCookie);
- }
- else
- NetLog_Server("Warning: Unexpected Contact Transfer ack from %s", strUID(dwUin, szUID));
- }
-}
-
-
-void CIcqProto::handleRecvServMsgType4(BYTE *buf, WORD wLen, DWORD dwUin, char *szUID, DWORD dwMsgID1, DWORD dwMsgID2, DWORD dwRef)
-{
- WORD wTLVType;
- WORD wTLVLen;
- BYTE* pDataBuf;
- DWORD dwUin2;
-
- if (wLen < 2)
- {
- NetLog_Server("Message (format %u) - Ignoring empty message", 4);
- return;
- }
-
- // Unpack the first TLV(5)
- unpackTypedTLV(buf, wLen, 5, &wTLVType, &wTLVLen, &pDataBuf);
- NetLog_Server("Message (format %u) - UID: %s", 4, strUID(dwUin, szUID));
-
- // It must be TLV(5)
- if (wTLVType == 5)
- {
- BYTE bMsgType;
- BYTE bFlags;
- BYTE* pmsg = pDataBuf;
- WORD wMsgLen;
-
-
- unpackLEDWord(&pmsg, &dwUin2);
-
- if (dwUin2 == dwUin)
- {
- unpackByte(&pmsg, &bMsgType);
- unpackByte(&pmsg, &bFlags);
- unpackLEWord(&pmsg, &wMsgLen);
-
- if (bMsgType == 0 && wMsgLen == 1)
- {
- NetLog_Server("User %u probably checks his ignore state.", dwUin);
- }
- else
- {
- cookie_offline_messages *cookie;
- DWORD dwRecvTime = (DWORD)time(NULL);
-
- if (!(dwRef & 0x80000000) && FindCookie(dwRef, NULL, (void**)&cookie))
- {
- WORD wTimeTLVType, wTimeTLVLen;
- BYTE *pTimeTLV = NULL;
-
- cookie->nMessages++;
-
- unpackTypedTLV(buf, wLen, 0x16, &wTimeTLVType, &wTimeTLVLen, &pTimeTLV);
- if (pTimeTLV && wTimeTLVType == 0x16 && wTimeTLVLen == 4)
- { // found Offline timestamp
- BYTE *pBuf = pTimeTLV;
-
- unpackDWord(&pBuf, &dwRecvTime);
- NetLog_Server("Message (format %u) - Offline timestamp is %s", 4, time2text(dwRecvTime));
- }
- SAFE_FREE((void**)&pTimeTLV);
- }
-
- if (bMsgType == MTYPE_PLUGIN)
- {
- WORD wLen = wTLVLen - 8;
- int typeId;
-
- NetLog_Server("Parsing Greeting message through server");
-
- pmsg += wMsgLen;
- wLen -= wMsgLen;
-
- if (unpackPluginTypeId(&pmsg, &wLen, &typeId, NULL, FALSE) && wLen > 8)
- {
- DWORD dwLengthToEnd;
- DWORD dwDataLen;
-
- // Length of remaining data
- unpackLEDWord(&pmsg, &dwLengthToEnd);
-
- // Length of message
- unpackLEDWord(&pmsg, &dwDataLen);
- wLen -= 8;
-
- if (dwDataLen > wLen)
- dwDataLen = wLen;
-
- if (typeId)
- {
- uid_str szUID;
- handleMessageTypes(dwUin, szUID, dwRecvTime, dwMsgID1, dwMsgID2, 0, 0, typeId, bFlags, 0, dwLengthToEnd, (WORD)dwDataLen, (char*)pmsg, MTF_PLUGIN, NULL);
- }
- else
- {
- NetLog_Server("Unsupported plugin message type %d", typeId);
- }
- }
- }
- else
- {
- uid_str szUID;
- handleMessageTypes(dwUin, szUID, dwRecvTime, dwMsgID1, dwMsgID2, 0, 0, bMsgType, bFlags, 0, wTLVLen - 8, wMsgLen, (char*)pmsg, 0, NULL);
- }
- }
- }
- else
- {
- NetLog_Server("Ignoring spoofed TYPE4 message thru server from %d", dwUin);
- }
- }
- else
- {
- NetLog_Server("Unsupported TLV (%u) in message (format %u)", wTLVType, 4);
- }
-
- SAFE_FREE((void**)&pDataBuf);
-}
-
-
-//
-// Helper functions
-//
-
-static int TypeGUIDToTypeId(DWORD dwGuid1, DWORD dwGuid2, DWORD dwGuid3, DWORD dwGuid4, WORD wType)
-{
- int nTypeID = MTYPE_UNKNOWN;
-
- if (CompareGUIDs(dwGuid1, dwGuid2, dwGuid3, dwGuid4, MGTYPE_STATUSMSGEXT))
- {
- nTypeID = MTYPE_STATUSMSGEXT;
- }
- else if (wType==MGTYPE_UNDEFINED)
- {
- if (CompareGUIDs(dwGuid1, dwGuid2, dwGuid3, dwGuid4, PSIG_MESSAGE))
- { // icq6 message ack
- nTypeID = MTYPE_PLAIN;
- }
- }
- else if (wType==MGTYPE_STANDARD_SEND)
- {
- if (CompareGUIDs(dwGuid1, dwGuid2, dwGuid3, dwGuid4, MGTYPE_WEBURL))
- {
- nTypeID = MTYPE_URL;
- }
- else if (CompareGUIDs(dwGuid1, dwGuid2, dwGuid3, dwGuid4, MGTYPE_CONTACTS))
- {
- nTypeID = MTYPE_CONTACTS;
- }
- else if (CompareGUIDs(dwGuid1, dwGuid2, dwGuid3, dwGuid4, MGTYPE_CHAT))
- {
- nTypeID = MTYPE_CHAT;
- }
- else if (CompareGUIDs(dwGuid1, dwGuid2, dwGuid3, dwGuid4, MGTYPE_FILE))
- {
- nTypeID = MTYPE_FILEREQ;
- }
- else if (CompareGUIDs(dwGuid1, dwGuid2, dwGuid3, dwGuid4, MGTYPE_GREETING_CARD))
- {
- nTypeID = MTYPE_GREETINGCARD;
- }
- else if (CompareGUIDs(dwGuid1, dwGuid2, dwGuid3, dwGuid4, MGTYPE_MESSAGE))
- {
- nTypeID = MTYPE_MESSAGE;
- }
- else if (CompareGUIDs(dwGuid1, dwGuid2, dwGuid3, dwGuid4, MGTYPE_SMS_MESSAGE))
- {
- nTypeID = MTYPE_SMS_MESSAGE;
- }
- }
- else if (wType==MGTYPE_CONTACTS_REQUEST)
- {
- if (CompareGUIDs(dwGuid1, dwGuid2, dwGuid3, dwGuid4, MGTYPE_CONTACTS))
- {
- nTypeID = MTYPE_REQUESTCONTACTS;
- }
- else if (CompareGUIDs(dwGuid1, dwGuid2, dwGuid3, dwGuid4, MGTYPE_XTRAZ_SCRIPT))
- {
- nTypeID = MTYPE_SCRIPT_DATA;
- }
- }
- else if (CompareGUIDs(dwGuid1, dwGuid2, dwGuid3, dwGuid4, MGTYPE_XTRAZ_SCRIPT))
- {
- if (wType==MGTYPE_SCRIPT_INVITATION)
- {
- nTypeID = MTYPE_SCRIPT_INVITATION;
- }
- else if (wType==MGTYPE_SCRIPT_NOTIFY)
- {
- nTypeID = MTYPE_SCRIPT_NOTIFY;
- }
- }
-
- return nTypeID;
-}
-
-
-int CIcqProto::unpackPluginTypeId(BYTE **pBuffer, WORD *pwLen, int *pTypeId, WORD *pFunctionId, BOOL bThruDC)
-{
- WORD wLen = *pwLen;
- WORD wInfoLen;
- DWORD dwPluginNameLen;
- DWORD q1,q2,q3,q4;
- WORD qt;
-
- if (wLen < 24)
- return 0; // Failure
-
- unpackLEWord(pBuffer, &wInfoLen);
-
- unpackDWord(pBuffer, &q1); // get data GUID & function id
- unpackDWord(pBuffer, &q2);
- unpackDWord(pBuffer, &q3);
- unpackDWord(pBuffer, &q4);
- unpackLEWord(pBuffer, &qt);
- wLen -= 20;
-
- if (pFunctionId) *pFunctionId = qt;
-
- unpackLEDWord(pBuffer, &dwPluginNameLen);
- wLen -= 4;
-
- if (dwPluginNameLen > wLen)
- { // check for malformed plugin name
- dwPluginNameLen = wLen;
- NetLog_Uni(bThruDC, "Warning: malformed size of plugin name.");
- }
- char *szPluginName = (char *)_alloca(dwPluginNameLen + 1);
- memcpy(szPluginName, *pBuffer, dwPluginNameLen);
- szPluginName[dwPluginNameLen] = '\0';
- wLen -= (WORD)dwPluginNameLen;
-
- *pBuffer += dwPluginNameLen;
-
- int typeId = TypeGUIDToTypeId(q1, q2, q3, q4, qt);
- if (!typeId)
- NetLog_Uni(bThruDC, "Error: Unknown type {%08x-%08x-%08x-%08x:%04x}: %s", q1,q2,q3,q4,qt, szPluginName);
-
- if (wInfoLen >= 22 + dwPluginNameLen)
- { // sanity checking
- wInfoLen -= (WORD)(22 + dwPluginNameLen);
-
- // check if enough data is available - skip remaining bytes of info block
- if (wLen >= wInfoLen)
- {
- *pBuffer += wInfoLen;
- wLen -= wInfoLen;
- }
- }
-
- *pwLen = wLen;
- *pTypeId = typeId;
-
- return 1; // Success
-}
-
-
-int getPluginTypeIdLen(int nTypeID)
-{
- switch (nTypeID)
- {
- case MTYPE_SCRIPT_NOTIFY:
- return 0x51;
-
- case MTYPE_FILEREQ:
- return 0x2B;
-
- case MTYPE_AUTOONLINE:
- case MTYPE_AUTOAWAY:
- case MTYPE_AUTOBUSY:
- case MTYPE_AUTODND:
- case MTYPE_AUTOFFC:
- return 0x3C;
-
- case MTYPE_AUTONA:
- return 0x3B;
-
- default:
- return 0;
- }
-}
-
-
-void packPluginTypeId(icq_packet *packet, int nTypeID)
-{
- switch (nTypeID)
- {
- case MTYPE_SCRIPT_NOTIFY:
- packLEWord(packet, 0x04f); // Length
-
- packGUID(packet, MGTYPE_XTRAZ_SCRIPT); // Message Type GUID
- packLEWord(packet, MGTYPE_SCRIPT_NOTIFY); // Function ID
- packLEDWord(packet, 0x002a); // Request type string
- packBuffer(packet, (LPBYTE)"Script Plug-in: Remote Notification Arrive", 0x002a);
-
- packDWord(packet, 0x00000100); // Unknown binary stuff
- packDWord(packet, 0x00000000);
- packDWord(packet, 0x00000000);
- packWord(packet, 0x0000);
- packByte(packet, 0x00);
-
- break;
-
- case MTYPE_FILEREQ:
- packLEWord(packet, 0x029); // Length
-
- packGUID(packet, MGTYPE_FILE); // Message Type GUID
- packWord(packet, 0x0000); // Unknown
- packLEDWord(packet, 0x0004); // Request type string
- packBuffer(packet, (LPBYTE)"File", 0x0004);
-
- packDWord(packet, 0x00000100); // More unknown binary stuff
- packDWord(packet, 0x00010000);
- packDWord(packet, 0x00000000);
- packWord(packet, 0x0000);
- packByte(packet, 0x00);
-
- break;
-
- case MTYPE_AUTOONLINE:
- case MTYPE_AUTOAWAY:
- case MTYPE_AUTOFFC:
- packLEWord(packet, 0x03A); // Length
-
- packGUID(packet, MGTYPE_STATUSMSGEXT); // Message Type GUID
-
- packLEWord(packet, 1); // Function ID
- packLEDWord(packet, 0x13); // Request type string
- packBuffer(packet, (LPBYTE)"Away Status Message", 0x13);
-
- packDWord(packet, 0x01000000); // Unknown binary stuff
- packDWord(packet, 0x00000000);
- packDWord(packet, 0x00000000);
- packDWord(packet, 0x00000000);
- packByte(packet, 0x00);
-
- break;
-
- case MTYPE_AUTOBUSY:
- case MTYPE_AUTODND:
- packLEWord(packet, 0x03A); // Length
-
- packGUID(packet, MGTYPE_STATUSMSGEXT); // Message Type GUID
-
- packLEWord(packet, 2); // Function ID
- packLEDWord(packet, 0x13); // Request type string
- packBuffer(packet, (LPBYTE)"Busy Status Message", 0x13);
-
- packDWord(packet, 0x02000000); // Unknown binary stuff
- packDWord(packet, 0x00000000);
- packDWord(packet, 0x00000000);
- packDWord(packet, 0x00000000);
- packByte(packet, 0x00);
-
- break;
-
- case MTYPE_AUTONA:
- packLEWord(packet, 0x039); // Length
-
- packGUID(packet, MGTYPE_STATUSMSGEXT); // Message Type GUID
-
- packLEWord(packet, 3); // Function ID
- packLEDWord(packet, 0x12); // Request type string
- packBuffer(packet, (LPBYTE)"N/A Status Message", 0x12);
-
- packDWord(packet, 0x03000000); // Unknown binary stuff
- packDWord(packet, 0x00000000);
- packDWord(packet, 0x00000000);
- packDWord(packet, 0x00000000);
- packByte(packet, 0x00);
-
- break;
- }
-}
-
-
-void CIcqProto::handleStatusMsgReply(const char *szPrefix, HANDLE hContact, DWORD dwUin, WORD wVersion, int bMsgType, WORD wCookie, const char *szMsg, int nMsgFlags)
-{
- CCSDATA ccs;
- PROTORECVEVENT pre = {0};
-
- if (hContact == INVALID_HANDLE_VALUE)
- {
- NetLog_Server("%sIgnoring status message from unknown contact %u", szPrefix, dwUin);
- return;
- }
-
- int status = AwayMsgTypeToStatus(bMsgType);
- if (status == ID_STATUS_OFFLINE)
- {
- NetLog_Server("%sIgnoring unknown status message from %u", szPrefix, dwUin);
- return;
- }
-
- // it is probably UTF-8 status reply
- if (wVersion == 9 || (nMsgFlags & MTF_PLUGIN) && wVersion == 10)
- {
- if (UTF8_IsValid(szMsg)) pre.flags |= PREF_UTF;
- }
-
- ccs.szProtoService = PSR_AWAYMSG;
- ccs.hContact = hContact;
- ccs.wParam = status;
- ccs.lParam = (LPARAM)&pre;
- pre.szMessage = (char*)szMsg;
- pre.timestamp = time(NULL);
- pre.lParam = wCookie;
-
- CallService(MS_PROTO_CHAINRECV,0,(LPARAM)&ccs);
-}
-
-
-HANDLE CIcqProto::handleMessageAck(DWORD dwUin, char *szUID, WORD wCookie, WORD wVersion, int type, WORD wMsgLen, PBYTE buf, BYTE bFlags, int nMsgFlags)
-{
- if (bFlags == 3)
- {
- HANDLE hCookieContact;
- cookie_message_data *pCookieData = NULL;
-
- HANDLE hContact = HContactFromUID(dwUin, szUID, NULL);
-
- if (!FindCookie(wCookie, &hCookieContact, (void**)&pCookieData))
- {
- NetLog_Server("%sIgnoring unrequested status message from %u", "handleMessageAck: ", dwUin);
-
- ReleaseCookie(wCookie);
- return INVALID_HANDLE_VALUE;
- }
-
- if (hContact != hCookieContact)
- {
- NetLog_Server("%sAck Contact does not match Cookie Contact(0x%x != 0x%x)", "handleMessageAck: ", hContact, hCookieContact);
-
- ReleaseCookie(wCookie);
- return INVALID_HANDLE_VALUE;
- }
- ReleaseCookie(wCookie);
-
- handleStatusMsgReply("handleMessageAck: ", hContact, dwUin, wVersion, type, wCookie, (char*)buf, nMsgFlags);
- }
- else
- {
- // Should not happen
- NetLog_Server("%sIgnored type %u ack message (this should not happen)", "handleMessageAck: ", type);
- }
-
- return INVALID_HANDLE_VALUE;
-}
-
-
-/* this function send all acks from handleMessageTypes */
-void CIcqProto::sendMessageTypesAck(HANDLE hContact, int bUnicode, message_ack_params *pArgs)
-{
- if (pArgs)
- {
- if ((pArgs->msgType == MTYPE_PLAIN && !CallService(MS_IGNORE_ISIGNORED, (WPARAM)hContact, IGNOREEVENT_MESSAGE))
- || (pArgs->msgType == MTYPE_URL && !CallService(MS_IGNORE_ISIGNORED, (WPARAM)hContact, IGNOREEVENT_URL))
- || pArgs->msgType == MTYPE_CONTACTS)
- {
- if (pArgs->bType == MAT_SERVER_ADVANCED)
- { // Only ack message packets
- icq_sendAdvancedMsgAck(pArgs->dwUin, pArgs->dwMsgID1, pArgs->dwMsgID2, pArgs->wCookie, (BYTE)pArgs->msgType, pArgs->bFlags);
- }
- else if (pArgs->bType == MAT_DIRECT)
- { // Send acknowledgement
- icq_sendDirectMsgAck(pArgs->pDC, pArgs->wCookie, (BYTE)pArgs->msgType, pArgs->bFlags, bUnicode ? (char *)CAP_UTF8MSGS : NULL);
- }
- }
- }
-}
-
-
-/* this function also processes direct packets, so it should be bulletproof */
-/* pMsg points to the beginning of the message */
-void CIcqProto::handleMessageTypes(DWORD dwUin, char *szUID, DWORD dwTimestamp, DWORD dwMsgID, DWORD dwMsgID2, WORD wCookie, WORD wVersion, int type, int flags, WORD wAckType, DWORD dwDataLen, WORD wMsgLen, char *pMsg, int nMsgFlags, message_ack_params *pAckParams)
-{
- HANDLE hContact = INVALID_HANDLE_VALUE;
- BOOL bThruDC = (nMsgFlags & MTF_DIRECT) == MTF_DIRECT;
- int bAdded;
-
-
- if (dwDataLen < wMsgLen)
- {
- NetLog_Uni(bThruDC, "Ignoring overflowed message");
- return;
- }
-
- if (wAckType == 2)
- {
- handleMessageAck(dwUin, szUID, wCookie, wVersion, type, wMsgLen, (LPBYTE)pMsg, (BYTE)flags, nMsgFlags);
- return;
- }
-
- char *szMsg = (char *)SAFE_MALLOC(wMsgLen + 1);
- if (wMsgLen > 0)
- {
- memcpy(szMsg, pMsg, wMsgLen);
- pMsg += wMsgLen;
- dwDataLen -= wMsgLen;
- }
- szMsg[wMsgLen] = '\0';
-
-
- char* pszMsgField[2*MAX_CONTACTSSEND+1];
- int nMsgFields = 0;
-
- pszMsgField[0] = szMsg;
- if (type == MTYPE_URL || type == MTYPE_AUTHREQ || type == MTYPE_ADDED || type == MTYPE_CONTACTS || type == MTYPE_EEXPRESS || type == MTYPE_WWP)
- {
- for (char *pszMsg=szMsg, nMsgFields=1; *pszMsg; pszMsg++)
- {
- if ((BYTE)*pszMsg == 0xFE)
- {
- *pszMsg = '\0';
- pszMsgField[nMsgFields++] = pszMsg + 1;
- if (nMsgFields >= SIZEOF(pszMsgField))
- break;
- }
- }
- }
-
- switch (type) {
-
- case MTYPE_PLAIN: /* plain message */
- {
- CCSDATA ccs;
- PROTORECVEVENT pre = {0};
-
- // Check if this message is marked as UTF8 encoded
- if (dwDataLen > 12)
- {
- DWORD dwGuidLen = 0;
- int bDoubleMsg = 0;
-
- if (bThruDC)
- {
- DWORD dwExtraLen = *(DWORD*)pMsg;
-
- if (dwExtraLen < dwDataLen && !strncmp(szMsg, "{\\rtf", 5))
- { // it is icq5 sending us crap, get real message from it
- WCHAR* usMsg = (WCHAR*)_alloca((dwExtraLen + 1)*sizeof(WCHAR));
- // make sure it is null-terminated
- wcsncpy(usMsg, (WCHAR*)(pMsg + 4), dwExtraLen);
- usMsg[dwExtraLen] = '\0';
- SAFE_FREE(&szMsg);
- szMsg = (char*)make_utf8_string(usMsg);
-
- if (!IsUnicodeAscii(usMsg, dwExtraLen))
- pre.flags = PREF_UTF; // only mark real non-ascii messages as unicode
-
- bDoubleMsg = 1;
- }
- }
-
- if (!bDoubleMsg)
- {
- dwGuidLen = *(DWORD*)(pMsg+8);
- dwDataLen -= 12;
- pMsg += 12;
- }
-
- while ((dwGuidLen >= 38) && (dwDataLen >= dwGuidLen))
- {
- if (!strncmp(pMsg, CAP_UTF8MSGS, 38))
- { // Found UTF8 cap, convert message to ansi
- pre.flags = PREF_UTF;
- break;
- }
- else if (!strncmp(pMsg, CAP_RTFMSGS, 38))
- { // Found RichText cap
- NetLog_Uni(bThruDC, "Warning: User %u sends us RichText.", dwUin);
- break;
- }
-
- dwGuidLen -= 38;
- dwDataLen -= 38;
- pMsg += 38;
- }
- }
-
- hContact = HContactFromUIN(dwUin, &bAdded);
- sendMessageTypesAck(hContact, pre.flags & PREF_UTF, pAckParams);
-
- if (!pre.flags && !IsUSASCII(szMsg, strlennull(szMsg)))
- { // message is Ansi and contains national characters, create Unicode part by codepage
- char *usMsg = convertMsgToUserSpecificUtf(hContact, szMsg);
- if (usMsg)
- {
- SAFE_FREE(&szMsg);
- szMsg = (char*)usMsg;
- pre.flags = PREF_UTF;
- }
- }
-
- ccs.szProtoService = PSR_MESSAGE;
- ccs.hContact = hContact;
- ccs.wParam = 0;
- ccs.lParam = (LPARAM)&pre;
- pre.timestamp = dwTimestamp;
- pre.szMessage = (char *)szMsg;
-
- CallService(MS_PROTO_CHAINRECV, 0, (LPARAM)&ccs);
- }
- break;
-
- case MTYPE_URL:
- {
- CCSDATA ccs;
- PROTORECVEVENT pre = {0};
-
- if (nMsgFields < 2)
- {
- NetLog_Uni(bThruDC, "Malformed '%s' message", "URL");
- break;
- }
-
- hContact = HContactFromUIN(dwUin, &bAdded);
- sendMessageTypesAck(hContact, 0, pAckParams);
-
- char *szTitle = ICQTranslateUtf(LPGEN("Incoming URL:"));
- char *szDataDescr = ansi_to_utf8(pszMsgField[0]);
- char *szDataUrl = ansi_to_utf8(pszMsgField[1]);
- char *szBlob = (char *)SAFE_MALLOC(strlennull(szTitle) + strlennull(szDataDescr) + strlennull(szDataUrl) + 8);
- strcpy(szBlob, szTitle);
- strcat(szBlob, " ");
- strcat(szBlob, szDataDescr); // Description
- strcat(szBlob, "\r\n");
- strcat(szBlob, szDataUrl); // URL
- SAFE_FREE(&szTitle);
- SAFE_FREE(&szDataDescr);
- SAFE_FREE(&szDataUrl);
-
- ccs.szProtoService = PSR_MESSAGE;
- ccs.hContact = hContact;
- ccs.wParam = 0;
- ccs.lParam = (LPARAM)&pre;
- pre.timestamp = dwTimestamp;
- pre.szMessage = (char *)szBlob;
- pre.flags = PREF_UTF;
-
- CallService(MS_PROTO_CHAINRECV, 0, (LPARAM)&ccs);
-
- SAFE_FREE(&szBlob);
- }
- break;
-
- case MTYPE_AUTHREQ: /* auth request */
- /* format: nick FE first FE last FE email FE unk-char FE msg 00 */
- {
- CCSDATA ccs;
- PROTORECVEVENT pre = {0};
- char* szBlob;
- char* pCurBlob;
-
-
- if (nMsgFields < 6)
- {
- NetLog_Server("Malformed '%s' message", "auth req");
- break;
- }
-
- ccs.szProtoService=PSR_AUTH;
- ccs.hContact=hContact=HContactFromUIN(dwUin, &bAdded);
- ccs.wParam=0;
- ccs.lParam=(LPARAM)&pre;
- pre.timestamp=dwTimestamp;
- pre.lParam=sizeof(DWORD)+sizeof(HANDLE)+strlennull(pszMsgField[0])+strlennull(pszMsgField[1])+strlennull(pszMsgField[2])+strlennull(pszMsgField[3])+strlennull(pszMsgField[5])+5;
-
- /*blob is: uin(DWORD), hcontact(HANDLE), nick(ASCIIZ), first(ASCIIZ), last(ASCIIZ), email(ASCIIZ), reason(ASCIIZ)*/
- pCurBlob=szBlob=(char *)_alloca(pre.lParam);
- memcpy(pCurBlob,&dwUin,sizeof(DWORD)); pCurBlob+=sizeof(DWORD);
- memcpy(pCurBlob,&hContact,sizeof(HANDLE)); pCurBlob+=sizeof(HANDLE);
- strcpy((char *)pCurBlob,pszMsgField[0]); pCurBlob+=strlennull((char *)pCurBlob)+1;
- strcpy((char *)pCurBlob,pszMsgField[1]); pCurBlob+=strlennull((char *)pCurBlob)+1;
- strcpy((char *)pCurBlob,pszMsgField[2]); pCurBlob+=strlennull((char *)pCurBlob)+1;
- strcpy((char *)pCurBlob,pszMsgField[3]); pCurBlob+=strlennull((char *)pCurBlob)+1;
- strcpy((char *)pCurBlob,pszMsgField[5]);
- pre.szMessage=(char *)szBlob;
-
- CallService(MS_PROTO_CHAINRECV,0,(LPARAM)&ccs);
- }
- break;
-
- case MTYPE_ADDED: /* 'you were added' */
- /* format: nick FE first FE last FE email 00 */
- {
- DWORD cbBlob;
- PBYTE pBlob, pCurBlob;
-
- if (nMsgFields < 4)
- {
- NetLog_Server("Malformed '%s' message", "you were added");
- break;
- }
-
- hContact = HContactFromUIN(dwUin, &bAdded);
-
- /*blob is: uin(DWORD), hcontact(HANDLE), nick(ASCIIZ), first(ASCIIZ), last(ASCIIZ), email(ASCIIZ) */
- cbBlob=sizeof(DWORD)*2+strlennull(pszMsgField[0])+strlennull(pszMsgField[1])+strlennull(pszMsgField[2])+strlennull(pszMsgField[3])+4;
- pCurBlob=pBlob=(PBYTE)_alloca(cbBlob);
- *(DWORD*)pCurBlob = dwUin; pCurBlob += sizeof(DWORD);
- *(DWORD*)pCurBlob = DWORD(hContact); pCurBlob += sizeof(DWORD);
- strcpy((char *)pCurBlob,pszMsgField[0]); pCurBlob += strlennull((char *)pCurBlob)+1;
- strcpy((char *)pCurBlob,pszMsgField[1]); pCurBlob += strlennull((char *)pCurBlob)+1;
- strcpy((char *)pCurBlob,pszMsgField[2]); pCurBlob += strlennull((char *)pCurBlob)+1;
- strcpy((char *)pCurBlob,pszMsgField[3]);
-
- AddEvent(NULL, EVENTTYPE_ADDED, dwTimestamp, 0, cbBlob, pBlob);
- }
- break;
-
- case MTYPE_CONTACTS:
- {
- CCSDATA ccs;
- PROTORECVEVENT pre = {0};
- char* pszNContactsEnd;
- int nContacts;
- int i;
-
-
- if (nMsgFields < 3
- || (nContacts = strtol(pszMsgField[0], &pszNContactsEnd, 10)) == 0
- || pszNContactsEnd - pszMsgField[0] != (int)strlennull(pszMsgField[0])
- || nMsgFields < nContacts * 2 + 1)
- {
- NetLog_Uni(bThruDC, "Malformed '%s' message", "contacts");
- break;
- }
-
- int valid = 1;
- ICQSEARCHRESULT** isrList = (ICQSEARCHRESULT**)_alloca(nContacts * sizeof(ICQSEARCHRESULT*));
- for (i = 0; i < nContacts; i++)
- {
- isrList[i] = (ICQSEARCHRESULT*)SAFE_MALLOC(sizeof(ICQSEARCHRESULT));
- isrList[i]->hdr.cbSize = sizeof(ICQSEARCHRESULT);
- isrList[i]->hdr.flags = PSR_TCHAR;
- if (IsStringUIN(pszMsgField[1 + i * 2]))
- { // icq contact
- isrList[i]->uin = atoi(pszMsgField[1 + i * 2]);
- if (isrList[i]->uin == 0)
- valid = 0;
- }
- else
- { // aim contact
- if (!strlennull(pszMsgField[1 + i * 2]))
- valid = 0;
- }
- isrList[i]->hdr.id = ansi_to_tchar(pszMsgField[1 + i * 2]);
- isrList[i]->hdr.nick = ansi_to_tchar(pszMsgField[2 + i * 2]);
- }
-
- if (!valid)
- {
- NetLog_Uni(bThruDC, "Malformed '%s' message", "contacts");
- }
- else
- {
- hContact = HContactFromUIN(dwUin, &bAdded);
- sendMessageTypesAck(hContact, 0, pAckParams);
-
- ccs.szProtoService = PSR_CONTACTS;
- ccs.hContact = hContact;
- ccs.wParam = 0;
- ccs.lParam = (LPARAM)&pre;
- pre.timestamp = dwTimestamp;
- pre.szMessage = (char *)isrList;
- pre.lParam = nContacts;
- pre.flags = PREF_TCHAR;
- CallService(MS_PROTO_CHAINRECV, 0, (LPARAM)&ccs);
- }
-
- for (i = 0; i < nContacts; i++)
- {
- SAFE_FREE(&isrList[i]->hdr.id);
- SAFE_FREE(&isrList[i]->hdr.nick);
- SAFE_FREE((void**)&isrList[i]);
- }
- }
- break;
-
- case MTYPE_PLUGIN: // FIXME: this should be removed - it is never called
- hContact = NULL;
-
- switch(dwUin)
- {
- case 1111: /* icqmail 'you've got mail' - not processed */
- break;
- }
- break;
-
- case MTYPE_SMS_MESSAGE:
- /* it's a SMS message from a mobile - broadcast to SMS plugin */
- if (dwUin != 1002)
- {
- NetLog_Uni(bThruDC, "Malformed '%s' message", "SMS Mobile");
- break;
- }
- NetLog_Server("Received SMS Mobile message");
-
- BroadcastAck(NULL, ICQACKTYPE_SMS, ACKRESULT_SUCCESS, NULL, (LPARAM)szMsg);
- break;
-
- case MTYPE_STATUSMSGEXT:
- /* it's either extended StatusMsg reply from icq2003b or a IcqWebMessage */
- if (dwUin == 1003)
- {
- NetLog_Server("Received ICQWebMessage - NOT SUPPORTED");
- }
- break;
-
- case MTYPE_WWP:
- /* format: fromname FE FE FE fromemail FE unknownbyte FE 'Sender IP: xxx.xxx.xxx.xxx' 0D 0A body */
- {
- DWORD cbBlob;
- PBYTE pBlob, pCurBlob;
-
- if (nMsgFields < 6)
- {
- NetLog_Server("Malformed '%s' message", "web pager");
- break;
- }
-
- /*blob is: body(ASCIIZ), name(ASCIIZ), email(ASCIIZ) */
- cbBlob=strlennull(pszMsgField[0])+strlennull(pszMsgField[3])+strlennull(pszMsgField[5])+3;
- pCurBlob=pBlob=(PBYTE)_alloca(cbBlob);
- strcpy((char *)pCurBlob,pszMsgField[5]); pCurBlob+=strlennull((char *)pCurBlob)+1;
- strcpy((char *)pCurBlob,pszMsgField[0]); pCurBlob+=strlennull((char *)pCurBlob)+1;
- strcpy((char *)pCurBlob,pszMsgField[3]);
-
- AddEvent(NULL, ICQEVENTTYPE_WEBPAGER, dwTimestamp, 0, cbBlob, pBlob);
- }
- break;
-
- case MTYPE_EEXPRESS:
- /* format: fromname FE FE FE fromemail FE unknownbyte FE body */
- {
- DWORD cbBlob;
- PBYTE pBlob, pCurBlob;
-
- if (nMsgFields < 6)
- {
- NetLog_Server("Malformed '%s' message", "e-mail express");
- break;
- }
-
- /*blob is: body(ASCIIZ), name(ASCIIZ), email(ASCIIZ) */
- cbBlob=strlennull(pszMsgField[0])+strlennull(pszMsgField[3])+strlennull(pszMsgField[5])+3;
- pCurBlob=pBlob=(PBYTE)_alloca(cbBlob);
- strcpy((char *)pCurBlob,pszMsgField[5]); pCurBlob+=strlennull((char *)pCurBlob)+1;
- strcpy((char *)pCurBlob,pszMsgField[0]); pCurBlob+=strlennull((char *)pCurBlob)+1;
- strcpy((char *)pCurBlob,pszMsgField[3]);
-
- AddEvent(NULL, ICQEVENTTYPE_EMAILEXPRESS, dwTimestamp, 0, cbBlob, pBlob);
- }
- break;
-
- case MTYPE_REQUESTCONTACTS:
- /* it's a contacts-request */
- NetLog_Uni(bThruDC, "Received %s from %u", "Request for Contacts", dwUin);
- break;
-
- case MTYPE_GREETINGCARD:
- /* it's a greeting card */
- NetLog_Uni(bThruDC, "Received %s from %u", "Greeting Card", dwUin);
- break;
-
- case MTYPE_SCRIPT_NOTIFY:
- /* it's a xtraz notify request */
- NetLog_Uni(bThruDC, "Received %s from %u", "Xtraz Notify Request", dwUin);
- handleXtrazNotify(dwUin, dwMsgID, dwMsgID2, wCookie, szMsg, wMsgLen, bThruDC);
- break;
-
- case MTYPE_SCRIPT_INVITATION:
- /* it's a xtraz invitation to session */
- NetLog_Uni(bThruDC, "Received %s from %u", "Xtraz Invitation", dwUin);
- handleXtrazInvitation(dwUin, dwMsgID, dwMsgID2, wCookie, szMsg, wMsgLen, bThruDC);
- break;
-
- case MTYPE_SCRIPT_DATA:
- /* it's a xtraz data packet */
- NetLog_Uni(bThruDC, "Received %s from %u", "Xtraz data packet", dwUin);
- handleXtrazData(dwUin, dwMsgID, dwMsgID2, wCookie, szMsg, wMsgLen, bThruDC);
- break;
-
- case MTYPE_AUTOONLINE:
- case MTYPE_AUTOAWAY:
- case MTYPE_AUTOBUSY:
- case MTYPE_AUTONA:
- case MTYPE_AUTODND:
- case MTYPE_AUTOFFC:
- {
- char **szMsg = MirandaStatusToAwayMsg(AwayMsgTypeToStatus(type));
- if (szMsg)
- {
- struct rates_status_message_response: public rates_queue_item
- {
- protected:
- virtual rates_queue_item* copyItem(rates_queue_item *aDest = NULL)
- {
- rates_status_message_response *pDest = (rates_status_message_response*)aDest;
- if (!pDest)
- pDest = new rates_status_message_response(ppro, wGroup);
-
- pDest->bExtended = bExtended;
- pDest->dwMsgID1 = dwMsgID1;
- pDest->dwMsgID2 = dwMsgID2;
- pDest->wCookie = wCookie;
- pDest->wVersion = wVersion;
- pDest->nMsgType = nMsgType;
-
- return rates_queue_item::copyItem(pDest);
- };
- public:
- rates_status_message_response(CIcqProto *ppro, WORD wGroup): rates_queue_item(ppro, wGroup) { };
- virtual ~rates_status_message_response() { };
-
- virtual void execute()
- {
- char **pszMsg = ppro->MirandaStatusToAwayMsg(AwayMsgTypeToStatus(nMsgType));
- if (bExtended)
- ppro->icq_sendAwayMsgReplyServExt(dwUin, szUid, dwMsgID1, dwMsgID2, wCookie, wVersion, nMsgType, pszMsg);
- else if (dwUin)
- ppro->icq_sendAwayMsgReplyServ(dwUin, dwMsgID1, dwMsgID2, wCookie, wVersion, (BYTE)nMsgType, pszMsg);
- else
- ppro->NetLog_Server("Error: Malformed UIN in packet");
- };
-
- BOOL bExtended;
- DWORD dwMsgID1;
- DWORD dwMsgID2;
- WORD wCookie;
- WORD wVersion;
- int nMsgType;
- };
-
- m_ratesMutex->Enter();
- WORD wGroup = m_rates->getGroupFromSNAC(ICQ_MSG_FAMILY, ICQ_MSG_RESPONSE);
- m_ratesMutex->Leave();
-
- rates_status_message_response rr(this, wGroup);
- rr.bExtended = (nMsgFlags & MTF_STATUS_EXTENDED) == MTF_STATUS_EXTENDED;
- rr.hContact = hContact;
- rr.dwUin = dwUin;
- rr.szUid = szUID;
- rr.dwMsgID1 = dwMsgID;
- rr.dwMsgID2 = dwMsgID2;
- rr.wCookie = wCookie;
- rr.wVersion = wVersion;
- rr.nMsgType = type;
-
- handleRateItem(&rr, RQT_RESPONSE);
- }
-
- break;
- }
-
- case MTYPE_FILEREQ: // Never happens
- default:
- NetLog_Uni(bThruDC, "Unprocessed message type %d", type);
- break;
-
- }
-
- SAFE_FREE(&szMsg);
-}
-
-
-void CIcqProto::handleRecvMsgResponse(BYTE *buf, WORD wLen, WORD wFlags, DWORD dwRef)
-{
- DWORD dwUin;
- uid_str szUid;
- DWORD dwCookie;
- WORD wMessageFormat;
- WORD wStatus;
- WORD bMsgType = 0;
- BYTE bFlags;
- WORD wLength;
- HANDLE hCookieContact;
- DWORD dwMsgID1, dwMsgID2;
- WORD wVersion = 0;
- cookie_message_data *pCookieData = NULL;
-
-
- unpackLEDWord(&buf, &dwMsgID1); // Message ID
- unpackLEDWord(&buf, &dwMsgID2);
- wLen -= 8;
-
- unpackWord(&buf, &wMessageFormat);
- wLen -= 2;
- if (wMessageFormat != 2)
- {
- NetLog_Server("SNAC(4.B) Unknown type");
- return;
- }
-
- if (!unpackUID(&buf, &wLen, &dwUin, &szUid)) return;
-
- HANDLE hContact = HContactFromUID(dwUin, szUid, NULL);
-
- buf += 2; // 3. unknown
- wLen -= 2;
-
- if (!FindMessageCookie(dwMsgID1, dwMsgID2, &dwCookie, &hCookieContact, &pCookieData))
- {
- NetLog_Server("SNAC(4.B) Received an ack that I did not ask for from (%u)", dwUin);
- return;
- }
-
- if (IsValidOscarTransfer(pCookieData))
- { // it is OFT response
- handleRecvServResponseOFT(buf, wLen, dwUin, szUid, pCookieData);
- return;
- }
-
- if (!dwUin)
- { // AIM cannot send this - just sanity
- NetLog_Server("Error: Invalid UID in message response.");
- return;
- }
-
- // Length of sub chunk?
- if (wLen >= 2)
- {
- unpackLEWord(&buf, &wLength);
- wLen -= 2;
- }
- else
- wLength = 0;
-
- if (wLength == 0x1b && pCookieData->bMessageType != MTYPE_REVERSE_REQUEST)
- { // this can be v8 greeting message reply
- WORD wCookie;
-
- unpackLEWord(&buf, &wVersion);
- buf += 27; /* unknowns from the msg we sent */
- wLen -= 29;
-
- // Message sequence (SEQ2)
- unpackLEWord(&buf, &wCookie);
- wLen -= 2;
-
- // Unknown (12 bytes)
- buf += 12;
- wLen -= 12;
-
- // Message type
- unpackByte(&buf, (BYTE*)&bMsgType);
- unpackByte(&buf, &bFlags);
- wLen -= 2;
-
- // Status
- unpackLEWord(&buf, &wStatus);
- wLen -= 2;
-
- // Priority?
- buf += 2;
- wLen -= 2;
-
- if (!FindCookie(wCookie, &hCookieContact, (void**)&pCookieData))
- { // use old reliable method
- NetLog_Server("Warning: Invalid cookie in %s from (%u)", "message response", dwUin);
-
- if (pCookieData->bMessageType != MTYPE_AUTOAWAY && bFlags == 3)
- { // most probably a broken ack of some kind (e.g. from R&Q), try to fix that
- bMsgType = pCookieData->bMessageType;
- bFlags = 0;
-
- NetLog_Server("Warning: Invalid message type in %s from (%u)", "message response", dwUin);
- }
- }
- else if (bMsgType != MTYPE_PLUGIN && pCookieData->bMessageType != MTYPE_AUTOAWAY)
- { // just because some clients break it...
- dwCookie = wCookie;
-
- if (bMsgType != pCookieData->bMessageType)
- NetLog_Server("Warning: Invalid message type in %s from (%u)", "message response", dwUin);
-
- bMsgType = pCookieData->bMessageType;
- }
- else if (pCookieData->bMessageType == MTYPE_AUTOAWAY && bMsgType != MTYPE_PLUGIN)
- {
- if (bMsgType != pCookieData->nAckType)
- NetLog_Server("Warning: Invalid message type in %s from (%u)", "message response", dwUin);
- }
- }
- else
- {
- bMsgType = pCookieData->bMessageType;
- bFlags = 0;
- }
-
- if (hCookieContact != hContact)
- {
- NetLog_Server("SNAC(4.B) Ack Contact does not match Cookie Contact(0x%x != 0x%x)", hContact, hCookieContact);
-
- ReleaseCookie(dwCookie); // This could be a bad idea, but I think it is safe
- return;
- }
-
- if (bFlags == 3) // A status message reply
- {
- handleStatusMsgReply("SNAC(4.B) ", hContact, dwUin, wVersion, bMsgType, (WORD)dwCookie, (char*)(buf + 2), 0);
- }
- else
- { // An ack of some kind
- int ackType;
-
-
- if (hContact == NULL || hContact == INVALID_HANDLE_VALUE)
- {
- NetLog_Server("SNAC(4.B) Message from unknown contact (%u)", dwUin);
-
- ReleaseCookie(dwCookie); // This could be a bad idea, but I think it is safe
- return;
- }
-
- switch (bMsgType) {
-
- case MTYPE_FILEREQ:
- {
- char* szMsg;
- WORD wMsgLen;
-
- // Message length
- unpackLEWord(&buf, &wMsgLen);
- wLen -= 2;
- szMsg = (char *)_alloca(wMsgLen + 1);
- szMsg[wMsgLen] = '\0';
- if (wMsgLen > 0)
- {
- memcpy(szMsg, buf, wMsgLen);
- buf += wMsgLen;
- wLen -= wMsgLen;
- }
- handleFileAck(buf, wLen, dwUin, dwCookie, wStatus, szMsg);
- // No success protoack will be sent here, since all file requests
- // will have been 'sent' when the server returns its ack
- return;
- }
-
- case MTYPE_PLUGIN:
- {
- WORD wMsgLen;
- DWORD dwLengthToEnd;
- DWORD dwDataLen;
- int typeId;
- WORD wFunctionId;
-
-
- if (wLength != 0x1B)
- {
- NetLog_Server("Invalid Greeting %s", "message response");
-
- ReleaseCookie(dwCookie);
- return;
- }
-
- NetLog_Server("Parsing Greeting %s", "message response");
-
- // Message
- unpackLEWord(&buf, &wMsgLen);
- wLen -= 2;
- buf += wMsgLen;
- wLen -= wMsgLen;
-
- // This packet is malformed. Possibly a file accept from Miranda IM 0.1.2.1
- if (wLen < 20)
- {
- ReleaseCookie(dwCookie);
- return;
- }
-
- if (!unpackPluginTypeId(&buf, &wLen, &typeId, &wFunctionId, FALSE))
- {
- ReleaseCookie(dwCookie);
- return;
- }
-
- if (wLen < 4)
- {
- NetLog_Server("Error: Invalid greeting %s", "message response");
-
- ReleaseCookie(dwCookie);
- return;
- }
-
- // Length of remaining data
- unpackLEDWord(&buf, &dwLengthToEnd);
- wLen -= 4;
-
- if (wLen >= 4 && dwLengthToEnd > 0)
- unpackLEDWord(&buf, &dwDataLen); // Length of message
- else
- dwDataLen = 0;
-
-
- switch (typeId)
- {
- case MTYPE_PLAIN:
- if (pCookieData && pCookieData->bMessageType == MTYPE_AUTOAWAY && dwLengthToEnd >= 4)
- { // ICQ 6 invented this
- char *szMsg = (char*)_alloca(dwDataLen + 1);
-
- if (dwDataLen > 0)
- memcpy(szMsg, buf, dwDataLen);
- szMsg[dwDataLen] = '\0';
- handleStatusMsgReply("SNAC(4.B) ", hContact, dwUin, wVersion, pCookieData->nAckType, (WORD)dwCookie, szMsg, 0);
-
- ReleaseCookie(dwCookie);
- return;
- }
- else
- ackType = ACKTYPE_MESSAGE;
- break;
-
- case MTYPE_URL:
- ackType = ACKTYPE_URL;
- break;
-
- case MTYPE_CONTACTS:
- ackType = ACKTYPE_CONTACTS;
- break;
-
- case MTYPE_FILEREQ:
- {
- NetLog_Server("This is file ack");
-
- char *szMsg = (char *)_alloca(dwDataLen + 1);
-
- if (dwDataLen > 0)
- memcpy(szMsg, buf, dwDataLen);
- szMsg[dwDataLen] = '\0';
- buf += dwDataLen;
- wLen -= (WORD)dwDataLen;
-
- handleFileAck(buf, wLen, dwUin, dwCookie, wStatus, szMsg);
- // No success protoack will be sent here, since all file requests
- // will have been 'sent' when the server returns its ack
- }
- return;
-
- case MTYPE_SCRIPT_NOTIFY:
- {
- char *szMsg = (char*)_alloca(dwDataLen + 1);
-
- if (dwDataLen > 0)
- memcpy(szMsg, buf, dwDataLen);
- szMsg[dwDataLen] = '\0';
-
- handleXtrazNotifyResponse(dwUin, hContact, (WORD)dwCookie, szMsg, dwDataLen);
-
- ReleaseCookie(dwCookie);
- }
- return;
-
- case MTYPE_STATUSMSGEXT:
- { // handle Away Message response (ICQ 6)
- char *szMsg = (char*)SAFE_MALLOC(dwDataLen + 1);
-
- if (dwDataLen > 0)
- memcpy(szMsg, buf, dwDataLen);
- szMsg[dwDataLen] = '\0';
- szMsg = EliminateHtml(szMsg, dwDataLen);
-
- handleStatusMsgReply("SNAC(4.B) ", hContact, dwUin, wVersion, pCookieData->nAckType, (WORD)dwCookie, szMsg, MTF_PLUGIN | MTF_STATUS_EXTENDED);
-
- SAFE_FREE(&szMsg);
-
- ReleaseCookie(dwCookie);
- }
- return;
-
- default:
- NetLog_Server("Error: Unknown plugin message response, type %d.", typeId);
- return;
- }
- }
- break;
-
- case MTYPE_PLAIN:
- ackType = ACKTYPE_MESSAGE;
- break;
-
- case MTYPE_URL:
- ackType = ACKTYPE_URL;
- break;
-
- case MTYPE_AUTHOK:
- case MTYPE_AUTHDENY:
- ackType = ACKTYPE_AUTHREQ;
- break;
-
- case MTYPE_ADDED:
- ackType = ACKTYPE_ADDED;
- break;
-
- case MTYPE_CONTACTS:
- ackType = ACKTYPE_CONTACTS;
- break;
-
- case MTYPE_REVERSE_REQUEST:
- {
- cookie_reverse_connect *pReverse = (cookie_reverse_connect*)pCookieData;
-
- if (pReverse->ft)
- {
- filetransfer *ft = (filetransfer*)pReverse->ft;
-
- BroadcastAck(ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft, 0);
- }
- NetLog_Server("Reverse Connect request failed");
- // Set DC status to failed
- setSettingByte(hContact, "DCStatus", 2);
-
- ReleaseCookie(dwCookie);
- }
- return;
-
- case MTYPE_CHAT:
- default:
- NetLog_Server("SNAC(4.B) Unknown message type (%u) in switch", bMsgType);
- return;
- }
-
- if ((ackType == MTYPE_PLAIN && pCookieData && (pCookieData->nAckType == ACKTYPE_CLIENT)) || ackType != MTYPE_PLAIN)
- {
- BroadcastAck(hContact, ackType, ACKRESULT_SUCCESS, (HANDLE)(WORD)dwCookie, 0);
- }
- }
-
- ReleaseCookie(dwCookie);
-}
-
-
-// A response to a CLI_SENDMSG
-void CIcqProto::handleRecvServMsgError(BYTE *buf, WORD wLen, WORD wFlags, DWORD dwSequence)
-{
- WORD wError;
- char *pszErrorMessage;
- HANDLE hContact;
- cookie_message_data *pCookieData = NULL;
- int nMessageType;
-
-
- if (wLen < 2)
- return;
-
- if (FindCookie((WORD)dwSequence, &hContact, (void**)&pCookieData))
- { // all packet cookies from msg family has command 0 in the queue
- DWORD dwUin;
- uid_str szUid;
-
- if (getContactUid(hContact, &dwUin, &szUid))
- { // Invalid contact
- FreeCookie((WORD)dwSequence);
- return;
- }
-
- // Error code
- unpackWord(&buf, &wError);
-
- if (wError == 9 && pCookieData->bMessageType == MTYPE_AUTOAWAY)
- { // we failed to request away message the normal way, try it AIM way
- icq_packet packet;
-
- serverPacketInit(&packet, (WORD)(13 + getUINLen(dwUin)));
- packFNACHeader(&packet, ICQ_LOCATION_FAMILY, ICQ_LOCATION_REQ_USER_INFO, 0, (WORD)dwSequence);
- packWord(&packet, 0x03);
- packUIN(&packet, dwUin);
-
- sendServPacket(&packet);
- return;
- }
-
- // Not all of these are actually used in family 4
- // This will be moved into a special error handling function later
- switch (wError) {
-
- case 0x0002: // Server rate limit exceeded
- pszErrorMessage = Translate("You are sending too fast. Wait a while and try again.\r\nSNAC(4.1) Error x02");
- break;
-
- case 0x0003: // Client rate limit exceeded
- pszErrorMessage = Translate("You are sending too fast. Wait a while and try again.\r\nSNAC(4.1) Error x03");
- break;
-
- case 0x0004: // Recipient is not logged in (resend in a offline message)
- if (pCookieData->bMessageType == MTYPE_PLAIN)
- {
- if (pCookieData->isOffline)
- { // offline failed - most probably to AIM contact
- pszErrorMessage = Translate("The contact does not support receiving offline messages.");
- break;
- }
- // TODO: this needs better solution
- setSettingWord(hContact, "Status", ID_STATUS_OFFLINE);
- }
- pszErrorMessage = Translate("The user has logged off. Select 'Retry' to send an offline message.\r\nSNAC(4.1) Error x04");
- break;
-
- case 0x0005: // Requested service unavailable
- pszErrorMessage = Translate("The messaging service is temporarily unavailable. Wait a while and try again.\r\nSNAC(4.1) Error x05");
- break;
-
- case 0x0009: // Not supported by client (resend in a simpler format)
- pszErrorMessage = Translate("The receiving client does not support this type of message.\r\nSNAC(4.1) Error x09");
- break;
-
- case 0x000A: // Refused by client
- pszErrorMessage = Translate("You sent too long message. The receiving client does not support it.\r\nSNAC(4.1) Error x0A");
- break;
-
- case 0x000E: // Incorrect SNAC format
- pszErrorMessage = Translate("The SNAC format was rejected by the server.\nSNAC(4.1) Error x0E");
- break;
-
- case 0x0013: // User temporarily unavailable
- pszErrorMessage = Translate("The user is temporarily unavailable. Wait a while and try again.\r\nSNAC(4.1) Error x13");
- break;
-
- case 0x0001: // Invalid SNAC header
- case 0x0006: // Requested service not defined
- case 0x0007: // You sent obsolete SNAC
- case 0x0008: // Not supported by server
- case 0x000B: // Reply too big
- case 0x000C: // Responses lost
- case 0x000D: // Request denied
- case 0x000F: // Insufficient rights
- case 0x0010: // In local permit/deny (recipient blocked)
- case 0x0011: // Sender too evil
- case 0x0012: // Receiver too evil
- case 0x0014: // No match
- case 0x0015: // List overflow
- case 0x0016: // Request ambiguous
- case 0x0017: // Server queue full
- case 0x0018: // Not while on AOL
- default:
- if (pszErrorMessage = (char*)_alloca(256))
- null_snprintf(pszErrorMessage, 256, Translate("SNAC(4.1) SENDMSG Error (x%02x)"), wError);
- break;
- }
-
-
- switch (pCookieData->bMessageType) {
-
- case MTYPE_PLAIN:
- nMessageType = ACKTYPE_MESSAGE;
- break;
-
- case MTYPE_CHAT:
- nMessageType = ACKTYPE_CHAT;
- break;
-
- case MTYPE_FILEREQ:
- nMessageType = ACKTYPE_FILE;
- break;
-
- case MTYPE_URL:
- nMessageType = ACKTYPE_URL;
- break;
-
- case MTYPE_CONTACTS:
- nMessageType = ACKTYPE_CONTACTS;
- break;
-
- default:
- nMessageType = -1;
- break;
- }
-
- if (nMessageType != -1)
- {
- BroadcastAck(hContact, nMessageType, ACKRESULT_FAILED, (HANDLE)(WORD)dwSequence, (LPARAM)pszErrorMessage);
- }
- else
- {
- NetLog_Server("Error: Message delivery to %u failed: %s", dwUin, pszErrorMessage);
- }
-
- FreeCookie((WORD)dwSequence);
-
- if (pCookieData->bMessageType != MTYPE_FILEREQ)
- SAFE_FREE((void**)&pCookieData);
- }
- else
- {
- unpackWord(&buf, &wError);
-
- LogFamilyError(ICQ_MSG_FAMILY, wError);
- }
-}
-
-
-void CIcqProto::handleServerAck(BYTE *buf, WORD wLen, WORD wFlags, DWORD dwSequence)
-{
- DWORD dwUin;
- uid_str szUID;
- WORD wChannel;
- cookie_message_data *pCookieData;
-
-
- if (wLen < 13)
- {
- NetLog_Server("Ignoring SNAC(4,C) Packet to short");
- return;
- }
-
- buf += 8; // Skip first 8 bytes
- wLen -= 8;
-
- // Message channel
- unpackWord(&buf, &wChannel);
- wLen -= 2;
-
- // Sender
- if (!unpackUID(&buf, &wLen, &dwUin, &szUID)) return;
-
- HANDLE hContact = HContactFromUID(dwUin, szUID, NULL);
-
- if (FindCookie((WORD)dwSequence, NULL, (void**)&pCookieData))
- {
- // If the user requested a full ack, the
- // server ack should be ignored here.
- if (pCookieData && (pCookieData->nAckType == ACKTYPE_SERVER))
- {
- if ((hContact != NULL) && (hContact != INVALID_HANDLE_VALUE))
- {
- int ackType;
- int ackRes = ACKRESULT_SUCCESS;
-
- switch (pCookieData->bMessageType) {
- case MTYPE_PLAIN:
- ackType = ACKTYPE_MESSAGE;
- break;
-
- case MTYPE_CONTACTS:
- ackType = ACKTYPE_CONTACTS;
- break;
-
- case MTYPE_URL:
- ackType = ACKTYPE_URL;
- break;
-
- case MTYPE_FILEREQ:
- ackType = ACKTYPE_FILE;
- ackRes = ACKRESULT_SENTREQUEST;
- // Note 1: We are not allowed to free the cookie here because it
- // contains the filetransfer struct that we will need later
- // Note 2: The cookiedata is NOT a message_cookie_data*, it is a
- // filetransfer*. IMPORTANT! (it's one of those silly things)
- break;
-
- default:
- ackType = -1;
- NetLog_Server("Error: Unknown message type %d in ack", pCookieData->bMessageType);
- break;
- }
- if (ackType != -1)
- BroadcastAck(hContact, ackType, ackRes, (HANDLE)(WORD)dwSequence, 0);
-
- if (pCookieData->bMessageType != MTYPE_FILEREQ)
- SAFE_FREE((void**)&pCookieData); // this could be a bad idea, but I think it is safe
- }
- FreeCookie((WORD)dwSequence);
- }
- else if (pCookieData && (pCookieData->nAckType == ACKTYPE_CLIENT))
- NetLog_Server("Received a server ack, waiting for client ack.");
- else
- NetLog_Server("Ignored a server ack I did not ask for");
- }
-}
-
-
-void CIcqProto::handleMissedMsg(BYTE *buf, WORD wLen, WORD wFlags, DWORD dwRef)
-{
- DWORD dwUin;
- uid_str szUid;
- WORD wChannel;
- WORD wWarningLevel;
- WORD wCount;
- WORD wError;
- WORD wTLVCount;
-
- if (wLen < 14)
- return; // Too short
-
- // Message channel?
- unpackWord(&buf, &wChannel);
- wLen -= 2;
-
- // Sender
- if (!unpackUID(&buf, &wLen, &dwUin, &szUid)) return;
-
- if (wLen < 8)
- return; // Too short
-
- // Warning level?
- unpackWord(&buf, &wWarningLevel);
- wLen -= 2;
-
- // TLV count
- unpackWord(&buf, &wTLVCount);
- wLen -= 2;
-
- // Read past user info TLVs
- oscar_tlv_chain *pChain = readIntoTLVChain(&buf, (WORD)(wLen-4), wTLVCount);
- if (pChain)
- disposeChain(&pChain);
-
- if (wLen < 4)
- return; // Too short
-
- // Number of missed messages
- unpackWord(&buf, &wCount);
- wLen -= 2;
-
- // Error code
- unpackWord(&buf, &wError);
- wLen -= 2;
-
- { // offline retrieval process in progress, note that we received missed message notification
- cookie_offline_messages *cookie;
-
- if (FindCookieByType(CKT_OFFLINEMESSAGE, NULL, NULL, (void**)&cookie))
- cookie->nMissed++;
- }
-
- switch (wError) {
-
- case 0: // The message was invalid
- case 1: // The message was too long
- case 2: // The sender has flooded the server
- case 4: // You are too evil
- break;
-
- default:
- // 3 = Sender too evil (sender warn level > your max_msg_sevil)
- return;
- break;
- }
-
- // Create event to notify user
- int bAdded;
-
- AddEvent(HContactFromUID(dwUin, szUid, &bAdded), ICQEVENTTYPE_MISSEDMESSAGE, time(NULL), 0, sizeof(wError), (PBYTE)&wError);
-}
-
-
-void CIcqProto::handleOffineMessagesReply(BYTE *buf, WORD wLen, WORD wFlags, DWORD dwRef)
-{
- cookie_offline_messages *cookie;
-
- if (FindCookie(dwRef, NULL, (void**)&cookie))
- {
- NetLog_Server("End of offline msgs, %u received", cookie->nMessages);
- if (cookie->nMissed)
- { // NASTY WORKAROUND!!
- // The ICQ server has a bug that causes offline messages to be received again and again when some
- // missed message notification is present (most probably it is not processed correctly and causes
- // the server to fail the purging process); try to purge them using the old offline messages
- // protocol. 2008/05/21
- NetLog_Server("Warning: Received %u missed message notifications, trying to fix the server.", cookie->nMissed);
-
- icq_packet packet;
- // This will delete the messages stored on server
- serverPacketInit(&packet, 24);
- packFNACHeader(&packet, ICQ_EXTENSIONS_FAMILY, ICQ_META_CLI_REQUEST);
- packWord(&packet, 1); // TLV Type
- packWord(&packet, 10); // TLV Length
- packLEWord(&packet, 8); // Data length
- packLEDWord(&packet, m_dwLocalUIN); // My UIN
- packLEWord(&packet, CLI_DELETE_OFFLINE_MSGS_REQ); // Ack offline msgs
- packLEWord(&packet, 0x0000); // Request sequence number (we dont use this for now)
-
- // Send it
- sendServPacket(&packet);
- }
-
- ReleaseCookie(dwRef);
- }
- else
- NetLog_Server("Error: Received unexpected end of offline msgs.");
-}
-
-
-void CIcqProto::handleTypingNotification(BYTE *buf, WORD wLen, WORD wFlags, DWORD dwRef)
-{
- DWORD dwUin;
- uid_str szUid;
- WORD wChannel;
- WORD wNotification;
-
- if (wLen < 14)
- {
- NetLog_Server("Ignoring SNAC(4.x11) Packet to short");
- return;
- }
-
-#ifndef DBG_CAPMTN
- {
- NetLog_Server("Ignoring unexpected typing notification");
- return;
- }
-#endif
-
- // The message ID, unused?
- buf += 8;
- wLen -= 8;
-
- // Message channel, unused?
- unpackWord(&buf, &wChannel);
- wLen -= 2;
-
- // Sender
- if (!unpackUID(&buf, &wLen, &dwUin, &szUid)) return;
-
- HANDLE hContact = HContactFromUID(dwUin, szUid, NULL);
-
- if (hContact == INVALID_HANDLE_VALUE) return;
-
- // Typing notification code
- unpackWord(&buf, &wNotification);
- wLen -= 2;
-
- SetContactCapabilities(hContact, CAPF_TYPING);
-
- // Notify user
- switch (wNotification) {
-
- case MTN_FINISHED:
- case MTN_TYPED:
- CallService(MS_PROTO_CONTACTISTYPING, (WPARAM)hContact, (LPARAM)PROTOTYPE_CONTACTTYPING_OFF);
- NetLog_Server("%s has stopped typing (ch %u).", strUID(dwUin, szUid), wChannel);
- break;
-
- case MTN_BEGUN:
- CallService(MS_PROTO_CONTACTISTYPING, (WPARAM)hContact, (LPARAM)60);
- NetLog_Server("%s is typing a message (ch %u).", strUID(dwUin, szUid), wChannel);
- break;
-
- case MTN_WINDOW_CLOSED:
- {
- char szFormat[MAX_PATH];
- char szMsg[MAX_PATH];
- char *nick = NickFromHandleUtf(hContact);
-
- null_snprintf(szMsg, MAX_PATH, ICQTranslateUtfStatic(LPGEN("Contact \"%s\" has closed the message window."), szFormat, MAX_PATH), nick);
- ShowPopUpMsg(hContact, ICQTranslateUtfStatic(LPGEN("ICQ Note"), szFormat, MAX_PATH), szMsg, LOG_NOTE);
- SAFE_FREE((void**)&nick);
-
- NetLog_Server("%s has closed the message window.", strUID(dwUin, szUid));
- }
- break;
-
- default:
- NetLog_Server("Unknown typing notification from %s, type %u (ch %u)", strUID(dwUin, szUid), wNotification, wChannel);
- break;
- }
-}
-
-
-void CIcqProto::sendTypingNotification(HANDLE hContact, WORD wMTNCode)
-{
- _ASSERTE((wMTNCode == MTN_FINISHED) || (wMTNCode == MTN_TYPED) || (wMTNCode == MTN_BEGUN) || (wMTNCode == MTN_WINDOW_CLOSED));
-
- DWORD dwUin;
- uid_str szUid;
- if (getContactUid(hContact, &dwUin, &szUid))
- return; // Invalid contact
-
- WORD wLen = getUIDLen(dwUin, szUid);
-
- icq_packet packet;
- serverPacketInit(&packet, 23 + wLen);
- packFNACHeader(&packet, ICQ_MSG_FAMILY, ICQ_MSG_MTN);
- packLEDWord(&packet, 0x0000); // Msg ID
- packLEDWord(&packet, 0x0000); // Msg ID
- packWord(&packet, 0x01); // Channel
- packUID(&packet, dwUin, szUid); // User ID
- packWord(&packet, wMTNCode); // Notification type
-
- sendServPacketAsync(&packet);
-}