From 38a93d167307c8d1912abeaf32182abe97a03598 Mon Sep 17 00:00:00 2001 From: Piotr Piastucki Date: Tue, 19 May 2015 21:00:49 +0000 Subject: Fixed some memleaks. Added contact list exchange feature. git-svn-id: http://svn.miranda-ng.org/main/trunk@13704 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/MSN/src/msn_auth.cpp | 2 ++ protocols/MSN/src/msn_avatar.cpp | 11 ++++-- protocols/MSN/src/msn_chat.cpp | 3 +- protocols/MSN/src/msn_commands.cpp | 55 ++++++++++++++++++++++++++---- protocols/MSN/src/msn_global.h | 1 + protocols/MSN/src/msn_misc.cpp | 14 ++++---- protocols/MSN/src/msn_proto.cpp | 68 +++++++++++++++++++++++++++++++++++--- protocols/MSN/src/msn_proto.h | 2 ++ 8 files changed, 137 insertions(+), 19 deletions(-) (limited to 'protocols/MSN') diff --git a/protocols/MSN/src/msn_auth.cpp b/protocols/MSN/src/msn_auth.cpp index 37167b7279..c2ca13612b 100644 --- a/protocols/MSN/src/msn_auth.cpp +++ b/protocols/MSN/src/msn_auth.cpp @@ -781,6 +781,7 @@ int CMsnProto::MSN_AuthOAuth(void) mHttpsTS = clock(); nlhr.dataLength = (int)strlen(post); nlhr.pData = (char*)(const char*)post; + nlhr.nlc = hHttpsConnection; NETLIBHTTPREQUEST *nlhrReply2 = (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)hNetlibUserHttps, (LPARAM)&nlhr); CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)nlhrReply); nlhrReply = nlhrReply2; @@ -845,6 +846,7 @@ int CMsnProto::MSN_AuthOAuth(void) nlhr.pData = "{\"trouterurl\":\"https://\",\"connectionid\":\"a\"}"; nlhr.dataLength = (int)strlen(nlhr.pData); nlhr.szUrl = "https://skypewebexperience.live.com/v1/User/Initialization"; + nlhr.nlc = hHttpsConnection; /* Request MappingContainer */ mHttpsTS = clock(); diff --git a/protocols/MSN/src/msn_avatar.cpp b/protocols/MSN/src/msn_avatar.cpp index 8f871b43ec..cc0a480418 100644 --- a/protocols/MSN/src/msn_avatar.cpp +++ b/protocols/MSN/src/msn_avatar.cpp @@ -22,7 +22,7 @@ along with this program. If not, see . void CMsnProto::AvatarQueue_Init() { - hevAvatarQueue = ::CreateEvent(NULL, FALSE, FALSE, NULL); + hevAvatarQueue = ::CreateSemaphore(NULL, 0, 255, NULL); ForkThread(&CMsnProto::MSN_AvatarsThread, 0); } @@ -44,7 +44,7 @@ void CMsnProto::pushAvatarRequest(MCONTACT hContact, LPCSTR pszUrl) return; lsAvatarQueue.insert(new AvatarQueueEntry(hContact, pszUrl)); - SetEvent(hevAvatarQueue); + ReleaseSemaphore(hevAvatarQueue, 1, NULL); } } @@ -119,4 +119,11 @@ void __cdecl CMsnProto::MSN_AvatarsThread(void*) ProtoBroadcastAck(p->hContact, ACKTYPE_AVATAR, ACKRESULT_FAILED, 0, 0); delete p; } + { + mir_cslock lck(csAvatarQueue); + while (lsAvatarQueue.getCount() > 0) { + delete lsAvatarQueue[0]; + lsAvatarQueue.remove(0); + } + } } diff --git a/protocols/MSN/src/msn_chat.cpp b/protocols/MSN/src/msn_chat.cpp index 3c0488dfde..afdc41d3a9 100644 --- a/protocols/MSN/src/msn_chat.cpp +++ b/protocols/MSN/src/msn_chat.cpp @@ -196,6 +196,7 @@ void CMsnProto::MSN_GCProcessThreadActivity(ezxml_t xmli, const TCHAR *mChatID) gce.ptszText = mir_a2t(ezxml_txt(ezxml_child(xmli, "value"))); CallServiceSync(MS_GC_EVENT, 0, (LPARAM)&gce); mir_free((TCHAR*)gce.ptszUID); + mir_free((TCHAR*)gce.ptszText); } else if (ezxml_t target = ezxml_child(xmli, "target")) { MCONTACT hContInitiator = NULL; @@ -258,9 +259,9 @@ void CMsnProto::MSN_GCProcessThreadActivity(ezxml_t xmli, const TCHAR *mChatID) CallServiceSync(MS_GC_EVENT, SESSION_OFFLINE, (LPARAM)&gce); break; } + mir_free((TCHAR*)gce.ptszUID); target = ezxml_next(target); } - mir_free((TCHAR*)gce.ptszUID); } } } diff --git a/protocols/MSN/src/msn_commands.cpp b/protocols/MSN/src/msn_commands.cpp index cc6591fa13..7060fcbf85 100644 --- a/protocols/MSN/src/msn_commands.cpp +++ b/protocols/MSN/src/msn_commands.cpp @@ -442,13 +442,56 @@ void CMsnProto::MSN_ReceiveMessage(ThreadData* info, char* cmdString, char* para } if (!_strnicmp(tContentType, "text/plain", 10) || - (!_strnicmp(tContentType, "application/user+xml", 10) && tHeader["Message-Type"] && !strcmp(tHeader["Message-Type"], "RichText"))) { + (!_strnicmp(tContentType, "application/user+xml", 10) && tHeader["Message-Type"] && !strncmp(tHeader["Message-Type"], "RichText", 8))) { MCONTACT hContact = strncmp(email, "19:", 3)?MSN_HContactFromEmail(email, nick, true, true):NULL; - int iTyping = -1; - if (!_stricmp(tHeader["Message-Type"], "Control/Typing")) iTyping=7; else - if (!_stricmp(tHeader["Message-Type"], "Control/ClearTyping")) iTyping=0; - if (iTyping == -1) { + if (!_stricmp(tHeader["Message-Type"], "RichText/Contacts")) { + ezxml_t xmli = ezxml_parse_str(msgBody, strlen(msgBody)); + if (xmli) { + if (!strcmp(xmli->name, "contacts")) { + ezxml_t c; + int cnt; + PROTOSEARCHRESULT **isr; + + for (c = ezxml_child(xmli, "c"), cnt=0; c; c = c->next) cnt++; + if (isr = (PROTOSEARCHRESULT**)mir_calloc(sizeof(PROTOSEARCHRESULT*) * cnt)) { + cnt=0; + for (c = ezxml_child(xmli, "c"); c; c = c->next) { + const char *t = ezxml_attr(c, "t"), *wlid; + if (t && (wlid = ezxml_attr(c, t))) { + switch (*t) + { + case 's': + case 'p': + isr[cnt] = (PROTOSEARCHRESULT*)mir_calloc(sizeof(PROTOSEARCHRESULT)); + isr[cnt]->cbSize = sizeof(isr); + isr[cnt]->flags = PSR_TCHAR; + isr[cnt]->id = isr[cnt]->nick = isr[cnt]->email = mir_a2t(wlid); + cnt++; + } + } + } + if (cnt) { + PROTORECVEVENT pre = { 0 }; + pre.timestamp = (DWORD)time(NULL); + pre.szMessage = (char *)isr; + pre.lParam = cnt; + pre.flags = PREF_TCHAR; + ProtoChainRecv(hContact, PSR_CONTACTS, 0, (LPARAM)&pre); + for (cnt=0; cntemail); + mir_free(isr[cnt]); + } + } + mir_free(isr); + } + } + ezxml_free(xmli); + } + } else + if (!_stricmp(tHeader["Message-Type"], "Control/Typing")) CallService(MS_PROTO_CONTACTISTYPING, hContact, 7); else + if (!_stricmp(tHeader["Message-Type"], "Control/ClearTyping")) CallService(MS_PROTO_CONTACTISTYPING, hContact, 0); + else { const char* p = tHeader["X-MMS-IM-Format"]; bool isRtl = p != NULL && strstr(p, "RL=1") != NULL; @@ -507,7 +550,7 @@ void CMsnProto::MSN_ReceiveMessage(ThreadData* info, char* cmdString, char* para db_event_add(hContact, &dbei); } } - } else CallService(MS_PROTO_CONTACTISTYPING, hContact, iTyping); + } } else if (!_strnicmp(tContentType, "text/x-msmsgsprofile", 20)) { replaceStr(msnExternalIP, tHeader["ClientIP"]); diff --git a/protocols/MSN/src/msn_global.h b/protocols/MSN/src/msn_global.h index 481080e507..b9ae399714 100644 --- a/protocols/MSN/src/msn_global.h +++ b/protocols/MSN/src/msn_global.h @@ -475,6 +475,7 @@ bool p2p_IsDlFileOk(filetransfer* ft); #define MSG_REQUIRE_ACK 2 #define MSG_RTL 4 #define MSG_OFFLINE 8 +#define MSG_CONTACT 16 struct CMsnProto; typedef void (__cdecl CMsnProto::*MsnThreadFunc)(void*); diff --git a/protocols/MSN/src/msn_misc.cpp b/protocols/MSN/src/msn_misc.cpp index ac44a8998b..1c877b2488 100644 --- a/protocols/MSN/src/msn_misc.cpp +++ b/protocols/MSN/src/msn_misc.cpp @@ -32,8 +32,8 @@ const char* CMsnProto::MirandaStatusToMSN(int status) { switch (status) { case ID_STATUS_OFFLINE: return "FLN"; - case ID_STATUS_ONTHEPHONE: - case ID_STATUS_OUTTOLUNCH: + case ID_STATUS_ONTHEPHONE: return "PHN"; + case ID_STATUS_OUTTOLUNCH: return "LUN"; case ID_STATUS_NA: case ID_STATUS_AWAY: return "AWY"; case ID_STATUS_DND: @@ -49,8 +49,8 @@ WORD CMsnProto::MSNStatusToMiranda(const char *status) switch ((*(PDWORD)status & 0x00FFFFFF) | 0x20000000) { case ' LDI': return ID_STATUS_IDLE; case ' NLN': return ID_STATUS_ONLINE; - case ' NHP': - case ' NUL': + case ' NHP': return ID_STATUS_ONTHEPHONE; + case ' NUL': return ID_STATUS_OUTTOLUNCH; case ' BRB': case ' YWA': return ID_STATUS_AWAY; case ' YSB': return ID_STATUS_OCCUPIED; @@ -486,12 +486,14 @@ int ThreadData::sendMessage(int msgType, const char* email, int netId, const cha buf.AppendFormat( "Messaging: 2.0\r\n" "Client-Message-ID: %llu\r\n" - "Message-Type: Text\r\n" + "Message-Type: %s\r\n" "IM-Display-Name: %s\r\n" - "Content-Type: Text/plain; charset=UTF-8\r\n" + "Content-Type: %s\r\n" "Content-Length: %d\r\n\r\n%s", msgid, + (parFlags & MSG_CONTACT)?"RichText/Contacts":"Text", pszNick, + (parFlags & MSG_CONTACT)?"application/user+xml\r\nSkype-Age: 18":"Text/plain; charset=UTF-8", strlen(parMsg), parMsg); if (pszNick!=proto->MyOptions.szEmail) db_free(&dbv); diff --git a/protocols/MSN/src/msn_proto.cpp b/protocols/MSN/src/msn_proto.cpp index b4e35c6f2c..4a0279b398 100644 --- a/protocols/MSN/src/msn_proto.cpp +++ b/protocols/MSN/src/msn_proto.cpp @@ -639,7 +639,7 @@ DWORD_PTR __cdecl CMsnProto::GetCaps(int type, MCONTACT) switch (type) { case PFLAGNUM_1: return PF1_IM | PF1_SERVERCLIST | PF1_AUTHREQ | PF1_BASICSEARCH | - PF1_ADDSEARCHRES | PF1_CHAT | + PF1_ADDSEARCHRES | PF1_CHAT | PF1_CONTACT | /*PF1_FILESEND | PF1_FILERECV | */PF1_URLRECV | PF1_VISLIST | PF1_MODEMSG; case PFLAGNUM_2: @@ -663,6 +663,9 @@ DWORD_PTR __cdecl CMsnProto::GetCaps(int type, MCONTACT) case PFLAG_MAXLENOFMESSAGE: return 1202; + + case PFLAG_MAXCONTACTSPERPACKET: + return 1024; // Only an assumption... } return 0; @@ -683,6 +686,35 @@ int __cdecl CMsnProto::RecvMsg(MCONTACT hContact, PROTORECVEVENT* pre) return Proto_RecvMessage(hContact, pre); } +///////////////////////////////////////////////////////////////////////////////////////// +// MsnRecvContacts - creates a database event from the contacts received + +int CMsnProto::RecvContacts(MCONTACT hContact, PROTORECVEVENT* pre) +{ + PROTOSEARCHRESULT **isrList = (PROTOSEARCHRESULT**)pre->szMessage; + DBEVENTINFO dbei = { sizeof(dbei) }; + BYTE *pCurBlob; + int i; + + for (i = 0; i < pre->lParam; i++) + dbei.cbBlob += mir_tstrlen(isrList[i]->nick) + 2 + mir_tstrlen(isrList[i]->id); + dbei.pBlob = (PBYTE)_alloca(dbei.cbBlob); + for (i = 0, pCurBlob = dbei.pBlob; i < pre->lParam; i++) { + mir_strcpy((char*)pCurBlob, _T2A(isrList[i]->nick)); + pCurBlob += mir_strlen((char*)pCurBlob) + 1; + mir_strcpy((char*)pCurBlob, _T2A(isrList[i]->id)); + pCurBlob += mir_strlen((char*)pCurBlob) + 1; + } + + dbei.szModule = m_szModuleName; + dbei.timestamp = pre->timestamp; + dbei.flags = (pre->flags & PREF_CREATEREAD) ? DBEF_READ : 0; + dbei.eventType = EVENTTYPE_CONTACTS; + db_event_add(hContact, &dbei); + return 0; +} + + ///////////////////////////////////////////////////////////////////////////////////////// // MsnSendFile - initiates a file transfer @@ -735,14 +767,16 @@ HANDLE __cdecl CMsnProto::SendFile(MCONTACT hContact, const PROTOCHAR*, PROTOCHA struct TFakeAckParams { - inline TFakeAckParams(MCONTACT p2, long p3, const char* p4, CMsnProto *p5) : + inline TFakeAckParams(MCONTACT p2, long p3, const char* p4, CMsnProto *p5, int p6=ACKTYPE_MESSAGE) : hContact(p2), id(p3), msg(p4), - proto(p5) + proto(p5), + type(p6) {} MCONTACT hContact; + int type; long id; const char* msg; CMsnProto *proto; @@ -753,7 +787,7 @@ void CMsnProto::MsnFakeAck(void* arg) TFakeAckParams* tParam = (TFakeAckParams*)arg; Sleep(150); - tParam->proto->ProtoBroadcastAck(tParam->hContact, ACKTYPE_MESSAGE, + tParam->proto->ProtoBroadcastAck(tParam->hContact, tParam->type, tParam->msg ? ACKRESULT_FAILED : ACKRESULT_SUCCESS, (HANDLE)tParam->id, LPARAM(tParam->msg)); @@ -863,6 +897,32 @@ int __cdecl CMsnProto::SendMsg(MCONTACT hContact, int flags, const char* pszSrc) return seq; } +///////////////////////////////////////////////////////////////////////////////////////// +// MsnSendContacts - sends contacts to a certain user +int __cdecl CMsnProto::SendContacts(MCONTACT hContact, int flags, int nContacts, MCONTACT *hContactsList) +{ + if (!msnLoggedIn) + return 0; + + char tEmail[MSN_MAX_EMAIL_LEN]; + if (MSN_IsMeByContact(hContact, tEmail)) return 0; + + int seq = 0; + int netId = Lists_GetNetId(tEmail); + CMStringA msg; + + msg.Append(""); + for (int i = 0; i < nContacts; i++) { + ptrA wlid(getStringA(hContactsList[i], "wlid")); + if (wlid != NULL) msg.AppendFormat("", wlid); + } + msg.Append(""); + seq = msnNsThread->sendMessage('1', tEmail, netId, msg, MSG_CONTACT); + ForkThread(&CMsnProto::MsnFakeAck, new TFakeAckParams(hContact, seq, NULL, this, ACKTYPE_CONTACTS)); + return seq; +} + + ///////////////////////////////////////////////////////////////////////////////////////// // MsnSetAwayMsg - sets the current status message for a user diff --git a/protocols/MSN/src/msn_proto.h b/protocols/MSN/src/msn_proto.h index 645b43a90d..dc139a6451 100644 --- a/protocols/MSN/src/msn_proto.h +++ b/protocols/MSN/src/msn_proto.h @@ -51,9 +51,11 @@ struct CMsnProto : public PROTO virtual HANDLE __cdecl SearchByEmail(const PROTOCHAR* email); virtual int __cdecl RecvMsg(MCONTACT hContact, PROTORECVEVENT*); + virtual int __cdecl RecvContacts(MCONTACT hContact, PROTORECVEVENT*); virtual HANDLE __cdecl SendFile(MCONTACT hContact, const PROTOCHAR* szDescription, PROTOCHAR** ppszFiles); virtual int __cdecl SendMsg(MCONTACT hContact, int flags, const char* msg); + virtual int __cdecl SendContacts(MCONTACT hContact, int flags, int nContacts, MCONTACT *hContactsList); virtual int __cdecl SetApparentMode(MCONTACT hContact, int mode); virtual int __cdecl SetStatus(int iNewStatus); -- cgit v1.2.3