summaryrefslogtreecommitdiff
path: root/protocols/MSN
diff options
context:
space:
mode:
authorPiotr Piastucki <leech.miranda@gmail.com>2015-05-19 21:00:49 +0000
committerPiotr Piastucki <leech.miranda@gmail.com>2015-05-19 21:00:49 +0000
commit38a93d167307c8d1912abeaf32182abe97a03598 (patch)
tree2602113bb73b15a4cd1a272a2d8464d60141c844 /protocols/MSN
parent05463e65c1fa74da551b9acf701366e185e516fc (diff)
Fixed some memleaks.
Added contact list exchange feature. git-svn-id: http://svn.miranda-ng.org/main/trunk@13704 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'protocols/MSN')
-rw-r--r--protocols/MSN/src/msn_auth.cpp2
-rw-r--r--protocols/MSN/src/msn_avatar.cpp11
-rw-r--r--protocols/MSN/src/msn_chat.cpp3
-rw-r--r--protocols/MSN/src/msn_commands.cpp55
-rw-r--r--protocols/MSN/src/msn_global.h1
-rw-r--r--protocols/MSN/src/msn_misc.cpp14
-rw-r--r--protocols/MSN/src/msn_proto.cpp68
-rw-r--r--protocols/MSN/src/msn_proto.h2
8 files changed, 137 insertions, 19 deletions
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 <http://www.gnu.org/licenses/>.
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; cnt<pre.lParam; cnt++) {
+ mir_free(isr[cnt]->email);
+ 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;
@@ -684,6 +687,35 @@ int __cdecl CMsnProto::RecvMsg(MCONTACT hContact, PROTORECVEVENT* 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
HANDLE __cdecl CMsnProto::SendFile(MCONTACT hContact, const PROTOCHAR*, PROTOCHAR** ppszFiles)
@@ -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));
@@ -864,6 +898,32 @@ int __cdecl CMsnProto::SendMsg(MCONTACT hContact, int flags, const char* pszSrc)
}
/////////////////////////////////////////////////////////////////////////////////////////
+// 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("<contacts alt=\"[Contacts enclosed. Please upgrade to latest Skype version to receive contacts.]\">");
+ for (int i = 0; i < nContacts; i++) {
+ ptrA wlid(getStringA(hContactsList[i], "wlid"));
+ if (wlid != NULL) msg.AppendFormat("<c t=\"s\" s=\"%s\"/>", wlid);
+ }
+ msg.Append("</contacts>");
+ 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
int __cdecl CMsnProto::SetAwayMsg(int status, const TCHAR* msg)
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<CMsnProto>
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);