From de1841e8600420cf3cf35cb73d6e0226a9519687 Mon Sep 17 00:00:00 2001 From: Piotr Piastucki Date: Thu, 4 Jun 2015 12:10:46 +0000 Subject: Fixed a memleak in groupchat Added support for contact list fetching for plain Skype user finally enabling usage of Skype accounts via skylogin.dll (login only working once in a session though, currently cannot find out why). Prevent launching of duplicate keepAliveThread git-svn-id: http://svn.miranda-ng.org/main/trunk@13995 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/MSN/msn_10.vcxproj | 1 + protocols/MSN/src/msn_auth.cpp | 41 ++-- protocols/MSN/src/msn_chat.cpp | 2 +- protocols/MSN/src/msn_commands.cpp | 3 +- protocols/MSN/src/msn_contact.cpp | 165 ++++++++------ protocols/MSN/src/msn_lists.cpp | 2 +- protocols/MSN/src/msn_opts.cpp | 4 +- protocols/MSN/src/msn_proto.cpp | 54 +++-- protocols/MSN/src/msn_proto.h | 14 ++ protocols/MSN/src/msn_skypeab.cpp | 448 +++++++++++++++++++++++++++++++++++++ protocols/MSN/src/msn_svcs.cpp | 2 +- 11 files changed, 624 insertions(+), 112 deletions(-) create mode 100644 protocols/MSN/src/msn_skypeab.cpp diff --git a/protocols/MSN/msn_10.vcxproj b/protocols/MSN/msn_10.vcxproj index 2cf0ee8aef..f00b7fdd97 100644 --- a/protocols/MSN/msn_10.vcxproj +++ b/protocols/MSN/msn_10.vcxproj @@ -207,6 +207,7 @@ NotUsing + Create diff --git a/protocols/MSN/src/msn_auth.cpp b/protocols/MSN/src/msn_auth.cpp index 47192116cd..ac3640694f 100644 --- a/protocols/MSN/src/msn_auth.cpp +++ b/protocols/MSN/src/msn_auth.cpp @@ -941,18 +941,10 @@ const char *CMsnProto::GetSkypeToken(bool bAsAuthHeader) char szToken[1024]; // Ensure that token isn't expired - MSN_AuthOAuth(); + if (MyOptions.netId == NETID_MSN) MSN_AuthOAuth(); // No token available, fetch it if (!authSkypeToken) { - // Get skype.com OAuth token needed to acquire skype_token - if (!authSkypeComToken) { - if (RefreshOAuth(authRefreshToken, "service::skype.com::MBI_SSL", szToken)) - replaceStr(authSkypeComToken, szToken); - else return NULL; - } - - // Get skype_token NETLIBHTTPREQUEST nlhr = { 0 }; NETLIBHTTPREQUEST *nlhrReply; NETLIBHTTPHEADER headers[1]; @@ -966,12 +958,33 @@ const char *CMsnProto::GetSkypeToken(bool bAsAuthHeader) nlhr.headers = headers; nlhr.headers[0].szName = "User-Agent"; nlhr.headers[0].szValue = (char*)MSN_USER_AGENT; - nlhr.szUrl = "https://api.skype.com/rps/skypetoken"; - mir_snprintf(szPOST, sizeof(szPOST), "scopes=client&clientVersion=%s&access_token=%s&partner=999", - msnProductVer, authSkypeComToken); - nlhr.dataLength = (int)strlen(szPOST); - nlhr.pData = (char*)(const char*)szPOST; + nlhr.pData = szPOST; + + if (MyOptions.netId == NETID_SKYPE) { + BYTE digest[16]; + int cbPasswd; + char szPassword[100]={0}; + + cbPasswd=mir_snprintf(szPassword, sizeof(szPassword), "%s\nskyper\n", MyOptions.szEmail); + db_get_static(NULL, m_szModuleName, "Password", szPassword+cbPasswd, sizeof(szPassword)-cbPasswd-1); + mir_md5_hash((BYTE*)szPassword, mir_strlen(szPassword), digest); + mir_base64_encodebuf(digest, sizeof(digest), szPassword, sizeof(szPassword)); + nlhr.szUrl = "https://api.skype.com/login/skypetoken"; + nlhr.dataLength = mir_snprintf(szPOST, sizeof(szPOST), "scopes=client&clientVersion=%s&username=%s&passwordHash=%s", + msnProductVer, MyOptions.szEmail, szPassword); + } else { + // Get skype.com OAuth token needed to acquire skype_token + if (!authSkypeComToken) { + if (RefreshOAuth(authRefreshToken, "service::skype.com::MBI_SSL", szToken)) + replaceStr(authSkypeComToken, szToken); + else return NULL; + } + // Get skype_token + nlhr.szUrl = "https://api.skype.com/rps/skypetoken"; + nlhr.dataLength = mir_snprintf(szPOST, sizeof(szPOST), "scopes=client&clientVersion=%s&access_token=%s&partner=999", + msnProductVer, authSkypeComToken); + } mHttpsTS = clock(); nlhrReply = (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)hNetlibUserHttps, (LPARAM)&nlhr); diff --git a/protocols/MSN/src/msn_chat.cpp b/protocols/MSN/src/msn_chat.cpp index 4e9b439eb7..4078b1bc65 100644 --- a/protocols/MSN/src/msn_chat.cpp +++ b/protocols/MSN/src/msn_chat.cpp @@ -253,13 +253,13 @@ void CMsnProto::MSN_GCProcessThreadActivity(ezxml_t xmli, const TCHAR *mChatID) MCONTACT hContTarget = MSN_HContactFromEmail(pszTarget); gce.ptszNick =GetContactNameT(hContTarget); CallServiceSync(MS_GC_EVENT, 0, (LPARAM)&gce); + mir_free((TCHAR*)gce.ptszUID); if ((gcd.iType == GC_EVENT_PART || gcd.iType == GC_EVENT_KICK) && gce.bIsMe) { GCDEST gcd = { m_szModuleName, mChatID, GC_EVENT_CONTROL }; GCEVENT gce = { sizeof(gce), &gcd }; CallServiceSync(MS_GC_EVENT, SESSION_OFFLINE, (LPARAM)&gce); break; } - mir_free((TCHAR*)gce.ptszUID); target = ezxml_next(target); } } diff --git a/protocols/MSN/src/msn_commands.cpp b/protocols/MSN/src/msn_commands.cpp index 938c3b6ea7..35af58d3aa 100644 --- a/protocols/MSN/src/msn_commands.cpp +++ b/protocols/MSN/src/msn_commands.cpp @@ -1019,7 +1019,7 @@ LBL_InvalidCommand: } bSentBND = false; - ForkThread(&CMsnProto::msn_keepAliveThread, NULL); + if (!hKeepAliveThreadEvt) ForkThread(&CMsnProto::msn_keepAliveThread, NULL); #ifdef OBSOLETE /* FIXME: Currently disabled, as P2P maybe not working anymore in MSNP24? */ ForkThread(&CMsnProto::MSNConnDetectThread, NULL); @@ -1122,6 +1122,7 @@ LBL_InvalidCommand: MSN_ProcessURIObject(hContact, xmlact); ezxml_free(xmlact); } + continue; } else if (mir_strcmp(msgtype->txt, "Text")) continue; /* TODO: Implement i.e. RichText/Files for announcement of file transfers */ } diff --git a/protocols/MSN/src/msn_contact.cpp b/protocols/MSN/src/msn_contact.cpp index ea27761a17..0683a6a628 100644 --- a/protocols/MSN/src/msn_contact.cpp +++ b/protocols/MSN/src/msn_contact.cpp @@ -39,7 +39,7 @@ MCONTACT CMsnProto::MSN_HContactFromEmail(const char* wlid, const char* msnNick, hContact = (MCONTACT)CallService(MS_DB_CONTACT_ADD, 0, 0); CallService(MS_PROTO_ADDTOCONTACT, hContact, (LPARAM)m_szModuleName); if (netId != NETID_SKYPE) setString(hContact, "e-mail", szEmail); - setStringUtf(hContact, "Nick", msnNick ? msnNick : wlid); + setStringUtf(hContact, "Nick", msnNick ? msnNick : szEmail); setWord(hContact, "netId", netId); setString(hContact, "wlid", szEmail); if (temporary) @@ -148,88 +148,102 @@ bool CMsnProto::MSN_AddUser(MCONTACT hContact, const char* email, int netId, int return true; bool res = false; - if (flags == LIST_FL) { - if (needRemove) { - if (hContact == NULL) { - hContact = MSN_HContactFromEmail(email); - if (hContact == NULL) - return false; - } - - char id[MSN_GUID_LEN]; - if (!db_get_static(hContact, m_szModuleName, "ID", id, sizeof(id))) { - int netId = Lists_GetNetId(email); - if (leaveHotmail) - res = MSN_ABAddRemoveContact(id, netId, false); - else - res = MSN_ABAddDelContactGroup(id, NULL, "ABContactDelete"); - if (res) AddDelUserContList(email, flags, netId, true); - - delSetting(hContact, "GroupID"); - delSetting(hContact, "ID"); - MSN_RemoveEmptyGroups(); - } + if (MyOptions.netId == NETID_SKYPE) { + if (flags & LIST_BL) { + if (needRemove) return MSN_SKYABBlockContact(email, "unblock"); + return MSN_SKYABBlockContact(email, "block"); } - else { - DBVARIANT dbv = { 0 }; - if (!mir_strcmp(email, MyOptions.szEmail)) - getStringUtf("Nick", &dbv); - - unsigned res1 = MSN_ABContactAdd(email, dbv.pszVal, netId, msg, false); - if (netId == NETID_MSN && res1 == 2) { - netId = NETID_LCS; - res = MSN_ABContactAdd(email, dbv.pszVal, netId, msg, false) == 0; - } - else if (netId == NETID_MSN && res1 == 3) { - char szContactID[100]; - hContact = MSN_HContactFromEmail(email); - if (db_get_static(hContact, m_szModuleName, "ID", szContactID, sizeof(szContactID)) == 0) { - MSN_ABAddRemoveContact(szContactID, netId, true); - res = true; + else if ((flags & LIST_FL)) { + if (!needRemove) return MSN_SKYABAuthRq(email, msg); + if (!leaveHotmail) return MSN_SKYABDeleteContact(email); + return true; + } + else if ((flags & LIST_AL) && !needRemove) return MSN_SKYABAuthRsp(email, "accept"); + else if ((flags & LIST_RL) && !needRemove) return MSN_SKYABAuthRsp(email, "decline"); + } else { + if (flags == LIST_FL) { + if (needRemove) { + if (hContact == NULL) { + hContact = MSN_HContactFromEmail(email); + if (hContact == NULL) + return false; } - } - else res = (res1 == 0); - if (res) { - DBVARIANT dbv; - if (!db_get_utf(hContact, "CList", "Group", &dbv)) { - MSN_MoveContactToGroup(hContact, dbv.pszVal); - db_free(&dbv); + char id[MSN_GUID_LEN]; + if (!db_get_static(hContact, m_szModuleName, "ID", id, sizeof(id))) { + int netId = Lists_GetNetId(email); + if (leaveHotmail) + res = MSN_ABAddRemoveContact(id, netId, false); + else + res = MSN_ABAddDelContactGroup(id, NULL, "ABContactDelete"); + if (res) AddDelUserContList(email, flags, netId, true); + + delSetting(hContact, "GroupID"); + delSetting(hContact, "ID"); + MSN_RemoveEmptyGroups(); + } + } + else { + DBVARIANT dbv = { 0 }; + if (!mir_strcmp(email, MyOptions.szEmail)) + getStringUtf("Nick", &dbv); + + unsigned res1 = MSN_ABContactAdd(email, dbv.pszVal, netId, msg, false); + if (netId == NETID_MSN && res1 == 2) { + netId = NETID_LCS; + res = MSN_ABContactAdd(email, dbv.pszVal, netId, msg, false) == 0; + } + else if (netId == NETID_MSN && res1 == 3) { + char szContactID[100]; + hContact = MSN_HContactFromEmail(email); + if (db_get_static(hContact, m_szModuleName, "ID", szContactID, sizeof(szContactID)) == 0) { + MSN_ABAddRemoveContact(szContactID, netId, true); + res = true; + } } + else res = (res1 == 0); - char szContactID[100]; - if (db_get_static(hContact, m_szModuleName, "ID", szContactID, sizeof(szContactID)) == 0) - MSN_ABFind("ABFindByContacts", szContactID); + if (res) { + DBVARIANT dbv; + if (!db_get_utf(hContact, "CList", "Group", &dbv)) { + MSN_MoveContactToGroup(hContact, dbv.pszVal); + db_free(&dbv); + } - MSN_SharingFindMembership(true); - AddDelUserContList(email, flags, netId, false); - } -#ifdef OBSOLETE - else if (netId == 1 && strstr(email, "@yahoo.com") != 0) - MSN_FindYahooUser(email); -#endif + char szContactID[100]; + if (db_get_static(hContact, m_szModuleName, "ID", szContactID, sizeof(szContactID)) == 0) + MSN_ABFind("ABFindByContacts", szContactID); + + MSN_SharingFindMembership(true); + AddDelUserContList(email, flags, netId, false); + } + #ifdef OBSOLETE + else if (netId == 1 && strstr(email, "@yahoo.com") != 0) + MSN_FindYahooUser(email); + #endif - db_free(&dbv); + db_free(&dbv); + } } - } - else if (flags == LIST_LL) { - if (needRemove) - Lists_Remove(LIST_LL, email); - else - Lists_Add(LIST_LL, NETID_MSN, email); - } - else { - if (netId == 0) - netId = Lists_GetNetId(email); - res = MSN_SharingAddDelMember(email, flags, netId, needRemove ? "DeleteMember" : "AddMember"); - AddDelUserContList(email, flags, netId, needRemove); - if ((flags & LIST_BL) && !needRemove) { - ThreadData* thread = MSN_GetThreadByContact(email, SERVER_SWITCHBOARD); - if (thread) thread->sendTerminate(); + else if (flags == LIST_LL) { + if (needRemove) + Lists_Remove(LIST_LL, email); + else + Lists_Add(LIST_LL, NETID_MSN, email); } + else { + if (netId == 0) + netId = Lists_GetNetId(email); + res = MSN_SharingAddDelMember(email, flags, netId, needRemove ? "DeleteMember" : "AddMember"); + AddDelUserContList(email, flags, netId, needRemove); + if ((flags & LIST_BL) && !needRemove) { + ThreadData* thread = MSN_GetThreadByContact(email, SERVER_SWITCHBOARD); + if (thread) thread->sendTerminate(); + } - if ((flags & LIST_PL) && needRemove) - MSN_AddUser(hContact, email, netId, LIST_RL); + if ((flags & LIST_PL) && needRemove) + MSN_AddUser(hContact, email, netId, LIST_RL); + } } return res; } @@ -285,7 +299,10 @@ bool CMsnProto::MSN_RefreshContactList(void) } else { - /* TODO: Add pulling Skype contacts from event server or skypeweb or other unknown method.. */ + // Refresh Skype contact list + MSN_SKYABRefreshClist(); + + // Populate Contact list on MSN network to get status updates of contacts MSN_CreateContList(); } diff --git a/protocols/MSN/src/msn_lists.cpp b/protocols/MSN/src/msn_lists.cpp index d1b578b36d..c9504c8011 100644 --- a/protocols/MSN/src/msn_lists.cpp +++ b/protocols/MSN/src/msn_lists.cpp @@ -280,7 +280,7 @@ void CMsnProto::MSN_CreateContList(void) CMStringA cxml; - cxml.Append(""); + cxml.AppendFormat("", MyOptions.netId == NETID_MSN?1:0); { mir_cslock lck(m_csLists); diff --git a/protocols/MSN/src/msn_opts.cpp b/protocols/MSN/src/msn_opts.cpp index 0758b6aed5..83fbd42411 100644 --- a/protocols/MSN/src/msn_opts.cpp +++ b/protocols/MSN/src/msn_opts.cpp @@ -231,7 +231,7 @@ LBL_Continue: mir_strcpy(proto->MyOptions.szEmail, szEmail); proto->setString("e-mail", szEmail); proto->setString("wlid", szEmail); - proto->setDword("netId", proto->GetMyNetID()); + proto->setDword("netId", (proto->MyOptions.netId = proto->GetMyNetID())); } GetDlgItemTextA(hwndDlg, IDC_PASSWORD, password, SIZEOF(password)); @@ -558,7 +558,7 @@ static INT_PTR CALLBACK DlgProcAccMgrUI(HWND hwndDlg, UINT msg, WPARAM wParam, L mir_strcpy(proto->MyOptions.szEmail, szEmail); proto->setString("e-mail", szEmail); proto->setString("wlid", szEmail); - proto->setDword("netId", proto->GetMyNetID()); + proto->setDword("netId", (proto->MyOptions.netId = proto->GetMyNetID())); } GetDlgItemTextA(hwndDlg, IDC_PASSWORD, password, SIZEOF(password)); diff --git a/protocols/MSN/src/msn_proto.cpp b/protocols/MSN/src/msn_proto.cpp index dce9ae50ff..9e8603def2 100644 --- a/protocols/MSN/src/msn_proto.cpp +++ b/protocols/MSN/src/msn_proto.cpp @@ -406,11 +406,13 @@ void __cdecl CMsnProto::MsnSearchAckThread(void* arg) return; } - unsigned res = MSN_ABContactAdd(email, NULL, NETID_MSN, NULL, 1, true); - switch (res) { - case 0: - case 2: - case 3: + if (MyOptions.netId == NETID_SKYPE) MSN_SKYABSearch(email, arg); + else { + unsigned res = MSN_ABContactAdd(email, NULL, NETID_MSN, NULL, 1, true); + switch (res) { + case 0: + case 2: + case 3: { PROTOSEARCHRESULT psr = { 0 }; psr.cbSize = sizeof(psr); @@ -418,25 +420,27 @@ void __cdecl CMsnProto::MsnSearchAckThread(void* arg) psr.id.t = (TCHAR*)emailT; psr.nick.t = (TCHAR*)emailT; psr.email.t = (TCHAR*)emailT; + ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, arg, (LPARAM)&psr); + ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, arg, 0); } - ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, arg, 0); break; - case 1: - if (strstr(email, "@yahoo.com") == NULL) + case 1: + if (strstr(email, "@yahoo.com") == NULL) + ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, arg, 0); + #ifdef OBSOLETE + else { + msnSearchId = arg; + MSN_FindYahooUser(email); + } + #endif + break; + + default: ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, arg, 0); -#ifdef OBSOLETE - else { - msnSearchId = arg; - MSN_FindYahooUser(email); + break; } -#endif - break; - - default: - ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, arg, 0); - break; } mir_free(arg); } @@ -814,6 +818,20 @@ int __cdecl CMsnProto::RecvMsg(MCONTACT hContact, PROTORECVEVENT* pre) return Proto_RecvMessage(hContact, pre); } +int CMsnProto::GetInfo(MCONTACT hContact, int infoType) +{ + if (MyOptions.netId == NETID_SKYPE) { + char tEmail[MSN_MAX_EMAIL_LEN]; + if (db_get_static(hContact, m_szModuleName, "wlid", tEmail, sizeof(tEmail))) + db_get_static(hContact, m_szModuleName, "e-mail", tEmail, sizeof(tEmail)); + + MSN_SKYABGetProfile(tEmail); + return 1; + } + return 0; +} + + ///////////////////////////////////////////////////////////////////////////////////////// // MsnRecvContacts - creates a database event from the contacts received diff --git a/protocols/MSN/src/msn_proto.h b/protocols/MSN/src/msn_proto.h index 08654d0020..abef0e03c2 100644 --- a/protocols/MSN/src/msn_proto.h +++ b/protocols/MSN/src/msn_proto.h @@ -46,6 +46,7 @@ struct CMsnProto : public PROTO virtual int __cdecl FileResume(HANDLE hTransfer, int* action, const TCHAR** szFilename); virtual DWORD_PTR __cdecl GetCaps(int type, MCONTACT hContact = NULL); + virtual int __cdecl GetInfo(MCONTACT hContact, int infoType); virtual HANDLE __cdecl SearchBasic(const TCHAR* id); virtual HANDLE __cdecl SearchByEmail(const TCHAR* email); @@ -529,6 +530,19 @@ struct CMsnProto : public PROTO void sttNotificationMessage(char* msgBody, bool isInitial); void displayEmailCount(MCONTACT hContact); + ///////////////////////////////////////////////////////////////////////////////////////// + // SKYPE JSON Address Book + bool MSN_SKYABRefreshClist(void); + bool MSN_SKYABBlockContact(const char *wlid, const char *pszAction); + bool MSN_SKYABAuthRq(const char *wlid, const char *pszGreeting); + bool MSN_SKYABAuthRsp(const char *wlid, const char *pszAction); + bool MSN_SKYABDeleteContact(const char *wlid); + bool MSN_SKYABSearch(const char *keyWord, HANDLE hSearch); + bool MSN_SKYABGetProfiles(const char *pszPOST); + bool MSN_SKYABGetProfile(const char *wlid); + + bool APISkypeComRequest(NETLIBHTTPREQUEST *nlhr, NETLIBHTTPHEADER *headers); + ///////////////////////////////////////////////////////////////////////////////////////// // MSN SOAP Address Book diff --git a/protocols/MSN/src/msn_skypeab.cpp b/protocols/MSN/src/msn_skypeab.cpp new file mode 100644 index 0000000000..a30f0fe357 --- /dev/null +++ b/protocols/MSN/src/msn_skypeab.cpp @@ -0,0 +1,448 @@ +/* +Plugin of Miranda IM for communicating with users of the MSN Messenger protocol. + +Copyright (c) 2012-2014 Miranda NG Team +Copyright (c) 2007-2012 Boris Krasnovskiy. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#include "msn_global.h" +#include "msn_proto.h" +#include + +bool CMsnProto::APISkypeComRequest(NETLIBHTTPREQUEST *nlhr, NETLIBHTTPHEADER *headers) +{ + const char *pszSkypeToken = GetSkypeToken(false); + + if (!pszSkypeToken) return false; + nlhr->cbSize = sizeof(NETLIBHTTPREQUEST); + nlhr->flags = NLHRF_HTTP11 | NLHRF_DUMPASTEXT | NLHRF_PERSISTENT | NLHRF_REDIRECT; + nlhr->nlc = hHttpsConnection; + nlhr->headersCount = 3; + nlhr->headers = headers; + nlhr->headers[0].szName = "User-Agent"; + nlhr->headers[0].szValue = (char*)MSN_USER_AGENT; + nlhr->headers[1].szName = "Accept"; + nlhr->headers[1].szValue = "application/json"; + nlhr->headers[2].szName = "X-Skypetoken"; + nlhr->headers[2].szValue = (char*)pszSkypeToken; + return true; +} + +static TCHAR *get_json_str(JSONNODE *item, const char *pszValue) +{ + JSONNODE *node; + TCHAR *ret; + + if (node=json_get(item, pszValue)) { + ret = json_as_string(node); + if (!mir_tstrcmp(ret, _T("null"))) { + mir_free(ret); + return NULL; + } + return ret; + } + return NULL; +} + +bool CMsnProto::MSN_SKYABRefreshClist(void) +{ + NETLIBHTTPREQUEST nlhr = { 0 }; + NETLIBHTTPREQUEST *nlhrReply; + NETLIBHTTPHEADER headers[3]; + CMStringA post; + bool bRet = false; + + // initialize the netlib request + if (!APISkypeComRequest(&nlhr, headers)) return false; + nlhr.requestType = REQUEST_GET; + nlhr.szUrl = "https://api.skype.com/users/self/contacts"; + + // Query addressbook + mHttpsTS = clock(); + nlhrReply = (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)hNetlibUserHttps, (LPARAM)&nlhr); + mHttpsTS = clock(); + if (nlhrReply) { + hHttpsConnection = nlhrReply->nlc; + if (nlhrReply->resultCode == 200 && nlhrReply->pData) { + JSONROOT root(nlhrReply->pData); + if (root == NULL) return false; + + JSONNODE *items = json_as_array(root), *item; + for (size_t i = 0; i < json_size(items); i++) + { + int lstId = LIST_FL; + ptrT nick; + + item = json_at(items, i); + if (item == NULL) + break; + + ptrA skypename(mir_t2a(ptrT(json_as_string(json_get(item, "skypename"))))); + ptrA pszNick(mir_t2a(ptrT(get_json_str(item, "fullname")))); + char szWLId[128]; + mir_snprintf(szWLId, sizeof(szWLId), "%d:%s", NETID_SKYPE, skypename); + MCONTACT hContact = MSN_HContactFromEmail(szWLId, pszNick, true, false); + if (hContact) + { + if (!json_as_bool(json_get(item, "authorized"))) lstId = LIST_PL; + if (!json_as_bool(json_get(item, "blocked"))) lstId = LIST_BL; + Lists_Add(lstId, NETID_SKYPE, skypename, NULL, pszNick, NULL); + post.AppendFormat("contacts[]=%s&", skypename); + } + } + bRet = true; + json_delete(items); + MSN_SKYABGetProfiles((const char*)post); + } + CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)nlhrReply); + } else hHttpsConnection = NULL; + return bRet; +} + +// pszPOST = contacts[]={skypename1}&contacts[]={skypename2}&... +bool CMsnProto::MSN_SKYABGetProfiles(const char *pszPOST) +{ + NETLIBHTTPREQUEST nlhr = { 0 }; + NETLIBHTTPREQUEST *nlhrReply; + NETLIBHTTPHEADER headers[4]; + bool bRet = false; + + // initialize the netlib request + if (!APISkypeComRequest(&nlhr, headers)) return false; + nlhr.requestType = REQUEST_POST; + nlhr.szUrl = "https://api.skype.com/users/self/contacts/profiles"; + nlhr.dataLength = mir_strlen(pszPOST); + nlhr.pData = (char*)pszPOST; + + mHttpsTS = clock(); + nlhrReply = (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)hNetlibUserHttps, (LPARAM)&nlhr); + mHttpsTS = clock(); + if (nlhrReply) { + hHttpsConnection = nlhrReply->nlc; + if (nlhrReply->resultCode == 200 && nlhrReply->pData) { + JSONROOT root(nlhrReply->pData); + if (root == NULL) return false; + + JSONNODE *items = json_as_array(root), *item, *node; + for (size_t i = 0; i < json_size(items); i++) + { + item = json_at(items, i); + if (item == NULL) + break; + + node = json_get(item, "username"); + ptrA skypename(mir_t2a(ptrT(json_as_string(node)))); + ptrT value; + char szWLId[128]; + mir_snprintf(szWLId, sizeof(szWLId), "%d:%s", NETID_SKYPE, skypename); + MCONTACT hContact = MSN_HContactFromEmail(szWLId, skypename, false, false); + + if (hContact) + { + if (value=get_json_str(item, "firstname")) setTString(hContact, "FirstName", value); + if (value=get_json_str(item, "lastname")) setTString(hContact, "LastName", value); + if (value=get_json_str(item, "displayname")) setTString(hContact, "Nick", value); + if (value=get_json_str(item, "country")) setString(hContact, "Country", (char*)CallService(MS_UTILS_GETCOUNTRYBYISOCODE, (WPARAM)(char*)_T2A(value), 0)); + if (value=get_json_str(item, "city")) setTString(hContact, "City", value); + if (value=get_json_str(item, "mood")) db_set_ts(hContact, "CList", "StatusMsg", value); + } + } + json_delete(items); + bRet = true; + } + CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)nlhrReply); + } else hHttpsConnection = NULL; + return bRet; +} + +bool CMsnProto::MSN_SKYABGetProfile(const char *wlid) +{ + NETLIBHTTPREQUEST nlhr = { 0 }; + NETLIBHTTPREQUEST *nlhrReply; + NETLIBHTTPHEADER headers[4]; + bool bRet = false; + char szURL[256]; + + // initialize the netlib request + if (!APISkypeComRequest(&nlhr, headers)) return false; + nlhr.requestType = REQUEST_GET; + mir_snprintf(szURL, sizeof(szURL), "https://api.skype.com/users/%s/profile", wlid); + nlhr.szUrl = szURL; + + mHttpsTS = clock(); + nlhrReply = (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)hNetlibUserHttps, (LPARAM)&nlhr); + mHttpsTS = clock(); + if (nlhrReply) { + hHttpsConnection = nlhrReply->nlc; + if (nlhrReply->resultCode == 200 && nlhrReply->pData) { + JSONROOT item(nlhrReply->pData); + JSONNODE *node; + if (item == NULL) return false; + + ptrA skypename(mir_t2a(ptrT(json_as_string(json_get(item, "username"))))); + ptrT value; + char szWLId[128]; + mir_snprintf(szWLId, sizeof(szWLId), "%d:%s", NETID_SKYPE, skypename); + MCONTACT hContact = MSN_HContactFromEmail(szWLId, skypename, false, false); + + if (hContact) + { + if (value=get_json_str(item, "firstname")) setTString(hContact, "FirstName", value); + if (value=get_json_str(item, "lastname")) setTString(hContact, "LastName", value); + if (value=get_json_str(item, "displayname")) setTString(hContact, "Nick", value); + if (value=get_json_str(item, "gender")) setByte(hContact, "Gender", (BYTE)(_ttoi(value) == 1 ? 'M' : 'F')); + if (value=get_json_str(item, "birthday")) { + int d, m, y; + _stscanf(value, _T("%d-%d-%d"), &y, &m, &d); + setWord(hContact, "BirthYear", y); + setByte(hContact, "BirthDay", d); + setByte(hContact, "BirthMonth", m); + } + if (value=get_json_str(item, "country")) setString(hContact, "Country", (char*)CallService(MS_UTILS_GETCOUNTRYBYISOCODE, (WPARAM)(char*)_T2A(value), 0)); + if (value=get_json_str(item, "province")) setTString(hContact, "State", value); + if (value=get_json_str(item, "city")) setTString(hContact, "City", value); + if (value=get_json_str(item, "homepage")) setTString(hContact, "Homepage", value); + if (value=get_json_str(item, "about")) setTString(hContact, "About", value); + if ((node = json_get(item, "emails")) && !json_empty(node)) + { + JSONNODE *items = json_as_array(node), *item; + char szName[16]; + for (size_t i = 0; i < min(json_size(items), 3); i++) + { + if (!(item = json_at(items, i))) break; + sprintf(szName, "e-mail%d", i); + setTString(hContact, szName, ptrT(json_as_string(item))); + } + json_delete(items); + } + if (value=get_json_str(item, "phoneMobile")) setTString(hContact, "Cellular", value); + if (value=get_json_str(item, "phone")) setTString(hContact, "Phone", value); + if (value=get_json_str(item, "phoneOffice")) setTString(hContact, "CompanyPhone", value); + if (value=get_json_str(item, "mood")) db_set_ts(hContact, "CList", "StatusMsg", value); + } + bRet = true; + } + CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)nlhrReply); + } else hHttpsConnection = NULL; + return bRet; +} + +// pszAction: "block" or "unblock" +bool CMsnProto::MSN_SKYABBlockContact(const char *wlid, const char *pszAction) +{ + NETLIBHTTPREQUEST nlhr = { 0 }; + NETLIBHTTPREQUEST *nlhrReply; + NETLIBHTTPHEADER headers[4]; + bool bRet = false; + char szURL[256], szPOST[128]; + + // initialize the netlib request + if (!APISkypeComRequest(&nlhr, headers)) return false; + nlhr.requestType = REQUEST_PUT; + mir_snprintf(szURL, sizeof(szURL), "https://api.skype.com/users/self/contacts/%s/%s", wlid, pszAction); + nlhr.szUrl = szURL; + nlhr.headers[3].szName = "Content-type"; + nlhr.headers[3].szValue = "application/x-www-form-urlencoded"; + nlhr.headersCount++; + nlhr.dataLength = mir_snprintf(szPOST, sizeof(szPOST), "reporterIp=123.123.123.123&uiVersion=%s", msnProductVer); + nlhr.pData = szPOST; + + mHttpsTS = clock(); + nlhrReply = (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)hNetlibUserHttps, (LPARAM)&nlhr); + mHttpsTS = clock(); + if (nlhrReply) { + hHttpsConnection = nlhrReply->nlc; + CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)nlhrReply); + bRet = true; + } else hHttpsConnection = NULL; + return bRet; +} + +bool CMsnProto::MSN_SKYABDeleteContact(const char *wlid) +{ + NETLIBHTTPREQUEST nlhr = { 0 }; + NETLIBHTTPREQUEST *nlhrReply; + NETLIBHTTPHEADER headers[4]; + bool bRet = false; + char szURL[256]; + + // initialize the netlib request + if (!APISkypeComRequest(&nlhr, headers)) return false; + nlhr.requestType = REQUEST_DELETE; + mir_snprintf(szURL, sizeof(szURL), "https://api.skype.com/users/self/contacts/%s", wlid); + nlhr.szUrl = szURL; + nlhr.headers[3].szName = "Content-type"; + nlhr.headers[3].szValue = "application/x-www-form-urlencoded"; + nlhr.headersCount++; + + mHttpsTS = clock(); + nlhrReply = (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)hNetlibUserHttps, (LPARAM)&nlhr); + mHttpsTS = clock(); + if (nlhrReply) { + hHttpsConnection = nlhrReply->nlc; + CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)nlhrReply); + bRet = true; + } else hHttpsConnection = NULL; + return bRet; +} + +// pszAction: "accept" or "decline" +bool CMsnProto::MSN_SKYABAuthRsp(const char *wlid, const char *pszAction) +{ + NETLIBHTTPREQUEST nlhr = { 0 }; + NETLIBHTTPREQUEST *nlhrReply; + NETLIBHTTPHEADER headers[3]; + bool bRet = false; + char szURL[256]; + + // initialize the netlib request + if (!APISkypeComRequest(&nlhr, headers)) return false; + nlhr.requestType = REQUEST_PUT; + mir_snprintf(szURL, sizeof(szURL), "https://api.skype.com/users/self/contacts/auth-request/%s/%s", wlid, pszAction); + nlhr.szUrl = szURL; + + mHttpsTS = clock(); + nlhrReply = (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)hNetlibUserHttps, (LPARAM)&nlhr); + mHttpsTS = clock(); + if (nlhrReply) { + hHttpsConnection = nlhrReply->nlc; + CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)nlhrReply); + bRet = true; + } else hHttpsConnection = NULL; + return bRet; +} + +bool CMsnProto::MSN_SKYABAuthRq(const char *wlid, const char *pszGreeting) +{ + NETLIBHTTPREQUEST nlhr = { 0 }; + NETLIBHTTPREQUEST *nlhrReply; + NETLIBHTTPHEADER headers[4]; + bool bRet = false; + char szURL[256]; + CMStringA post; + + // initialize the netlib request + if (!APISkypeComRequest(&nlhr, headers)) return false; + nlhr.requestType = REQUEST_PUT; + mir_snprintf(szURL, sizeof(szURL), "https://api.skype.com/users/self/contacts/auth-request/%s", wlid); + nlhr.szUrl = szURL; + nlhr.headers[3].szName = "Content-type"; + nlhr.headers[3].szValue = "application/x-www-form-urlencoded"; + nlhr.headersCount++; + post.Format("greeting=%s", pszGreeting); + nlhr.dataLength = mir_strlen(post); + nlhr.pData = (char*)(const char*)post; + + mHttpsTS = clock(); + nlhrReply = (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)hNetlibUserHttps, (LPARAM)&nlhr); + mHttpsTS = clock(); + if (nlhrReply) { + hHttpsConnection = nlhrReply->nlc; + CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)nlhrReply); + bRet = true; + } else hHttpsConnection = NULL; + return bRet; +} + +bool CMsnProto::MSN_SKYABSearch(const char *keyWord, HANDLE hSearch) +{ + NETLIBHTTPREQUEST nlhr = { 0 }; + NETLIBHTTPREQUEST *nlhrReply; + NETLIBHTTPHEADER headers[4]; + bool bRet = false; + char szURL[256]; + + // initialize the netlib request + if (!APISkypeComRequest(&nlhr, headers)) { + ProtoBroadcastAck(0, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, hSearch, 0); + return false; + } + nlhr.requestType = REQUEST_GET; + mir_snprintf(szURL, sizeof(szURL), "https://api.skype.com/search/users/any?keyWord=%s&contactTypes[]=skype", keyWord); + nlhr.szUrl = szURL; + nlhr.headers[3].szName = "Connection"; + nlhr.headers[3].szValue = "keep-alive"; + nlhr.headersCount++; + + mHttpsTS = clock(); + nlhrReply = (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)hNetlibUserHttps, (LPARAM)&nlhr); + mHttpsTS = clock(); + if (nlhrReply) { + hHttpsConnection = nlhrReply->nlc; + if (nlhrReply->resultCode == 200 && nlhrReply->pData) { + JSONROOT root(nlhrReply->pData); + if (root == NULL) + { + ProtoBroadcastAck(0, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, hSearch, 0); + return false; + } + + JSONNODE *items = json_as_array(root); + for (size_t i = 0; i < json_size(items); i++) + { + JSONNODE *item = json_at(items, i); + JSONNODE *ContactCards = json_get(item, "ContactCards"); + JSONNODE *Skype = json_get(ContactCards, "Skype"); + + TCHAR *sDisplayName = json_as_string(json_get(Skype, "DisplayName")); + TCHAR *sSkypeName = json_as_string(json_get(Skype, "SkypeName")); + + PROTOSEARCHRESULT psr = { sizeof(psr) }; + psr.flags = PSR_TCHAR; + psr.id.t = sSkypeName; + psr.nick.t = sDisplayName; + ProtoBroadcastAck(0, ACKTYPE_SEARCH, ACKRESULT_DATA, hSearch, (LPARAM)&psr); + } + json_free(items); + ProtoBroadcastAck(0, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, hSearch, 0); + bRet = true; + } + CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)nlhrReply); + } else hHttpsConnection = NULL; + return bRet; +} + +/* +class GetContactsInfoRequest : public HttpRequest +{ +public: + GetContactsInfoRequest(const char *token, const LIST &skypenames, const char *skypename = "self") : + HttpRequest(REQUEST_POST, FORMAT, "api.skype.com/users/%s/contacts/profiles", skypename) + { + Headers + << CHAR_VALUE("X-Skypetoken", token) + << CHAR_VALUE("Accept", "application/json"); + + for (int i = 0; i < skypenames.getCount(); i++) + Body << CHAR_VALUE("contacts[]", skypenames[i]); + } +}; + +class GetContactStatusRequest : public HttpRequest +{ +public: + GetContactStatusRequest(const char *regToken, const char *skypename, const char *server = SKYPE_ENDPOINTS_HOST) : + HttpRequest(REQUEST_GET, FORMAT, "%s/v1/users/ME/contacts/8:%s/presenceDocs/messagingService", server, skypename) + { + Headers + << CHAR_VALUE("Accept", "application/json, text/javascript") + << FORMAT_VALUE("RegistrationToken", "registrationToken=%s", regToken); + } +}; + + + +*/ \ No newline at end of file diff --git a/protocols/MSN/src/msn_svcs.cpp b/protocols/MSN/src/msn_svcs.cpp index 22fa3d1b6b..3ca83db2b0 100644 --- a/protocols/MSN/src/msn_svcs.cpp +++ b/protocols/MSN/src/msn_svcs.cpp @@ -449,7 +449,7 @@ int CMsnProto::OnDbSettingChanged(WPARAM hContact, LPARAM lParam) { DBCONTACTWRITESETTING* cws = (DBCONTACTWRITESETTING*)lParam; - if (!msnLoggedIn) + if (!msnLoggedIn || MyOptions.netId != NETID_MSN) return 0; if (hContact == NULL) { -- cgit v1.2.3