From a50ae784ce7394b2621cf42a28cab7edd31e6c6a Mon Sep 17 00:00:00 2001 From: Kirill Volinsky Date: Fri, 3 Apr 2015 05:33:18 +0000 Subject: login fix and some other fixes (patch by MikalaiR) git-svn-id: http://svn.miranda-ng.org/main/trunk@12581 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/SkypeWeb/src/common.h | 1 + protocols/SkypeWeb/src/requests/endpoint.h | 9 +- protocols/SkypeWeb/src/requests/messages.h | 29 +++++- protocols/SkypeWeb/src/requests/poll.h | 4 +- protocols/SkypeWeb/src/requests/reg_info.h | 4 +- protocols/SkypeWeb/src/requests/status.h | 8 +- protocols/SkypeWeb/src/requests/subscriptions.h | 4 +- protocols/SkypeWeb/src/skype_contacts.cpp | 2 + protocols/SkypeWeb/src/skype_events.cpp | 81 ++++++++------- protocols/SkypeWeb/src/skype_poll_processing.cpp | 84 +++++++++++++++- protocols/SkypeWeb/src/skype_polling.cpp | 21 +++- protocols/SkypeWeb/src/skype_proto.cpp | 29 ++++-- protocols/SkypeWeb/src/skype_proto.h | 11 ++- protocols/SkypeWeb/src/skype_utils.cpp | 120 +++++++++++++++++++++++ 14 files changed, 340 insertions(+), 67 deletions(-) diff --git a/protocols/SkypeWeb/src/common.h b/protocols/SkypeWeb/src/common.h index 97e8356f09..e2f4ef2f95 100644 --- a/protocols/SkypeWeb/src/common.h +++ b/protocols/SkypeWeb/src/common.h @@ -35,6 +35,7 @@ #include #include #include +#include struct CSkypeProto; diff --git a/protocols/SkypeWeb/src/requests/endpoint.h b/protocols/SkypeWeb/src/requests/endpoint.h index f6dd9c604c..a5d05b7ec7 100644 --- a/protocols/SkypeWeb/src/requests/endpoint.h +++ b/protocols/SkypeWeb/src/requests/endpoint.h @@ -4,8 +4,8 @@ class GetEndpointRequest : public HttpRequest { public: - GetEndpointRequest(const char *regToken, const char *endpointID) : - HttpRequest(REQUEST_PUT, FORMAT, "client-s.gateway.messenger.live.com/v1/users/ME/endpoints/%s/presenceDocs/messagingService", ptrA(mir_urlEncode(endpointID))) + GetEndpointRequest(const char *regToken, const char *endpointID, const char *server = "client-s.gateway.messenger.live.com") : + HttpRequest(REQUEST_PUT, FORMAT, "%s/v1/users/ME/endpoints/%s/presenceDocs/messagingService", server, ptrA(mir_urlEncode(endpointID))) { Headers << CHAR_VALUE("Accept", "application/json, text/javascript") @@ -16,9 +16,10 @@ public: << CHAR_VALUE("Referer", "https://web.skype.com/main") << CHAR_VALUE("Origin", "https://web.skype.com") << CHAR_VALUE("Connection", "keep-alive"); - + CMStringA data; + data.AppendFormat ("{\"id\":\"messagingService\",\"type\":\"EndpointPresenceDoc\",\"selfLink\":\"uri\",\"privateInfo\":{\"epname\":\"Miranda\"},\"publicInfo\":{\"capabilities\":\"\",\"typ\":125,\"skypeNameVersion\":\"0/%s//\",\"nodeInfo\":\"xx\",\"version\":\"0/%s\"}}", MIRANDA_VERSION_STRING, MIRANDA_VERSION_STRING); Body << - VALUE("{\"id\":\"messagingService\",\"type\":\"EndpointPresenceDoc\",\"selfLink\":\"uri\",\"privateInfo\":{\"epname\":\"Miranda\"},\"publicInfo\":{\"capabilities\":\"\",\"type\":1,\"skypeNameVersion\":\"0/0.95.4//\",\"nodeInfo\":\"xx\",\"version\":\"0/0.95.4\"}}"); + VALUE(data); } }; #endif //_SKYPE_REQUEST_ENDPOINT_H_ \ No newline at end of file diff --git a/protocols/SkypeWeb/src/requests/messages.h b/protocols/SkypeWeb/src/requests/messages.h index e86f54fce9..ecd939bbd0 100644 --- a/protocols/SkypeWeb/src/requests/messages.h +++ b/protocols/SkypeWeb/src/requests/messages.h @@ -4,8 +4,8 @@ class SendMsgRequest : public HttpRequest { public: - SendMsgRequest(const char *regToken, const char *username, const char *message) : - HttpRequest(REQUEST_POST, FORMAT, "client-s.gateway.messenger.live.com/v1/users/ME/conversations/8:%s/messages", username) + SendMsgRequest(const char *regToken, const char *username, const char *message, const char *server = "client-s.gateway.messenger.live.com") : + HttpRequest(REQUEST_POST, FORMAT, "%s/v1/users/ME/conversations/8:%s/messages", server, username) { Headers << CHAR_VALUE("Accept", "application / json, text / javascript") @@ -21,4 +21,29 @@ public: } }; +class SendTypingRequest : public HttpRequest +{ +public: + SendTypingRequest(const char *regToken, const char *username,bool bstate, const char *server = "client-s.gateway.messenger.live.com") : + HttpRequest(REQUEST_POST, FORMAT, "%s/v1/users/ME/conversations/8:%s/messages", server, mir_urlEncode(username)) + { + Headers + << CHAR_VALUE("Accept", "application / json, text / javascript") + << CHAR_VALUE("Expires", "0") + << FORMAT_VALUE("RegistrationToken", "registrationToken=%s", regToken) + << CHAR_VALUE("Content-Type", "application/json; charset = UTF-8") + << CHAR_VALUE("BehaviorOverride", "redirectAs404") + << CHAR_VALUE("Referer", "https://web.skype.com/main") + << CHAR_VALUE("Origin", "https://web.skype.com") + << CHAR_VALUE("Connection", "keep-alive"); + CMStringA state; + if (bstate) state = "Control/Typing"; + else state = "Control/ClearTyping"; + CMStringA data; + data.AppendFormat("{\"clienmessageid\":%d, \"content\":\"\", \"messagetype\":\"%s\", \"contenttype\":\"text\"}", time(NULL), state); + + Body << VALUE(data); + } +}; + #endif //_SKYPE_REQUEST_MESSAGES_H_ diff --git a/protocols/SkypeWeb/src/requests/poll.h b/protocols/SkypeWeb/src/requests/poll.h index 48108ccdbc..538e482eac 100644 --- a/protocols/SkypeWeb/src/requests/poll.h +++ b/protocols/SkypeWeb/src/requests/poll.h @@ -4,8 +4,8 @@ class PollRequest : public HttpRequest { public: - PollRequest(const char *regToken) : - HttpRequest(REQUEST_POST, "client-s.gateway.messenger.live.com/v1/users/ME/endpoints/SELF/subscriptions/0/poll") + PollRequest(const char *regToken, const char *server = "client-s.gateway.messenger.live.com") : + HttpRequest(REQUEST_POST, FORMAT, "%s/v1/users/ME/endpoints/SELF/subscriptions/0/poll", server) { //timeout = 30 * 1000; //flags |= NLHRF_PERSISTENT; diff --git a/protocols/SkypeWeb/src/requests/reg_info.h b/protocols/SkypeWeb/src/requests/reg_info.h index 47f649ec61..d1f5191fc9 100644 --- a/protocols/SkypeWeb/src/requests/reg_info.h +++ b/protocols/SkypeWeb/src/requests/reg_info.h @@ -4,8 +4,8 @@ class GetRegInfoRequest : public HttpRequest { public: - GetRegInfoRequest(const char *token) : - HttpRequest(REQUEST_POST, "client-s.gateway.messenger.live.com/v1/users/ME/endpoints") + GetRegInfoRequest(const char *token, const char *server = "client-s.gateway.messenger.live.com") : + HttpRequest(REQUEST_POST, FORMAT, "%s/v1/users/ME/endpoints", server) { Headers << CHAR_VALUE("Accept", "application/json, text/javascript") diff --git a/protocols/SkypeWeb/src/requests/status.h b/protocols/SkypeWeb/src/requests/status.h index 1fc30bac81..a8bbdc82f0 100644 --- a/protocols/SkypeWeb/src/requests/status.h +++ b/protocols/SkypeWeb/src/requests/status.h @@ -4,10 +4,12 @@ class SetStatusRequest : public HttpRequest { public: - SetStatusRequest(const char *regToken, const char *status) : - HttpRequest(REQUEST_PUT, "client-s.gateway.messenger.live.com/v1/users/ME/presenceDocs/messagingService") + SetStatusRequest(const char *regToken, const char *status, const char *server = "client-s.gateway.messenger.live.com") : + HttpRequest(REQUEST_PUT, FORMAT, "%s/v1/users/ME/presenceDocs/messagingService", server) { CMStringA auth = "registrationToken="; + CMStringA statuss; + statuss.AppendFormat("{\"status\":\"%s\"}", status); auth += regToken; Headers << CHAR_VALUE("Accept", "application/json, text/javascript") @@ -19,7 +21,7 @@ public: << CHAR_VALUE("Origin", "https://web.skype.com") << CHAR_VALUE("Connection", "keep-alive"); - Body << FORMAT_VALUE("{\"status\":\"%s\"}", status); + Body << VALUE(statuss); } }; diff --git a/protocols/SkypeWeb/src/requests/subscriptions.h b/protocols/SkypeWeb/src/requests/subscriptions.h index 624c7685a4..cd29aa8da4 100644 --- a/protocols/SkypeWeb/src/requests/subscriptions.h +++ b/protocols/SkypeWeb/src/requests/subscriptions.h @@ -4,8 +4,8 @@ class SubscriptionsRequest : public HttpRequest { public: - SubscriptionsRequest(const char *regToken) : - HttpRequest(REQUEST_POST, "client-s.gateway.messenger.live.com/v1/users/ME/endpoints/SELF/subscriptions") + SubscriptionsRequest(const char *regToken, const char *server = "client-s.gateway.messenger.live.com") : + HttpRequest(REQUEST_POST, FORMAT, "%s/v1/users/ME/endpoints/SELF/subscriptions", server) { Headers << CHAR_VALUE("Accept", "application/json, text/javascript") diff --git a/protocols/SkypeWeb/src/skype_contacts.cpp b/protocols/SkypeWeb/src/skype_contacts.cpp index c8a889d316..98563bcda5 100644 --- a/protocols/SkypeWeb/src/skype_contacts.cpp +++ b/protocols/SkypeWeb/src/skype_contacts.cpp @@ -11,6 +11,8 @@ void CSkypeProto::SetContactStatus(MCONTACT hContact, WORD status) if (oldStatus != status) { setWord(hContact, "Status", status); + if (status == ID_STATUS_OFFLINE) + db_unset(hContact, m_szModuleName, "MirVer"); } } diff --git a/protocols/SkypeWeb/src/skype_events.cpp b/protocols/SkypeWeb/src/skype_events.cpp index 35f3746713..945770255a 100644 --- a/protocols/SkypeWeb/src/skype_events.cpp +++ b/protocols/SkypeWeb/src/skype_events.cpp @@ -89,7 +89,7 @@ void CSkypeProto::OnLoginSecond(const NETLIBHTTPREQUEST *response) cookies[match[1]] = match[2]; } - PushRequest(new GetRegInfoRequest(token.c_str()), &CSkypeProto::OnGetRegInfo); + PushRequest(new GetRegInfoRequest(token.c_str(), getStringA("Server")), &CSkypeProto::OnGetRegInfo); PushRequest(new GetProfileRequest(token.c_str()), &CSkypeProto::LoadProfile); PushRequest(new GetContactListRequest(token.c_str()), &CSkypeProto::LoadContactList); } @@ -103,33 +103,56 @@ void CSkypeProto::OnGetRegInfo(const NETLIBHTTPREQUEST *response) std::smatch match; std::string content = response->pData; for (int i = 0; i < response->headersCount; i++) { - if (_stricmp(response->headers[i].szName, "Set-RegistrationToken")) - continue; - - CMStringA szValue = response->headers[i].szValue, szCookieName, szCookieVal; - int iStart = 0; - while (true) { - bool bFirstToken = (iStart == 0); - CMStringA szToken = szValue.Tokenize(";", iStart).Trim(); - if (iStart == -1) - break; - int iStart2 = 0; - szCookieName = szToken.Tokenize("=", iStart2); - szCookieVal = szToken.Mid(iStart2); - setString(szCookieName, szCookieVal); + if (!mir_strcmpi(response->headers[i].szName, "Set-RegistrationToken")) + { + CMStringA szValue = response->headers[i].szValue, szCookieName, szCookieVal; + int iStart = 0; + while (true) { + bool bFirstToken = (iStart == 0); + CMStringA szToken = szValue.Tokenize(";", iStart).Trim(); + if (iStart == -1) + break; + int iStart2 = 0; + szCookieName = szToken.Tokenize("=", iStart2); + szCookieVal = szToken.Mid(iStart2); + setString(szCookieName, szCookieVal); + } + } + else if (!mir_strcmpi(response->headers[i].szName, "Location")) + { + CMStringA szValue = response->headers[i].szValue, szCookieName, szCookieVal; + setString("Server", GetServerFromUrl(szValue)); } - } - PushRequest(new GetEndpointRequest(getStringA("registrationToken"), getStringA("endpointId"))); - SubscriptionsRequest *request = new SubscriptionsRequest(getStringA("registrationToken")); - request->Send(m_hNetlibUser); - delete request; + } + if (response->resultCode != 201) + { + PushRequest(new GetRegInfoRequest(getStringA("Token"), getStringA("Server")), &CSkypeProto::OnGetRegInfo); + return; + } + PushRequest(new GetEndpointRequest(getStringA("registrationToken"), getStringA("endpointId"), getStringA("Server")), &CSkypeProto::OnGetEndpoint); + isTerminated = false; m_hPollingThread = ForkThreadEx(&CSkypeProto::PollingThread, 0, NULL); m_iStatus = m_iDesiredStatus; ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)ID_STATUS_CONNECTING, m_iStatus); - PushRequest(new SetStatusRequest(ptrA(getStringA("registrationToken")), MirandaToSkypeStatus(m_iStatus)), &CSkypeProto::OnSetStatus); + PushRequest(new SetStatusRequest(ptrA(getStringA("registrationToken")), MirandaToSkypeStatus(m_iStatus), getStringA("Server")), &CSkypeProto::OnSetStatus); +} + +void CSkypeProto::OnGetEndpoint(const NETLIBHTTPREQUEST *response) +{ + if (response == NULL) + return; + + JSONROOT root(response->pData); + + if (root == NULL) + return; + + ptrA selfLink(mir_t2a(ptrT(json_as_string(json_get(root, "selfLink"))))); + + setString("SelfEndpointName", SelfUrlToName(selfLink)); } void CSkypeProto::OnSetStatus(const NETLIBHTTPREQUEST *response) @@ -143,21 +166,9 @@ void CSkypeProto::OnSetStatus(const NETLIBHTTPREQUEST *response) return; JSONNODE *status_json = json_get(root, "status"); - TCHAR *status = json_as_string(status_json); + ptrA status(mir_t2a(ptrT(json_as_string(status_json)))); int old_status = m_iStatus; - int iNewStatus; - if (!mir_tstrcmpi(status, _T("Online"))) - iNewStatus = ID_STATUS_ONLINE; - else if (!mir_tstrcmpi(status, _T("Hidden"))) - iNewStatus = ID_STATUS_INVISIBLE; - else if (!mir_tstrcmpi(status, _T("Away"))) - iNewStatus = ID_STATUS_AWAY; - else if (!mir_tstrcmpi(status, _T("Idle"))) - iNewStatus = ID_STATUS_IDLE; - else if (!mir_tstrcmpi(status, _T("Busy"))) - iNewStatus = ID_STATUS_DND; - else - iNewStatus = ID_STATUS_OFFLINE; + int iNewStatus = SkypeToMirandaStatus(status); m_iStatus = iNewStatus; if (iNewStatus == ID_STATUS_OFFLINE) diff --git a/protocols/SkypeWeb/src/skype_poll_processing.cpp b/protocols/SkypeWeb/src/skype_poll_processing.cpp index 4bf8b3e689..d357c5b5ee 100644 --- a/protocols/SkypeWeb/src/skype_poll_processing.cpp +++ b/protocols/SkypeWeb/src/skype_poll_processing.cpp @@ -1,12 +1,92 @@ #include "common.h" +void CSkypeProto::ProcessEndpointPresenceRes(JSONNODE *node) +{ + debugLogA("CSkypeProto::ProcessEndpointPresenceRes"); + ptrA selfLink(mir_t2a(ptrT(json_as_string(json_get(node, "selfLink"))))); + char *skypename = ContactUrlToName(selfLink); + if (skypename == NULL) + return; + MCONTACT hContact = GetContact(skypename); + + //"publicInfo":{"capabilities":"","typ":"11","skypeNameVersion":"0/7.1.0.105//","nodeInfo":"","version":"24"} + JSONNODE *publicInfo = json_get(node, "publicInfo"); + if (publicInfo != NULL) + { + ptrA version(mir_t2a(ptrT(json_as_string(json_get(publicInfo, "skypeNameVersion"))))); + ptrA typ(mir_t2a(ptrT(json_as_string(json_get(publicInfo, "typ"))))); + if (typ != NULL) + { + if (!mir_strcmpi(typ, "17")) //Android + db_set_s(hContact, m_szModuleName, "MirVer", "Skype (Android)"); + else if (!mir_strcmpi(typ, "16")) //iOS + db_set_s(hContact, m_szModuleName, "MirVer", "Skype (iOS)"); + else if (!mir_strcmpi(typ, "12")) //WinRT/Metro + db_set_s(hContact, m_szModuleName, "MirVer", "Skype (WinRT)"); + else if (!mir_strcmpi(typ, "15")) //Winphone + db_set_s(hContact, m_szModuleName, "MirVer", "Skype (WP)"); + else if (!mir_strcmpi(typ, "13")) //OSX + db_set_s(hContact, m_szModuleName, "MirVer", "Skype (OSX)"); + else if (!mir_strcmpi(typ, "11")) //Windows + db_set_s(hContact, m_szModuleName, "MirVer", "Skype (Windows)"); + else if (!mir_strcmpi(typ, "14")) //Linux + db_set_s(hContact, m_szModuleName, "MirVer", "Skype (Linux)"); + else if (!mir_strcmpi(typ, "10"))//XBox ? skypeNameVersion 11/1.8.0.1006 + db_set_s(hContact, m_szModuleName, "MirVer", "Skype (XBOX)"); + else if (!mir_strcmpi(typ, "1")) //SkypeWeb + db_set_s(hContact, m_szModuleName, "MirVer", "Skype (Web)"); + else if (!mir_strcmpi(typ, "125")) //Miranda + db_set_s(hContact, m_szModuleName, "MirVer", "Miranda NG"); + + } + + } +} + void CSkypeProto::ProcessUserPresenceRes(JSONNODE *node) { debugLogA("CSkypeProto::ProcessUserPresenceRes"); + ptrA selfLink(mir_t2a(ptrT(json_as_string(json_get(node, "selfLink"))))); ptrA status(mir_t2a(ptrT(json_as_string(json_get(node, "status"))))); - char *skypename = ContactUrlToName(selfLink); + if (skypename == NULL) + { + if (IsMe(SelfUrlToName(selfLink))) + { + int iNewStatus = SkypeToMirandaStatus(status); + int old_status = m_iStatus; + m_iDesiredStatus = iNewStatus; + m_iStatus = iNewStatus; + if (old_status != iNewStatus) + ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)old_status, iNewStatus); + return; + } + return; + } MCONTACT hContact = GetContact(skypename); - SetContactStatus(hContact, ID_STATUS_ONLINE); + SetContactStatus(hContact, SkypeToMirandaStatus(status)); +} + +void CSkypeProto::ProcessNewMessageRes(JSONNODE *node) +{ + ptrA clientMsgId(mir_t2a(ptrT(json_as_string(json_get(node, "clientmessageid"))))); + ptrA skypeeditedid(mir_t2a(ptrT(json_as_string(json_get(node, "skypeeditedid"))))); + ptrA messagetype(mir_t2a(ptrT(json_as_string(json_get(node, "messagetype"))))); + ptrA from(mir_t2a(ptrT(json_as_string(json_get(node, "from"))))); + ptrA content(mir_t2a(ptrT(json_as_string(json_get(node, "content"))))); + //ptrA composeTime(mir_t2a(ptrT(json_as_string(json_get(node, "composetime"))))); + TCHAR *composeTime = json_as_string (json_get(node, "composetime")); + ptrA conversationLink(mir_t2a(ptrT(json_as_string(json_get(node, "conversationLink"))))); + time_t timeStamp = IsoToUnixTime(composeTime);//time(NULL); // it should be rewritten + + PROTORECVEVENT recv = { 0 }; + recv.flags = PREF_UTF; + recv.timestamp = timeStamp; + recv.szMessage = content; + debugLogA("Incoming message from %s", ContactUrlToName(from)); + if(IsMe(ContactUrlToName(from))) + return; //it should be rewritten + MCONTACT hContact = GetContact(ContactUrlToName(from)); + OnReceiveMessage(hContact, &recv); } \ No newline at end of file diff --git a/protocols/SkypeWeb/src/skype_polling.cpp b/protocols/SkypeWeb/src/skype_polling.cpp index 8dc73280a7..aed47be086 100644 --- a/protocols/SkypeWeb/src/skype_polling.cpp +++ b/protocols/SkypeWeb/src/skype_polling.cpp @@ -20,7 +20,7 @@ void CSkypeProto::ParsePollData(JSONNODE *data) if (!mir_tstrcmpi(resourceType, L"NewMessage")) { - continue; + ProcessNewMessageRes(resource); } else if (!mir_tstrcmpi(resourceType, L"UserPresence")) { @@ -28,7 +28,7 @@ void CSkypeProto::ParsePollData(JSONNODE *data) } else if (!mir_tstrcmpi(resourceType, L"EndpointPresence")) { - continue; + ProcessEndpointPresenceRes(resource); } else if (!mir_tstrcmpi(resourceType, L"ConversationUpdate")) { @@ -40,8 +40,7 @@ void CSkypeProto::ParsePollData(JSONNODE *data) } } - } - + } } void CSkypeProto::PollingThread(void*) @@ -49,18 +48,29 @@ void CSkypeProto::PollingThread(void*) debugLog(_T("CSkypeProto::PollingThread: entering")); ptrA regToken(getStringA("registrationToken")); + const char *server = getStringA("Server"); + + SubscriptionsRequest *request = new SubscriptionsRequest(regToken, server); + request->Send(m_hNetlibUser); + delete request; int errors = 0; bool breaked = false; while (!isTerminated && !breaked && errors < POLLING_ERRORS_LIMIT) { - PollRequest *request = new PollRequest(regToken); + PollRequest *request = new PollRequest(regToken, server); NETLIBHTTPREQUEST *response = request->Send(m_hNetlibUser); delete request; if (response != NULL) { + m_pollingConnection = response->nlc; JSONROOT root(response->pData); + if (json_get(root, "errorCode") != NULL) + { + errors++; + continue; + } ParsePollData (root); } /*if (response->resultCode != 200) @@ -72,6 +82,7 @@ void CSkypeProto::PollingThread(void*) errors = 0;*/ } m_hPollingThread = NULL; + m_pollingConnection = NULL; debugLog(_T("CSkypeProto::PollingThread: leaving")); if (!isTerminated) diff --git a/protocols/SkypeWeb/src/skype_proto.cpp b/protocols/SkypeWeb/src/skype_proto.cpp index 6f0905c785..88a9241d0f 100644 --- a/protocols/SkypeWeb/src/skype_proto.cpp +++ b/protocols/SkypeWeb/src/skype_proto.cpp @@ -31,13 +31,13 @@ DWORD_PTR CSkypeProto::GetCaps(int type, MCONTACT) switch (type) { case PFLAGNUM_1: - return PF1_AUTHREQ; + return PF1_IM | PF1_AUTHREQ; case PFLAGNUM_2: return PF2_ONLINE | PF2_INVISIBLE | PF2_SHORTAWAY | PF2_HEAVYDND; case PFLAGNUM_3: return PF2_ONLINE | PF2_INVISIBLE | PF2_SHORTAWAY | PF2_HEAVYDND; case PFLAGNUM_4: - return PF4_FORCEADDED | PF4_NOAUTHDENYREASON; + return PF4_FORCEADDED | PF4_NOAUTHDENYREASON | PF4_SUPPORTTYPING; case PFLAG_UNIQUEIDTEXT: return (INT_PTR)"Skypename"; case PFLAG_UNIQUEIDSETTING: @@ -137,6 +137,9 @@ int CSkypeProto::SetStatus(int iNewStatus) if (iNewStatus == ID_STATUS_OFFLINE) { // logout + isTerminated = true; + //if (m_pollingConnection) + // CallService(MS_NETLIB_SHUTDOWN, (WPARAM)m_pollingConnection, 0); PushRequest(new LogoutRequest()); requestQueue->Stop(); @@ -156,6 +159,8 @@ int CSkypeProto::SetStatus(int iNewStatus) else if (old_status == ID_STATUS_OFFLINE && m_iStatus == ID_STATUS_OFFLINE) { // login + if (getStringA("Server") == NULL) + setString("Server", "client-s.gateway.messenger.live.com"); m_iStatus = ID_STATUS_CONNECTING; requestQueue->Start(); @@ -165,11 +170,8 @@ int CSkypeProto::SetStatus(int iNewStatus) { // set status m_iStatus = iNewStatus; - // it should be rewritten - //GetEndpointRequest *request = new GetEndpointRequest(getStringA("registrationToken"), getStringA("endpointId")); - //request->Send(m_hNetlibUser); - //delete request; - PushRequest(new SetStatusRequest(ptrA(getStringA("registrationToken")), MirandaToSkypeStatus(m_iStatus)), &CSkypeProto::OnSetStatus); + PushRequest(new SetStatusRequest(ptrA(getStringA("registrationToken")), MirandaToSkypeStatus(m_iStatus), getStringA("Server")), &CSkypeProto::OnSetStatus); + PushRequest(new GetEndpointRequest(getStringA("registrationToken"), getStringA("endpointId"), getStringA("Server"))); } } @@ -183,7 +185,18 @@ int CSkypeProto::RecvAwayMsg(MCONTACT, int, PROTORECVEVENT*) { return 0; } int CSkypeProto::SetAwayMsg(int, const PROTOCHAR *msg) { return 0; } -int CSkypeProto::UserIsTyping(MCONTACT hContact, int type) { return 0; } +int CSkypeProto::UserIsTyping(MCONTACT hContact, int type) +{ + switch (type) { + case PROTOTYPE_SELFTYPING_OFF: + PushRequest(new SendTypingRequest(getStringA("registrationToken"), db_get_sa(hContact, m_szModuleName, "Skypename"), false, getStringA("Server"))); + break; + case PROTOTYPE_SELFTYPING_ON: + PushRequest(new SendTypingRequest(getStringA("registrationToken"), db_get_sa(hContact, m_szModuleName, "Skypename"), true, getStringA("Server"))); + break; + } + return 0; +} int CSkypeProto::OnEvent(PROTOEVENTTYPE iEventType, WPARAM wParam, LPARAM lParam) { diff --git a/protocols/SkypeWeb/src/skype_proto.h b/protocols/SkypeWeb/src/skype_proto.h index f312fc38e5..5d86f4ce92 100644 --- a/protocols/SkypeWeb/src/skype_proto.h +++ b/protocols/SkypeWeb/src/skype_proto.h @@ -125,7 +125,7 @@ private: void OnLoginSecond(const NETLIBHTTPREQUEST *response); void OnGetRegInfo(const NETLIBHTTPREQUEST *response); void OnSetStatus(const NETLIBHTTPREQUEST *response); - + void OnGetEndpoint(const NETLIBHTTPREQUEST *response); // profile void UpdateProfileFirstName(JSONNODE *root, MCONTACT hContact = NULL); void UpdateProfileLastName(JSONNODE *root, MCONTACT hContact = NULL); @@ -174,15 +174,22 @@ private: //polling void __cdecl ParsePollData(JSONNODE *data); void __cdecl PollingThread(void*); + void CSkypeProto::ProcessEndpointPresenceRes(JSONNODE *node); void CSkypeProto::ProcessUserPresenceRes(JSONNODE *node); + void CSkypeProto::ProcessNewMessageRes(JSONNODE *node); // utils + time_t __stdcall IsoToUnixTime(const TCHAR *stamp); + char *GetStringChunk(const char *haystack, size_t len, const char *start, const char *end); + bool IsMe(const char *skypeName); + int SkypeToMirandaStatus(const char *status); char *MirandaToSkypeStatus(int status); static void ShowNotification(const TCHAR *message, int flags = 0, MCONTACT hContact = NULL); static void ShowNotification(const TCHAR *caption, const TCHAR *message, int flags = 0, MCONTACT hContact = NULL); void SetServerStatus(int iNewStatus); static bool IsFileExists(std::tstring path); char *ContactUrlToName(const char *url); - + char *SelfUrlToName(const char *url); + char *GetServerFromUrl(const char *url); template static INT_PTR __cdecl GlobalService(WPARAM wParam, LPARAM lParam) { diff --git a/protocols/SkypeWeb/src/skype_utils.cpp b/protocols/SkypeWeb/src/skype_utils.cpp index 0e32b56723..a85f9c9eec 100644 --- a/protocols/SkypeWeb/src/skype_utils.cpp +++ b/protocols/SkypeWeb/src/skype_utils.cpp @@ -1,5 +1,67 @@ #include "common.h" +time_t __stdcall CSkypeProto::IsoToUnixTime(const TCHAR *stamp) +{ + TCHAR date[9]; + int i, y; + + if (stamp == NULL) + return 0; + + const TCHAR *p = stamp; + + // Get the date part + for (i = 0; *p != '\0' && i < 8 && isdigit(*p); p++, i++) + date[i] = *p; + + // Parse year + if (i == 6) { + // 2-digit year (1970-2069) + y = (date[0] - '0') * 10 + (date[1] - '0'); + if (y < 70) y += 100; + } + else if (i == 8) { + // 4-digit year + y = (date[0] - '0') * 1000 + (date[1] - '0') * 100 + (date[2] - '0') * 10 + date[3] - '0'; + y -= 1900; + } + else return 0; + + struct tm timestamp; + timestamp.tm_year = y; + + // Parse month + timestamp.tm_mon = (date[i - 4] - '0') * 10 + date[i - 3] - '0' - 1; + + // Parse date + timestamp.tm_mday = (date[i - 2] - '0') * 10 + date[i - 1] - '0'; + + // Skip any date/time delimiter + for (; *p != '\0' && !isdigit(*p); p++); + + // Parse time + if (_stscanf(p, _T("%d:%d:%d"), ×tamp.tm_hour, ×tamp.tm_min, ×tamp.tm_sec) != 3) + return (time_t)0; + + timestamp.tm_isdst = 0; // DST is already present in _timezone below + time_t t = mktime(×tamp); + + _tzset(); + t -= _timezone; + return (t >= 0) ? t : 0; +} + + +bool CSkypeProto::IsMe(const char *skypeName) +{ + ptrA mySkypeName(getStringA("Skypename")); + ptrA SelfEndpointName(getStringA("SelfEndpointName")); + if (!lstrcmpA(skypeName, mySkypeName) || !lstrcmpA(skypeName, SelfEndpointName)) + return true; + + return false; +} + char *CSkypeProto::MirandaToSkypeStatus(int status) { char *result = "Online"; @@ -20,6 +82,22 @@ char *CSkypeProto::MirandaToSkypeStatus(int status) return "Online"; } +int CSkypeProto::SkypeToMirandaStatus(const char *status) +{ + if (!mir_strcmpi(status, "Online")) + return ID_STATUS_ONLINE; + else if (!mir_strcmpi(status, "Hidden")) + return ID_STATUS_INVISIBLE; + else if (!mir_strcmpi(status, "Away")) + return ID_STATUS_AWAY; + else if (!mir_strcmpi(status, "Idle")) + return /*ID_STATUS_IDLE*/ID_STATUS_AWAY; + else if (!mir_strcmpi(status, "Busy")) + return ID_STATUS_DND; + else + return ID_STATUS_OFFLINE; +} + void CSkypeProto::ShowNotification(const TCHAR *caption, const TCHAR *message, int flags, MCONTACT hContact) { if (Miranda_Terminated()) @@ -79,3 +157,45 @@ char *CSkypeProto::ContactUrlToName(const char *url) return tempname; } + +char *CSkypeProto::SelfUrlToName(const char *url) +{ + char *tempname = NULL; + const char *start, *end; + start = strstr(url, "/1:"); + + if (!start) + return NULL; + start = start + 3; + if ((end = strchr(start, '/'))) + { + mir_free(tempname); + tempname = mir_strndup(start, end - start); + return tempname; + } + mir_free(tempname); + tempname = mir_strdup(start); + + return tempname; +} + +char *CSkypeProto::GetServerFromUrl(const char *url) +{ + char *tempname = NULL; + const char *start, *end; + start = strstr(url, "://"); + + if (!start) + return NULL; + start = start + 3; + if ((end = strchr(start, '/'))) + { + mir_free(tempname); + tempname = mir_strndup(start, end - start); + return tempname; + } + mir_free(tempname); + tempname = mir_strdup(start); + + return tempname; +} \ No newline at end of file -- cgit v1.2.3