From cb4a46e7fbe62d788e66ed6121c717a2d22a4d7c Mon Sep 17 00:00:00 2001 From: watcherhd Date: Thu, 21 Apr 2011 14:14:52 +0000 Subject: svn.miranda.im is moving to a new home! git-svn-id: http://miranda-plugins.googlecode.com/svn/trunk@7 e753b5eb-9565-29b2-b5c5-2cc6f99dfbcb --- miranda-wine/protocols/IcqOscarJ/icq_directmsg.c | 418 +++++++++++++++++++++++ 1 file changed, 418 insertions(+) create mode 100644 miranda-wine/protocols/IcqOscarJ/icq_directmsg.c (limited to 'miranda-wine/protocols/IcqOscarJ/icq_directmsg.c') diff --git a/miranda-wine/protocols/IcqOscarJ/icq_directmsg.c b/miranda-wine/protocols/IcqOscarJ/icq_directmsg.c new file mode 100644 index 0000000..3c94ce5 --- /dev/null +++ b/miranda-wine/protocols/IcqOscarJ/icq_directmsg.c @@ -0,0 +1,418 @@ +// ---------------------------------------------------------------------------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,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater +// Copyright © 2004,2005,2006 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// ----------------------------------------------------------------------------- +// +// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icq_directmsg.c,v $ +// Revision : $Revision: 2874 $ +// Last change on : $Date: 2006-05-17 01:38:00 +0400 (Срд, 17 Май 2006) $ +// Last change by : $Author: ghazan $ +// +// DESCRIPTION: +// +// Describe me here please... +// +// ----------------------------------------------------------------------------- + +#include "icqoscar.h" + + + +extern WORD wListenPort; + +void icq_sendAwayMsgReplyDirect(directconnect *dc, WORD wCookie, BYTE msgType, const char **szMsg); + +void handleDirectGreetingMessage(directconnect *dc, PBYTE buf, WORD wLen, WORD wCommand, WORD wCookie, BYTE bMsgType, BYTE bMsgFlags, WORD wStatus, WORD wFlags, char* pszText); + + + +void handleDirectMessage(directconnect* dc, PBYTE buf, WORD wLen) +{ + WORD wCommand; + WORD wCookie; + BYTE bMsgType,bMsgFlags; + WORD wStatus; + WORD wFlags; + WORD wTextLen; + char* pszText = NULL; + + + // The first part of the packet should always be at least 31 bytes + if (wLen < 31) + { + NetLog_Direct("Error during parsing of DC packet 2 PEER_MSG (too short)"); + return; + } + + // Skip packet checksum + buf += 4; + wLen -= 4; + + // Command: + // 0x07d0 = 2000 - cancel given message. + // 0x07da = 2010 - acknowledge message. + // 0x07ee = 2030 - normal message/request. + unpackLEWord(&buf, &wCommand); + wLen -= 2; + + // Unknown, always 0xe (14) + buf += 2; + wLen -= 2; + + // Sequence number + unpackLEWord(&buf, &wCookie); + wLen -=2; + + // Unknown, always zeroes + buf += 12; + wLen -= 12; + + // Peer message type + unpackByte(&buf, &bMsgType); + // Peer message flags + unpackByte(&buf, &bMsgFlags); + wLen -= 2; + + // The current status of the user, or whether the message was accepted or not. + // 0x00 - user is online, or message was receipt, or file transfer accepted + // 0x01 - refused + // 0x04 - auto-refused, because of away + // 0x09 - auto-refused, because of occupied + // 0x0a - auto-refused, because of dnd + // 0x0e - auto-refused, because of na + unpackLEWord(&buf, &wStatus); + wLen -= 2; + + // Flags, or priority + // Seen: 1 - Chat request + // 0 - File auto accept (type 3) + // 33 - priority ? + unpackLEWord(&buf, &wFlags); + wLen -= 2; + + // Messagetext. This is either the status message or the actual message + // when this is a PEER_MSG_MSG packet + unpackLEWord(&buf, &wTextLen); + if (wTextLen > 0) + { + pszText = _alloca(wTextLen+1); + unpackString(&buf, pszText, wTextLen); + pszText[wTextLen] = '\0'; + } + wLen = (wLen - 2) - wTextLen; + +#ifdef _DEBUG + NetLog_Direct("Handling PEER_MSG '%s', command %u, cookie %u, messagetype %u, messageflags %u, status %u, flags %u", pszText, wCommand, wCookie, bMsgType, bMsgFlags, wStatus, wFlags); +#else + NetLog_Direct("Message through direct - UID: %u", dc->dwRemoteUin); +#endif + + // The remaining actual message is handled either as a status message request, + // a greeting message, a acknowledge or a normal (text, url, file) message + if (wCommand == DIRECT_MESSAGE) + switch (bMsgType) + { + case MTYPE_FILEREQ: // File inits + handleFileRequest(buf, wLen, dc->dwRemoteUin, wCookie, 0, 0, pszText, 7, TRUE); + break; + + case MTYPE_AUTOAWAY: + case MTYPE_AUTOBUSY: + case MTYPE_AUTONA: + case MTYPE_AUTODND: + case MTYPE_AUTOFFC: + { + char** szMsg = MirandaStatusToAwayMsg(AwayMsgTypeToStatus(bMsgType)); + + if (szMsg) + icq_sendAwayMsgReplyDirect(dc, wCookie, bMsgType, szMsg); + } + break; + + case MTYPE_PLUGIN: // Greeting + handleDirectGreetingMessage(dc, buf, wLen, wCommand, wCookie, bMsgType, bMsgFlags, wStatus, wFlags, pszText); + break; + + default: + { + buf -= wTextLen; + wLen += wTextLen; + + handleMessageTypes(dc->dwRemoteUin, time(NULL), 0, 0, wCookie, dc->wVersion, (int)bMsgType, (int)bMsgFlags, 0, (DWORD)wLen, wTextLen, buf, TRUE); + + // Send acknowledgement + if (bMsgType == MTYPE_PLAIN || bMsgType == MTYPE_URL || bMsgType == MTYPE_CONTACTS) + { + icq_sendDirectMsgAck(dc, wCookie, bMsgType, bMsgFlags, CAP_RTFMSGS); + } + break; + } + } + else if (wCommand == DIRECT_ACK) + { + if (bMsgFlags == 3) + { // this is status reply + buf -= wTextLen; + wLen += wTextLen; + + handleMessageTypes(dc->dwRemoteUin, time(NULL), 0, 0, wCookie, dc->wVersion, (int)bMsgType, (int)bMsgFlags, 2, (DWORD)wLen, wTextLen, buf, TRUE); + } + else + { + DWORD dwCookieUin; + message_cookie_data* pCookieData = NULL; + + if (!FindCookie(wCookie, &dwCookieUin, &pCookieData)) + { + NetLog_Direct("Received an unexpected direct ack"); + } + else if (dwCookieUin != dc->dwRemoteUin) + { + NetLog_Direct("Direct UIN does not match Cookie UIN(%u != %u)", dc->dwRemoteUin, dwCookieUin); + ReleaseCookie(wCookie); // This could be a bad idea, but I think it is safe + } + else + { // the ack is correct + int ackType = -1; + + switch (bMsgType) + { + case MTYPE_PLAIN: + ackType = ACKTYPE_MESSAGE; + break; + case MTYPE_URL: + ackType = ACKTYPE_URL; + break; + case MTYPE_CONTACTS: + ackType = ACKTYPE_CONTACTS; + break; + + case MTYPE_FILEREQ: // File acks + handleFileAck(buf, wLen, dc->dwRemoteUin, wCookie, wStatus, pszText); + break; + + case MTYPE_PLUGIN: // Greeting + handleDirectGreetingMessage(dc, buf, wLen, wCommand, wCookie, bMsgType, bMsgFlags, wStatus, wFlags, pszText); + break; + + default: + NetLog_Direct("Skipped packet from direct connection"); + break; + } + if (ackType != -1) + { // was a good ack to broadcast ? + ICQBroadcastAck(dc->hContact, ackType, ACKRESULT_SUCCESS, (HANDLE)wCookie, 0); + ReleaseCookie(wCookie); + } + } + } + } + else if (wCommand == DIRECT_CANCEL) + { + NetLog_Direct("Cannot handle abort messages yet... :("); + } + else + NetLog_Direct("Unknown wCommand, packet skipped"); +} + + + +void handleDirectGreetingMessage(directconnect* dc, PBYTE buf, WORD wLen, WORD wCommand, WORD wCookie, BYTE bMsgType, BYTE bMsgFlags, WORD wStatus, WORD wFlags, char* pszText) +{ + DWORD dwMsgTypeLen; + DWORD dwLengthToEnd; + DWORD dwDataLength; + char* szMsgType = NULL; + char* pszFileName = NULL; + int typeId; + WORD wPacketCommand; + DWORD q1,q2,q3,q4; + WORD qt; + +#ifdef _DEBUG + NetLog_Direct("Handling PEER_MSG_GREETING, command %u, cookie %u, messagetype %u, messageflags %u, status %u, flags %u", wCommand, wCookie, bMsgType, bMsgFlags, wStatus, wFlags); +#endif + + // The command in this packet. + unpackLEWord(&buf, &wPacketCommand); // TODO: this is most probably length... + wLen -= 2; + + // Data type GUID + unpackDWord(&buf, &q1); + unpackDWord(&buf, &q2); + unpackDWord(&buf, &q3); + unpackDWord(&buf, &q4); + wLen -= 16; + + // Data type function id + unpackLEWord(&buf, &qt); + wLen -= 2; + + // A text string + // "ICQ Chat" for chat request, "File" for file request, + // "File Transfer" for file request grant/refusal. This text is + // displayed in the requester opened by Windows. + unpackLEDWord(&buf, &dwMsgTypeLen); + wLen -= 4; + if (dwMsgTypeLen == 0 || dwMsgTypeLen>256) + { + NetLog_Direct("Error: Sanity checking failed (%d) in handleDirectGreetingMessage, len is %u", 1, dwMsgTypeLen); + return; + } + szMsgType = (char *)_alloca(dwMsgTypeLen + 1); + memcpy(szMsgType, buf, dwMsgTypeLen); + szMsgType[dwMsgTypeLen] = '\0'; + typeId = TypeGUIDToTypeId(q1,q2,q3,q4,qt); + if (!typeId) + NetLog_Direct("Error: Unknown type {%04x%04x%04x%04x-%02x}: %s", q1,q2,q3,q4,qt,szMsgType); + + buf += dwMsgTypeLen; + wLen -= (WORD)dwMsgTypeLen; + + NetLog_Direct("PEER_MSG_GREETING, command: %u, type: %s, typeID: %u", typeId, szMsgType, typeId); + + // Unknown + buf += 15; + wLen -= 15; + + // Length of remaining data + unpackLEDWord(&buf, &dwLengthToEnd); + if (dwLengthToEnd < 4 || dwLengthToEnd > wLen) + { + NetLog_Direct("Error: Sanity checking failed (%d) in handleDirectGreetingMessage, datalen %u wLen %u", 2, dwLengthToEnd, wLen); + return; + } + + // Length of message/reason + unpackLEDWord(&buf, &dwDataLength); + wLen -= 4; + if (dwDataLength > wLen) + { + NetLog_Direct("Error: Sanity checking failed (%d) in handleDirectGreetingMessage, datalen %u wLen %u", 3, dwDataLength, wLen); + return; + } + + if (typeId == MTYPE_FILEREQ && wCommand == DIRECT_MESSAGE) + { + char* szMsg; + + NetLog_Direct("This is file request"); + szMsg = _alloca(dwDataLength+1); + unpackString(&buf, szMsg, (WORD)dwDataLength); + szMsg[dwDataLength] = '\0'; + wLen = wLen - (WORD)dwDataLength; + + handleFileRequest(buf, wLen, dc->dwRemoteUin, wCookie, 0, 0, szMsg, 8, TRUE); + } + else if (typeId == MTYPE_FILEREQ && wCommand == DIRECT_ACK) + { + char* szMsg; + + NetLog_Direct("This is file ack"); + szMsg = _alloca(dwDataLength+1); + unpackString(&buf, szMsg, (WORD)dwDataLength); + szMsg[dwDataLength] = '\0'; + wLen = wLen - (WORD)dwDataLength; + + // 50 - file request granted/refused + handleFileAck(buf, wLen, dc->dwRemoteUin, wCookie, wStatus, szMsg); + } + else if (typeId && wCommand == DIRECT_MESSAGE) + { + if (typeId == MTYPE_URL || typeId == MTYPE_CONTACTS) + { + icq_sendDirectMsgAck(dc, wCookie, (BYTE)typeId, 0, CAP_RTFMSGS); + } + handleMessageTypes(dc->dwRemoteUin, time(NULL), 0, 0, wCookie, dc->wVersion, typeId, 0, 0, dwLengthToEnd, (WORD)dwDataLength, buf, TRUE); + } + else if (typeId == MTYPE_STATUSMSGEXT && wCommand == DIRECT_ACK) + { // especially for icq2003b + char* szMsg; + + NetLog_Direct("This is extended status reply"); + szMsg = _alloca(dwDataLength+1); + unpackString(&buf, szMsg, (WORD)dwDataLength); + szMsg[dwDataLength] = '\0'; + + handleMessageTypes(dc->dwRemoteUin, time(NULL), 0, 0, wCookie, dc->wVersion, (int)(qt + 0xE7), 3, 2, (DWORD)wLen, (WORD)dwDataLength, szMsg, TRUE); + } + else if (typeId && wCommand == DIRECT_ACK) + { + DWORD dwCookieUin; + message_cookie_data* pCookieData = NULL; + + if (!FindCookie(wCookie, &dwCookieUin, &pCookieData)) + { + NetLog_Direct("Received an unexpected direct ack"); + } + else if (dwCookieUin != dc->dwRemoteUin) + { + NetLog_Direct("Direct UIN does not match Cookie UIN(%u != %u)", dc->dwRemoteUin, dwCookieUin); + ReleaseCookie(wCookie); // This could be a bad idea, but I think it is safe + } + else + { + int ackType = -1; + + switch (typeId) + { + case MTYPE_MESSAGE: + ackType = ACKTYPE_MESSAGE; + break; + case MTYPE_URL: + ackType = ACKTYPE_URL; + break; + case MTYPE_CONTACTS: + ackType = ACKTYPE_CONTACTS; + break; + case MTYPE_SCRIPT_NOTIFY: + { + char *szMsg; + + szMsg = (char*)_alloca(dwDataLength + 1); + if (dwDataLength > 0) + memcpy(szMsg, buf, dwDataLength); + szMsg[dwDataLength] = '\0'; + + handleXtrazNotifyResponse(dwCookieUin, dc->hContact, wCookie, szMsg, dwDataLength); + } + break; + + default: + NetLog_Direct("Skipped packet from direct connection"); + break; + } + + if (ackType != -1) + { // was a good ack to broadcast ? + ICQBroadcastAck(dc->hContact, ackType, ACKRESULT_SUCCESS, (HANDLE)wCookie, 0); + } + // Release cookie + ReleaseCookie(wCookie); + } + } + else + { + NetLog_Direct("Unsupported plugin message type '%s'", szMsgType); + } +} -- cgit v1.2.3