diff options
author | Kirill Volinsky <Mataes2007@gmail.com> | 2017-11-30 07:57:29 +0300 |
---|---|---|
committer | Kirill Volinsky <Mataes2007@gmail.com> | 2017-11-30 07:57:29 +0300 |
commit | 6532896923fdf6e3d3b341ce21153b913fcda3dc (patch) | |
tree | aeccfbfbb5d4995d146eb62fd61fa7e4207dfcb1 /protocols/Tlen/src/tlen_thread.cpp | |
parent | cc3d5628fade322f81abad8715d3d2ab031bc8b6 (diff) |
Tlen moved to deprecated (#1050)
Diffstat (limited to 'protocols/Tlen/src/tlen_thread.cpp')
-rw-r--r-- | protocols/Tlen/src/tlen_thread.cpp | 1321 |
1 files changed, 0 insertions, 1321 deletions
diff --git a/protocols/Tlen/src/tlen_thread.cpp b/protocols/Tlen/src/tlen_thread.cpp deleted file mode 100644 index 0cbe1c4819..0000000000 --- a/protocols/Tlen/src/tlen_thread.cpp +++ /dev/null @@ -1,1321 +0,0 @@ -/*
-
-Jabber Protocol Plugin for Miranda IM
-Tlen Protocol Plugin for Miranda NG
-Copyright (C) 2002-2004 Santithorn Bunchua
-Copyright (C) 2004-2007 Piotr Piastucki
-
-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.
-
-*/
-
-#include "stdafx.h"
-
-#include "commons.h"
-#include "tlen_list.h"
-#include "tlen_iq.h"
-#include "resource.h"
-#include "tlen_p2p_old.h"
-#include "tlen_file.h"
-#include "tlen_muc.h"
-#include "tlen_voice.h"
-#include "tlen_avatar.h"
-#include "tlen_presence.h"
-#include "tlen_picture.h"
-#include <io.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-
-extern void __cdecl TlenProcessP2P(XmlNode *node, ThreadData *info);
-
-
-//static void __cdecl TlenProcessInvitation(struct ThreadData *info);
-static void __cdecl TlenKeepAliveThread(void *ptr);
-static void TlenProcessStreamOpening(XmlNode *node, ThreadData *info);
-static void TlenProcessStreamClosing(XmlNode *node, ThreadData *info);
-static void TlenProcessProtocol(XmlNode *node, ThreadData *info);
-static void TlenProcessMessage(XmlNode *node, ThreadData *info);
-static void TlenProcessIq(XmlNode *node, ThreadData *info);
-static void TlenProcessW(XmlNode *node, ThreadData *info);
-static void TlenProcessM(XmlNode *node, ThreadData *info);
-static void TlenProcessN(XmlNode *node, ThreadData *info);
-static void TlenProcessP(XmlNode *node, ThreadData *info);
-static void TlenProcessV(XmlNode *node, ThreadData *info);
-static void TlenProcessAvatar(XmlNode* node, ThreadData *info);
-static void TlenProcessCipher(XmlNode *node, ThreadData *info);
-
-static VOID NTAPI TlenDummyApcFunc(ULONG_PTR)
-{
- return;
-}
-
-static char onlinePassword[128];
-static HANDLE hEventPasswdDlg;
-
-static INT_PTR CALLBACK TlenPasswordDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
-{
- char text[128];
-
- switch (msg) {
- case WM_INITDIALOG:
- TranslateDialogDefault(hwndDlg);
- mir_snprintf(text, Translate("Enter password for %s"), (char *) lParam);
- SetDlgItemTextA(hwndDlg, IDC_JID, text);
- return TRUE;
- case WM_COMMAND:
- switch (LOWORD(wParam)) {
- case IDOK:
- GetDlgItemTextA(hwndDlg, IDC_PASSWORD, onlinePassword, _countof(onlinePassword));
- //EndDialog(hwndDlg, (int) onlinePassword);
- //return TRUE;
- // Fall through
- case IDCANCEL:
- //EndDialog(hwndDlg, 0);
- SetEvent(hEventPasswdDlg);
- DestroyWindow(hwndDlg);
- return TRUE;
- }
- break;
- }
-
- return FALSE;
-}
-
-static VOID NTAPI TlenPasswordCreateDialogApcProc(ULONG_PTR param)
-{
- CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_PASSWORD), nullptr, TlenPasswordDlgProc, (LPARAM) param);
-}
-
-void __cdecl TlenServerThread(ThreadData *info)
-{
- char *connectHost;
- int datalen;
- XmlState xmlState;
- int tlenNetworkBufferSize;
- int oldStatus = ID_STATUS_OFFLINE;
- int reconnectMaxTime;
- int numRetry;
- int reconnectTime;
- int loginErr = 0;
- info->proto->debugLogA("Thread started");
-
- // Normal server connection, we will fetch all connection parameters
- // e.g. username, password, etc. from the database.
-
- if (info->proto->threadData != nullptr) {
- // Will not start another connection thread if a thread is already running.
- // Make APC call to the main thread. This will immediately wake the thread up
- // in case it is asleep in the reconnect loop so that it will immediately
- // reconnect.
- QueueUserAPC(TlenDummyApcFunc, info->proto->threadData->hThread, 0);
- info->proto->debugLogA("Thread ended, another normal thread is running");
- mir_free(info);
- return;
- }
-
- info->proto->threadData = info;
-
- DBVARIANT dbv;
- if (!db_get(NULL, info->proto->m_szModuleName, "LoginName", &dbv)) {
- strncpy(info->username, dbv.pszVal, sizeof(info->username));
- info->username[sizeof(info->username)-1] = '\0';
- _strlwr(info->username);
- db_set_s(NULL, info->proto->m_szModuleName, "LoginName", info->username);
- db_free(&dbv);
-
- } else {
- info->proto->debugLogA("Thread ended, login name is not configured");
- loginErr = LOGINERR_BADUSERID;
- }
-
- if (loginErr == 0) {
- if (!db_get(NULL, info->proto->m_szModuleName, "LoginServer", &dbv)) {
- strncpy(info->server, dbv.pszVal, sizeof(info->server));
- info->server[sizeof(info->server)-1] = '\0';
- _strlwr(info->server);
- db_set_s(NULL, info->proto->m_szModuleName, "LoginServer", info->server);
- db_free(&dbv);
- } else {
- info->proto->debugLogA("Thread ended, login server is not configured");
- loginErr = LOGINERR_NONETWORK;
- }
- }
-
- char jidStr[128];
- if (loginErr == 0) {
- if (!info->proto->tlenOptions.savePassword) {
- // Ugly hack: continue logging on only the return value is &(onlinePassword[0])
- // because if WM_QUIT while dialog box is still visible, p is returned with some
- // exit code which may not be NULL.
- // Should be better with modeless.
- onlinePassword[0] = (char) -1;
- hEventPasswdDlg = CreateEvent(nullptr, FALSE, FALSE, nullptr);
- QueueUserAPC(TlenPasswordCreateDialogApcProc, hMainThread, (UINT_PTR)jidStr);
- WaitForSingleObject(hEventPasswdDlg, INFINITE);
- CloseHandle(hEventPasswdDlg);
-
- if (onlinePassword[0] != (char) -1) {
- strncpy(info->password, onlinePassword, sizeof(info->password));
- info->password[sizeof(info->password)-1] = '\0';
- }
- else {
- info->proto->debugLogA("Thread ended, password request dialog was canceled");
- loginErr = LOGINERR_BADUSERID;
- }
- }
- else {
- if (!db_get(NULL, info->proto->m_szModuleName, "Password", &dbv)) {
- strncpy(info->password, dbv.pszVal, sizeof(info->password));
- info->password[sizeof(info->password)-1] = '\0';
- db_free(&dbv);
- }
- else {
- info->proto->debugLogA("Thread ended, password is not configured");
- loginErr = LOGINERR_BADUSERID;
- }
- }
- }
-
- tlenNetworkBufferSize = 2048;
- char *buffer = (char *) mir_alloc(tlenNetworkBufferSize+1); // +1 is for '\0' when debug logging this buffer
- if (buffer == nullptr) {
- info->proto->debugLogA("Thread ended, network buffer cannot be allocated");
- loginErr = LOGINERR_NONETWORK;
- }
-
- if (loginErr != 0) {
- info->proto->threadData = nullptr;
- oldStatus = info->proto->m_iStatus;
- info->proto->m_iStatus = ID_STATUS_OFFLINE;
- ProtoBroadcastAck(info->proto->m_szModuleName, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE) oldStatus, info->proto->m_iStatus);
- ProtoBroadcastAck(info->proto->m_szModuleName, NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, nullptr, loginErr);
- mir_free(info);
- mir_free(buffer);
- return;
- }
-
- mir_snprintf(jidStr, "%s@%s", info->username, info->server);
- db_set_s(NULL, info->proto->m_szModuleName, "jid", jidStr);
-
- if (!db_get(NULL, info->proto->m_szModuleName, "ManualHost", &dbv)) {
- strncpy(info->manualHost, dbv.pszVal, sizeof(info->manualHost));
- info->manualHost[sizeof(info->manualHost)-1] = '\0';
- db_free(&dbv);
- }
- info->port = db_get_w(NULL, info->proto->m_szModuleName, "ManualPort", TLEN_DEFAULT_PORT);
- info->useEncryption = info->proto->tlenOptions.useEncryption;
-
- if (info->manualHost[0])
- connectHost = info->manualHost;
- else
- connectHost = info->server;
-
- info->proto->debugLogA("Thread server='%s' port='%d'", connectHost, info->port);
-
-
- if (!db_get(NULL, info->proto->m_szModuleName, "AvatarHash", &dbv)) {
- strncpy(info->proto->threadData->avatarHash, dbv.pszVal, sizeof(info->proto->threadData->avatarHash)-1);
- db_free(&dbv);
- }
- info->avatarFormat = db_get_dw(NULL, info->proto->m_szModuleName, "AvatarFormat", PA_FORMAT_UNKNOWN);
-
-
- reconnectMaxTime = 10;
- numRetry = 0;
-
- for (;;) { // Reconnect loop
-
- info->s = TlenWsConnect(info->proto, connectHost, info->port);
- if (info->s == nullptr) {
- info->proto->debugLogA("Connection failed (%d)", WSAGetLastError());
- if (info->proto->threadData == info) {
- oldStatus = info->proto->m_iStatus;
- info->proto->m_iStatus = ID_STATUS_OFFLINE;
- ProtoBroadcastAck(info->proto->m_szModuleName, NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, nullptr, LOGINERR_NONETWORK);
- ProtoBroadcastAck(info->proto->m_szModuleName, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE) oldStatus, info->proto->m_iStatus);
- if (info->proto->tlenOptions.reconnect == TRUE) {
- reconnectTime = rand() % reconnectMaxTime;
- info->proto->debugLogA("Sleeping %d seconds before automatic reconnecting...", reconnectTime);
- SleepEx(reconnectTime * 1000, TRUE);
- if (reconnectMaxTime < 10*60) // Maximum is 10 minutes
- reconnectMaxTime *= 2;
- if (info->proto->threadData == info) { // Make sure this is still the active thread for the main Tlen connection
- info->proto->debugLogA("Reconnecting to the network...");
- if (numRetry < MAX_CONNECT_RETRIES)
- numRetry++;
- oldStatus = info->proto->m_iStatus;
- info->proto->m_iStatus = ID_STATUS_CONNECTING + numRetry;
- ProtoBroadcastAck(info->proto->m_szModuleName, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE) oldStatus, info->proto->m_iStatus);
- continue;
- }
- else {
- info->proto->debugLogA("Thread ended, connection failed");
- mir_free(buffer);
- mir_free(info);
- return;
- }
- }
- info->proto->threadData = nullptr;
- }
- info->proto->debugLogA("Thread ended, connection failed");
- mir_free(buffer);
- mir_free(info);
- return;
- }
-
- // User may change status to OFFLINE while we are connecting above
- if (info->proto->m_iDesiredStatus != ID_STATUS_OFFLINE) {
-
- info->proto->isConnected = TRUE;
- mir_forkthread(TlenKeepAliveThread, info->proto);
-
- TlenXmlInitState(&xmlState);
- TlenXmlSetCallback(&xmlState, 1, ELEM_OPEN, (void (__cdecl *)(XmlNode *,void *))TlenProcessStreamOpening, info);
- TlenXmlSetCallback(&xmlState, 1, ELEM_CLOSE, (void (__cdecl *)(XmlNode *,void *))TlenProcessStreamClosing, info);
- TlenXmlSetCallback(&xmlState, 2, ELEM_CLOSE, (void (__cdecl *)(XmlNode *,void *))TlenProcessProtocol, info);
-
- info->useAES = FALSE;
-
- if (info->useEncryption) {
- TlenSend(info->proto, "<s s='1' v='9' t='06000106'>");
-
- } else {
- TlenSend(info->proto, "<s v='3'>");
- }
-
- info->proto->debugLogA("Entering main recv loop");
- datalen = 0;
-
- for (;;) {
- int recvResult, bytesParsed;
-
- if (info->useAES) {
- recvResult = TlenWsRecvAES(info->proto, buffer+datalen, tlenNetworkBufferSize-datalen, &info->aes_in_context, info->aes_in_iv);
- } else {
- recvResult = TlenWsRecv(info->proto, info->s, buffer+datalen, tlenNetworkBufferSize-datalen);
- }
-
- if (recvResult <= 0)
- break;
- datalen += recvResult;
-
- buffer[datalen] = '\0';
- info->proto->debugLogA("RECV:%s", buffer);
-
- bytesParsed = TlenXmlParse(&xmlState, buffer, datalen);
- info->proto->debugLogA("bytesParsed = %d", bytesParsed);
- if (bytesParsed > 0) {
- if (bytesParsed < datalen)
- memmove(buffer, buffer+bytesParsed, datalen-bytesParsed);
- datalen -= bytesParsed;
- }
- else if (datalen == tlenNetworkBufferSize) {
- tlenNetworkBufferSize += 2048;
- info->proto->debugLogA("Increasing network buffer size to %d", tlenNetworkBufferSize);
- if ((buffer=(char *) mir_realloc(buffer, tlenNetworkBufferSize+1)) == nullptr) {
- info->proto->debugLogA("Cannot reallocate more network buffer, go offline now");
- break;
- }
- }
- else {
- info->proto->debugLogA("Unknown state: bytesParsed=%d, datalen=%d, tlenNetworkBufferSize=%d", bytesParsed, datalen, tlenNetworkBufferSize);
- }
- }
-
- TlenXmlDestroyState(&xmlState);
-
- info->proto->isOnline = FALSE;
- info->proto->isConnected = FALSE;
-
- Menu_EnableItem(info->proto->hMenuMUC, false);
- if (info->proto->hMenuChats != nullptr)
- Menu_EnableItem(info->proto->hMenuChats, false);
-
- // Set status to offline
- char *szProto = info->proto->m_szModuleName;
- oldStatus = info->proto->m_iStatus;
- info->proto->m_iStatus = ID_STATUS_OFFLINE;
- ProtoBroadcastAck(szProto, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE) oldStatus, info->proto->m_iStatus);
-
- // Set all contacts to offline
- for (MCONTACT hContact = db_find_first(szProto); hContact; hContact = db_find_next(hContact, szProto))
- if (db_get_w(hContact, szProto, "Status", ID_STATUS_OFFLINE) != ID_STATUS_OFFLINE)
- db_set_w(hContact, szProto, "Status", ID_STATUS_OFFLINE);
-
- TlenListWipeSpecial(info->proto);
- }
- else {
- oldStatus = info->proto->m_iStatus;
- info->proto->m_iStatus = ID_STATUS_OFFLINE;
- ProtoBroadcastAck(info->proto->m_szModuleName, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE) oldStatus, info->proto->m_iStatus);
- }
-
- Netlib_CloseHandle(info->s);
-
- if (info->proto->tlenOptions.reconnect == FALSE)
- break;
-
- if (info->proto->threadData != info) // Make sure this is still the main Tlen connection thread
- break;
- reconnectTime = rand() % 10;
- info->proto->debugLogA("Sleeping %d seconds before automatic reconnecting...", reconnectTime);
- SleepEx(reconnectTime * 1000, TRUE);
- reconnectMaxTime = 20;
- if (info->proto->threadData != info) // Make sure this is still the main Tlen connection thread
- break;
- info->proto->debugLogA("Reconnecting to the network...");
- info->proto->m_iDesiredStatus = oldStatus; // Reconnect to my last status
- oldStatus = info->proto->m_iStatus;
- info->proto->m_iStatus = ID_STATUS_CONNECTING;
- numRetry = 1;
- ProtoBroadcastAck(info->proto->m_szModuleName, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE) oldStatus, info->proto->m_iStatus);
- }
-
- info->proto->debugLogA("Thread ended: server='%s'", info->server);
-
- if (info->proto->threadData == info) {
- info->proto->threadData = nullptr;
- }
-
- mir_free(buffer);
- if (info->streamId) mir_free(info->streamId);
- info->proto->debugLogA("Exiting ServerThread");
- mir_free(info);
-}
-
-static void TlenSendAuth(TlenProtocol *proto) {
- int iqId;
- char text[128];
- char *str = TlenPasswordHash(proto->threadData->password);
- mir_snprintf(text, "%s%s", proto->threadData->streamId, str);
- mir_free(str);
- str = TlenSha1(text);
- char *p=TlenTextEncode(proto->threadData->username);
- if (p != nullptr) {
- iqId = TlenSerialNext(proto->threadData->proto);
- TlenIqAdd(proto, iqId, IQ_PROC_NONE, TlenIqResultAuth);
- TlenSend(proto, "<iq type='set' id='" TLEN_IQID "%d'><query xmlns='jabber:iq:auth'><username>%s</username><digest>%s</digest><resource>t</resource><host>tlen.pl</host></query></iq>", iqId, p /*info->username*/, str);
- mir_free(p);
- }
- mir_free(str);
-}
-
-/* processing <s ... > tag sent from server on session opening */
-static void TlenProcessStreamOpening(XmlNode *node, ThreadData *info)
-{
- if (node->name == nullptr || mir_strcmp(node->name, "s"))
- return;
-
- char *sid=TlenXmlGetAttrValue(node, "i");
- if (sid != nullptr) {
- if (info->streamId) mir_free(info->streamId);
- info->streamId = mir_strdup(sid);
- }
- char *s=TlenXmlGetAttrValue(node, "s");
- if (s != nullptr && !mir_strcmp(s, "1")) {
- int i;
- unsigned char aes_key[32];
- char aes_key_str[140], aes_iv_str[40];
- mpi k1_mpi, k2_mpi, aes_mpi;
- size_t slen;
-
- char *k1=TlenXmlGetAttrValue(node, "k1");
- char *k2=TlenXmlGetAttrValue(node, "k2");
- char *k3=TlenXmlGetAttrValue(node, "k3");
-
- memset(&info->aes_in_context, 0, sizeof (aes_context));
- memset(&info->aes_out_context, 0, sizeof (aes_context));
- memset(&aes_mpi, 0, sizeof (mpi));
- mpi_read_string(&aes_mpi, 16, k3);
- mpi_write_binary(&aes_mpi, info->aes_in_iv, 16);
- for (i = 0; i < 16; i++) {
- info->aes_out_iv[i] = rand();
- aes_key[i] = rand();
- }
- memset(&aes_mpi, 0, sizeof (mpi));
- mpi_read_binary(&aes_mpi, info->aes_out_iv, 16);
- slen = 40;
- mpi_write_string(&aes_mpi, 16, aes_iv_str, &slen);
- aes_setkey_dec(&info->aes_in_context, aes_key, 128);
- aes_setkey_enc(&info->aes_out_context, aes_key, 128);
- memset(&aes_mpi, 0, sizeof (mpi));
- mpi_read_binary(&aes_mpi, aes_key, 16);
- memset(&k1_mpi, 0, sizeof (mpi));
- mpi_read_string( &k1_mpi, 16, k1 );
- memset(&k2_mpi, 0, sizeof (mpi));
- mpi_read_string( &k2_mpi, 16, k2 );
- memset(&aes_mpi, 0, sizeof (mpi));
- mpi_read_binary(&aes_mpi, (unsigned char *)aes_key, 16);
- mpi_exp_mod( &aes_mpi, &aes_mpi, &k1_mpi, &k2_mpi, nullptr );
- slen = 140;
- mpi_write_string(&aes_mpi, 16, aes_key_str, &slen);
- TlenSend(info->proto, "<cipher k1='%s' k2='%s'/>", aes_key_str, aes_iv_str);
- } else {
- TlenSendAuth(info->proto);
- }
-}
-
-/* processing </s> tag sent from server on session close */
-static void TlenProcessStreamClosing(XmlNode *node, ThreadData *info)
-{
- Netlib_CloseHandle(info->proto);
- if (node->name && !mir_strcmp(node->name, "stream:error") && node->text){
- char buffer[1024];
- mir_snprintf(buffer, "%s\n%s", Translate("Tlen Connection Error"), Translate(node->text));
- PUShowMessage(buffer, SM_WARNING);
- } else if (!mir_strcmp(node->name, "s")){
- info->proto->debugLogA("Disconnected server message");
- }
-}
-
-/* processing session tags sent from server */
-static void TlenProcessProtocol(XmlNode *node, ThreadData *info)
-{
- if (!mir_strcmp(node->name, "message"))
- TlenProcessMessage(node, info);
- else if (!mir_strcmp(node->name, "presence"))
- TlenProcessPresence(node, info->proto);
- else if (!mir_strcmp(node->name, "iq"))
- TlenProcessIq(node, info);
- else if (!mir_strcmp(node->name, "f"))
- TlenProcessF(node, info);
- else if (!mir_strcmp(node->name, "w"))
- TlenProcessW(node, info);
- else if (!mir_strcmp(node->name, "m"))
- TlenProcessM(node, info);
- else if (!mir_strcmp(node->name, "n"))
- TlenProcessN(node, info);
- else if (!mir_strcmp(node->name, "p"))
- TlenProcessP(node, info);
- else if (!mir_strcmp(node->name, "v"))
- TlenProcessV(node, info);
- else if (!mir_strcmp(node->name, "avatar"))
- TlenProcessAvatar(node, info);
- else if (!mir_strcmp(node->name, "cipher"))
- TlenProcessCipher(node, info);
- else
- info->proto->debugLogA("Invalid top-level tag (only <message/> <presence/> <iq/> <f/> <w/> <m/> <n/> <p/> <v/> <cipher/> and <avatar/> allowed)");
-
-}
-
-static void TlenProcessCipher(XmlNode*, ThreadData *info)
-{
- info->useAES = TRUE;
- TlenSend(info->proto, "<cipher type='ok'/>");
- TlenSendAuth(info->proto);
-}
-
-static void TlenProcessIqGetVersion(TlenProtocol *proto, XmlNode *node)
-{
- OSVERSIONINFO osvi = { 0 };
- char mversion[256];
- char *mver;
- char* os = nullptr;
-
- if (proto->m_iStatus == ID_STATUS_INVISIBLE) return;
- if (!proto->tlenOptions.enableVersion) return;
- char *from = TlenXmlGetAttrValue(node, "from");
- if (from == nullptr)
- return;
-
- TLEN_LIST_ITEM *item = TlenListGetItemPtr(proto, LIST_ROSTER, from);
- if (item == nullptr)
- return;
-
- char *version = TlenTextEncode(TLEN_VERSION_STRING);
- osvi.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
- if ( GetVersionEx( &osvi )) {
- switch ( osvi.dwPlatformId ) {
- case VER_PLATFORM_WIN32_NT:
- if ( osvi.dwMajorVersion == 5 ) {
- if ( osvi.dwMinorVersion == 2 ) os = TlenTextEncode("Windows Server 2003");
- else if ( osvi.dwMinorVersion == 1 ) os = TlenTextEncode("Windows XP");
- else if ( osvi.dwMinorVersion == 0 ) os = TlenTextEncode("Windows 2000");
- }
- else if ( osvi.dwMajorVersion <= 4 ) {
- os = TlenTextEncode("Windows NT");
- }
- break;
- case VER_PLATFORM_WIN32_WINDOWS:
- if ( osvi.dwMajorVersion == 4 ) {
- if ( osvi.dwMinorVersion == 0 ) os = TlenTextEncode("Windows 95");
- if ( osvi.dwMinorVersion == 10 ) os = TlenTextEncode("Windows 98");
- if ( osvi.dwMinorVersion == 90 ) os = TlenTextEncode("Windows ME");
- }
- break;
- } }
-
- if ( os == nullptr ) os = TlenTextEncode("Windows");
-
- mir_strcpy(mversion, "Miranda NG ");
- Miranda_GetVersionText(mversion + 11, sizeof(mversion) - 11);
- mir_strcat(mversion, " (Tlen v.");
- mir_strcat(mversion, TLEN_VERSION_STRING);
- mir_strcat(mversion, ")");
- mver = TlenTextEncode( mversion );
- TlenSend( proto, "<message to='%s' type='iq'><iq type='result'><query xmlns='jabber:iq:version'><name>%s</name><version>%s</version><os>%s</os></query></iq></message>", from, mver?mver:"", version?version:"", os?os:"" );
- if (!item->versionRequested) {
- item->versionRequested = TRUE;
- TlenSend(proto, "<message to='%s' type='iq'><iq type='get'><query xmlns='jabber:iq:version'/></iq></message>", from);
- }
-
- if ( mver ) mir_free( mver );
- if ( version ) mir_free( version );
- if ( os ) mir_free( os );
-}
-
-// Support for Tlen avatars - avatar token used to access web interface
-static void TlenProcessAvatar(XmlNode* node, ThreadData *info)
-{
- XmlNode *tokenNode = TlenXmlGetChild(node, "token");
- XmlNode *aNode = TlenXmlGetChild(node, "a");
- if (tokenNode != nullptr) {
- char *token = tokenNode->text;
- strncpy(info->avatarToken, token, sizeof(info->avatarToken)-1);
- }
- if (aNode != nullptr) {
- if (TlenProcessAvatarNode(info->proto, node, nullptr)) {
- }
- }
-}
-
-static void TlenProcessMessage(XmlNode *node, ThreadData *info)
-{
- MCONTACT hContact;
- XmlNode *bodyNode, *subjectNode, *xNode, *n;
- char *nick, *p, *localMessage, *idStr;
- DWORD msgTime;
- BOOL delivered, composing;
- int i;
-
- if (!node->name || mir_strcmp(node->name, "message")) return;
-
- char *type=TlenXmlGetAttrValue(node, "type");
- if (type != nullptr && !mir_strcmp(type, "error")) {
- }
- else {
- char *from=TlenXmlGetAttrValue(node, "from");
- if (from != nullptr) {
- if (info->proto->tlenOptions.ignoreAdvertisements && strstr(from, "b73@tlen.pl") == from) {
- return;
- }
- char *fromJid = TlenLoginFromJID(from);
- // If message is from a stranger (not in roster), item is NULL
- TLEN_LIST_ITEM *item = TlenListGetItemPtr(info->proto, LIST_ROSTER, fromJid);
- BOOL isChatRoomJid = TlenListExist(info->proto, LIST_CHATROOM, from);
-
- if (isChatRoomJid && type != nullptr && !mir_strcmp(type, "groupchat")) {
- //TlenGroupchatProcessMessage(node, userdata);
- } else if (type != nullptr && !mir_strcmp(type, "pic")) {
- TlenProcessPic(node, info->proto);
- } else if (type != nullptr && !mir_strcmp(type, "iq")) {
- XmlNode *iqNode;
- // Tlen-compatible iq
- if ((iqNode=TlenXmlGetChild(node, "iq")) != nullptr) {
- TlenXmlAddAttr(iqNode, "from", from);
- TlenProcessIq(iqNode, info);
- }
- } else {
- if ((bodyNode=TlenXmlGetChild(node, "body")) != nullptr) {
- if (bodyNode->text != nullptr) {
- if ((subjectNode=TlenXmlGetChild(node, "subject")) != nullptr && subjectNode->text != nullptr && subjectNode->text[0] != '\0') {
- size_t size = mir_strlen(subjectNode->text)+mir_strlen(bodyNode->text)+5;
- p = (char *)mir_alloc(size);
- mir_snprintf(p, size, "%s\r\n%s", subjectNode->text, bodyNode->text);
- localMessage = TlenTextDecode(p);
- mir_free(p);
- } else {
- localMessage = TlenTextDecode(bodyNode->text);
- }
-
- msgTime = 0;
- delivered = composing = FALSE;
- i = 1;
- while ((xNode=TlenXmlGetNthChild(node, "x", i)) != nullptr) {
- if ((p=TlenXmlGetAttrValue(xNode, "xmlns")) != nullptr) {
- if (!mir_strcmp(p, "jabber:x:delay") && msgTime==0) {
- if ((p=TlenXmlGetAttrValue(xNode, "stamp")) != nullptr) {
- msgTime = TlenIsoToUnixTime(p);
- }
- }
- else if (!mir_strcmp(p, "jabber:x:event")) {
- // Check whether any event is requested
- if (!delivered && (n=TlenXmlGetChild(xNode, "delivered")) != nullptr) {
- delivered = TRUE;
- idStr = TlenXmlGetAttrValue(node, "id");
- TlenSend(info->proto, "<message to='%s'><x xmlns='jabber:x:event'><delivered/><id>%s</id></x></message>", from, (idStr != nullptr)?idStr:"");
- }
- if (item != nullptr && TlenXmlGetChild(xNode, "composing") != nullptr) {
- composing = TRUE;
- if (item->messageEventIdStr)
- mir_free(item->messageEventIdStr);
- idStr = TlenXmlGetAttrValue(node, "id");
- item->messageEventIdStr = (idStr == nullptr)?nullptr:mir_strdup(idStr);
- }
- }
- }
- i++;
- }
-
- if (item != nullptr) {
- item->wantComposingEvent = composing;
- if (item->isTyping) {
- item->isTyping = FALSE;
- if ((hContact=TlenHContactFromJID(info->proto, fromJid)) != NULL)
- CallService(MS_PROTO_CONTACTISTYPING, hContact, PROTOTYPE_CONTACTTYPING_OFF);
- }
- }
-
- if ((hContact=TlenHContactFromJID(info->proto, fromJid)) == NULL) {
- // Create a temporary contact
- if (isChatRoomJid) {
- if ((p=strchr(from, '/')) != nullptr && p[1]!='\0')
- p++;
- else
- p = from;
- nick = TlenTextEncode(p);
- hContact = TlenDBCreateContact(info->proto, from, nick, TRUE);
- }
- else {
- nick = TlenLocalNickFromJID(from);
- hContact = TlenDBCreateContact(info->proto, from, nick, TRUE);
- }
- mir_free(nick);
- }
-
- if (msgTime == 0) {
- msgTime = time(nullptr);
- } else {
- MEVENT hDbEvent = db_event_last(hContact);
- if (hDbEvent != NULL) {
- DBEVENTINFO dbei = {};
- db_event_get( hDbEvent, &dbei);
- if (msgTime < dbei.timestamp) {
- msgTime = dbei.timestamp + 1;
- }
- }
- if (msgTime > (DWORD)time(nullptr)) {
- msgTime = time(nullptr);
- }
- }
- char* localMessage_Utf8 = mir_utf8encode(localMessage);
-
- PROTORECVEVENT recv = { 0 };
- recv.timestamp = (DWORD) msgTime;
- recv.szMessage = localMessage_Utf8;
- recv.lParam = 0;
- ProtoChainRecvMsg(hContact, &recv);
-
- mir_free(localMessage_Utf8);
- mir_free(localMessage);
- }
- }
- }
- mir_free(fromJid);
- }
- }
-}
-
-static void TlenProcessIq(XmlNode *node, ThreadData *info)
-{
- MCONTACT hContact;
- XmlNode *queryNode = nullptr;
- char *jid, *nick;
- char *xmlns = nullptr;
- char *idStr, *str;
- int id;
- int i;
-
- if (!node->name || mir_strcmp(node->name, "iq")) return;
- char *type=TlenXmlGetAttrValue(node, "type");
-// if ((type=TlenXmlGetAttrValue(node, "type")) == NULL) return;
-
- id = -1;
- if ((idStr=TlenXmlGetAttrValue(node, "id")) != nullptr) {
- if (!strncmp(idStr, TLEN_IQID, mir_strlen(TLEN_IQID)))
- id = atoi(idStr+mir_strlen(TLEN_IQID));
- }
-
- queryNode = TlenXmlGetChild(node, "query");
- if (queryNode != nullptr) {
- xmlns = TlenXmlGetAttrValue(queryNode, "xmlns");
- }
-
-
- /////////////////////////////////////////////////////////////////////////
- // MATCH BY ID
- /////////////////////////////////////////////////////////////////////////
- TLEN_IQ_PFUNC pfunc=TlenIqFetchFunc(info->proto, id);
- if (pfunc != nullptr) {
- info->proto->debugLogA("Handling iq request for id=%d", id);
- pfunc(info->proto, node);
- /////////////////////////////////////////////////////////////////////////
- // MORE GENERAL ROUTINES, WHEN ID DOES NOT MATCH
- /////////////////////////////////////////////////////////////////////////
- // new p2p connections
- } else if (xmlns != nullptr && !mir_strcmp(xmlns, "p2p")) {
- if (info->proto->tlenOptions.useNewP2P) {
- TlenProcessP2P(node, info);
- }
- }
- // RECVED: <iq type='set'><query ...
- else if (!mir_strcmp(type, "set") && queryNode != nullptr && xmlns != nullptr) {
-
- // RECVED: roster push
- // ACTION: similar to iqIdGetRoster above
- if (!mir_strcmp(xmlns, "jabber:iq:roster")) {
- XmlNode *itemNode, *groupNode;
- TLEN_LIST_ITEM *item;
- char *name;
-
- info->proto->debugLogA("<iq/> Got roster push, query has %d children", queryNode->numChild);
- for (i=0; i<queryNode->numChild; i++) {
- itemNode = queryNode->child[i];
- if (!mir_strcmp(itemNode->name, "item")) {
- if ((jid=TlenXmlGetAttrValue(itemNode, "jid")) != nullptr) {
- if ((str=TlenXmlGetAttrValue(itemNode, "subscription")) != nullptr) {
- // we will not add new account when subscription=remove
- if (!mir_strcmp(str, "to") || !mir_strcmp(str, "both") || !mir_strcmp(str, "from") || !mir_strcmp(str, "none")) {
- if ((name=TlenXmlGetAttrValue(itemNode, "name")) != nullptr) {
- nick = TlenTextDecode(name);
- } else {
- nick = TlenLocalNickFromJID(jid);
- }
- if (nick != nullptr) {
- if ((item=TlenListAdd(info->proto, LIST_ROSTER, jid)) != nullptr) {
- if (item->nick) mir_free(item->nick);
- item->nick = nick;
- if ((hContact=TlenHContactFromJID(info->proto, jid)) == NULL) {
- // Received roster has a new JID.
- // Add the jid (with empty resource) to Miranda contact list.
- hContact = TlenDBCreateContact(info->proto, jid, nick, FALSE);
- }
- db_set_s(hContact, "CList", "MyHandle", nick);
- if (item->group) mir_free(item->group);
- if ((groupNode=TlenXmlGetChild(itemNode, "group")) != nullptr && groupNode->text != nullptr) {
- item->group = TlenGroupDecode(groupNode->text);
- Clist_GroupCreate(0, _A2T(item->group));
- db_set_s(hContact, "CList", "Group", item->group);
- }
- else {
- item->group = nullptr;
- db_unset(hContact, "CList", "Group");
- }
- if (!mir_strcmp(str, "none") || (!mir_strcmp(str, "from") && strchr(jid, '@') != nullptr)) {
- if (db_get_w(hContact, info->proto->m_szModuleName, "Status", ID_STATUS_OFFLINE) != ID_STATUS_OFFLINE)
- db_set_w(hContact, info->proto->m_szModuleName, "Status", ID_STATUS_OFFLINE);
- }
- }
- else {
- mir_free(nick);
- }
- }
- }
- if ((item=TlenListGetItemPtr(info->proto, LIST_ROSTER, jid)) != nullptr) {
- if (!mir_strcmp(str, "both"))
- item->subscription = SUB_BOTH;
- else if (!mir_strcmp(str, "to"))
- item->subscription = SUB_TO;
- else if (!mir_strcmp(str, "from"))
- item->subscription = SUB_FROM;
- else
- item->subscription = SUB_NONE;
- info->proto->debugLogA("Roster push for jid=%s, set subscription to %s", jid, str);
- // subscription = remove is to remove from roster list
- // but we will just set the contact to offline and not actually
- // remove, so that history will be retained.
- if (!mir_strcmp(str, "remove")) {
- if ((hContact=TlenHContactFromJID(info->proto, jid)) != NULL) {
- if (db_get_w(hContact, info->proto->m_szModuleName, "Status", ID_STATUS_OFFLINE) != ID_STATUS_OFFLINE)
- db_set_w(hContact, info->proto->m_szModuleName, "Status", ID_STATUS_OFFLINE);
- TlenListRemove(info->proto, LIST_ROSTER, jid);
- }
- }
- }
- }
- }
- }
- }
- }
-
- }
- // RECVED: <iq type='get'><query ...
- else if ( !mir_strcmp( type, "get" ) && queryNode != nullptr && xmlns != nullptr ) {
- // RECVED: software version query
- // ACTION: return my software version
- if ( !mir_strcmp( xmlns, "jabber:iq:version" )) TlenProcessIqGetVersion(info->proto, node);
- }
- // RECVED: <iq type='result'><query ...
- else if ( !mir_strcmp( type, "result") && queryNode != nullptr) {
- if (xmlns != nullptr ) {
- if ( !mir_strcmp(xmlns, "jabber:iq:roster" )) {
- TlenIqResultRoster(info->proto, node);
- } else if ( !mir_strcmp( xmlns, "jabber:iq:version" )) {
- TlenIqResultVersion(info->proto, node);
- } else if ( !mir_strcmp( xmlns, "jabber:iq:info" )) {
- TlenIqResultInfo(info->proto, node);
- }
- } else {
- char *from;
- if (( from=TlenXmlGetAttrValue( node, "from" )) != nullptr ) {
- if ( !mir_strcmp(from, "tcfg" )) {
- TlenIqResultTcfg(info->proto, node);
- }
- }
- }
- }
- // RECVED: <iq type='error'> ...
- else if (!mir_strcmp(type, "error")) {
- TLEN_LIST_ITEM *item;
- // Check for file transfer deny by comparing idStr with ft->iqId
- i = 0;
- while ((i=TlenListFindNext(info->proto, LIST_FILE, i)) >= 0) {
- item = TlenListGetItemPtrFromIndex(info->proto,i);
- if (item->ft->state==FT_CONNECTING && !mir_strcmp(idStr, item->ft->iqId)) {
- item->ft->state = FT_DENIED;
- if (item->ft->hFileEvent != nullptr)
- SetEvent(item->ft->hFileEvent); // Simulate the termination of file server connection
- }
- i++;
- }
- }
-}
-
-/*
- * Web messages
- */
-static void TlenProcessW(XmlNode *node, ThreadData *info)
-{
- char *e, *s;
- char *str, *localMessage;
- int strSize;
-
- if (!node->name || mir_strcmp(node->name, "w"))
- return;
-
- char *body=node->text;
- if (body == nullptr)
- return;
-
- char *f = TlenXmlGetAttrValue(node, "f");
- if (f != nullptr) {
- char webContactName[128];
- mir_snprintf(webContactName, Translate("%s Web Messages"), info->proto->m_szModuleName);
- MCONTACT hContact = TlenHContactFromJID(info->proto, webContactName);
- if (hContact == NULL) {
- hContact = TlenDBCreateContact(info->proto, webContactName, webContactName, TRUE);
- }
-
- s = TlenXmlGetAttrValue(node, "s");
- e = TlenXmlGetAttrValue(node, "e");
-
- str = nullptr;
- strSize = 0;
- TlenStringAppend(&str, &strSize, "%s\r\n%s: ", Translate("Web message"), Translate("From"));
-
- if (f != nullptr)
- TlenStringAppend(&str, &strSize, "%s", f);
- TlenStringAppend(&str, &strSize, "\r\n%s: ", Translate("E-mail"));
- if (e != nullptr)
- TlenStringAppend(&str, &strSize, "%s", e);
- TlenStringAppend(&str, &strSize, "\r\n\r\n%s", body);
-
- localMessage = TlenTextDecode(str);
- char* localMessage_Utf8 = mir_utf8encode(localMessage);
-
- PROTORECVEVENT recv = { 0 };
- recv.timestamp = (DWORD) time(nullptr);
- recv.szMessage = localMessage_Utf8;
- ProtoChainRecvMsg(hContact, &recv);
-
- mir_free(localMessage_Utf8);
- mir_free(localMessage);
- mir_free(str);
- }
-}
-
-/*
- * Typing notification, multi-user conference messages and invitations
- */
-static void TlenProcessM(XmlNode *node, ThreadData *info)
-{
- char *p, *n, *r, *s, *str, *localMessage;
- int i;
- XmlNode *xNode, *invNode, *bNode;
-
- if (!node->name || mir_strcmp(node->name, "m")) return;
-
- char *f = TlenXmlGetAttrValue(node, "f"); //, *from;//username
- if (f != nullptr) {
- char *fLogin = TlenLoginFromJID(f);
- MCONTACT hContact=TlenHContactFromJID(info->proto, fLogin);
- if (hContact != NULL) {
- char *tp=TlenXmlGetAttrValue(node, "tp");//typing start/stop
- if (tp != nullptr) {
- TLEN_LIST_ITEM *item = TlenListGetItemPtr(info->proto, LIST_ROSTER, fLogin);
- if (!mir_strcmp(tp, "t")) { //contact is writing
- if (item != nullptr ) {
- item->isTyping = TRUE;
- CallService(MS_PROTO_CONTACTISTYPING, hContact, (LPARAM)PROTOTYPE_CONTACTTYPING_INFINITE);
- }
- }
- else if (!mir_strcmp(tp, "u")) {//contact stopped writing
- if (item != nullptr) {
- item->isTyping = FALSE;
- CallService(MS_PROTO_CONTACTISTYPING, hContact, (LPARAM)PROTOTYPE_CONTACTTYPING_OFF);
- }
- }
- else if (!mir_strcmp(tp, "a")) {//alert was received
- int bAlert = TRUE;
- if (info->proto->tlenOptions.alertPolicy == TLEN_ALERTS_IGNORE_ALL) {
- bAlert = FALSE;
- } else if (info->proto->tlenOptions.alertPolicy == TLEN_ALERTS_IGNORE_NIR) {
- bAlert = IsAuthorized(info->proto, fLogin);
- }
- if (bAlert) {
- if (info->proto->tlenOptions.useNudge)
- NotifyEventHooks(info->proto->hTlenNudge, hContact, 0);
- else {
- if (info->proto->tlenOptions.logAlerts)
- TlenLogMessage(info->proto, hContact, 0, Translate("An alert has been received."));
- Skin_PlaySound("TlenAlertNotify");
- }
- }
- }
- }
- }
- mir_free(fLogin);
- if ((p=strchr(f, '@')) != nullptr) {
- if ((p=strchr(p, '/')) != nullptr && p[1]!='\0') { // message from user
- time_t timestamp;
- s = TlenXmlGetAttrValue(node, "s");
- if (s != nullptr) {
- timestamp = TlenTimeToUTC(atol(s));
- if (timestamp > time(nullptr)) {
- timestamp = time(nullptr);
- }
- } else {
- timestamp = time(nullptr);
- }
- char *tp=TlenXmlGetAttrValue(node, "tp");//typing start/stop
- bNode = TlenXmlGetChild(node, "b");
- f = TlenTextDecode(f);
- if (bNode != nullptr && bNode->text != nullptr) {
- if (tp != nullptr && !mir_strcmp(tp, "p")) {
- /* MUC private message */
- str = TlenResourceFromJID(f);
- hContact = TlenDBCreateContact(info->proto, f, str, TRUE);
- db_set_b(hContact, info->proto->m_szModuleName, "bChat", TRUE);
- mir_free(str);
- localMessage = TlenTextDecode(bNode->text);
- char* localMessage_Utf8 = mir_utf8encode(localMessage);
-
- PROTORECVEVENT recv = { 0 };
- recv.timestamp = (DWORD) timestamp;
- recv.szMessage = localMessage_Utf8;
- ProtoChainRecvMsg(hContact, &recv);
-
- mir_free(localMessage_Utf8);
- mir_free(localMessage);
- }
- }
- mir_free(f);
- }
- }
- i=1;
- while ((xNode=TlenXmlGetNthChild(node, "x", i)) != nullptr) {
- invNode=TlenXmlGetChild(xNode, "inv");
- if (invNode != nullptr) {
- r = TlenTextDecode(f);
- f = TlenXmlGetAttrValue(invNode, "f");
- f = TlenTextDecode(f);
- n = TlenXmlGetAttrValue(invNode, "n");
- if (n != nullptr && strstr(r, n) != r) {
- n = TlenTextDecode(n);
- } else {
- n = mir_strdup(Translate("Private conference"));
- //n = TlenNickFromJID(r);
- }
- TlenMUCRecvInvitation(info->proto, r, n, f, "");
- mir_free(n);
- mir_free(r);
- mir_free(f);
- break;
- }
- i++;
- }
- }
-}
-
-static void TlenMailPopup(TlenProtocol *proto, char *title, char *emailInfo)
-{
- if ( !ServiceExists(MS_POPUP_ADDPOPUPT))
- return;
- if (!db_get_b(NULL, proto->m_szModuleName, "MailPopupEnabled", TRUE))
- return;
-
- POPUPDATAT ppd = { 0 };
- ppd.lchIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_MAIL));
- wcsncpy(ppd.lptzContactName, _A2T(title), MAX_CONTACTNAME -1);
- wcsncpy(ppd.lptzText, _A2T(emailInfo), MAX_SECONDLINE - 1);
- ppd.colorBack = db_get_dw(NULL, proto->m_szModuleName, "MailPopupBack", 0);
- ppd.colorText = db_get_dw(NULL, proto->m_szModuleName, "MailPopupText", 0);
- BYTE delayMode = db_get_b(NULL, proto->m_szModuleName, "MailPopupDelayMode", 0);
- if (delayMode == 1)
- ppd.iSeconds = db_get_dw(NULL, proto->m_szModuleName, "MailPopupDelay", 4);
- else if (delayMode == 2)
- ppd.iSeconds = -1;
- PUAddPopupT(&ppd);
-}
-/*
- * Incoming e-mail notification
- */
-static void TlenProcessN(XmlNode *node, ThreadData *info)
-{
- char *str, *popupTitle, *popupText;
- int strSize;
-
- if (!node->name || mir_strcmp(node->name, "n")) return;
-
- char *s = TlenXmlGetAttrValue(node, "s");
- char *f = TlenXmlGetAttrValue(node, "f");
- if (s != nullptr && f != nullptr) {
- str = nullptr;
- strSize = 0;
-
- TlenStringAppend(&str, &strSize, Translate("%s mail"), info->proto->m_szModuleName);
- popupTitle = TlenTextDecode(str);
- mir_free(str);
-
- str = nullptr;
- strSize = 0;
-
- TlenStringAppend(&str, &strSize, "%s: %s\n", Translate("From"), f);
- TlenStringAppend(&str, &strSize, "%s: %s", Translate("Subject"), s);
- popupText = TlenTextDecode(str);
- TlenMailPopup(info->proto, popupTitle, popupText);
- Skin_PlaySound("TlenMailNotify");
-
- mir_free(popupTitle);
- mir_free(popupText);
- mir_free(str);
- }
-}
-
-/*
- * Presence is chat rooms
- */
-static void TlenProcessP(XmlNode *node, ThreadData*)
-{
- char *f, *a, *k;
- XmlNode *sNode, *xNode, *iNode, *kNode;
- int status, flags;
-
- if (!node->name || mir_strcmp(node->name, "p")) return;
-
-// presence from users in chat room
- flags = 0;
- status = ID_STATUS_ONLINE;
- f = TlenXmlGetAttrValue(node, "f");
- xNode = TlenXmlGetChild(node, "x");
- if (xNode != nullptr) { // x subtag present (message from chat room) - change user rights only
- char *temp, *iStr;
- iNode = TlenXmlGetChild(xNode, "i");
- if (iNode != nullptr) {
- iStr = TlenXmlGetAttrValue(iNode, "i");
- temp = (char*)mir_alloc(mir_strlen(f)+mir_strlen(iStr)+2);
- mir_strcpy(temp, f);
- mir_strcat(temp, "/");
- mir_strcat(temp, iStr);
- f = TlenTextDecode(temp);
- mir_free(temp);
- node = iNode;
- status = 0;
- } else {
- f = TlenTextDecode(f);
- }
- } else {
- f = TlenTextDecode(f);
- }
- a = TlenXmlGetAttrValue(node, "z");
- if (a != nullptr) {
- if (atoi(a) &1 ) {
- flags |= USER_FLAGS_REGISTERED;
- }
- }
- a = TlenXmlGetAttrValue(node, "a");
- if (a != nullptr) {
- if (atoi(a) == 2) {
- flags |= USER_FLAGS_ADMIN;
- }
- if (atoi(a) == 1) {
- flags |= USER_FLAGS_OWNER;
- }
- if (atoi(a) == 3) {
- //flags |= USER_FLAGS_MEMBER;
- }
- if (atoi(a) == 5) {
- flags |= USER_FLAGS_GLOBALOWNER;
- }
- }
- sNode = TlenXmlGetChild(node, "s");
- if (sNode != nullptr) {
- if (!mir_strcmp(sNode->text, "unavailable")) {
- status = ID_STATUS_OFFLINE;
- }
- }
- kNode = TlenXmlGetChild(node, "kick");
- k = nullptr;
- if (kNode != nullptr) {
- k = TlenXmlGetAttrValue(kNode, "r");
- if (k == nullptr) {
- k = "";
- }
- k = TlenTextDecode(k);
- }
- if (k != nullptr) {
- mir_free(k);
- }
- mir_free(f);
-}
-/*
- * Voice chat
- */
-static void TlenProcessV(XmlNode *node, ThreadData *info)
-{
- char jid[128];
- TLEN_LIST_ITEM *item;
- char *id, *e, *p;
-// if (!node->name || mir_strcmp(node->name, "v")) return;
-
- char *from=TlenXmlGetAttrValue(node, "f");
- if (from != nullptr) {
- if (strchr(from, '@') == nullptr) {
- mir_snprintf(jid, "%s@%s", from, info->server);
- } else {
- strncpy_s(jid, from, _TRUNCATE);
- }
- if ((e=TlenXmlGetAttrValue(node, "e")) != nullptr) {
- if (!mir_strcmp(e, "1")) {
- if ((id=TlenXmlGetAttrValue(node, "i")) != nullptr) {
- Skin_PlaySound("TlenVoiceNotify");
- TlenVoiceAccept(info->proto, id, from);
- }
- } else if (!mir_strcmp(e, "3")) {
- // FILE_RECV : e='3' : invalid transfer error
- if ((p=TlenXmlGetAttrValue(node, "i")) != nullptr) {
- if ((item=TlenListGetItemPtr(info->proto, LIST_VOICE, p)) != nullptr) {
- if (item->ft != nullptr) {
- HANDLE hEvent = item->ft->hFileEvent;
- item->ft->hFileEvent = nullptr;
- item->ft->state = FT_ERROR;
- if (item->ft->s != nullptr) {
- Netlib_CloseHandle(item->ft->s);
- item->ft->s = nullptr;
- if (hEvent != nullptr) {
- SetEvent(hEvent);
- }
- } else {
- TlenP2PFreeFileTransfer(item->ft);
- }
- } else {
- TlenListRemove(info->proto, LIST_VOICE, p);
- }
- }
- }
- } else if (!mir_strcmp(e, "4")) {
- // FILE_SEND : e='4' : File sending request was denied by the remote client
- if ((p=TlenXmlGetAttrValue(node, "i")) != nullptr) {
- if ((item=TlenListGetItemPtr(info->proto, LIST_VOICE, p)) != nullptr) {
- if (!mir_strcmp(item->ft->jid, jid)) {
- TlenVoiceCancelAll(info->proto);
- //TlenListRemove(info->proto, LIST_VOICE, p);
- }
- }
- }
- } else if (!mir_strcmp(e, "5")) {
- // FILE_SEND : e='5' : Voice request was accepted
- if ((p=TlenXmlGetAttrValue(node, "i")) != nullptr) {
- if ((item=TlenListGetItemPtr(info->proto, LIST_VOICE, p)) != nullptr) {
- info->proto->debugLogA("should start voice 1 ? %s ?? %s", jid, item->ft->jid);
- if (!mir_strcmp(item->ft->jid, jid)) {
- info->proto->debugLogA("starting voice 1");
- TlenVoiceStart(item->ft, 1);
- }
- }
- }
- } else if (!mir_strcmp(e, "6")) {
- // FILE_RECV : e='6' : IP and port information to connect to get file
- if ((p=TlenXmlGetAttrValue(node, "i")) != nullptr) {
- if ((item=TlenListGetItemPtr(info->proto, LIST_VOICE, p)) != nullptr) {
- if ((p=TlenXmlGetAttrValue(node, "a")) != nullptr) {
- item->ft->hostName = mir_strdup(p);
- if ((p=TlenXmlGetAttrValue(node, "p")) != nullptr) {
- item->ft->wPort = atoi(p);
- TlenVoiceStart(item->ft, 0);
- //forkthread((pThreadFunc)TlenVoiceReceiveThread, 0, item->ft);
- }
- }
- }
- }
- }
- else if (!mir_strcmp(e, "7")) {
- // FILE_RECV : e='7' : IP and port information to connect to send file
- // in case the conection to the given server was not successful
- if ((p=TlenXmlGetAttrValue(node, "i")) != nullptr) {
- if ((item=TlenListGetItemPtr(info->proto, LIST_VOICE, p)) != nullptr) {
- if ((p=TlenXmlGetAttrValue(node, "a")) != nullptr) {
- if (item->ft->hostName != nullptr) mir_free(item->ft->hostName);
- item->ft->hostName = mir_strdup(p);
- if ((p=TlenXmlGetAttrValue(node, "p")) != nullptr) {
- item->ft->wPort = atoi(p);
- item->ft->state = FT_SWITCH;
- SetEvent(item->ft->hFileEvent);
- }
- }
- }
- }
- }
- else if (!mir_strcmp(e, "8")) {
- // FILE_RECV : e='8' : transfer error
- if ((p=TlenXmlGetAttrValue(node, "i")) != nullptr) {
- if ((item=TlenListGetItemPtr(info->proto, LIST_VOICE, p)) != nullptr) {
- item->ft->state = FT_ERROR;
- SetEvent(item->ft->hFileEvent);
- }
- }
- }
-
- }
- }
-}
-
-static void __cdecl TlenKeepAliveThread(void *ptr)
-{
- TlenProtocol *proto = (TlenProtocol *)ptr;
-
- NETLIBSELECT nls = {};
- nls.dwTimeout = 60000; // 60000 millisecond (1 minute)
- nls.hExceptConns[0] = proto->threadData->s;
- for (;;) {
- if (Netlib_Select(&nls) != 0)
- break;
- if (proto->tlenOptions.sendKeepAlive)
- TlenSend(proto, " \t ");
- }
- proto->debugLogA("Exiting KeepAliveThread");
-}
-
|