summaryrefslogtreecommitdiff
path: root/protocols/IcqOscarJ/icq_packet.cpp
diff options
context:
space:
mode:
authorVadim Dashevskiy <watcherhd@gmail.com>2012-05-15 10:38:20 +0000
committerVadim Dashevskiy <watcherhd@gmail.com>2012-05-15 10:38:20 +0000
commit48540940b6c28bb4378abfeb500ec45a625b37b6 (patch)
tree2ef294c0763e802f91d868bdef4229b6868527de /protocols/IcqOscarJ/icq_packet.cpp
parent5c350913f011e119127baeb32a6aedeb4f0d33bc (diff)
initial commit
git-svn-id: http://svn.miranda-ng.org/main/trunk@2 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'protocols/IcqOscarJ/icq_packet.cpp')
-rw-r--r--protocols/IcqOscarJ/icq_packet.cpp908
1 files changed, 908 insertions, 0 deletions
diff --git a/protocols/IcqOscarJ/icq_packet.cpp b/protocols/IcqOscarJ/icq_packet.cpp
new file mode 100644
index 0000000000..7642c82ace
--- /dev/null
+++ b/protocols/IcqOscarJ/icq_packet.cpp
@@ -0,0 +1,908 @@
+// ---------------------------------------------------------------------------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, Bio
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $URL: http://miranda.googlecode.com/svn/trunk/miranda/protocols/IcqOscarJ/icq_packet.cpp $
+// Revision : $Revision: 13213 $
+// Last change on : $Date: 2010-12-22 08:54:39 +0200 (Ср, 22 дек 2010) $
+// Last change by : $Author: borkra $
+//
+// DESCRIPTION:
+//
+// Describe me here please...
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+WORD generate_flap_sequence()
+{
+ DWORD n = rand(), s = 0;
+
+ for (DWORD i = n; i >>= 3; s += i);
+
+ return (((0 - s) ^ (BYTE)n) & 7 ^ n) + 2;
+}
+
+void __fastcall init_generic_packet(icq_packet *pPacket, WORD wHeaderLen)
+{
+ pPacket->wPlace = 0;
+ pPacket->wLen += wHeaderLen;
+ pPacket->pData = (BYTE*)SAFE_MALLOC(pPacket->wLen);
+}
+
+void write_httphdr(icq_packet *pPacket, WORD wType, DWORD dwSeq)
+{
+ init_generic_packet(pPacket, 14);
+
+ packWord(pPacket, (WORD)(pPacket->wLen - 2));
+ packWord(pPacket, HTTP_PROXY_VERSION);
+ packWord(pPacket, wType);
+ packDWord(pPacket, 0); // Flags?
+ packDWord(pPacket, dwSeq); // Connection sequence ?
+}
+
+void __fastcall write_flap(icq_packet *pPacket, BYTE byFlapChannel)
+{
+ init_generic_packet(pPacket, 6);
+
+ pPacket->nChannel = byFlapChannel;
+
+ packByte(pPacket, FLAP_MARKER);
+ packByte(pPacket, byFlapChannel);
+ packWord(pPacket, 0); // This is the sequence ID, it is filled in during the actual sending
+ packWord(pPacket, (WORD)(pPacket->wLen - 6)); // This counter should not include the flap header (thus the -6)
+}
+
+void __fastcall serverPacketInit(icq_packet *pPacket, WORD wSize)
+{
+ pPacket->wLen = wSize;
+ write_flap(pPacket, ICQ_DATA_CHAN);
+}
+
+void __fastcall directPacketInit(icq_packet *pPacket, DWORD dwSize)
+{
+ pPacket->wPlace = 0;
+ pPacket->wLen = (WORD)dwSize;
+ pPacket->pData = (BYTE *)SAFE_MALLOC(dwSize + 2);
+
+ packLEWord(pPacket, pPacket->wLen);
+}
+
+void __fastcall serverCookieInit(icq_packet *pPacket, BYTE *pCookie, WORD wCookieSize)
+{
+ pPacket->wLen = (WORD)(wCookieSize + 8 + sizeof(CLIENT_ID_STRING) + 66);
+
+ write_flap(pPacket, ICQ_LOGIN_CHAN);
+ packDWord(pPacket, 0x00000001);
+ packTLV(pPacket, 0x06, wCookieSize, pCookie);
+
+ // Pack client identification details.
+ packTLV(pPacket, 0x0003, (WORD)sizeof(CLIENT_ID_STRING)-1, (LPBYTE)CLIENT_ID_STRING);
+ packTLVWord(pPacket, 0x0017, CLIENT_VERSION_MAJOR);
+ packTLVWord(pPacket, 0x0018, CLIENT_VERSION_MINOR);
+ packTLVWord(pPacket, 0x0019, CLIENT_VERSION_LESSER);
+ packTLVWord(pPacket, 0x001a, CLIENT_VERSION_BUILD);
+ packTLVWord(pPacket, 0x0016, CLIENT_ID_CODE);
+ packTLVDWord(pPacket, 0x0014, CLIENT_DISTRIBUTION);
+ packTLV(pPacket, 0x000f, 0x0002, (LPBYTE)CLIENT_LANGUAGE);
+ packTLV(pPacket, 0x000e, 0x0002, (LPBYTE)CLIENT_COUNTRY);
+ packDWord(pPacket, 0x00940001); // reconnect flag
+ packByte(pPacket, 0);
+ packTLVDWord(pPacket, 0x8003, 0x00100000); // Unknown
+}
+
+void __fastcall packByte(icq_packet *pPacket, BYTE byValue)
+{
+ pPacket->pData[pPacket->wPlace++] = byValue;
+}
+
+void __fastcall packWord(icq_packet *pPacket, WORD wValue)
+{
+ pPacket->pData[pPacket->wPlace++] = ((wValue & 0xff00) >> 8);
+ pPacket->pData[pPacket->wPlace++] = (wValue & 0x00ff);
+}
+
+void __fastcall packDWord(icq_packet *pPacket, DWORD dwValue)
+{
+ pPacket->pData[pPacket->wPlace++] = (BYTE)((dwValue & 0xff000000) >> 24);
+ pPacket->pData[pPacket->wPlace++] = (BYTE)((dwValue & 0x00ff0000) >> 16);
+ pPacket->pData[pPacket->wPlace++] = (BYTE)((dwValue & 0x0000ff00) >> 8);
+ pPacket->pData[pPacket->wPlace++] = (BYTE) (dwValue & 0x000000ff);
+}
+
+void __fastcall packQWord(icq_packet *pPacket, DWORD64 qwValue)
+{
+ packDWord(pPacket, (DWORD)(qwValue >> 32));
+ packDWord(pPacket, (DWORD)(qwValue & 0xffffffff));
+}
+
+void packTLV(icq_packet *pPacket, WORD wType, WORD wLength, const BYTE *pbyValue)
+{
+ packWord(pPacket, wType);
+ packWord(pPacket, wLength);
+ packBuffer(pPacket, pbyValue, wLength);
+}
+
+void packTLVWord(icq_packet *pPacket, WORD wType, WORD wValue)
+{
+ packWord(pPacket, wType);
+ packWord(pPacket, 0x02);
+ packWord(pPacket, wValue);
+}
+
+void packTLVDWord(icq_packet *pPacket, WORD wType, DWORD dwValue)
+{
+ packWord(pPacket, wType);
+ packWord(pPacket, 0x04);
+ packDWord(pPacket, dwValue);
+}
+
+
+void packTLVUID(icq_packet *pPacket, WORD wType, DWORD dwUin, const char *szUid)
+{
+ if (dwUin)
+ {
+ char szUin[UINMAXLEN];
+
+ _ltoa(dwUin, szUin, 10);
+
+ packTLV(pPacket, wType, getUINLen(dwUin), (BYTE*)szUin);
+ }
+ else if (szUid)
+ packTLV(pPacket, wType, strlennull(szUid), (BYTE*)szUid);
+}
+
+
+// Pack a preformatted buffer.
+// This can be used to pack strings or any type of raw data.
+void packBuffer(icq_packet *pPacket, const BYTE* pbyBuffer, WORD wLength)
+{
+ while (wLength)
+ {
+ pPacket->pData[pPacket->wPlace++] = *pbyBuffer++;
+ wLength--;
+ }
+}
+
+// Pack a buffer and prepend it with the size as a LE WORD.
+// Commented out since its not actually used anywhere right now.
+//void packLEWordSizedBuffer(icq_packet* pPacket, const BYTE* pbyBuffer, WORD wLength)
+//{
+//
+// packLEWord(pPacket, wLength);
+// packBuffer(pPacket, pbyBuffer, wLength);
+//
+//}
+
+int __fastcall getUINLen(DWORD dwUin)
+{ // TODO: invent something more clever
+ if (dwUin >= 1000000000) return 10;
+ if (dwUin >= 100000000) return 9;
+ if (dwUin >= 10000000) return 8;
+ if (dwUin >= 1000000) return 7;
+ if (dwUin >= 100000) return 6;
+ if (dwUin >= 10000) return 5;
+ if (dwUin >= 1000) return 4;
+ if (dwUin >= 100) return 3;
+ if (dwUin >= 10) return 2;
+ return 1;
+}
+
+int __fastcall getUIDLen(DWORD dwUin, const char *szUid)
+{
+ if (dwUin)
+ return getUINLen(dwUin);
+ else
+ return strlennull(szUid);
+}
+
+void __fastcall packUIN(icq_packet *pPacket, DWORD dwUin)
+{
+ char pszUin[UINMAXLEN];
+ BYTE nUinLen = getUINLen(dwUin);
+
+ _ltoa(dwUin, pszUin, 10);
+
+ packByte(pPacket, nUinLen); // Length of user id
+ packBuffer(pPacket, (LPBYTE)pszUin, nUinLen); // Receiving user's id
+}
+
+void __fastcall packUID(icq_packet *pPacket, DWORD dwUin, const char *szUid)
+{
+ if (dwUin)
+ packUIN(pPacket, dwUin);
+ else
+ {
+ BYTE nLen = strlennull(szUid);
+ packByte(pPacket, nLen);
+ packBuffer(pPacket, (LPBYTE)szUid, nLen);
+ }
+}
+
+
+void packFNACHeader(icq_packet *pPacket, WORD wFamily, WORD wSubtype)
+{
+ packFNACHeader(pPacket, wFamily, wSubtype, 0, wSubtype << 0x10);
+}
+
+
+void packFNACHeader(icq_packet *pPacket, WORD wFamily, WORD wSubtype, WORD wFlags, DWORD dwSequence)
+{
+ WORD wSequence = (WORD)dwSequence & 0x7FFF; // this is necessary, if that bit is there we get disconnected
+
+ packWord(pPacket, wFamily); // Family type
+ packWord(pPacket, wSubtype); // Family subtype
+ packWord(pPacket, wFlags); // SNAC flags
+ packWord(pPacket, wSequence); // SNAC request id (sequence)
+ packWord(pPacket, (WORD)(dwSequence >> 0x10)); // SNAC request id (command)
+}
+
+
+void packFNACHeader(icq_packet *pPacket, WORD wFamily, WORD wSubtype, WORD wFlags, DWORD dwSequence, WORD wVersion)
+{
+ packFNACHeader(pPacket, wFamily, wSubtype, wFlags | 0x8000, dwSequence);
+ packWord(pPacket, 0x06);
+ packTLVWord(pPacket, 0x01, wVersion);
+}
+
+
+void __fastcall packLEWord(icq_packet *pPacket, WORD wValue)
+{
+ pPacket->pData[pPacket->wPlace++] = (wValue & 0x00ff);
+ pPacket->pData[pPacket->wPlace++] = ((wValue & 0xff00) >> 8);
+}
+
+void __fastcall packLEDWord(icq_packet *pPacket, DWORD dwValue)
+{
+ pPacket->pData[pPacket->wPlace++] = (BYTE) (dwValue & 0x000000ff);
+ pPacket->pData[pPacket->wPlace++] = (BYTE)((dwValue & 0x0000ff00) >> 8);
+ pPacket->pData[pPacket->wPlace++] = (BYTE)((dwValue & 0x00ff0000) >> 16);
+ pPacket->pData[pPacket->wPlace++] = (BYTE)((dwValue & 0xff000000) >> 24);
+}
+
+
+/* helper function to place numerics to buffer */
+static void packWord(PBYTE buf, WORD wValue)
+{
+ *(buf) = ((wValue & 0xff00) >> 8);
+ *(buf + 1) = (wValue & 0x00ff);
+}
+
+
+static void packDWord(PBYTE buf, DWORD dwValue)
+{
+ *(buf) = (BYTE)((dwValue & 0xff000000) >> 24);
+ *(buf + 1) = (BYTE)((dwValue & 0x00ff0000) >> 16);
+ *(buf + 2) = (BYTE)((dwValue & 0x0000ff00) >> 8);
+ *(buf + 3) = (BYTE) (dwValue & 0x000000ff);
+}
+
+
+static void packQWord(PBYTE buf, DWORD64 qwValue)
+{
+ packDWord(buf, (DWORD)(qwValue >> 32));
+ packDWord(buf + 4, (DWORD)(qwValue & 0xffffffff));
+}
+
+
+void ppackByte(PBYTE *buf, int *buflen, BYTE byValue)
+{
+ *buf = (PBYTE)SAFE_REALLOC(*buf, 1 + *buflen);
+ *(*buf + *buflen) = byValue;
+ ++*buflen;
+}
+
+
+void ppackWord(PBYTE *buf, int *buflen, WORD wValue)
+{
+ *buf = (PBYTE)SAFE_REALLOC(*buf, 2 + *buflen);
+ packWord(*buf + *buflen, wValue);
+ *buflen += 2;
+}
+
+
+void ppackLEWord(PBYTE *buf, int *buflen, WORD wValue)
+{
+ *buf=(PBYTE)SAFE_REALLOC(*buf, 2 + *buflen);
+ *(PWORD)(*buf + *buflen) = wValue;
+ *buflen+=2;
+}
+
+
+void ppackLEDWord(PBYTE *buf, int *buflen, DWORD dwValue)
+{
+ *buf = (PBYTE)SAFE_REALLOC(*buf, 4 + *buflen);
+ *(PDWORD)(*buf + *buflen) = dwValue;
+ *buflen += 4;
+}
+
+
+void ppackLELNTS(PBYTE *buf, int *buflen, const char *str)
+{
+ WORD len = strlennull(str);
+ ppackLEWord(buf, buflen, len);
+ *buf = (PBYTE)SAFE_REALLOC(*buf, *buflen + len);
+ memcpy(*buf + *buflen, str, len);
+ *buflen += len;
+}
+
+
+void ppackBuffer(PBYTE *buf, int *buflen, WORD wLength, const BYTE *pbyValue)
+{
+ if (wLength)
+ {
+ *buf = (PBYTE)SAFE_REALLOC(*buf, wLength + *buflen);
+ memcpy(*buf + *buflen, pbyValue, wLength);
+ *buflen += wLength;
+ }
+}
+
+
+void ppackTLV(PBYTE *buf, int *buflen, WORD wType, WORD wLength, const BYTE *pbyValue)
+{
+ *buf = (PBYTE)SAFE_REALLOC(*buf, 4 + wLength + *buflen);
+ packWord(*buf + *buflen, wType);
+ packWord(*buf + *buflen + 2, wLength);
+ if (wLength)
+ memcpy(*buf + *buflen + 4, pbyValue, wLength);
+ *buflen += 4 + wLength;
+}
+
+
+void ppackTLVByte(PBYTE *buf, int *buflen, WORD wType, BYTE byValue)
+{
+ *buf = (PBYTE)SAFE_REALLOC(*buf, 5 + *buflen);
+ packWord(*buf + *buflen, wType);
+ packWord(*buf + *buflen + 2, 1);
+ *(*buf + *buflen + 4) = byValue;
+ *buflen += 5;
+}
+
+
+void ppackTLVWord(PBYTE *buf, int *buflen, WORD wType, WORD wValue)
+{
+ *buf = (PBYTE)SAFE_REALLOC(*buf, 6 + *buflen);
+ packWord(*buf + *buflen, wType);
+ packWord(*buf + *buflen + 2, 2);
+ packWord(*buf + *buflen + 4, wValue);
+ *buflen += 6;
+}
+
+
+void ppackTLVDWord(PBYTE *buf, int *buflen, WORD wType, DWORD dwValue)
+{
+ *buf = (PBYTE)SAFE_REALLOC(*buf, 8 + *buflen);
+ packWord(*buf + *buflen, wType);
+ packWord(*buf + *buflen + 2, 4);
+ packDWord(*buf + *buflen + 4, dwValue);
+ *buflen += 8;
+}
+
+
+void ppackTLVDouble(PBYTE *buf, int *buflen, WORD wType, double dValue)
+{
+ DWORD64 qwValue;
+
+ memcpy(&qwValue, &dValue, 8);
+
+ *buf = (PBYTE)SAFE_REALLOC(*buf, 12 + *buflen);
+ packWord(*buf + *buflen, wType);
+ packWord(*buf + *buflen + 2, 8);
+ packQWord(*buf + *buflen + 4, qwValue);
+ *buflen += 12;
+}
+
+
+void ppackTLVUID(PBYTE *buf, int *buflen, WORD wType, DWORD dwUin, const char *szUid)
+{
+ if (dwUin)
+ {
+ char szUin[UINMAXLEN];
+
+ _ltoa(dwUin, szUin, 10);
+
+ ppackTLV(buf, buflen, wType, getUINLen(dwUin), (BYTE*)szUin);
+ }
+ else if (szUid)
+ ppackTLV(buf, buflen, wType, strlennull(szUid), (BYTE*)szUid);
+}
+
+
+// *** TLV based (!!! WORDs and DWORDs are LE !!!)
+void ppackLETLVByte(PBYTE *buf, int *buflen, BYTE byValue, WORD wType, BYTE always)
+{
+ if (!always && !byValue) return;
+
+ *buf = (PBYTE)SAFE_REALLOC(*buf, 5 + *buflen);
+ *(PWORD)(*buf + *buflen) = wType;
+ *(PWORD)(*buf + *buflen + 2) = 1;
+ *(*buf + *buflen + 4) = byValue;
+ *buflen += 5;
+}
+
+
+void ppackLETLVWord(PBYTE *buf, int *buflen, WORD wValue, WORD wType, BYTE always)
+{
+ if (!always && !wValue) return;
+
+ *buf = (PBYTE)SAFE_REALLOC(*buf, 6 + *buflen);
+ *(PWORD)(*buf + *buflen) = wType;
+ *(PWORD)(*buf + *buflen + 2) = 2;
+ *(PWORD)(*buf + *buflen + 4) = wValue;
+ *buflen += 6;
+}
+
+
+void ppackLETLVDWord(PBYTE *buf, int *buflen, DWORD dwValue, WORD wType, BYTE always)
+{
+ if (!always && !dwValue) return;
+
+ *buf = (PBYTE)SAFE_REALLOC(*buf, 8 + *buflen);
+ *(PWORD)(*buf + *buflen) = wType;
+ *(PWORD)(*buf + *buflen + 2) = 4;
+ *(PDWORD)(*buf + *buflen + 4) = dwValue;
+ *buflen += 8;
+}
+
+
+void packLETLVLNTS(PBYTE *buf, int *bufpos, const char *str, WORD wType)
+{
+ int len = strlennull(str) + 1;
+
+ *(PWORD)(*buf + *bufpos) = wType;
+ *(PWORD)(*buf + *bufpos + 2) = len + 2;
+ *(PWORD)(*buf + *bufpos + 4) = len;
+ memcpy(*buf + *bufpos + 6, str, len);
+ *bufpos += len + 6;
+}
+
+
+void ppackLETLVLNTS(PBYTE *buf, int *buflen, const char *str, WORD wType, BYTE always)
+{
+ int len = strlennull(str) + 1;
+
+ if (!always && len < 2) return;
+
+ *buf = (PBYTE)SAFE_REALLOC(*buf, 6 + *buflen + len);
+ packLETLVLNTS(buf, buflen, str, wType);
+}
+
+
+void ppackLETLVWordLNTS(PBYTE *buf, int *buflen, WORD w, const char *str, WORD wType, BYTE always)
+{
+ int len = strlennull(str) + 1;
+
+ if (!always && len < 2 && !w) return;
+
+ *buf = (PBYTE)SAFE_REALLOC(*buf, 8 + *buflen + len);
+ *(PWORD)(*buf + *buflen) = wType;
+ *(PWORD)(*buf + *buflen + 2) = len + 4;
+ *(PWORD)(*buf + *buflen + 4) = w;
+ *(PWORD)(*buf + *buflen + 6) = len;
+ memcpy(*buf + *buflen + 8, str, len);
+ *buflen += len + 8;
+}
+
+
+void ppackLETLVLNTSByte(PBYTE *buf, int *buflen, const char *str, BYTE b, WORD wType)
+{
+ int len = strlennull(str) + 1;
+
+ *buf = (PBYTE)SAFE_REALLOC(*buf, 7 + *buflen + len);
+ *(PWORD)(*buf + *buflen) = wType;
+ *(PWORD)(*buf + *buflen + 2) = len + 3;
+ *(PWORD)(*buf + *buflen + 4) = len;
+ memcpy(*buf + *buflen + 6, str, len);
+ *(*buf + *buflen + 6 + len) = b;
+ *buflen += len + 7;
+}
+
+
+void CIcqProto::ppackLETLVLNTSfromDB(PBYTE *buf, int *buflen, const char *szSetting, WORD wType)
+{
+ char szTmp[1024];
+ char *str = "";
+
+ if (!getSettingStringStatic(NULL, szSetting, szTmp, sizeof(szTmp)))
+ str = szTmp;
+
+ ppackLETLVLNTS(buf, buflen, str, wType, 1);
+}
+
+void CIcqProto::ppackLETLVWordLNTSfromDB(PBYTE *buf, int *buflen, WORD w, const char *szSetting, WORD wType)
+{
+ char szTmp[1024];
+ char *str = "";
+
+ if (!getSettingStringStatic(NULL, szSetting, szTmp, sizeof(szTmp)))
+ str = szTmp;
+
+ ppackLETLVWordLNTS(buf, buflen, w, str, wType, 1);
+}
+
+void CIcqProto::ppackLETLVLNTSBytefromDB(PBYTE *buf, int *buflen, const char *szSetting, BYTE b, WORD wType)
+{
+ char szTmp[1024];
+ char *str = "";
+
+ if (!getSettingStringStatic(NULL, szSetting, szTmp, sizeof(szTmp)))
+ str = szTmp;
+
+ ppackLETLVLNTSByte(buf, buflen, str, b, wType);
+}
+
+
+void CIcqProto::ppackTLVStringFromDB(PBYTE *buf, int *buflen, const char *szSetting, WORD wType)
+{
+ char szTmp[1024];
+ char *str = "";
+
+ if (!getSettingStringStatic(NULL, szSetting, szTmp, sizeof(szTmp)))
+ str = szTmp;
+
+ ppackTLV(buf, buflen, wType, strlennull(str), (PBYTE)str);
+}
+
+
+void CIcqProto::ppackTLVStringUtfFromDB(PBYTE *buf, int *buflen, const char *szSetting, WORD wType)
+{
+ char *str = getSettingStringUtf(NULL, szSetting, NULL);
+
+ ppackTLV(buf, buflen, wType, strlennull(str), (PBYTE)str);
+
+ SAFE_FREE((void**)&str);
+}
+
+
+void CIcqProto::ppackTLVDateFromDB(PBYTE *buf, int *buflen, const char *szSettingYear, const char *szSettingMonth, const char *szSettingDay, WORD wType)
+{
+ SYSTEMTIME sTime = {0};
+ double time = 0;
+
+ sTime.wYear = getSettingWord(NULL, szSettingYear, 0);
+ sTime.wMonth = getSettingByte(NULL, szSettingMonth, 0);
+ sTime.wDay = getSettingByte(NULL, szSettingDay, 0);
+ if (sTime.wYear || sTime.wMonth || sTime.wDay)
+ {
+ SystemTimeToVariantTime(&sTime, &time);
+ time -= 2;
+ }
+
+ ppackTLVDouble(buf, buflen, wType, time);
+}
+
+
+int CIcqProto::ppackTLVWordStringItemFromDB(PBYTE *buf, int *buflen, const char *szSetting, WORD wTypeID, WORD wTypeData, WORD wID)
+{
+ char szTmp[1024];
+ char *str = NULL;
+
+ if (!getSettingStringStatic(NULL, szSetting, szTmp, sizeof(szTmp)))
+ str = szTmp;
+
+ if (str)
+ {
+ WORD wLen = strlennull(str);
+
+ ppackWord(buf, buflen, wLen + 0x0A);
+ ppackTLVWord(buf, buflen, wTypeID, wID);
+ ppackTLV(buf, buflen, wTypeData, wLen, (PBYTE)str);
+
+ return 1; // Success
+ }
+
+ return 0; // No data
+}
+
+
+int CIcqProto::ppackTLVWordStringUtfItemFromDB(PBYTE *buf, int *buflen, const char *szSetting, WORD wTypeID, WORD wTypeData, WORD wID)
+{
+ char *str = getSettingStringUtf(NULL, szSetting, NULL);
+
+ if (str)
+ {
+ WORD wLen = strlennull(str);
+
+ ppackWord(buf, buflen, wLen + 0x0A);
+ ppackTLVWord(buf, buflen, wTypeID, wID);
+ ppackTLV(buf, buflen, wTypeData, wLen, (PBYTE)str);
+
+ SAFE_FREE(&str);
+
+ return 1; // Success
+ }
+
+ return 0; // No data
+}
+
+
+void ppackTLVBlockItems(PBYTE *buf, int *buflen, WORD wType, int *nItems, PBYTE *pBlock, WORD *wLength, BOOL bSingleItem)
+{
+ *buf = (PBYTE)SAFE_REALLOC(*buf, 8 + *buflen + *wLength);
+ packWord(*buf + *buflen, wType);
+ packWord(*buf + *buflen + 2, (bSingleItem ? 4 : 2) + *wLength);
+ packWord(*buf + *buflen + 4, *nItems);
+ if (bSingleItem)
+ packWord(*buf + *buflen + 6, *wLength);
+ if (*wLength)
+ memcpy(*buf + *buflen + (bSingleItem ? 8 : 6), *pBlock, *wLength);
+ *buflen += (bSingleItem ? 8 : 6) + *wLength;
+
+ SAFE_FREE((void**)pBlock);
+ *wLength = 0;
+ *nItems = 0;
+}
+
+
+void ppackTLVBlockItem(PBYTE *buf, int *buflen, WORD wType, PBYTE *pItem, WORD *wLength)
+{
+ if (wLength)
+ {
+ *buf = (PBYTE)SAFE_REALLOC(*buf, 8 + *buflen + *wLength);
+ packWord(*buf + *buflen, wType);
+ packWord(*buf + *buflen + 2, 4 + *wLength);
+ packWord(*buf + *buflen + 4, 1);
+ packWord(*buf + *buflen + 6, *wLength);
+ memcpy(*buf + *buflen + 8, *pItem, *wLength);
+ *buflen += 8 + *wLength;
+ }
+ else
+ {
+ *buf = (PBYTE)SAFE_REALLOC(*buf, 6 + *buflen);
+ packWord(*buf + *buflen, wType);
+ packWord(*buf + *buflen + 2, 0x02);
+ packWord(*buf + *buflen + 4, 0);
+ *buflen += 6;
+ }
+
+ SAFE_FREE((void**)pItem);
+ *wLength = 0;
+}
+
+
+void __fastcall unpackByte(BYTE **pSource, BYTE *byDestination)
+{
+ if (byDestination)
+ *byDestination = *(*pSource)++;
+ else
+ *pSource += 1;
+}
+
+void __fastcall unpackWord(BYTE **pSource, WORD *wDestination)
+{
+ BYTE *tmp = *pSource;
+
+ if (wDestination)
+ {
+ *wDestination = *tmp++ << 8;
+ *wDestination |= *tmp++;
+
+ *pSource = tmp;
+ }
+ else
+ *pSource += 2;
+}
+
+void __fastcall unpackDWord(BYTE **pSource, DWORD *dwDestination)
+{
+ BYTE *tmp = *pSource;
+
+ if (dwDestination)
+ {
+ *dwDestination = *tmp++ << 24;
+ *dwDestination |= *tmp++ << 16;
+ *dwDestination |= *tmp++ << 8;
+ *dwDestination |= *tmp++;
+
+ *pSource = tmp;
+ }
+ else
+ *pSource += 4;
+}
+
+void __fastcall unpackQWord(BYTE **pSource, DWORD64 *qwDestination)
+{
+ DWORD dwData;
+
+ if (qwDestination)
+ {
+ unpackDWord(pSource, &dwData);
+ *qwDestination = ((DWORD64)dwData) << 32;
+ unpackDWord(pSource, &dwData);
+ *qwDestination |= dwData;
+ }
+ else
+ *pSource += 8;
+}
+
+void __fastcall unpackLEWord(BYTE **buf, WORD *w)
+{
+ BYTE *tmp = *buf;
+
+ if (w)
+ {
+ *w = (*tmp++);
+ *w |= ((*tmp++) << 8);
+ }
+ else
+ tmp += 2;
+
+ *buf = tmp;
+}
+
+void __fastcall unpackLEDWord(BYTE **buf, DWORD *dw)
+{
+ BYTE *tmp = *buf;
+
+ if (dw)
+ {
+ *dw = (*tmp++);
+ *dw |= ((*tmp++) << 8);
+ *dw |= ((*tmp++) << 16);
+ *dw |= ((*tmp++) << 24);
+ }
+ else
+ tmp += 4;
+
+ *buf = tmp;
+}
+
+void unpackString(BYTE **buf, char *string, WORD len)
+{
+ BYTE *tmp = *buf;
+
+ if (string)
+ {
+ while (len) /* Can have 0x00 so go by len */
+ {
+ *string++ = *tmp++;
+ len--;
+ }
+ }
+ else
+ tmp += len;
+
+ *buf = tmp;
+}
+
+void unpackWideString(BYTE **buf, WCHAR *string, WORD len)
+{
+ BYTE *tmp = *buf;
+
+ while (len > 1)
+ {
+ *string = (*tmp++ << 8);
+ *string |= *tmp++;
+
+ string++;
+ len -= 2;
+ }
+
+ // We have a stray byte at the end, this means that the buffer had an odd length
+ // which indicates an error.
+ _ASSERTE(len == 0);
+ if (len != 0)
+ {
+ // We dont copy the last byte but we still need to increase the buffer pointer
+ // (we assume that 'len' was correct) since the calling function expects
+ // that it is increased 'len' bytes.
+ *tmp += len;
+ }
+
+ *buf = tmp;
+}
+
+void unpackTypedTLV(BYTE *buf, int buflen, WORD type, WORD *ttype, WORD *tlen, BYTE **ttlv)
+{
+ WORD wType, wLen;
+
+NextTLV:
+ // Unpack type and length
+ unpackWord(&buf, &wType);
+ unpackWord(&buf, &wLen);
+ buflen -= 4;
+
+ if (wType != type && buflen >= wLen + 4)
+ { // Not the right TLV, try next
+ buflen -= wLen;
+ buf += wLen;
+ goto NextTLV;
+ }
+ // Check buffer size
+ if (wLen > buflen) wLen = buflen;
+
+ // Make sure we have a good pointer
+ if (ttlv)
+ {
+ if (wLen)
+ { // Unpack and save value
+ *ttlv = (BYTE*)SAFE_MALLOC(wLen + 1); // Add 1 for \0
+ unpackString(&buf, (char*)*ttlv, wLen);
+ *(*ttlv + wLen) = '\0';
+ }
+ else
+ *ttlv = NULL;
+ }
+
+ // Save type and length
+ if (ttype)
+ *ttype = wType;
+ if (tlen)
+ *tlen = wLen;
+}
+
+
+BOOL CIcqProto::unpackUID(BYTE **ppBuf, WORD *pwLen, DWORD *pdwUIN, uid_str *ppszUID)
+{
+ BYTE nUIDLen;
+
+ // sanity check
+ if (!ppBuf || !pwLen || *pwLen < 1)
+ return FALSE;
+
+ // Sender UIN
+ unpackByte(ppBuf, &nUIDLen);
+ *pwLen -= 1;
+
+ if ((nUIDLen > *pwLen) || (nUIDLen == 0))
+ return FALSE;
+
+ if (nUIDLen <= UINMAXLEN)
+ { // it can be uin, check
+ char szUIN[UINMAXLEN+1];
+
+ unpackString(ppBuf, szUIN, nUIDLen);
+ szUIN[nUIDLen] = '\0';
+ *pwLen -= nUIDLen;
+
+ if (IsStringUIN(szUIN))
+ {
+ *pdwUIN = atoi(szUIN);
+ return TRUE;
+ }
+ else
+ { // go back
+ *ppBuf -= nUIDLen;
+ *pwLen += nUIDLen;
+ }
+ }
+ if (!m_bAimEnabled || !ppszUID || !(*ppszUID))
+ { // skip the UID data
+ *ppBuf += nUIDLen;
+ *pwLen -= nUIDLen;
+
+ NetLog_Server("Malformed UIN in packet");
+ return FALSE;
+ }
+
+ unpackString(ppBuf, *ppszUID, nUIDLen);
+ *pwLen -= nUIDLen;
+ (*ppszUID)[nUIDLen] = '\0';
+
+ *pdwUIN = 0; // this is how we determine aim contacts internally
+
+ return TRUE;
+}