From 48540940b6c28bb4378abfeb500ec45a625b37b6 Mon Sep 17 00:00:00 2001 From: Vadim Dashevskiy Date: Tue, 15 May 2012 10:38:20 +0000 Subject: initial commit git-svn-id: http://svn.miranda-ng.org/main/trunk@2 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/MRA/Mra_proto.cpp | 2581 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2581 insertions(+) create mode 100644 protocols/MRA/Mra_proto.cpp (limited to 'protocols/MRA/Mra_proto.cpp') diff --git a/protocols/MRA/Mra_proto.cpp b/protocols/MRA/Mra_proto.cpp new file mode 100644 index 0000000000..7d1c865d5f --- /dev/null +++ b/protocols/MRA/Mra_proto.cpp @@ -0,0 +1,2581 @@ +#include "Mra.h" +#include "MraOfflineMsg.h" +#include "MraRTFMsg.h" +#include "MraPlaces.h" + + + + + + +void MraThreadProc (LPVOID lpParameter); +DWORD MraGetNLBData (LPSTR lpszHost,SIZE_T dwHostBuffSize,WORD *pwPort); +DWORD MraNetworkDispather (); +DWORD MraCommandDispather (mrim_packet_header_t *pmaHeader,DWORD *pdwPingPeriod,DWORD *pdwNextPingSendTickTime,BOOL *pbContinue); + + + + +//DWORD GetMraStatusFromMiradaStatus (DWORD dwMirandaStatus,DWORD dwXStatusMir,DWORD *pdwXStatusMra); +//DWORD GetMiradaStatusFromMraStatus (DWORD dwMraStatus,DWORD dwXStatusMra,DWORD *pdwXStatusMir); +//DWORD GetMraXStatusIDFromMraUriStatus (LPSTR lpszStatusUri,SIZE_T dwStatusUriSize); + +DWORD GetUL (LPBYTE *plpData); +DWORDLONG GetUIDL (LPBYTE *plpData); +MRA_GUID GetGUID (LPBYTE *plpData); +DWORD GetLPS (LPBYTE lpbData,DWORD dwDataSize,LPBYTE *plpCurrentData,MRA_LPS *plpsString); + + + + + + +DWORD StartConnect() +{ + DWORD dwRetErrorCode=NO_ERROR; + + if (InterlockedExchangeAdd((volatile LONG*)&masMraSettings.dwGlobalPluginRunning,0)) + { + if (InterlockedCompareExchange((volatile LONG*)&masMraSettings.dwThreadWorkerRunning,TRUE,FALSE)==FALSE) + {// поток ещё/уже не работал, поставили статус что работает и запускаем + char szPass[MAX_PATH]; + SIZE_T dwEMailSize=0,dwPasswordSize=0; + + DB_Mra_GetStaticStringA(NULL,"e-mail",NULL,0,&dwEMailSize); + + if (dwEMailSize>5 && GetPassDB(szPass,sizeof(szPass),&dwPasswordSize)) + {// mir_forkthread + InterlockedExchange((volatile LONG*)&masMraSettings.dwThreadWorkerLastPingTime,GetTickCount()); + masMraSettings.hThreadWorker=mir_forkthread(MraThreadProc,NULL); + if (masMraSettings.hThreadWorker==NULL) + { + dwRetErrorCode=GetLastError(); + InterlockedExchange((volatile LONG*)&masMraSettings.dwThreadWorkerRunning,FALSE); + MraSetStatus(ID_STATUS_OFFLINE,0); + } + }else{ + MraThreadClean(); + if (!(dwEMailSize>5)) + { + MraPopupShowFromAgentW(MRA_POPUP_TYPE_WARNING,0,TranslateW(L"Please, setup e-mail in options")); + }else{ + MraPopupShowFromAgentW(MRA_POPUP_TYPE_WARNING,0,TranslateW(L"Please, setup password in options")); + } + } + SecureZeroMemory(szPass,sizeof(szPass)); + }else{ + DebugBreak(); + } + }else{ + dwRetErrorCode=ERROR_OPERATION_ABORTED; + //DebugBreak(); + } +return(dwRetErrorCode); +} + + +void MraThreadProc(LPVOID lpParameter) +{ + DWORD dwRetErrorCode=NO_ERROR; + + if (TRUE) + { + BOOL bConnected=FALSE; + char szHost[MAX_PATH]; + DWORD dwConnectReTryCount,dwCurConnectReTryCount; + NETLIBOPENCONNECTION nloc={0}; + + SleepEx(100,FALSE);// to prevent high CPU load by some status plugins like allwaysonline + + dwConnectReTryCount=DB_Mra_GetDword(NULL,"ConnectReTryCountMRIM",MRA_DEFAULT_CONN_RETRY_COUNT_MRIM); + + nloc.cbSize=sizeof(nloc); + nloc.flags=NLOCF_V2; + nloc.szHost=szHost; + nloc.timeout=DB_Mra_GetDword(NULL,"TimeOutConnectMRIM",MRA_DEFAULT_TIMEOUT_CONN_MRIM); + if (nloc.timeoutMRA_TIMEOUT_CONN_МАХ) nloc.timeout=MRA_TIMEOUT_CONN_МАХ; + + InterlockedExchange((volatile LONG*)&masMraSettings.dwThreadWorkerLastPingTime,GetTickCount()); + if (MraGetNLBData((LPSTR)nloc.szHost,MAX_PATH,&nloc.wPort)==NO_ERROR) + { + dwCurConnectReTryCount=dwConnectReTryCount; + do{ + InterlockedExchange((volatile LONG*)&masMraSettings.dwThreadWorkerLastPingTime,GetTickCount()); + masMraSettings.hConnection=(HANDLE)CallService(MS_NETLIB_OPENCONNECTION,(WPARAM)masMraSettings.hNetlibUser,(LPARAM)&nloc); + }while(--dwCurConnectReTryCount && masMraSettings.hConnection==NULL); + + if (masMraSettings.hConnection) + { + bConnected=TRUE; + } + } + + if (bConnected==FALSE) + if (DB_Mra_GetByte(NULL,"NLBFailDirectConnect",MRA_DEFAULT_NLB_FAIL_DIRECT_CONNECT)) + { + if (IsHTTPSProxyUsed(masMraSettings.hNetlibUser)) + {// через https прокси только 443 порт + nloc.wPort=MRA_SERVER_PORT_HTTPS; + }else{ + nloc.wPort=DB_Mra_GetWord(NULL,"ServerPort",MRA_DEFAULT_SERVER_PORT); + if (nloc.wPort==MRA_SERVER_PORT_STANDART_NLB) nloc.wPort=MRA_SERVER_PORT_STANDART; + } + + for(DWORD i=1;(iMRA_TIMEOUT_CONN_МАХ) nloc.timeout=MRA_TIMEOUT_CONN_МАХ; + + + dwCurConnectReTryCount=dwConnectReTryCount; + do{ + InterlockedExchange((volatile LONG*)&masMraSettings.dwThreadWorkerLastPingTime,GetTickCount()); + nls.hReadConns[0]=(HANDLE)CallService(MS_NETLIB_OPENCONNECTION,(WPARAM)masMraSettings.hNetlibUser,(LPARAM)&nloc); + }while(--dwCurConnectReTryCount && nls.hReadConns[0]==NULL); + + if (nls.hReadConns[0]) + { + nls.cbSize=sizeof(nls); + nls.dwTimeout=(1000*DB_Mra_GetDword(NULL,"TimeOutReceiveNLB",MRA_DEFAULT_TIMEOUT_RECV_NLB)); + InterlockedExchange((volatile LONG*)&masMraSettings.dwThreadWorkerLastPingTime,GetTickCount()); + + while(MraGetStatus(0,0)!=ID_STATUS_OFFLINE && bContinue) + { + switch(CallService(MS_NETLIB_SELECT,0,(LPARAM)&nls)){ + case SOCKET_ERROR: + case 0:// Time out + bContinue=FALSE; + break; + case 1: + dwBytesReceived=Netlib_Recv(nls.hReadConns[0],(LPSTR)(btBuff+dwRcvBuffSizeUsed),(SIZEOF(btBuff)-dwRcvBuffSizeUsed),0); + if (dwBytesReceived && dwBytesReceived!=SOCKET_ERROR) + { + dwRcvBuffSizeUsed+=dwBytesReceived; + }else{ + bContinue=FALSE; + } + break; + } + InterlockedExchange((volatile LONG*)&masMraSettings.dwThreadWorkerLastPingTime,GetTickCount()); + } + Netlib_CloseHandle(nls.hReadConns[0]); + + if (dwRcvBuffSizeUsed) + {// received, work with data + lpszPort=(LPSTR)MemoryFindByte(0,btBuff,dwRcvBuffSizeUsed,':'); + if (lpszPort) + { + (*lpszPort)=0; + lpszPort++; + + lstrcpynA(lpszHost,(LPSTR)btBuff,dwHostBuffSize); + if (pwPort) (*pwPort)=(WORD)StrToUNum32(lpszPort,(dwRcvBuffSizeUsed-(lpszPort-(LPSTR)btBuff))); + dwRetErrorCode=NO_ERROR; + }else{ + dwRetErrorCode=ERROR_INVALID_USER_BUFFER; + ShowFormatedErrorMessage(L"NLB data corrupted",NO_ERROR); + } + }else{ + dwRetErrorCode=GetLastError(); + ShowFormatedErrorMessage(L"Can't get data for NLB, error",dwRetErrorCode); + } + }else{ + dwRetErrorCode=GetLastError(); + ShowFormatedErrorMessage(L"Can't connect to NLB server, error",dwRetErrorCode); + } +return(dwRetErrorCode); +} + + +DWORD MraNetworkDispather() +{ + DWORD dwRetErrorCode=NO_ERROR; + + BOOL bContinue=TRUE; + DWORD dwSelectRet,dwBytesReceived,dwDataCurrentBuffSize,dwDataCurrentBuffSizeUsed,dwPingPeriod=MAXDWORD,dwNextPingSendTickTime=MAXDWORD; + SIZE_T dwRcvBuffSize=BUFF_SIZE_RCV,dwRcvBuffSizeUsed=0,dwDataCurrentBuffOffset=0; + LPBYTE lpbBufferRcv; + NETLIBSELECT nls={0}; + mrim_packet_header_t *pmaHeader; + + nls.cbSize=sizeof(nls); + nls.dwTimeout=NETLIB_SELECT_TIMEOUT; + nls.hReadConns[0]=masMraSettings.hConnection; + + lpbBufferRcv=(LPBYTE)MEMALLOC(dwRcvBuffSize); + + masMraSettings.dwCMDNum=0; + MraSendCMD(MRIM_CS_HELLO,NULL,0); + InterlockedExchange((volatile LONG*)&masMraSettings.dwThreadWorkerLastPingTime,GetTickCount()); + while(MraGetStatus(0,0)!=ID_STATUS_OFFLINE && bContinue) + { + dwSelectRet=CallService(MS_NETLIB_SELECT,0,(LPARAM)&nls); + switch(dwSelectRet){ + case SOCKET_ERROR: + if (MraGetStatus(0,0)!=ID_STATUS_OFFLINE) + { + dwRetErrorCode=GetLastError(); + ShowFormatedErrorMessage(L"Disconnected, socket error",dwRetErrorCode); + } + bContinue=FALSE; + break; + case 0:// Time out + case 1: + dwBytesReceived=GetTickCount(); + InterlockedExchange((volatile LONG*)&masMraSettings.dwThreadWorkerLastPingTime,dwBytesReceived); + if (dwNextPingSendTickTime<=dwBytesReceived) + {// server ping + dwNextPingSendTickTime=(dwBytesReceived+(dwPingPeriod*1000)); + MraSendCMD(MRIM_CS_PING,NULL,0); + } + { + DWORD dwCMDNum,dwFlags,dwAckType; + HANDLE hContact; + LPBYTE lpbData; + SIZE_T dwDataSize; + while (MraSendQueueFindOlderThan(masMraSettings.hSendQueueHandle,SEND_QUEUE_TIMEOUT,&dwCMDNum,&dwFlags,&hContact,&dwAckType,&lpbData,&dwDataSize)==NO_ERROR) + { + switch(dwAckType){ + case ACKTYPE_ADDED: + case ACKTYPE_AUTHREQ: + case ACKTYPE_CONTACTS: + //nothink to do + break; + case ACKTYPE_MESSAGE: + ProtoBroadcastAckAsynchEx(PROTOCOL_NAMEA,hContact,dwAckType,ACKRESULT_FAILED,(HANDLE)dwCMDNum,(LPARAM)"Undefined message deliver error, time out",-1); + break; + case ACKTYPE_GETINFO: + ProtoBroadcastAckAsynchEx(PROTOCOL_NAMEA,hContact,dwAckType,ACKRESULT_FAILED,(HANDLE)1,(LPARAM)NULL,0); + break; + case ACKTYPE_SEARCH: + ProtoBroadcastAckAsynchEx(PROTOCOL_NAMEA,hContact,dwAckType,ACKRESULT_SUCCESS,(HANDLE)dwCMDNum,(LPARAM)NULL,0); + break; + case ICQACKTYPE_SMS: + MEMFREE(lpbData); + break; + } + MraSendQueueFree(masMraSettings.hSendQueueHandle,dwCMDNum); + } + } + if (dwSelectRet==0) break;// Time out + + + if ((dwRcvBuffSize-dwRcvBuffSizeUsed)=sizeof(mrim_packet_header_t)) + {// packet header received + if (pmaHeader->magic==CS_MAGIC) + {// packet OK + if ((dwDataCurrentBuffSizeUsed-sizeof(mrim_packet_header_t))>=pmaHeader->dlen) + {// full packet received, may be more than one + + MraCommandDispather(pmaHeader,&dwPingPeriod,&dwNextPingSendTickTime,&bContinue); + + if ((dwDataCurrentBuffSizeUsed-sizeof(mrim_packet_header_t))>pmaHeader->dlen) + {// move pointer to next packet in buffer + dwDataCurrentBuffOffset+=(sizeof(mrim_packet_header_t)+pmaHeader->dlen); + }else{// move pointer to begin of buffer + if (dwRcvBuffSize>BUFF_SIZE_RCV) + {// динамическое уменьшение буффера приёма + dwRcvBuffSize=BUFF_SIZE_RCV; + lpbBufferRcv=(LPBYTE)MEMREALLOC(lpbBufferRcv,dwRcvBuffSize); + } + dwDataCurrentBuffOffset=0; + dwRcvBuffSizeUsed=0; + break; + } + }else{// not all packet received, continue receiving + if (dwDataCurrentBuffOffset) + { + memmove(lpbBufferRcv,(lpbBufferRcv+dwDataCurrentBuffOffset),dwDataCurrentBuffSizeUsed); + dwRcvBuffSizeUsed=dwDataCurrentBuffSizeUsed; + dwDataCurrentBuffOffset=0; + } + DebugPrintCRLFW(L"Not all packet received, continue receiving"); + break; + } + }else{// bad packet + DebugPrintCRLFW(L"Bad packet"); + dwDataCurrentBuffOffset=0; + dwRcvBuffSizeUsed=0; + break; + } + }else{// packet to small, continue receiving + DebugPrintCRLFW(L"Packet to small, continue receiving"); + memmove(lpbBufferRcv,(lpbBufferRcv+dwDataCurrentBuffOffset),dwDataCurrentBuffSizeUsed); + dwRcvBuffSizeUsed=dwDataCurrentBuffSizeUsed; + dwDataCurrentBuffOffset=0; + break; + } + } + }else{// disconnected + if (MraGetStatus(0,0)!=ID_STATUS_OFFLINE) + { + dwRetErrorCode=GetLastError(); + ShowFormatedErrorMessage(L"Disconnected, socket read error",dwRetErrorCode); + } + bContinue=FALSE; + } + break; + }// end switch + }// end while + MEMFREE(lpbBufferRcv); + +return(dwRetErrorCode); +} + + +DWORD MraCommandDispather(mrim_packet_header_t *pmaHeader,DWORD *pdwPingPeriod,DWORD *pdwNextPingSendTickTime,BOOL *pbContinue) +{ + WCHAR szBuff[4096]={0}; + DWORD dwDataSize,dwTemp,dwAckType; + SIZE_T dwStringSize; + MRA_LPS lpsString={0},lpsEMail={0}; + HANDLE hContact=NULL; + LPBYTE lpbData,lpbDataCurrent; + + lpbData=((((LPBYTE)pmaHeader))+sizeof(mrim_packet_header_t)); + lpbDataCurrent=lpbData; + dwDataSize=pmaHeader->dlen; + + + switch(pmaHeader->msg){ + case MRIM_CS_HELLO_ACK://Подтверждение установки соединения// UL ## ping_period ## Ожидаемая частота подтверждения соединения (в секундах) + //CredUIPromptForCredentials + //CYPTPROTECTMEMORY_BLOCK_SIZE=RTL_ENCRYPT_MEMORY_SIZE=8 + //CryptProtectMemory(szBuff,sizeof(szBuff),CRYPTPROTECTMEMORY_SAME_PROCESS); + if(GetPassDB((LPSTR)szBuff,SIZEOF(szBuff),&dwStringSize)) + {//bit of a security hole here, since it's easy to extract a password from an edit box + CHAR szEMail[MAX_EMAIL_LEN],szSelfVersionString[MAX_PATH],szUserAgentFormated[USER_AGENT_MAX+MAX_PATH],szValueName[MAX_PATH]; + WCHAR wszStatusTitle[STATUS_TITLE_MAX+4],wszStatusDesc[STATUS_DESC_MAX+4]; + DWORD dwStatus,dwXStatus,dwXStatusMir,dwFutureFlags; + LPWSTR lpwszStatusTitle,lpwszStatusDesc; + SIZE_T dwEMailSize,dwSelfVersionSize,dwStatusTitleSize,dwStatusDescSize,dwUserAgentFormatedSize; + + dwXStatusMir=MraGetXStatusInternal(); + dwStatus=GetMraStatusFromMiradaStatus(masMraSettings.dwDesiredStatusMode,dwXStatusMir,&dwXStatus); + if (IsXStatusValid(dwXStatusMir)) + {// xstatuses + mir_snprintf(szValueName,SIZEOF(szValueName),"XStatus%ldName",dwXStatusMir); + if (DB_Mra_GetStaticStringW(NULL,szValueName,wszStatusTitle,(STATUS_TITLE_MAX+1),&dwStatusTitleSize)) + {// custom xstatus name + lpwszStatusTitle=wszStatusTitle; + }else{// default xstatus name + lpwszStatusTitle=TranslateW(lpcszXStatusNameDef[dwXStatusMir]); + dwStatusTitleSize=lstrlenW(lpwszStatusTitle); + } + + mir_snprintf(szValueName,SIZEOF(szValueName),"XStatus%ldMsg",dwXStatusMir); + if (DB_Mra_GetStaticStringW(NULL,szValueName,wszStatusDesc,(STATUS_DESC_MAX+1),&dwStatusDescSize)) + {// custom xstatus description + lpwszStatusDesc=wszStatusDesc; + }else{// default xstatus description + lpwszStatusDesc=NULL; + dwStatusDescSize=0; + } + }else{// not xstatuses + lpwszStatusTitle=GetStatusModeDescriptionW(masMraSettings.dwDesiredStatusMode); + dwStatusTitleSize=lstrlenW(lpwszStatusTitle); + lpwszStatusDesc=NULL; + dwStatusDescSize=0; + } + + MraGetSelfVersionString(szSelfVersionString,SIZEOF(szSelfVersionString),&dwSelfVersionSize); + if (DB_Mra_GetStaticStringA(NULL,"MirVerCustom",szUserAgentFormated,SIZEOF(szUserAgentFormated),&dwUserAgentFormatedSize)==FALSE) + { + dwUserAgentFormatedSize=mir_snprintf(szUserAgentFormated,SIZEOF(szUserAgentFormated),"client=\"magent\" name=\"Miranda IM\" title=\"%s\" version=\"777.%lu.%lu.%lu\" build=\"%lu\" protocol=\"%lu.%lu\"",szSelfVersionString,(((PLUGIN_VERSION_DWORD)>>24)&0xFF),(((PLUGIN_VERSION_DWORD)>>16)&0xFF),(((PLUGIN_VERSION_DWORD)>>8)&0xFF),((PLUGIN_VERSION_DWORD)&0xFF),PROTO_MAJOR(PROTO_VERSION),PROTO_MINOR(PROTO_VERSION));// "client=\"magent\" version=\"9.3\" build=\"777\"" + } + + dwFutureFlags=((DB_Mra_GetByte(NULL,"RTFReceiveEnable",MRA_DEFAULT_RTF_RECEIVE_ENABLE)? FEATURE_FLAG_RTF_MESSAGE:0)|MRA_FEATURE_FLAGS); + + if (DB_Mra_GetStaticStringA(NULL,"e-mail",szEMail,SIZEOF(szEMail),&dwEMailSize)) + { + MraSendCommand_Login2W(szEMail,dwEMailSize,(LPSTR)szBuff,dwStringSize,dwStatus,lpcszStatusUri[dwXStatus],lstrlenA(lpcszStatusUri[dwXStatus]),lpwszStatusTitle,dwStatusTitleSize,lpwszStatusDesc,dwStatusDescSize,dwFutureFlags,szUserAgentFormated,dwUserAgentFormatedSize,szSelfVersionString,dwSelfVersionSize); + }else{// no login + (*pbContinue)=FALSE; + } + SecureZeroMemory(szBuff,sizeof(szBuff)); + }else{// no password + (*pbContinue)=FALSE; + } + (*pdwPingPeriod)=GetUL(&lpbDataCurrent); + break; + case MRIM_CS_LOGIN_ACK://Успешная авторизация + masMraSettings.bLoggedIn=TRUE; + (*pdwNextPingSendTickTime)=0;// force send ping + MraSendCMD(MRIM_CS_PING,NULL,0); + MraSetStatus(masMraSettings.dwDesiredStatusMode,masMraSettings.dwDesiredStatusMode); + //(*((LPBYTE)NULL))=1;// force exception + //while(TRUE) Sleep(1); // force infinite loop + MraAvatarsQueueGetAvatarSimple(masMraSettings.hAvatarsQueueHandle,GAIF_FORCE,NULL,0); + break; + case MRIM_CS_LOGIN_REJ://Неверная авторизация //LPS ## reason ## причина отказа + ProtoBroadcastAckAsynchEx(PROTOCOL_NAMEA,NULL,ACKTYPE_LOGIN,ACKRESULT_FAILED,NULL,LOGINERR_WRONGPASSWORD,0); + + GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString); + dwStringSize=MultiByteToWideChar(MRA_CODE_PAGE,0,lpsString.lpszData,lpsString.dwSize,szBuff,SIZEOF(szBuff)); + szBuff[dwStringSize]=0; + MraPopupShowW(NULL,MRA_POPUP_TYPE_ERROR,0,TranslateW(L"Logon error: invalid login/password"),szBuff); + (*pbContinue)=FALSE; + break; + case MRIM_CS_MESSAGE_ACK:// Доставка сообщения + { + DWORD dwMsgID,dwFlags; + MRA_LPS lpsText,lpsRTFText,lpsMultiChatData; + + dwMsgID=GetUL(&lpbDataCurrent); + dwFlags=GetUL(&lpbDataCurrent); + GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsEMail);//LPS ## from ## Адрес отправителя + GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsText);//LPS ## message ## текстовая версия сообщения + //if (dwFlags&MESSAGE_FLAG_RTF) + GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsRTFText);//LPS ## rtf-message ## форматированная версия сообщения + if (dwFlags&MESSAGE_FLAG_MULTICHAT) GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsMultiChatData); // LPS multichat_data + + if (MraRecvCommand_Message((DWORD)_time32(NULL),dwFlags,&lpsEMail,&lpsText,&lpsRTFText,&lpsMultiChatData)==NO_ERROR) + {// подтверждаем получение, только если удалось его обработать + if ((dwFlags&MESSAGE_FLAG_NORECV)==0) + {// need send delivery status + MraSendCommand_MessageRecv(lpsEMail.lpszData,lpsEMail.dwSize,dwMsgID); + } + } + } + break; + case MRIM_CS_MESSAGE_STATUS: + if (MraSendQueueFind(masMraSettings.hSendQueueHandle,pmaHeader->seq,NULL,&hContact,&dwAckType,(LPBYTE*)&lpsString.lpszData,&lpsString.dwSize)==NO_ERROR) + { + dwTemp=GetUL(&lpbDataCurrent); + switch(dwTemp){ + case MESSAGE_DELIVERED:// Message delivered directly to user + ProtoBroadcastAckAsynchEx(PROTOCOL_NAMEA,hContact,dwAckType,ACKRESULT_SUCCESS,(HANDLE)pmaHeader->seq,(LPARAM)NULL,0); + break;//***deb возможны сбои из-за асинхронности тк там передаётся указатель + case MESSAGE_REJECTED_NOUSER:// Message rejected - no such user + ProtoBroadcastAckAsynchEx(PROTOCOL_NAMEA,hContact,dwAckType,ACKRESULT_FAILED,(HANDLE)pmaHeader->seq,(LPARAM)"Message rejected - no such user",-1); + break; + case MESSAGE_REJECTED_INTERR:// Internal server error + ProtoBroadcastAckAsynchEx(PROTOCOL_NAMEA,hContact,dwAckType,ACKRESULT_FAILED,(HANDLE)pmaHeader->seq,(LPARAM)"Internal server error",-1); + break; + case MESSAGE_REJECTED_LIMIT_EXCEEDED:// Offline messages limit exceeded + ProtoBroadcastAckAsynchEx(PROTOCOL_NAMEA,hContact,dwAckType,ACKRESULT_FAILED,(HANDLE)pmaHeader->seq,(LPARAM)"Offline messages limit exceeded",-1); + break; + case MESSAGE_REJECTED_TOO_LARGE:// Message is too large + ProtoBroadcastAckAsynchEx(PROTOCOL_NAMEA,hContact,dwAckType,ACKRESULT_FAILED,(HANDLE)pmaHeader->seq,(LPARAM)"Message is too large",-1); + break; + case MESSAGE_REJECTED_DENY_OFFMSG:// User does not accept offline messages + ProtoBroadcastAckAsynchEx(PROTOCOL_NAMEA,hContact,dwAckType,ACKRESULT_FAILED,(HANDLE)pmaHeader->seq,(LPARAM)"User does not accept offline messages",-1); + break; + case MESSAGE_REJECTED_DENY_OFFFLSH:// User does not accept offline flash animation + ProtoBroadcastAckAsynchEx(PROTOCOL_NAMEA,hContact,dwAckType,ACKRESULT_FAILED,(HANDLE)pmaHeader->seq,(LPARAM)"User does not accept offline flash animation",-1); + break; + default: + dwTemp=mir_snprintf((LPSTR)szBuff,SIZEOF(szBuff),"Undefined message deliver error, code: %lu",dwTemp); + ProtoBroadcastAckAsynchEx(PROTOCOL_NAMEA,hContact,dwAckType,ACKRESULT_FAILED,(HANDLE)pmaHeader->seq,(LPARAM)szBuff,dwTemp); + break; + } + MraSendQueueFree(masMraSettings.hSendQueueHandle,pmaHeader->seq); + }else{// not found in queue + if (GetUL(&lpbDataCurrent)!=MESSAGE_DELIVERED) MraPopupShowFromAgentW(MRA_POPUP_TYPE_DEBUG,0,TranslateW(L"MRIM_CS_MESSAGE_STATUS: not found in queue")); + } + break; + case MRIM_CS_CONNECTION_PARAMS:// Изменение параметров соединения + (*pdwPingPeriod)=GetUL(&lpbDataCurrent); + (*pdwNextPingSendTickTime)=0;// force send ping + MraSendCMD(MRIM_CS_PING,NULL,0); + break; + case MRIM_CS_USER_INFO: + while (lpbDataCurrent<(lpbData+dwDataSize)) + { + GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString); + if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,lpsString.lpszData,lpsString.dwSize,"MESSAGES.TOTAL",14)==CSTR_EQUAL) + { + GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString); + masMraSettings.dwEmailMessagesTotal=StrToUNum32(lpsString.lpszData,lpsString.dwSize); + }else + if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,lpsString.lpszData,lpsString.dwSize,"MESSAGES.UNREAD",15)==CSTR_EQUAL) + { + GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString); + masMraSettings.dwEmailMessagesUnRead=StrToUNum32(lpsString.lpszData,lpsString.dwSize); + }else + if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,lpsString.lpszData,lpsString.dwSize,"MRIM.NICKNAME",13)==CSTR_EQUAL) + { + GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString); + DB_Mra_SetLPSStringW(NULL,"Nick",&lpsString); + }else + if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,lpsString.lpszData,lpsString.dwSize,"client.endpoint",15)==CSTR_EQUAL) + { + LPSTR lpszDelimiter; + + GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString); + dwStringSize=WideCharToMultiByte(MRA_CODE_PAGE,0,lpsString.lpwszData,lpsString.dwSize,(LPSTR)szBuff,sizeof(szBuff),NULL,NULL); + lpszDelimiter=(LPSTR)MemoryFind(0,szBuff,dwStringSize,":",1); + if (lpszDelimiter) + { + (*lpszDelimiter)=0; + lpszDelimiter=(LPSTR)szBuff; + DB_Mra_SetDword(NULL,"IP",HTONL(inet_addr(lpszDelimiter))); + } + }else + if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,lpsString.lpszData,lpsString.dwSize,"connect.xml",11)==CSTR_EQUAL) + { + DebugPrintA(lpsString.lpszData); + GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString); + DebugPrintCRLFW(lpsString.lpwszData); + }else + if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,lpsString.lpszData,lpsString.dwSize,"micblog.show_title",18)==CSTR_EQUAL) + { + DebugPrintA(lpsString.lpszData); + GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString); + DebugPrintCRLFW(lpsString.lpwszData); + }else + if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,lpsString.lpszData,lpsString.dwSize,"micblog.status.id",17)==CSTR_EQUAL) + { + DWORDLONG dwBlogStatusID; + + GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString); + dwBlogStatusID=StrToUNum64(lpsString.lpszData,lpsString.dwSize); + DB_Mra_WriteContactSettingBlob(NULL,DBSETTING_BLOGSTATUSID,&dwBlogStatusID,sizeof(DWORDLONG)); + }else + if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,lpsString.lpszData,lpsString.dwSize,"micblog.status.time",19)==CSTR_EQUAL) + { + GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString); + DB_Mra_SetDword(NULL,DBSETTING_BLOGSTATUSTIME,StrToUNum32(lpsString.lpszData,lpsString.dwSize)); + }else + if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,lpsString.lpszData,lpsString.dwSize,"micblog.status.text",19)==CSTR_EQUAL) + { + GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString); + DB_Mra_SetLPSStringW(NULL,DBSETTING_BLOGSTATUS,&lpsString); + }else + if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,lpsString.lpszData,lpsString.dwSize,"HAS_MYMAIL",10)==CSTR_EQUAL) + {// ??? + GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString); + //DB_Mra_SetDword(NULL,DBSETTING_BLOGSTATUSTIME,StrToUNum32(lpsString.lpszData,lpsString.dwSize)); + }else + if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,lpsString.lpszData,lpsString.dwSize,"mrim.status.open_search",23)==CSTR_EQUAL) + {// ??? + GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString); + //DB_Mra_SetDword(NULL,DBSETTING_BLOGSTATUSTIME,StrToUNum32(lpsString.lpszData,lpsString.dwSize)); + }else + if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,lpsString.lpszData,lpsString.dwSize,"rb.target.cookie",16)==CSTR_EQUAL) + {// ??? + GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString); + //DB_Mra_SetDword(NULL,DBSETTING_BLOGSTATUSTIME,StrToUNum32(lpsString.lpszData,lpsString.dwSize)); + }else + if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,lpsString.lpszData,lpsString.dwSize,"show_web_history_link",21)==CSTR_EQUAL) + {// ??? + GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString); + //DB_Mra_SetDword(NULL,DBSETTING_BLOGSTATUSTIME,StrToUNum32(lpsString.lpszData,lpsString.dwSize)); + }else + if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,lpsString.lpszData,lpsString.dwSize,"friends_suggest",15)==CSTR_EQUAL) + {// ??? + GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString); + //DB_Mra_SetDword(NULL,DBSETTING_BLOGSTATUSTIME,StrToUNum32(lpsString.lpszData,lpsString.dwSize)); + }else + if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,lpsString.lpszData,lpsString.dwSize,"timestamp",9)==CSTR_EQUAL) + {// ??? + GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString); + //DB_Mra_SetDword(NULL,DBSETTING_BLOGSTATUSTIME,StrToUNum32(lpsString.lpszData,lpsString.dwSize)); + }else + if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,lpsString.lpszData,lpsString.dwSize,"trusted_update",14)==CSTR_EQUAL) + {// ??? + GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString); + //DB_Mra_SetDword(NULL,DBSETTING_BLOGSTATUSTIME,StrToUNum32(lpsString.lpszData,lpsString.dwSize)); + }else{ + #ifdef _DEBUG + LPSTR lpszCurrentPos=(LPSTR)szBuff; + memmove(lpszCurrentPos,lpsString.lpszData,lpsString.dwSize); + lpszCurrentPos+=lpsString.dwSize; + (*((WORD*)lpszCurrentPos))=(*((WORD*)": ")); + lpszCurrentPos+=sizeof(WORD); + + GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString); + memmove(lpszCurrentPos,lpsString.lpszData,lpsString.dwSize); + lpszCurrentPos+=lpsString.dwSize; + (*((WORD*)lpszCurrentPos))=(*((WORD*)szCRLF)); + lpszCurrentPos+=sizeof(WORD);(*((WORD*)lpszCurrentPos))=0; + + DebugPrintCRLFA((LPSTR)szBuff); + //MraPopupShowFromAgentW(MRA_POPUP_TYPE_DEBUG,0,szBuff); + DebugBreak(); + #endif + } + } + MraUpdateEmailStatus(NULL,0,NULL,0,0,0); + break; + case MRIM_CS_OFFLINE_MESSAGE_ACK://Сообщение доставленное, пока пользователь не был подключен к сети + { + DWORD dwTime,dwFlags; + MRA_LPS lpsText,lpsRTFText,lpsMultiChatData; + LPBYTE lpbBuff=NULL; + DWORDLONG dwMsgUIDL; + + dwMsgUIDL=GetUIDL(&lpbDataCurrent); + GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString); + + if (MraOfflineMessageGet(&lpsString,&dwTime,&dwFlags,&lpsEMail,&lpsText,&lpsRTFText,&lpsMultiChatData,&lpbBuff)==NO_ERROR) + { + dwTemp=MraRecvCommand_Message(dwTime,dwFlags,&lpsEMail,&lpsText,&lpsRTFText,&lpsMultiChatData); + if (dwTemp==NO_ERROR || dwTemp==ERROR_ACCESS_DENIED) + {// подтверждаем получение, только если удалось его обработать + MraSendCommand_OfflineMessageDel(dwMsgUIDL); + }else{ + ShowFormatedErrorMessage(L"Offline message processing error, message will not deleted from server",NO_ERROR); + } + }else{ + ShowFormatedErrorMessage(L"Offline message processing error, message will not deleted from server",NO_ERROR); + } + MEMFREE(lpbBuff); + } + break; + case MRIM_CS_AUTHORIZE_ACK://Информация об авторизации + {// нас автоизовали, те разрешили нам получать уведомление об изменении статуса, значит юзер у нас в списке + BOOL bAdded; + BYTE btBuff[BUFF_SIZE_BLOB]; + DBEVENTINFO dbei={0}; + + GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsEMail); + hContact=MraHContactFromEmail(lpsEMail.lpszData,lpsEMail.dwSize,TRUE,TRUE,&bAdded); + if (bAdded) MraUpdateContactInfo(hContact); + + if (IsEMailChatAgent(lpsEMail.lpszData,lpsEMail.dwSize)==FALSE) + { + dbei.cbSize=sizeof(dbei); + dbei.szModule=PROTOCOL_NAMEA; + dbei.timestamp=(DWORD)_time32(NULL); + dbei.flags=0; + dbei.eventType=EVENTTYPE_ADDED; + //dbei.cbBlob=0; + CreateBlobFromContact(hContact,NULL,0,(LPBYTE)&btBuff,SIZEOF(btBuff),&dwStringSize); + dbei.cbBlob=dwStringSize; + dbei.pBlob=btBuff; + + CallService(MS_DB_EVENT_ADD,(WPARAM)NULL,(LPARAM)&dbei); + } + + GetContactBasicInfoW(hContact,NULL,NULL,NULL,&dwTemp,NULL,NULL,0,NULL,NULL,0,NULL,NULL,0,NULL); + dwTemp&=~CONTACT_INTFLAG_NOT_AUTHORIZED; + SetContactBasicInfoW(hContact,SCBIFSI_LOCK_CHANGES_EVENTS,SCBIF_SERVER_FLAG,0,0,0,dwTemp,0,NULL,0,NULL,0,NULL,0); + DB_Mra_SetDword(hContact,"HooksLocked",TRUE); + DBDeleteContactSetting(hContact,"CList","NotOnList"); + DB_Mra_SetDword(hContact,"HooksLocked",FALSE); + } + break; + case MRIM_CS_MPOP_SESSION://Ключ для web-авторизации // + if (GetUL(&lpbDataCurrent)) + { + GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString); + MraMPopSessionQueueSetNewMPopKey(masMraSettings.hMPopSessionQueue,lpsString.lpszData,lpsString.dwSize); + MraMPopSessionQueueStart(masMraSettings.hMPopSessionQueue); + }else{//error + MraPopupShowFromAgentW(MRA_POPUP_TYPE_WARNING,0,TranslateW(L"Server error: cant get MPOP key for web authorize")); + MraMPopSessionQueueFlush(masMraSettings.hMPopSessionQueue); + } + break; +///////////////////////////////////////////////////////////////////////////////////// + case MRIM_CS_FILE_TRANSFER: + { + BOOL bAdded; + DWORD dwIDRequest,dwFilesTotalSize; + MRA_LPS lpsFiles={0},lpsFilesW={0},lpsAddreses={0}; + + GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsEMail);// LPS TO/FROM ANSI + dwIDRequest=GetUL(&lpbDataCurrent);// DWORD id_request + dwFilesTotalSize=GetUL(&lpbDataCurrent);// DWORD FILESIZE + if (GetUL(&lpbDataCurrent))//LPS: + { + GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsFiles);// LPS Files (FileName;FileSize;FileName;FileSize;) ANSI + if (GetUL(&lpbDataCurrent))// LPS DESCRIPTION + { + dwTemp=GetUL(&lpbDataCurrent);// ??? + DebugBreakIf(dwTemp!=1); + GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsFilesW);// LPS Files (FileName;FileSize;FileName;FileSize;) UNICODE + } + GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsAddreses);// LPS Conn (IP:Port;IP:Port;) ANSI + } + + hContact=MraHContactFromEmail(lpsEMail.lpszData,lpsEMail.dwSize,TRUE,TRUE,&bAdded); + if (bAdded) MraUpdateContactInfo(hContact); + + bAdded=FALSE; + if (lpsFilesW.dwSize==0) + { + lpsFilesW.lpwszData=(LPWSTR)MEMALLOC((lpsFiles.dwSize+MAX_PATH)*sizeof(WCHAR)); + if (lpsFilesW.lpwszData) + { + lpsFilesW.dwSize=MultiByteToWideChar(MRA_CODE_PAGE,0,lpsFiles.lpszData,lpsFiles.dwSize,lpsFilesW.lpwszData,(lpsFiles.dwSize+MAX_PATH)); + bAdded=TRUE; + } + } + + if (lpsFilesW.dwSize) MraFilesQueueAddReceive(masMraSettings.hFilesQueueHandle,0,hContact,dwIDRequest,lpsFilesW.lpwszData,lpsFilesW.dwSize,lpsAddreses.lpszData,lpsAddreses.dwSize); + if (bAdded) MEMFREE(lpsFilesW.lpwszData); + } + break; + case MRIM_CS_FILE_TRANSFER_ACK: + dwAckType=GetUL(&lpbDataCurrent);// DWORD status + GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsEMail);// LPS TO/FROM + dwTemp=GetUL(&lpbDataCurrent);// DWORD id_request + GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString);// LPS DESCRIPTION + + switch(dwAckType){ + case FILE_TRANSFER_STATUS_OK:// игнорируем, мы и так уже слушаем порт(ждём), то что кто то согласился ничего не меняет + //hContact=MraHContactFromEmail(lpsEMail.lpszData,lpsEMail.dwSize,TRUE,TRUE,NULL); + break; + case FILE_TRANSFER_STATUS_DECLINE: + MraFilesQueueCancel(masMraSettings.hFilesQueueHandle,dwTemp,FALSE); + break; + case FILE_TRANSFER_STATUS_ERROR: + ShowFormatedErrorMessage(L"File transfer: error",NO_ERROR); + MraFilesQueueCancel(masMraSettings.hFilesQueueHandle,dwTemp,FALSE); + break; + case FILE_TRANSFER_STATUS_INCOMPATIBLE_VERS: + ShowFormatedErrorMessage(L"File transfer: incompatible versions",NO_ERROR); + MraFilesQueueCancel(masMraSettings.hFilesQueueHandle,dwTemp,FALSE); + break; + case FILE_TRANSFER_MIRROR: + MraFilesQueueSendMirror(masMraSettings.hFilesQueueHandle,dwTemp,lpsString.lpszData,lpsString.dwSize); + break; + default:// ## unknown error + mir_sntprintf(szBuff,SIZEOF(szBuff),TranslateW(L"MRIM_CS_FILE_TRANSFER_ACK: unknown error, code: %lu"),dwAckType); + ShowFormatedErrorMessage(szBuff,NO_ERROR); + break; + } + break; +///////////////////////////////////////////////////////////////////////////////////// + case MRIM_CS_USER_STATUS://Смена статуса другого пользователя + { + BOOL bAdded; + DWORD dwStatus,dwXStatus,dwFutureFlags; + MRA_LPS lpsSpecStatusUri,lpsStatusTitle,lpsStatusDesc,lpsUserAgentFormated; + + dwStatus=GetUL(&lpbDataCurrent); + GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsSpecStatusUri); + GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsStatusTitle); + GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsStatusDesc); + GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsEMail); + dwFutureFlags=GetUL(&lpbDataCurrent);// com_support (>=1.14) + GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsUserAgentFormated); + + + if ((hContact=MraHContactFromEmail(lpsEMail.lpszData,lpsEMail.dwSize,TRUE,TRUE,&bAdded))) + { + if (bAdded) MraUpdateContactInfo(hContact); + + dwTemp=GetMiradaStatusFromMraStatus(dwStatus,GetMraXStatusIDFromMraUriStatus(lpsSpecStatusUri.lpszData,lpsSpecStatusUri.dwSize),&dwXStatus); + + MraContactCapabilitiesSet(hContact,dwFutureFlags); + DB_Mra_SetByte(hContact,DBSETTING_XSTATUSID,(BYTE)dwXStatus); + DB_Mra_SetLPSStringW(hContact,DBSETTING_XSTATUSNAME,&lpsStatusTitle); + DB_Mra_SetLPSStringW(hContact,DBSETTING_XSTATUSMSG,&lpsStatusDesc); + + if (dwTemp!=ID_STATUS_OFFLINE)// пишем клиента только если юзер не отключён, иначе не затираем старое + { + if (lpsUserAgentFormated.dwSize) + {// есть чё писать + if (DB_Mra_GetByte(NULL,"MirVerRaw",MRA_DEFAULT_MIRVER_RAW)==FALSE) + {// приводим к человеческому виду, если получится... + MraGetVersionStringFromFormated(lpsUserAgentFormated.lpszData,lpsUserAgentFormated.dwSize,(LPSTR)szBuff,SIZEOF(szBuff),&dwStringSize); + lpsUserAgentFormated.lpszData=(LPSTR)szBuff; + lpsUserAgentFormated.dwSize=dwStringSize; + } + }else{// хз чё за клиент + lpsUserAgentFormated.lpszData=MIRVER_UNKNOWN; + lpsUserAgentFormated.dwSize=(sizeof(MIRVER_UNKNOWN)-1); + } + DB_Mra_SetLPSStringA(hContact,"MirVer",&lpsUserAgentFormated); + } + + if (dwTemp==MraGetContactStatus(hContact)) + {// меняем шило на шило, подозрительно? ;) + if (dwTemp==ID_STATUS_OFFLINE) + {// was/now invisible + WCHAR szEMail[MAX_EMAIL_LEN]; + + DB_Mra_GetStaticStringW(hContact,"e-mail",szEMail,SIZEOF(szEMail),NULL); + mir_sntprintf(szBuff,SIZEOF(szBuff),L"%s <%s> - %s",GetContactNameW(hContact),szEMail,TranslateW(L"invisible status changed")); + MraPopupShowFromContactW(hContact,MRA_POPUP_TYPE_INFORMATION,0,szBuff); + + MraSetContactStatus(hContact,ID_STATUS_INVISIBLE); + }else{// server or miranda bug or status change + //DebugBreak(); + } + } + MraSetContactStatus(hContact,dwTemp); + SetExtraIcons(hContact); + } + } + break; + case MRIM_CS_LOGOUT:// Пользователь отключен из-за параллельного входа с его логином. + if (GetUL(&lpbDataCurrent)==LOGOUT_NO_RELOGIN_FLAG) ShowFormatedErrorMessage(L"Another user connected with your login",NO_ERROR); + (*pbContinue)=FALSE; + break; + case MRIM_CS_ADD_CONTACT_ACK: + case MRIM_CS_MODIFY_CONTACT_ACK: + if (MraSendQueueFind(masMraSettings.hSendQueueHandle,pmaHeader->seq,NULL,&hContact,&dwAckType,(LPBYTE*)&lpsString.lpszData,&lpsString.dwSize)==NO_ERROR) + { + dwTemp=GetUL(&lpbDataCurrent); + switch(dwTemp){ + case CONTACT_OPER_SUCCESS:// ## добавление произведено успешно + if (pmaHeader->msg==MRIM_CS_ADD_CONTACT_ACK) SetContactBasicInfoW(hContact,0,(SCBIF_ID|SCBIF_SERVER_FLAG),GetUL(&lpbDataCurrent),0,0,CONTACT_INTFLAG_NOT_AUTHORIZED,0,NULL,0,NULL,0,NULL,0); + break; + case CONTACT_OPER_ERROR:// ## переданные данные были некорректны + ShowFormatedErrorMessage(L"Sended data is invalid",NO_ERROR); + break; + case CONTACT_OPER_INTERR:// ## при обработке запроса произошла внутренняя ошибка + ShowFormatedErrorMessage(L"Internal server error",NO_ERROR); + break; + case CONTACT_OPER_NO_SUCH_USER:// ## добавляемого пользователя не существует в системе + SetContactBasicInfoW(hContact,0,SCBIF_SERVER_FLAG,0,0,0,-1,0,NULL,0,NULL,0,NULL,0); + ShowFormatedErrorMessage(L"User does not registred",NO_ERROR); + break; + case CONTACT_OPER_INVALID_INFO:// ## некорректное имя пользователя + ShowFormatedErrorMessage(L"Invalid user name",NO_ERROR); + break; + case CONTACT_OPER_USER_EXISTS:// ## пользователь уже есть в контакт-листе + ShowFormatedErrorMessage(L"User allready added",NO_ERROR); + break; + case CONTACT_OPER_GROUP_LIMIT:// ## превышено максимально допустимое количество групп (20) + ShowFormatedErrorMessage(L"Group limit is 20",NO_ERROR); + break; + default:// ## unknown error + mir_sntprintf(szBuff,SIZEOF(szBuff),TranslateW(L"MRIM_CS_*_CONTACT_ACK: unknown server error, code: %lu"),dwTemp); + MraPopupShowFromAgentW(MRA_POPUP_TYPE_DEBUG,0,szBuff); + break; + } + MraSendQueueFree(masMraSettings.hSendQueueHandle,pmaHeader->seq); + }else{// not found in queue + MraPopupShowFromAgentW(MRA_POPUP_TYPE_DEBUG,0,TranslateW(L"MRIM_CS_*_CONTACT_ACK: not found in queue")); + } + break; + case MRIM_CS_ANKETA_INFO: + if (MraSendQueueFind(masMraSettings.hSendQueueHandle,pmaHeader->seq,NULL,&hContact,&dwAckType,(LPBYTE*)&lpsString.lpszData,&lpsString.dwSize)==NO_ERROR) + { + switch(GetUL(&lpbDataCurrent)){ + case MRIM_ANKETA_INFO_STATUS_OK:// поиск успешно завершен + { + DWORD dwFeildsNum,dwMaxRows,dwServerTime,dwStatus; + SIZE_T i; + MRA_LPS *pmralpsFeilds,*pmralpsValues; + + dwFeildsNum=GetUL(&lpbDataCurrent); + dwMaxRows=GetUL(&lpbDataCurrent); + dwServerTime=GetUL(&lpbDataCurrent); + + pmralpsFeilds=(MRA_LPS*)MEMALLOC(((dwFeildsNum*2)+4)*sizeof(MRA_LPS)); + if (pmralpsFeilds) + { + pmralpsValues=(pmralpsFeilds+dwFeildsNum); + // read headers name + for (i=0;i9) + {// calc "Age" + SYSTEMTIME stTime={0}; + + stTime.wYear=(WORD)StrToUNum32(pmralpsValues[i].lpszData,4); + stTime.wMonth=(WORD)StrToUNum32((pmralpsValues[i].lpszData+5),2); + stTime.wDay=(WORD)StrToUNum32((pmralpsValues[i].lpszData+8),2); + DB_Mra_SetWord(hContact,"BirthYear",stTime.wYear); + DB_Mra_SetByte(hContact,"BirthMonth",(BYTE)stTime.wMonth); + DB_Mra_SetByte(hContact,"BirthDay",(BYTE)stTime.wDay); + + DB_Mra_SetWord(hContact,"Age",(WORD)GetYears(&stTime)); + }else{ + DB_Mra_DeleteValue(hContact,"BirthYear"); + DB_Mra_DeleteValue(hContact,"BirthMonth"); + DB_Mra_DeleteValue(hContact,"BirthDay"); + DB_Mra_DeleteValue(hContact,"Age"); + } + }else + if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,pmralpsFeilds[i].lpszData,pmralpsFeilds[i].dwSize,"City_id",7)==CSTR_EQUAL) + { + dwTemp=StrToUNum32(pmralpsValues[i].lpszData,pmralpsValues[i].dwSize); + if (dwTemp) + { + for(SIZE_T j=0;mrapPlaces[j].lpszData;j++) + { + if (mrapPlaces[j].dwCityID==dwTemp) + { + DB_Mra_SetStringW(hContact,"City",mrapPlaces[j].lpszData); + break; + } + } + }else{ + DB_Mra_DeleteValue(hContact,"City"); + } + }else + if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,pmralpsFeilds[i].lpszData,pmralpsFeilds[i].dwSize,"Location",8)==CSTR_EQUAL) + {//*** + DB_Mra_SetLPSStringW(hContact,"About",&pmralpsValues[i]); + }else + if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,pmralpsFeilds[i].lpszData,pmralpsFeilds[i].dwSize,"Zodiac",6)==CSTR_EQUAL) + { + //*** + }else + if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,pmralpsFeilds[i].lpszData,pmralpsFeilds[i].dwSize,"BMonth",6)==CSTR_EQUAL) + {// used Birthday + //if (pmralpsValues[i].dwSize) DB_Mra_SetByte(hContact,"BirthMonth",(BYTE)StrToUNum32(pmralpsValues[i].lpszData,pmralpsValues[i].dwSize)); + }else + if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,pmralpsFeilds[i].lpszData,pmralpsFeilds[i].dwSize,"BDay",4)==CSTR_EQUAL) + {// used Birthday + //if (pmralpsValues[i].dwSize) DB_Mra_SetByte(hContact,"BirthDay",(BYTE)StrToUNum32(pmralpsValues[i].lpszData,pmralpsValues[i].dwSize)); + }else + if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,pmralpsFeilds[i].lpszData,pmralpsFeilds[i].dwSize,"Country_id",10)==CSTR_EQUAL) + { + dwTemp=StrToUNum32(pmralpsValues[i].lpszData,pmralpsValues[i].dwSize); + if (dwTemp) + { + for(SIZE_T j=0;mrapPlaces[j].lpszData;j++) + { + if (mrapPlaces[j].dwCountryID==dwTemp) + { + DB_Mra_SetStringW(hContact,"Country",mrapPlaces[j].lpszData); + break; + } + } + }else{ + DB_Mra_DeleteValue(hContact,"Country"); + } + }else + if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,pmralpsFeilds[i].lpszData,pmralpsFeilds[i].dwSize,"Phone",5)==CSTR_EQUAL) + { + DB_Mra_DeleteValue(hContact,"Phone"); + DB_Mra_DeleteValue(hContact,"Cellular"); + DB_Mra_DeleteValue(hContact,"Fax"); + + if (pmralpsValues[i].dwSize) + { + LPSTR lpszCurPos; + + lpsString.lpszData=pmralpsValues[i].lpszData; + lpszCurPos=(LPSTR)MemoryFindByte(0,pmralpsValues[i].lpszData,pmralpsValues[i].dwSize,','); + if (lpszCurPos) + { + lpsString.dwSize=(lpszCurPos-lpsString.lpszData); + }else{ + lpsString.dwSize=((pmralpsValues[i].lpszData+pmralpsValues[i].dwSize)-lpsString.lpszData); + } + DB_Mra_SetLPSStringA(hContact,"Phone",&lpsString); + + if (lpszCurPos) + { + lpsString.lpszData=(++lpszCurPos); + lpszCurPos=(LPSTR)MemoryFindByte((lpszCurPos-pmralpsValues[i].lpszData),pmralpsValues[i].lpszData,pmralpsValues[i].dwSize,','); + if (lpszCurPos) + { + lpsString.dwSize=(lpszCurPos-lpsString.lpszData); + }else{ + lpsString.dwSize=((pmralpsValues[i].lpszData+pmralpsValues[i].dwSize)-lpsString.lpszData); + } + DB_Mra_SetLPSStringA(hContact,"Cellular",&lpsString); + } + + if (lpszCurPos) + { + lpsString.lpszData=(++lpszCurPos); + lpszCurPos=(LPSTR)MemoryFindByte((lpszCurPos-pmralpsValues[i].lpszData),pmralpsValues[i].lpszData,pmralpsValues[i].dwSize,','); + if (lpszCurPos) + { + lpsString.dwSize=(lpszCurPos-lpsString.lpszData); + }else{ + lpsString.dwSize=((pmralpsValues[i].lpszData+pmralpsValues[i].dwSize)-lpsString.lpszData); + } + DB_Mra_SetLPSStringA(hContact,"Fax",&lpsString); + } + } + }else + if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,pmralpsFeilds[i].lpszData,pmralpsFeilds[i].dwSize,"mrim_status",11)==CSTR_EQUAL) + { + if (pmralpsValues[i].dwSize) + { + DWORD dwID,dwContactSeverFlags; + + GetContactBasicInfoW(hContact,&dwID,NULL,NULL,&dwContactSeverFlags,NULL,NULL,0,NULL,NULL,0,NULL,NULL,0,NULL); + if (dwID==-1 || dwContactSeverFlags&CONTACT_INTFLAG_NOT_AUTHORIZED) + {// для авторизованного нам и так присылают правильный статус + dwStatus=StrHexToUNum32(pmralpsValues[i].lpszData,pmralpsValues[i].dwSize); + MraSetContactStatus(hContact,GetMiradaStatusFromMraStatus(dwStatus,MRA_MIR_XSTATUS_NONE,NULL)); + DB_Mra_SetByte(hContact,DBSETTING_XSTATUSID,(BYTE)MRA_MIR_XSTATUS_NONE); + } + } + }else + if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,pmralpsFeilds[i].lpszData,pmralpsFeilds[i].dwSize,"status_uri",10)==CSTR_EQUAL) + { + if (pmralpsValues[i].dwSize) + { + DWORD dwID,dwContactSeverFlags,dwXStatus; + + GetContactBasicInfoW(hContact,&dwID,NULL,NULL,&dwContactSeverFlags,NULL,NULL,0,NULL,NULL,0,NULL,NULL,0,NULL); + if (dwID==-1 || dwContactSeverFlags&CONTACT_INTFLAG_NOT_AUTHORIZED) + {// для авторизованного нам и так присылают правильный статус + MraSetContactStatus(hContact,GetMiradaStatusFromMraStatus(dwStatus,GetMraXStatusIDFromMraUriStatus(pmralpsValues[i].lpszData,pmralpsValues[i].dwSize),&dwXStatus)); + DB_Mra_SetByte(hContact,DBSETTING_XSTATUSID,(BYTE)dwXStatus); + } + } + }else + if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,pmralpsFeilds[i].lpszData,pmralpsFeilds[i].dwSize,"status_title",12)==CSTR_EQUAL) + { + if (pmralpsValues[i].dwSize) + { + DWORD dwID,dwContactSeverFlags; + + GetContactBasicInfoW(hContact,&dwID,NULL,NULL,&dwContactSeverFlags,NULL,NULL,0,NULL,NULL,0,NULL,NULL,0,NULL); + if (dwID==-1 || dwContactSeverFlags&CONTACT_INTFLAG_NOT_AUTHORIZED) + {// для авторизованного нам и так присылают правильный статус + DB_Mra_SetLPSStringW(hContact,DBSETTING_XSTATUSNAME,&pmralpsValues[i]); + } + } + }else + if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,pmralpsFeilds[i].lpszData,pmralpsFeilds[i].dwSize,"status_desc",11)==CSTR_EQUAL) + { + if (pmralpsValues[i].dwSize) + { + DWORD dwID,dwContactSeverFlags; + + GetContactBasicInfoW(hContact,&dwID,NULL,NULL,&dwContactSeverFlags,NULL,NULL,0,NULL,NULL,0,NULL,NULL,0,NULL); + if (dwID==-1 || dwContactSeverFlags&CONTACT_INTFLAG_NOT_AUTHORIZED) + {// для авторизованного нам и так присылают правильный статус + DB_Mra_SetLPSStringW(hContact,DBSETTING_XSTATUSMSG,&pmralpsValues[i]); + } + } + }else{// for DEBUG ONLY + #ifdef _DEBUG + DebugPrintCRLFA(pmralpsFeilds[i].lpszData); + DebugPrintCRLFA(pmralpsValues[i].lpszData); + //DebugBreak(); + #endif + } + } + }else + if (dwAckType==ACKTYPE_SEARCH) + { + WCHAR szNick[MAX_EMAIL_LEN]={0}, + szFirstName[MAX_EMAIL_LEN]={0}, + szLastName[MAX_EMAIL_LEN]={0}, + szEMail[MAX_EMAIL_LEN]={0}; + MRA_LPS mralpsUsernameValue={0}; + PROTOSEARCHRESULT psr={0}; + + psr.cbSize=sizeof(psr); + psr.flags=PSR_UNICODE; + psr.nick=szNick; + psr.firstName=szFirstName; + psr.lastName=szLastName; + psr.email=szEMail; + psr.id=szEMail; + + for (i=0;iseq,(LPARAM)&psr); + } + }// end while + + MEMFREE(pmralpsFeilds); + } + } + + switch(dwAckType){ + case ACKTYPE_GETINFO: + ProtoBroadcastAckAsynchEx(PROTOCOL_NAMEA,hContact,dwAckType,ACKRESULT_SUCCESS,(HANDLE)1,(LPARAM)NULL,0); + break; + case ACKTYPE_SEARCH: + default: + ProtoBroadcastAckAsynchEx(PROTOCOL_NAMEA,hContact,dwAckType,ACKRESULT_SUCCESS,(HANDLE)pmaHeader->seq,(LPARAM)NULL,0); + break; + } + break; + case MRIM_ANKETA_INFO_STATUS_NOUSER:// не найдено ни одной подходящей записи + SetContactBasicInfoW(hContact,0,SCBIF_SERVER_FLAG,0,0,0,-1,0,NULL,0,NULL,0,NULL,0); + case MRIM_ANKETA_INFO_STATUS_DBERR:// ошибка базы данных + case MRIM_ANKETA_INFO_STATUS_RATELIMERR:// слишком много запросов, поиск временно запрещен + switch(dwAckType){ + case ACKTYPE_GETINFO: + ProtoBroadcastAckAsynchEx(PROTOCOL_NAMEA,hContact,dwAckType,ACKRESULT_FAILED,(HANDLE)1,(LPARAM)NULL,0); + break; + case ACKTYPE_SEARCH: + ProtoBroadcastAckAsynchEx(PROTOCOL_NAMEA,hContact,dwAckType,ACKRESULT_SUCCESS,(HANDLE)pmaHeader->seq,(LPARAM)NULL,0); + break; + default: + DebugBreak(); + break; + } + break; + default:// unknown + DebugBreak(); + break; + } + MraSendQueueFree(masMraSettings.hSendQueueHandle,pmaHeader->seq); + }else{// not found in queue + MraPopupShowFromAgentW(MRA_POPUP_TYPE_DEBUG,0,TranslateW(L"MRIM_ANKETA_INFO: not found in queue")); + } + break; + case MRIM_CS_MAILBOX_STATUS: + dwTemp=GetUL(&lpbDataCurrent); + if (dwTemp > masMraSettings.dwEmailMessagesTotal) masMraSettings.dwEmailMessagesTotal+=(dwTemp-masMraSettings.dwEmailMessagesUnRead); + + dwAckType=masMraSettings.dwEmailMessagesUnRead;// save old value + masMraSettings.dwEmailMessagesUnRead=dwTemp;// store new value + if (DB_Mra_GetByte(NULL,"IncrementalNewMailNotify",MRA_DEFAULT_INC_NEW_MAIL_NOTIFY)==0 || dwAckType1)// все параметры правильно инициализированны! + //if (dwGroupFlags&CONTACT_FLAG_GROUP && (dwGroupFlags&CONTACT_FLAG_REMOVED)==0) + { + #ifdef _DEBUG + memmove(szBuff,mralpsGroupName.lpszData,mralpsGroupName.dwSize); + szBuff[(mralpsGroupName.dwSize/sizeof(WCHAR))]=0; + DebugPrintW(szBuff); + + mir_snprintf((LPSTR)szBuff,SIZEOF(szBuff),": flags: %lu (",dwGroupFlags); + DebugPrintA((LPSTR)szBuff); + if (dwGroupFlags&CONTACT_FLAG_REMOVED) DebugPrintA("CONTACT_FLAG_REMOVED, "); + if (dwGroupFlags&CONTACT_FLAG_GROUP) DebugPrintA("CONTACT_FLAG_GROUP, "); + if (dwGroupFlags&CONTACT_FLAG_INVISIBLE) DebugPrintA("CONTACT_FLAG_INVISIBLE, "); + if (dwGroupFlags&CONTACT_FLAG_VISIBLE) DebugPrintA("CONTACT_FLAG_VISIBLE, "); + if (dwGroupFlags&CONTACT_FLAG_IGNORE) DebugPrintA("CONTACT_FLAG_IGNORE, "); + if (dwGroupFlags&CONTACT_FLAG_SHADOW) DebugPrintA("CONTACT_FLAG_SHADOW, "); + if (dwGroupFlags&CONTACT_FLAG_AUTHORIZED) DebugPrintA("CONTACT_FLAG_AUTHORIZED, "); + if (dwGroupFlags&CONTACT_FLAG_MULTICHAT) DebugPrintA("CONTACT_FLAG_MULTICHAT, "); + if (dwGroupFlags&CONTACT_FLAG_UNICODE_NAME) DebugPrintA("CONTACT_FLAG_UNICODE_NAME, "); + if (dwGroupFlags&CONTACT_FLAG_PHONE) DebugPrintA("CONTACT_FLAG_PHONE, "); + DebugPrintCRLFA(")"); + #endif//*/ + } + dwID++; + }// end for (processing groups) + + + DebugPrintCRLFW(L"Contacts:"); + DebugPrintCRLFA(szContactMask); + dwID=20; + while (lpbDataCurrent<(lpbData+dwDataSize)) + { + dwControlParam=0; + for(j=0;j5)// все параметры правильно инициализированны! + if ((dwContactFlag&(CONTACT_FLAG_GROUP|CONTACT_FLAG_REMOVED))==0) + { + hContact=MraHContactFromEmail(lpsEMail.lpszData,lpsEMail.dwSize,TRUE,FALSE,&bAdded); + if (hContact) + { + if (GetContactBasicInfoW(hContact,&dwTemp,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,0,NULL,NULL,0,NULL)==NO_ERROR && dwTemp!=-1) + {//deb контакт уже в списке, нахуй дубликата!!!! + dwTemp=dwTemp; + //MraSendCommand_ModifyContactW(hContact,dwID,CONTACT_FLAG_REMOVED,dwGroupID,lpsEMail.lpszData,lpsEMail.dwSize,mralpsNick.lpszData,mralpsNick.dwSize,mralpsCustomPhones.lpszData,mralpsCustomPhones.dwSize); + DebugBreak(); + }else{ + dwTemp=GetMiradaStatusFromMraStatus(dwStatus,GetMraXStatusIDFromMraUriStatus(lpsSpecStatusUri.lpszData,lpsSpecStatusUri.dwSize),&dwXStatus); + if((dwContactFlag&CONTACT_FLAG_UNICODE_NAME)) mralpsNick.dwSize/=sizeof(WCHAR); + + if (bAdded) + {// update user info + SetContactBasicInfoW(hContact,SCBIFSI_LOCK_CHANGES_EVENTS,(SCBIF_ID|SCBIF_GROUP_ID|SCBIF_FLAG|SCBIF_SERVER_FLAG|SCBIF_STATUS|SCBIF_NICK|SCBIF_PHONES),dwID,dwGroupID,dwContactFlag,dwContactSeverFlags,dwTemp,NULL,0,mralpsNick.lpwszData,mralpsNick.dwSize,mralpsCustomPhones.lpszData,mralpsCustomPhones.dwSize); + + // request user info from server + MraUpdateContactInfo(hContact); + }else{//****deb - check group ID param + SetContactBasicInfoW(hContact,SCBIFSI_LOCK_CHANGES_EVENTS,(SCBIF_ID|SCBIF_GROUP_ID|SCBIF_SERVER_FLAG|SCBIF_STATUS),dwID,dwGroupID,dwContactFlag,dwContactSeverFlags,dwTemp,NULL,0,mralpsNick.lpwszData,mralpsNick.dwSize,mralpsCustomPhones.lpszData,mralpsCustomPhones.dwSize); + if (mralpsNick.dwSize==0) + {// прописываем ник в листе на сервере + lstrcpynW(szBuff,GetContactNameW(hContact),SIZEOF(szBuff)); + mralpsNick.lpwszData=szBuff; + mralpsNick.dwSize=lstrlenW(mralpsNick.lpwszData); + + MraSendCommand_ModifyContactW(hContact,dwID,dwContactFlag,dwGroupID,lpsEMail.lpszData,lpsEMail.dwSize,mralpsNick.lpwszData,mralpsNick.dwSize,mralpsCustomPhones.lpszData,mralpsCustomPhones.dwSize); + } + } + + MraContactCapabilitiesSet(hContact,dwFutureFlags); + DB_Mra_SetByte(hContact,DBSETTING_XSTATUSID,(BYTE)dwXStatus); + DB_Mra_SetLPSStringW(hContact,DBSETTING_XSTATUSNAME,&lpsStatusTitle); + DB_Mra_SetLPSStringW(hContact,DBSETTING_XSTATUSMSG,&lpsStatusDesc); + DB_Mra_SetDword(hContact,DBSETTING_BLOGSTATUSTIME,dwBlogStatusTime); + DB_Mra_WriteContactSettingBlob(hContact,DBSETTING_BLOGSTATUSID,&dwBlogStatusID.QuadPart,sizeof(DWORDLONG)); + DB_Mra_SetLPSStringW(hContact,DBSETTING_BLOGSTATUS,&lpsBlogStatus); + DB_Mra_SetLPSStringW(hContact,DBSETTING_BLOGSTATUSMUSIC,&lpsBlogStatusMusic); + if (IsXStatusValid(dwXStatus)) SetExtraIcons(hContact); + + if (dwTemp!=ID_STATUS_OFFLINE)// пишем клиента только если юзер не отключён, иначе не затираем старое + { + if (lpsUserAgentFormated.dwSize) + {// есть чё писать + if (DB_Mra_GetByte(NULL,"MirVerRaw",MRA_DEFAULT_MIRVER_RAW)==FALSE) + { + MraGetVersionStringFromFormated(lpsUserAgentFormated.lpszData,lpsUserAgentFormated.dwSize,(LPSTR)szBuff,SIZEOF(szBuff),&dwStringSize); + lpsUserAgentFormated.lpszData=(LPSTR)szBuff; + lpsUserAgentFormated.dwSize=dwStringSize; + } + }else{// хз чё за клиент + lpsUserAgentFormated.lpszData=MIRVER_UNKNOWN; + lpsUserAgentFormated.dwSize=(sizeof(MIRVER_UNKNOWN)-1); + } + DB_Mra_SetLPSStringA(hContact,"MirVer",&lpsUserAgentFormated); + } + + if (dwContactSeverFlags&CONTACT_INTFLAG_NOT_AUTHORIZED) + if (DB_Mra_GetByte(NULL,"AutoAuthRequestOnLogon",MRA_DEFAULT_AUTO_AUTH_REQ_ON_LOGON)) CallProtoService(PROTOCOL_NAMEA,MRA_REQ_AUTH,(WPARAM)hContact,0); + } + } + } + dwID++; + }// end while (processing contacts) + + // post processing contact list + { + CHAR szEMail[MAX_EMAIL_LEN],szPhones[MAX_EMAIL_LEN]; + WCHAR wszAuthMessage[MAX_PATH],wszNick[MAX_EMAIL_LEN]; + SIZE_T dwEMailSize,dwNickSize,dwPhonesSize,dwAuthMessageSize; + + if (DB_Mra_GetStaticStringW(NULL,"AuthMessage",wszAuthMessage,SIZEOF(wszAuthMessage),&dwAuthMessageSize)==FALSE) + {// def auth message + lstrcpynW(wszAuthMessage,TranslateW(MRA_DEFAULT_AUTH_MESSAGE),SIZEOF(wszAuthMessage)); + dwAuthMessageSize=lstrlenW(wszAuthMessage); + } + + for(hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0);hContact!=NULL;hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact,0)) + { + if (GetContactBasicInfoW(hContact,&dwID,NULL,NULL,NULL,NULL,szEMail,SIZEOF(szEMail),&dwEMailSize,NULL,0,NULL,NULL,0,NULL)==NO_ERROR) + if (dwID==-1) + { + if (IsEMailChatAgent(szEMail,dwEMailSize)) + {// чат: ещё раз запросим авторизацию, пометим как видимый в списке, постоянный + DBDeleteContactSetting(hContact,"CList","Hidden"); + DBDeleteContactSetting(hContact,"CList","NotOnList"); + SetExtraIcons(hContact); + MraSetContactStatus(hContact,ID_STATUS_ONLINE); + + lstrcpynW(szBuff,GetContactNameW(hContact),SIZEOF(szBuff)); + MraSendCommand_AddContactW(hContact,(CONTACT_FLAG_VISIBLE|CONTACT_FLAG_MULTICHAT|CONTACT_FLAG_UNICODE_NAME),-1,szEMail,dwEMailSize,szBuff,lstrlenW(szBuff),NULL,0,NULL,0,0); + }else{ + if (DBGetContactSettingByte(hContact,"CList","NotOnList",0)==0) + {// set extra icons and upload contact + SetExtraIcons(hContact); + if (DB_Mra_GetByte(NULL,"AutoAddContactsToServer",MRA_DEFAULT_AUTO_ADD_CONTACTS_TO_SERVER)) + {//add all contacts to server + GetContactBasicInfoW(hContact,NULL,&dwGroupID,NULL,NULL,NULL,NULL,0,NULL,wszNick,SIZEOF(wszNick),&dwNickSize,szPhones,SIZEOF(szPhones),&dwPhonesSize); + MraSendCommand_AddContactW(hContact,(CONTACT_FLAG_VISIBLE|CONTACT_FLAG_UNICODE_NAME),dwGroupID,szEMail,dwEMailSize,wszNick,dwNickSize,szPhones,dwPhonesSize,wszAuthMessage,dwAuthMessageSize,0); + } + } + } + MraUpdateContactInfo(hContact); + } + } + } + }else{// контакт лист почемуто не получили + // всех в offline и id в нестандарт + for(HANDLE hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0);hContact!=NULL;hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact,0)) + {// функция сама проверяет принадлежность контакта к MRA + SetContactBasicInfoW(hContact,SCBIFSI_LOCK_CHANGES_EVENTS,(SCBIF_ID|SCBIF_GROUP_ID|SCBIF_SERVER_FLAG|SCBIF_STATUS),-1,-2,0,0,ID_STATUS_OFFLINE,NULL,0,NULL,0,NULL,0); + // request user info from server + MraUpdateContactInfo(hContact); + } + + if (dwTemp==GET_CONTACTS_ERROR) + {// найденный контакт-лист некорректен + ShowFormatedErrorMessage(L"MRIM_CS_CONTACT_LIST2: bad contact list",NO_ERROR); + }else + if (dwTemp==GET_CONTACTS_INTERR) + {// произошла внутренняя ошибка + ShowFormatedErrorMessage(L"MRIM_CS_CONTACT_LIST2: internal server error",NO_ERROR); + }else{ + mir_sntprintf(szBuff,SIZEOF(szBuff),TranslateW(L"MRIM_CS_CONTACT_LIST2: unknown server error, code: %lu"),dwTemp); + MraPopupShowFromAgentW(MRA_POPUP_TYPE_DEBUG,0,szBuff); + } + } + break; + case MRIM_CS_SMS_ACK: + dwTemp=GetUL(&lpbDataCurrent); + if (MraSendQueueFind(masMraSettings.hSendQueueHandle,pmaHeader->seq,NULL,&hContact,&dwAckType,(LPBYTE*)&lpsString.lpszData,&lpsString.dwSize)==NO_ERROR) + { + char szEMail[MAX_EMAIL_LEN]; + LPSTR lpszPhone; + LPWSTR lpwszMessage; + SIZE_T dwEMailSize,dwPhoneSize,dwMessageSize; + + if (DB_Mra_GetStaticStringA(NULL,"e-mail",szEMail,SIZEOF(szEMail),&dwEMailSize)) + { + dwPhoneSize=(*(DWORD*)lpsString.lpszData); + dwMessageSize=lpsString.dwSize-(dwPhoneSize+sizeof(DWORD)+2); + lpszPhone=(lpsString.lpszData+sizeof(DWORD)); + lpwszMessage=(LPWSTR)(lpszPhone+dwPhoneSize+1); + + dwTemp=mir_snprintf((LPSTR)szBuff,SIZEOF(szBuff),"Mail.ruYesMail.ru, Russia%s-1-1955988055-%s%s0\r\n",szEMail,lpszPhone,lpszPhone); + ProtoBroadcastAckAsynchEx(PROTOCOL_NAMEA,NULL,dwAckType,ACKRESULT_SENTREQUEST,(HANDLE)pmaHeader->seq,(LPARAM)szBuff,dwTemp); + } + + MEMFREE(lpsString.lpszData); + MraSendQueueFree(masMraSettings.hSendQueueHandle,pmaHeader->seq); + }else{// not found in queue + MraPopupShowFromAgentW(MRA_POPUP_TYPE_DEBUG,0,TranslateW(L"MRIM_CS_SMS_ACK: not found in queue")); + } + break; + case MRIM_CS_PROXY: + { + DWORD dwIDRequest; + MRA_LPS lpsAddreses={0}; + MRA_GUID mguidSessionID; + + GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsEMail);// LPS to + dwIDRequest=GetUL(&lpbDataCurrent);// DWORD id_request + dwAckType=GetUL(&lpbDataCurrent);// DWORD data_type + GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString);// LPS user_data + GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsAddreses);// LPS lps_ip_port + mguidSessionID=GetGUID(&lpbDataCurrent);// DWORD session_id[4] + + if (dwAckType==MRIM_PROXY_TYPE_FILES) + {// файлы, on file recv + if (MraMrimProxySetData(MraFilesQueueItemProxyByID(masMraSettings.hFilesQueueHandle,dwIDRequest),lpsEMail.lpszData,lpsEMail.dwSize,dwIDRequest,dwAckType,lpsString.lpszData,lpsString.dwSize,lpsAddreses.lpszData,lpsAddreses.dwSize,&mguidSessionID)==NO_ERROR) + {// сессия передачи ещё жива/proxy enabled// set proxy info to file transfer context + MraFilesQueueStartMrimProxy(masMraSettings.hFilesQueueHandle,dwIDRequest); + }else{// дохлая сессия/не существующая + MraSendCommand_ProxyAck(PROXY_STATUS_ERROR,lpsEMail.lpszData,lpsEMail.dwSize,dwIDRequest,dwAckType,lpsString.lpszData,lpsString.dwSize,lpsAddreses.lpszData,lpsAddreses.dwSize,mguidSessionID); + DebugBreak(); + } + } + //DebugBreak(); + } + break; + case MRIM_CS_PROXY_ACK: + { + DWORD dwIDRequest; + HANDLE hMraMrimProxyData; + MRA_LPS lpsAddreses={0}; + MRA_GUID mguidSessionID; + + dwTemp=GetUL(&lpbDataCurrent);// DWORD status + GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsEMail);// LPS to + dwIDRequest=GetUL(&lpbDataCurrent);// DWORD id_request + dwAckType=GetUL(&lpbDataCurrent);// DWORD data_type + GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString);// LPS user_data + GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsAddreses);// LPS lps_ip_port + mguidSessionID=GetGUID(&lpbDataCurrent);// DWORD session_id[4] + + if (dwAckType==MRIM_PROXY_TYPE_FILES) + {// файлы, on file send + if ((hMraMrimProxyData=MraFilesQueueItemProxyByID(masMraSettings.hFilesQueueHandle,dwIDRequest))) + {// сессия передачи ещё жива/proxy enabled + switch(dwTemp){ + case PROXY_STATUS_DECLINE: + MraFilesQueueCancel(masMraSettings.hFilesQueueHandle,dwIDRequest,FALSE); + break; + case PROXY_STATUS_OK: + if (MraMrimProxySetData(hMraMrimProxyData,lpsEMail.lpszData,lpsEMail.dwSize,dwIDRequest,dwAckType,lpsString.lpszData,lpsString.dwSize,lpsAddreses.lpszData,lpsAddreses.dwSize,&mguidSessionID)==NO_ERROR) + {// set proxy info to file transfer context + MraFilesQueueStartMrimProxy(masMraSettings.hFilesQueueHandle,dwIDRequest); + } + break; + case PROXY_STATUS_ERROR: + ShowFormatedErrorMessage(L"Proxy File transfer: error",NO_ERROR); + MraFilesQueueCancel(masMraSettings.hFilesQueueHandle,dwIDRequest,FALSE); + break; + case PROXY_STATUS_INCOMPATIBLE_VERS: + ShowFormatedErrorMessage(L"Proxy File transfer: incompatible versions",NO_ERROR); + MraFilesQueueCancel(masMraSettings.hFilesQueueHandle,dwIDRequest,FALSE); + break; + case PROXY_STATUS_NOHARDWARE: + case PROXY_STATUS_MIRROR: + case PROXY_STATUS_CLOSED: + default: + DebugBreak(); + break; + } + }else{// дохлая сессия/не существующая + DebugBreak(); + } + } + + /*if (dwTemp!=2) + if ((hContact=MraHContactFromEmail(lpsEMail.lpszData,lpsEMail.dwSize,FALSE,TRUE,NULL))) + if (MraGetContactStatus(hContact)==ID_STATUS_OFFLINE) + { + MraSetContactStatus(hContact,ID_STATUS_INVISIBLE); + }*/ + + //DebugBreak(); + } + break; + case MRIM_CS_PROXY_HELLO: + // DWORD[4] Session_id + DebugBreak(); + break; + case MRIM_CS_PROXY_HELLO_ACK: + DebugBreak(); + break; + case MRIM_CS_NEW_MAIL: + { + DWORD dwDate,dwUIDL; + + dwTemp=GetUL(&lpbDataCurrent);// UL unread count + GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsEMail);// LPS from + GetLPS(lpbData,dwDataSize,&lpbDataCurrent,&lpsString);// LPS subject + dwDate=GetUL(&lpbDataCurrent);// UL date + dwUIDL=GetUL(&lpbDataCurrent);// UL uidl + + if (dwTemp > masMraSettings.dwEmailMessagesTotal) masMraSettings.dwEmailMessagesTotal+=(dwTemp-masMraSettings.dwEmailMessagesUnRead); + + dwAckType=masMraSettings.dwEmailMessagesUnRead;// save old value + masMraSettings.dwEmailMessagesUnRead=dwTemp;// store new value + if (DB_Mra_GetByte(NULL,"IncrementalNewMailNotify",MRA_DEFAULT_INC_NEW_MAIL_NOTIFY)==0 || dwAckTypelpszData==NULL || plpsRFTText->dwSize==0) dwFlags&=~MESSAGE_FLAG_RTF; + }else{ + dwFlags&=~MESSAGE_FLAG_RTF; + } + } + + if (dwFlags&MESSAGE_FLAG_MULTICHAT) + { + if (plpsMultiChatData) + { + if (plpsMultiChatData->lpszData==NULL || plpsMultiChatData->dwSize==0) dwFlags&=~MESSAGE_FLAG_MULTICHAT; + }else{ + dwFlags&=~MESSAGE_FLAG_MULTICHAT; + } + } + + + // pre processing - extracting/decoding + if (dwFlags&MESSAGE_FLAG_AUTHORIZE) + {// extract auth message из обычного текста + SIZE_T dwAuthPartsCount,dwAuthBuffSize=(plpsText->dwSize+32),dwAuthDataSize; + LPBYTE lpbAuthData,lpbDataCurrent; + MRA_LPS lpsAuthFrom,lpsAuthMessage; + + lpbAuthData=(LPBYTE)MEMALLOC(dwAuthBuffSize); + if (lpbAuthData) + { + BASE64DecodeFormated(plpsText->lpszData,plpsText->dwSize,lpbAuthData,dwAuthBuffSize,&dwAuthDataSize); + + lpbDataCurrent=lpbAuthData; + dwAuthPartsCount=GetUL(&lpbDataCurrent); + if (GetLPS(lpbAuthData,dwAuthDataSize,&lpbDataCurrent,&lpsAuthFrom)==NO_ERROR) + if (GetLPS(lpbAuthData,dwAuthDataSize,&lpbDataCurrent,&lpsAuthMessage)==NO_ERROR) + { + if (dwFlags&MESSAGE_FLAG_v1p16 && (dwFlags&MESSAGE_FLAG_CP1251)==0) + {// unicode text + memmove(lpbAuthData,lpsAuthMessage.lpszData,lpsAuthMessage.dwSize); + lpwszMessage=(LPWSTR)lpbAuthData; + dwMessageSize=(lpsAuthMessage.dwSize/sizeof(WCHAR)); + }else{// преобразуем в юникод текст только если он в АНСИ и если это не Флэш мультик и будильник тоже не нуждается в этом + lpwszMessage=(LPWSTR)MEMALLOC(((lpsAuthMessage.dwSize+MAX_PATH)*sizeof(WCHAR))); + if (lpwszMessage) + { + dwMessageSize=MultiByteToWideChar(MRA_CODE_PAGE,0,lpsAuthMessage.lpszData,lpsAuthMessage.dwSize,lpwszMessage,(lpsAuthMessage.dwSize+MAX_PATH)); + (*(lpwszMessage+dwMessageSize))=0; + }else{// не удалось выделить память + dwRetErrorCode=GetLastError(); + } + } + } + if (lpwszMessage!=(LPWSTR)lpbAuthData) MEMFREE(lpbAuthData); + } + }else{ + /*// пупер затычка + if (dwFlags&MESSAGE_FLAG_v1p16 && dwFlags&MESSAGE_FLAG_CP1251) + {// и какая же кодировка у текста...мммм...бум гадать! + DebugPrintW(L"Unknown message encoding: "); + if (MemoryFindByte(0,plpsText->lpszData,(plpsText->dwSize-1),0)) + {//ооо похоже это юникод! + dwFlags&=~MESSAGE_FLAG_CP1251; + DebugPrintCRLFW(plpsText->lpwszData); + }else{// наверное анси + dwFlags&=~MESSAGE_FLAG_v1p16; + DebugPrintCRLFA(plpsText->lpszData); + } + }*/ + + if (dwFlags&(MESSAGE_FLAG_ALARM|MESSAGE_FLAG_FLASH|MESSAGE_FLAG_v1p16) && (dwFlags&MESSAGE_FLAG_CP1251)==0) + {// unicode text + lpwszMessage=plpsText->lpwszData; + dwMessageSize=(plpsText->dwSize/sizeof(WCHAR)); + }else{// преобразуем в юникод текст только если он в АНСИ и если это не Флэш мультик и будильник тоже не нуждается в этом + lpwszMessage=(LPWSTR)MEMALLOC(((plpsText->dwSize+MAX_PATH)*sizeof(WCHAR))); + if (lpwszMessage) + { + dwMessageSize=MultiByteToWideChar(MRA_CODE_PAGE,0,plpsText->lpszData,plpsText->dwSize,lpwszMessage,(plpsText->dwSize+MAX_PATH)); + (*(lpwszMessage+dwMessageSize))=0; + }else{// не удалось выделить память + dwRetErrorCode=GetLastError(); + } + } + + if (dwFlags&(MESSAGE_FLAG_CONTACT|MESSAGE_FLAG_NOTIFY|MESSAGE_FLAG_SMS|MESSAGE_SMS_DELIVERY_REPORT|MESSAGE_FLAG_ALARM)) + { + // ничего не делаем, сообщение не содержит расширенной части или её содержимое игнорируется + }else{ + if ((dwFlags&MESSAGE_FLAG_RTF) && plpsRFTText) //MESSAGE_FLAG_FLASH there + if (masMraSettings.lpfnUncompress)// only if uncompress function exist + if (plpsRFTText->lpszData && plpsRFTText->dwSize) + {// decode RTF + SIZE_T dwRTFPartsCount,dwCompressedSize,dwRFTBuffSize=((plpsRFTText->dwSize*16)+8192),dwRTFDataSize; + LPBYTE lpbRTFData,lpbCompressed,lpbDataCurrent; + MRA_LPS lpsRTFString,lpsBackColour,lpsString; + + lpbRTFData=(LPBYTE)MEMALLOC(dwRFTBuffSize); + lpbCompressed=(LPBYTE)MEMALLOC((plpsRFTText->dwSize+32)); + if (lpbRTFData && lpbCompressed) + { + BASE64DecodeFormated(plpsRFTText->lpszData,plpsRFTText->dwSize,lpbCompressed,(plpsRFTText->dwSize+32),&dwCompressedSize); + dwRTFDataSize=dwRFTBuffSize; + if ((PUNCOMPRESS(masMraSettings.lpfnUncompress))(lpbRTFData,(DWORD*)&dwRTFDataSize,lpbCompressed,dwCompressedSize)==Z_OK) + { + lpbDataCurrent=lpbRTFData; + dwRTFPartsCount=GetUL(&lpbDataCurrent);// колличество частей в некоторых случаях больше 2, тогда нужно игнорировать первый текст, тк там сообщения об ущербности + if (GetLPS(lpbRTFData,dwRTFDataSize,&lpbDataCurrent,&lpsRTFString)==NO_ERROR) + if (GetLPS(lpbRTFData,dwRTFDataSize,&lpbDataCurrent,&lpsBackColour)==NO_ERROR) + { + dwBackColour=(*(DWORD*)lpsBackColour.lpszData); + if (dwFlags&MESSAGE_FLAG_FLASH) + {// Флэш мультик в обычный текст// затирем lpwszMessage=plpsText->lpwszData, тк там затычка с текстом об ущербности + if (dwRTFPartsCount==3) + {// только анси текст с мультиком + DebugBreak();// наверное это уже не должно приходить, ну разве что от совсем старых клиентов, 2008 + GetLPS(lpbRTFData,dwRTFDataSize,&lpbDataCurrent,&lpsString); + lpwszMessage=(LPWSTR)MEMALLOC(((lpsString.dwSize+MAX_PATH)*sizeof(WCHAR))); + if (lpwszMessage) + { + memmove(lpwszMessage,lpsString.lpszData,lpsString.dwSize); + dwMessageSize=MultiByteToWideChar(MRA_CODE_PAGE,0,lpsString.lpszData,lpsString.dwSize,lpwszMessage,(lpsString.dwSize+MAX_PATH)); + (*(lpwszMessage+dwMessageSize))=0; + }else{// не удалось выделить память + dwRetErrorCode=GetLastError(); + } + }else + if (dwRTFPartsCount==4) + { + GetLPS(lpbRTFData,dwRTFDataSize,&lpbDataCurrent,&lpsString); + GetLPS(lpbRTFData,dwRTFDataSize,&lpbDataCurrent,&lpsString); + lpwszMessage=(LPWSTR)MEMALLOC(lpsString.dwSize); + if (lpwszMessage) + { + memmove(lpwszMessage,lpsString.lpszData,lpsString.dwSize); + dwMessageSize=lpsString.dwSize; + }else{// не удалось выделить память + dwRetErrorCode=GetLastError(); + } + }else{ + DebugBreak(); + } + }else{// РТФ текст + if (dwRTFPartsCount>2) + { + GetLPS(lpbRTFData,dwRTFDataSize,&lpbDataCurrent,&lpsString); + DebugBreak(); + } + + lpszMessageExt=(LPSTR)MEMALLOC(lpsRTFString.dwSize); + if (lpszMessageExt) + { + memmove(lpszMessageExt,lpsRTFString.lpszData,lpsRTFString.dwSize); + dwMessageExtSize=lpsRTFString.dwSize; + }else{// не удалось выделить память + //dwRetErrorCode=GetLastError(); // не смертельно! + DebugBreak(); + } + } + } + }else{ + MEMFREE(lpszMessageExt); + dwMessageExtSize=0; + DebugBreak(); + } + } + MEMFREE(lpbCompressed); + MEMFREE(lpbRTFData); + } + } + } + + + // processing + if (dwRetErrorCode==NO_ERROR) + if (MraAntiSpamReceivedMessageW(plpsFrom->lpszData,plpsFrom->dwSize,dwFlags,lpwszMessage,dwMessageSize)==MESSAGE_NOT_SPAM) + { + if (dwFlags&(MESSAGE_FLAG_SMS|MESSAGE_SMS_DELIVERY_REPORT)) + {// SMS //if (IsPhone(plpsFrom->lpszData,plpsFrom->dwSize)) + char szPhone[MAX_EMAIL_LEN],szEMail[MAX_EMAIL_LEN],szTime[MAX_PATH]; + LPSTR lpszMessageUTF,lpszBuff; + LPWSTR lpwszMessageXMLEncoded; + SIZE_T dwBuffLen,dwMessageXMLEncodedSize; + INTERNET_TIME itTime; + + dwBuffLen=((dwMessageSize+MAX_PATH)*6); + lpszMessageUTF=(LPSTR)MEMALLOC(dwBuffLen); + lpwszMessageXMLEncoded=(LPWSTR)MEMALLOC((dwBuffLen*sizeof(WCHAR))); + if (lpszMessageUTF && lpwszMessageXMLEncoded) + { + InternetTimeGetCurrentTime(&itTime); + InternetTimeGetString(&itTime,szTime,SIZEOF(szTime),NULL); + CopyNumber(szPhone,plpsFrom->lpszData,plpsFrom->dwSize); + DB_Mra_GetStaticStringA(NULL,"e-mail",szEMail,SIZEOF(szEMail),NULL); + + EncodeXML(lpwszMessage,dwMessageSize,lpwszMessageXMLEncoded,dwBuffLen,&dwMessageXMLEncodedSize); + WideCharToMultiByte(CP_UTF8,0,lpwszMessageXMLEncoded,dwMessageXMLEncodedSize,lpszMessageUTF,dwBuffLen,NULL,NULL); + lpszBuff=(LPSTR)lpwszMessageXMLEncoded; + + if (dwFlags&MESSAGE_SMS_DELIVERY_REPORT) + {// отчёт о неудаче доставки смс + dwBuffLen=mir_snprintf(lpszBuff,(dwBuffLen*sizeof(WCHAR)),"%s-1-1955988055-%s%sNo%s015%s",szEMail,szPhone,szPhone,szTime,lpszMessageUTF); + ProtoBroadcastAckAsynchEx(PROTOCOL_NAMEA,NULL,ICQACKTYPE_SMS,ACKRESULT_FAILED,(HANDLE)0,(LPARAM)lpszBuff,dwBuffLen); + }else{// новое смс!!! + dwBuffLen=mir_snprintf(lpszBuff,(dwBuffLen*sizeof(WCHAR)),"Mail.ru%s%sMail.ru%s",szEMail,szPhone,lpszMessageUTF,szTime); + ProtoBroadcastAckAsynchEx(PROTOCOL_NAMEA,NULL,ICQACKTYPE_SMS,ACKRESULT_SUCCESS,(HANDLE)0,(LPARAM)lpszBuff,dwBuffLen); + } + }else{// не удалось выделить память + dwRetErrorCode=GetLastError(); + } + MEMFREE(lpwszMessageXMLEncoded); + MEMFREE(lpszMessageUTF); + }else{ + ccs.hContact=MraHContactFromEmail(plpsFrom->lpszData,plpsFrom->dwSize,TRUE,TRUE,&bAdded); + if (bAdded) MraUpdateContactInfo(ccs.hContact); + + if (dwFlags&MESSAGE_FLAG_NOTIFY) + {// user typing + CallService(MS_PROTO_CONTACTISTYPING,(WPARAM)ccs.hContact,MAILRU_CONTACTISTYPING_TIMEOUT); + }else{// text/contact/auth // typing OFF + CallService(MS_PROTO_CONTACTISTYPING,(WPARAM)ccs.hContact,PROTOTYPE_CONTACTTYPING_OFF); + + if (dwFlags&MESSAGE_FLAG_MULTICHAT) + {// MULTICHAT + LPBYTE lpbMultiChatData,lpbDataCurrent; + SIZE_T dwMultiChatDataSize; + DWORD dwMultiChatEventType; + MRA_LPS lpsEMailInMultiChat,lpsString,lpsMultichatName; + + lpbMultiChatData=(LPBYTE)plpsMultiChatData->lpszData; + dwMultiChatDataSize=plpsMultiChatData->dwSize; + lpbDataCurrent=lpbMultiChatData; + + dwMultiChatEventType=GetUL(&lpbDataCurrent);// type + GetLPS(lpbMultiChatData,dwMultiChatDataSize,&lpbDataCurrent,&lpsMultichatName);// multichat_name + GetLPS(lpbMultiChatData,dwMultiChatDataSize,&lpbDataCurrent,&lpsEMailInMultiChat); + + switch(dwMultiChatEventType){ + case MULTICHAT_MESSAGE: + MraChatSessionMessageAdd(ccs.hContact,lpsEMailInMultiChat.lpszData,lpsEMailInMultiChat.dwSize,lpwszMessage,dwMessageSize,dwTime);// LPS sender + break; + case MULTICHAT_ADD_MEMBERS: + MraChatSessionMembersAdd(ccs.hContact,lpsEMailInMultiChat.lpszData,lpsEMailInMultiChat.dwSize,dwTime);// LPS sender + GetLPS(lpbMultiChatData,dwMultiChatDataSize,&lpbDataCurrent,&lpsString);// CLPS members + MraChatSessionSetIviter(ccs.hContact,lpsEMailInMultiChat.lpszData,lpsEMailInMultiChat.dwSize); + case MULTICHAT_MEMBERS: + { + LPBYTE lpbMultiChatDataLocal,lpbDataCurrentLocal; + SIZE_T i,dwMultiChatMembersCount,dwMultiChatDataLocalSize; + + if (dwMultiChatEventType==MULTICHAT_MEMBERS) lpsString=lpsEMailInMultiChat; + + lpbMultiChatDataLocal=(LPBYTE)lpsString.lpszData; + dwMultiChatDataLocalSize=lpsString.dwSize; + lpbDataCurrentLocal=lpbMultiChatDataLocal; + + dwMultiChatMembersCount=GetUL(&lpbDataCurrentLocal);// count + for (i=0;ilpszData,plpsFrom->dwSize,lpsMultichatName.lpwszData,(lpsMultichatName.dwSize/sizeof(WCHAR)),NULL,0,NULL,0,0); + break; + default: + DebugBreak(); + break; + } + }else + if (dwFlags&MESSAGE_FLAG_AUTHORIZE) + {// auth request + BYTE btBuff[BUFF_SIZE_BLOB]; + BOOL bAutoGrandAuth=FALSE; + + if (IsEMailChatAgent(plpsFrom->lpszData,plpsFrom->dwSize)) + { + bAutoGrandAuth=FALSE; + }else{ + if (DBGetContactSettingByte(ccs.hContact,"CList","NotOnList",0)) + {// временный контакт + if (DB_Mra_GetByte(NULL,"AutoAuthGrandNewUsers",MRA_DEFAULT_AUTO_AUTH_GRAND_NEW_USERS)) bAutoGrandAuth=TRUE; + }else{// постоянный контакт + if (DB_Mra_GetByte(NULL,"AutoAuthGrandUsersInCList",MRA_DEFAULT_AUTO_AUTH_GRAND_IN_CLIST)) bAutoGrandAuth=TRUE; + } + } + + if (bAdded) DBWriteContactSettingByte(ccs.hContact,"CList","Hidden",1); + if (bAutoGrandAuth) + {// auto grand auth + DBEVENTINFO dbei={0}; + + dbei.cbSize=sizeof(dbei); + dbei.szModule=PROTOCOL_NAMEA; + dbei.timestamp=_time32(NULL); + dbei.flags=DBEF_READ; + dbei.eventType=EVENTTYPE_AUTHREQUEST; + dbei.pBlob=(PBYTE)btBuff; + + CreateBlobFromContact(ccs.hContact,lpwszMessage,dwMessageSize,btBuff,SIZEOF(btBuff),(SIZE_T*)&dbei.cbBlob); + CallService(MS_DB_EVENT_ADD,(WPARAM)NULL,(LPARAM)&dbei); + MraSendCommand_Authorize(plpsFrom->lpszData,plpsFrom->dwSize); + }else{ + ccs.szProtoService=PSR_AUTH; + pre.szMessage=(LPSTR)btBuff; + CreateBlobFromContact(ccs.hContact,lpwszMessage,dwMessageSize,btBuff,SIZEOF(btBuff),(SIZE_T*)&pre.lParam); + CallService(MS_PROTO_CHAINRECV,0,(LPARAM)&ccs); + } + }else{ + DBDeleteContactSetting(ccs.hContact,"CList","Hidden"); + + if (dwFlags&MESSAGE_FLAG_CONTACT) + {// contacts received + LPBYTE lpbBuffer,lpbBufferCurPos; + + lpbBuffer=(LPBYTE)MEMALLOC((dwMessageSize+MAX_PATH)); + if (lpbBuffer) + { + ccs.szProtoService=PSR_CONTACTS; + pre.flags=0; + pre.szMessage=(LPSTR)lpbBuffer; + pre.lParam=WideCharToMultiByte(MRA_CODE_PAGE,0,lpwszMessage,dwMessageSize,(LPSTR)lpbBuffer,(dwMessageSize+MAX_PATH),NULL,NULL); + + lpbBufferCurPos=lpbBuffer; + while(TRUE) + {// цикл замены ; на 0 + lpbBufferCurPos=(LPBYTE)MemoryFindByte((lpbBufferCurPos-lpbBuffer),lpbBuffer,pre.lParam,';'); + if (lpbBufferCurPos) + {// founded + (*lpbBufferCurPos)=0; + lpbBufferCurPos++; + }else{ + break; + } + } + CallService(MS_PROTO_CHAINRECV,0,(LPARAM)&ccs); + MEMFREE(lpbBuffer); + }else{// не удалось выделить память + dwRetErrorCode=GetLastError(); + } + }else + if (dwFlags&MESSAGE_FLAG_ALARM) + {// alarm + if (masMraSettings.heNudgeReceived) + { + NotifyEventHooks(masMraSettings.heNudgeReceived,(WPARAM)ccs.hContact,NULL); + }else{ + pre.flags=0; + pre.szMessage=(LPSTR)TranslateTS(MRA_ALARM_MESSAGE); + //pre.lParam=lstrlenA(pre.szMessage); + ccs.szProtoService=PSR_MESSAGE; + CallService(MS_PROTO_CHAINRECV,0,(LPARAM)&ccs); + } + }else{// standart message// flash animation + if ((dwFlags&MESSAGE_FLAG_RTF) && (dwFlags&MESSAGE_FLAG_FLASH)==0 && lpszMessageExt && dwMessageExtSize && DB_Mra_GetByte(NULL,"RTFReceiveEnable",MRA_DEFAULT_RTF_RECEIVE_ENABLE)) + {// пишем в ANSI, всё равно RTF + pre.flags=0; + pre.szMessage=lpszMessageExt; + //pre.lParam=dwMessageExtSize; + ccs.szProtoService=PSR_MESSAGE; + CallService(MS_PROTO_CHAINRECV,0,(LPARAM)&ccs); + }else{ + LPSTR lpszMessageUTF;// some plugins can change pre.szMessage pointer and we failed to free it + + lpszMessageUTF=(LPSTR)MEMALLOC(((dwMessageSize+MAX_PATH)*sizeof(WCHAR))); + if (lpszMessageUTF) + { + pre.szMessage=lpszMessageUTF; + pre.flags=PREF_UTF; + //pre.lParam= + WideCharToMultiByte(CP_UTF8,0,lpwszMessage,dwMessageSize,lpszMessageUTF,((dwMessageSize+MAX_PATH)*sizeof(WCHAR)),NULL,NULL); + ccs.szProtoService=PSR_MESSAGE; + CallService(MS_PROTO_CHAINRECV,0,(LPARAM)&ccs); + MEMFREE(lpszMessageUTF); + }else{// не удалось выделить память + dwRetErrorCode=GetLastError(); + } + } + if (dwFlags&MESSAGE_FLAG_SYSTEM) + { + MraPopupShowW(ccs.hContact,MRA_POPUP_TYPE_INFORMATION,0,TranslateW(L"Mail.ru System notify"),(LPWSTR)pre.szMessage); + } + } + } + } + } + }else{// spam blocked + if (DB_Mra_GetByte(NULL,"AntiSpamSendSpamReportToSrv",MRA_ANTISPAM_DEFAULT_SEND_SPAM_REPORT_TO_SERVER)) + {// рапортуем о спаме + //MraSendCommand_MessageAskW(1,(dwFlags|MESSAGE_FLAG_SPAMF_SPAM),plpsFrom->lpszData,plpsFrom->dwSize,plpsText->lpwszData,plpsText->dwSize,plpsRFTText->lpszData,plpsRFTText->dwSize); + } + dwRetErrorCode=ERROR_ACCESS_DENIED; + } + + if (lpwszMessage!=plpsText->lpwszData && lpwszMessage!=(LPWSTR)lpszMessageExt) MEMFREE(lpwszMessage); + MEMFREE(lpszMessageExt); + +return(dwRetErrorCode); +} + + + + + +DWORD GetMraXStatusIDFromMraUriStatus(LPSTR lpszStatusUri,SIZE_T dwStatusUriSize) +{ + DWORD dwRet=MRA_XSTATUS_UNKNOWN; + + if (lpszStatusUri) + { + for(SIZE_T i=0;lpcszStatusUri[i];i++) + { + if (CompareStringA(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NORM_IGNORECASE,lpcszStatusUri[i],-1,lpszStatusUri,dwStatusUriSize)==CSTR_EQUAL) + { + dwRet=i; + break; + } + } + } +return(dwRet); +} + + +DWORD GetMraStatusFromMiradaStatus(DWORD dwMirandaStatus,DWORD dwXStatusMir,DWORD *pdwXStatusMra) +{ + DWORD dwRet; + + if (IsXStatusValid(dwXStatusMir)) + { + if (pdwXStatusMra) (*pdwXStatusMra)=(dwXStatusMir+MRA_XSTATUS_INDEX_OFFSET-1); + dwRet=STATUS_USER_DEFINED; + }else{ + switch(dwMirandaStatus){ + case ID_STATUS_OFFLINE: + if (pdwXStatusMra) (*pdwXStatusMra)=MRA_XSTATUS_OFFLINE; + dwRet=STATUS_OFFLINE; + break; + case ID_STATUS_ONLINE: + if (pdwXStatusMra) (*pdwXStatusMra)=MRA_XSTATUS_ONLINE; + dwRet=STATUS_ONLINE; + break; + case ID_STATUS_AWAY: + case ID_STATUS_NA: + case ID_STATUS_ONTHEPHONE: + case ID_STATUS_OUTTOLUNCH: + if (pdwXStatusMra) (*pdwXStatusMra)=MRA_XSTATUS_AWAY; + dwRet=STATUS_AWAY; + break; + case ID_STATUS_DND: + case ID_STATUS_OCCUPIED: + if (pdwXStatusMra) (*pdwXStatusMra)=MRA_XSTATUS_DND; + dwRet=STATUS_USER_DEFINED; + break; + case ID_STATUS_FREECHAT: + if (pdwXStatusMra) (*pdwXStatusMra)=MRA_XSTATUS_CHAT; + dwRet=STATUS_USER_DEFINED; + break; + case ID_STATUS_INVISIBLE: + if (pdwXStatusMra) (*pdwXStatusMra)=MRA_XSTATUS_INVISIBLE; + dwRet=(STATUS_ONLINE|STATUS_FLAG_INVISIBLE); + break; + default: + if (pdwXStatusMra) (*pdwXStatusMra)=MRA_XSTATUS_OFFLINE; + dwRet=STATUS_OFFLINE; + break; + } + } +return(dwRet); +} + + +DWORD GetMiradaStatusFromMraStatus(DWORD dwMraStatus,DWORD dwXStatusMra,DWORD *pdwXStatusMir) +{ + DWORD dwRet; + + if (pdwXStatusMir) (*pdwXStatusMir)=0; + + switch(dwMraStatus){ + case STATUS_OFFLINE: + dwRet=ID_STATUS_OFFLINE; + break; + case STATUS_ONLINE: + dwRet=ID_STATUS_ONLINE; + break; + case STATUS_AWAY: + dwRet=ID_STATUS_AWAY; + break; + case STATUS_UNDETERMINATED: + dwRet=ID_STATUS_OFFLINE; + break; + case STATUS_USER_DEFINED: + switch(dwXStatusMra){ + //case MRA_XSTATUS_OFFLINE: dwRet=ID_STATUS_OFFLINE; break; + //case MRA_XSTATUS_ONLINE: dwRet=ID_STATUS_ONLINE; break; + //case MRA_XSTATUS_AWAY: dwRet=ID_STATUS_AWAY; break; + //case MRA_XSTATUS_INVISIBLE: dwRet=ID_STATUS_INVISIBLE; break; + case MRA_XSTATUS_DND: dwRet=ID_STATUS_DND; break; + case MRA_XSTATUS_CHAT: dwRet=ID_STATUS_FREECHAT; break; + case MRA_XSTATUS_UNKNOWN: + if (pdwXStatusMir) (*pdwXStatusMir)=MRA_MIR_XSTATUS_UNKNOWN; + dwRet=ID_STATUS_ONLINE; + break; + default: + if (pdwXStatusMir) (*pdwXStatusMir)=(dwXStatusMra-MRA_XSTATUS_INDEX_OFFSET+1); + dwRet=ID_STATUS_ONLINE; + break; + } + break; + default:// STATUS_FLAG_INVISIBLE + if (dwMraStatus&STATUS_FLAG_INVISIBLE) + { + dwRet=ID_STATUS_INVISIBLE; + }else{ + dwRet=ID_STATUS_OFFLINE; + DebugBreak(); + } + break; + } +return(dwRet); +} + + +DWORD GetUL(LPBYTE *plpData) +{ + DWORD dwRet=(*(DWORD*)(*plpData)); + (*plpData)+=sizeof(DWORD); +return(dwRet); +} + + +DWORDLONG GetUIDL(LPBYTE *plpData) +{ + DWORDLONG dwRet=(*(DWORDLONG*)(*plpData)); + (*plpData)+=sizeof(DWORDLONG); +return(dwRet); +} + + +MRA_GUID GetGUID(LPBYTE *plpData) +{ + MRA_GUID guidRet=(*(MRA_GUID*)(*plpData)); + (*plpData)+=sizeof(MRA_GUID); +return(guidRet); +} + + +DWORD GetLPS(LPBYTE lpbData,DWORD dwDataSize,LPBYTE *plpCurrentData,MRA_LPS *plpsString) +{ + DWORD dwRetErrorCode; + LPBYTE lpbDataEnd=(lpbData+dwDataSize); + + if (lpbDataEnd>=((*plpCurrentData)+sizeof(DWORD))) + {// хотябы длинна данных есть + if (lpbDataEnd>=((*plpCurrentData)+sizeof(DWORD)+(*(DWORD*)(*plpCurrentData)))) + {// все длинна данных в буфере равна или меньше размера буфера + plpsString->dwSize=(*(DWORD*)(*plpCurrentData)); + plpsString->lpszData=(LPSTR)((*plpCurrentData)+sizeof(DWORD)); + (*plpCurrentData)+=(sizeof(DWORD)+plpsString->dwSize); + dwRetErrorCode=NO_ERROR; + }else{ + plpsString->dwSize=0; + plpsString->lpszData=NULL; + dwRetErrorCode=ERROR_INVALID_USER_BUFFER; + } + }else{ + plpsString->dwSize=0; + plpsString->lpszData=NULL; + dwRetErrorCode=ERROR_INVALID_USER_BUFFER; + } +return(dwRetErrorCode); +} + + -- cgit v1.2.3