diff options
Diffstat (limited to 'protocols/MSN/src')
| -rw-r--r-- | protocols/MSN/src/msn_auth.cpp | 2 | ||||
| -rw-r--r-- | protocols/MSN/src/msn_avatar.cpp | 11 | ||||
| -rw-r--r-- | protocols/MSN/src/msn_chat.cpp | 3 | ||||
| -rw-r--r-- | protocols/MSN/src/msn_commands.cpp | 55 | ||||
| -rw-r--r-- | protocols/MSN/src/msn_global.h | 1 | ||||
| -rw-r--r-- | protocols/MSN/src/msn_misc.cpp | 14 | ||||
| -rw-r--r-- | protocols/MSN/src/msn_proto.cpp | 68 | ||||
| -rw-r--r-- | protocols/MSN/src/msn_proto.h | 2 | 
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);
  | 
