summaryrefslogtreecommitdiff
path: root/protocols/MSN/src
diff options
context:
space:
mode:
authorPiotr Piastucki <leech.miranda@gmail.com>2015-08-10 00:23:39 +0000
committerPiotr Piastucki <leech.miranda@gmail.com>2015-08-10 00:23:39 +0000
commit623da26184c4e642d5a2bcee09091ff412aea7d4 (patch)
tree12201e53cc9f7f209235e1938c2ee16d595de2dd /protocols/MSN/src
parent6272fc3926670e181b9d6a4015d62ca2573fc321 (diff)
Added embedded Internet Explorer Window for MSN 2-factor authentication or other login issues where manual user intervention is necessary.
git-svn-id: http://svn.miranda-ng.org/main/trunk@14890 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'protocols/MSN/src')
-rw-r--r--protocols/MSN/src/msn_auth.cpp437
-rw-r--r--protocols/MSN/src/msn_errors.cpp1
-rw-r--r--protocols/MSN/src/msn_ieembed.cpp365
-rw-r--r--protocols/MSN/src/msn_ieembed.h140
-rw-r--r--protocols/MSN/src/msn_proto.h3
-rw-r--r--protocols/MSN/src/stdafx.h6
6 files changed, 819 insertions, 133 deletions
diff --git a/protocols/MSN/src/msn_auth.cpp b/protocols/MSN/src/msn_auth.cpp
index ca0764fd11..0a7cff86bf 100644
--- a/protocols/MSN/src/msn_auth.cpp
+++ b/protocols/MSN/src/msn_auth.cpp
@@ -19,9 +19,21 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "stdafx.h"
+#include <WinInet.h>
#include "msn_proto.h"
+#include "msn_ieembed.h"
#include "des.h"
+#define LOGIN_POST_PARAMS "client_id=00000000480BC46C&scope=service%3A%3Askype.com%3A%3AMBI_SSL&response_type=token&redirect_uri=https%3A%2F%2Flogin.live.com%2Foauth20_desktop.srf"
+#define AUTH_URL "https://login.live.com/oauth20_authorize.srf?"LOGIN_POST_PARAMS
+#define POST_URL "https://login.live.com/ppsecure/post.srf?"LOGIN_POST_PARAMS
+
+
+/* WinINET delayloading */
+typedef BOOL (*pfnInternetGetCookieExA)(LPCSTR, LPCSTR, LPSTR, LPDWORD, DWORD, LPVOID);
+pfnInternetGetCookieExA fpInternetGetCookieExA = NULL;
+
+
/* SkyLogin Prototypes */
typedef void* SkyLogin;
typedef SkyLogin (*pfnSkyLogin_Init)();
@@ -717,6 +729,164 @@ void CMsnProto::SaveAuthTokensDB(void)
setString("authRefreshToken", authRefreshToken);
}
+typedef struct {
+ /* Input */
+ CMsnProto *pProto;
+ NETLIBHTTPREQUEST *nlhr;
+ NETLIBHTTPREQUEST *nlhrReply;
+ /* Output */
+ char *pszURL;
+ char *pszCookies;
+ /* Internal */
+ IEEmbed *pEmbed;
+} IEAUTH_PARAM;
+
+LRESULT CALLBACK AuthWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_SIZE:
+ {
+ IEAUTH_PARAM *pAuth = (IEAUTH_PARAM*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+ if (pAuth && pAuth->pEmbed) pAuth->pEmbed->ResizeBrowser();
+ return(0);
+ }
+
+ case WM_CREATE:
+ {
+ IEAUTH_PARAM *pAuth = (IEAUTH_PARAM*)((LPCREATESTRUCT)lParam)->lpCreateParams;
+ pAuth->pEmbed = new IEEmbed(hwnd);
+ WCHAR *pwszCookies = mir_a2u(pAuth->nlhr->headers[1].szValue);
+ SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pAuth);
+ pAuth->pEmbed->addCookie(pwszCookies);
+ pAuth->pEmbed->navigate(AUTH_URL);
+ mir_free(pwszCookies);
+ return(0);
+ }
+
+ case UM_DOCCOMPLETE:
+ {
+ if (!lParam) return 1;
+ IEAUTH_PARAM *pAuth = (IEAUTH_PARAM*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+
+ if (wcsstr((WCHAR*)lParam, L"oauth20_authorize")) {
+ char *pszDoc = pAuth->pEmbed->GetHTMLDoc();
+ CMStringA post;
+
+ if (pszDoc) {
+ if (pAuth->pProto->parseLoginPage(pszDoc, pAuth->nlhr, &post)) {
+ pAuth->pEmbed->navigate(pAuth->nlhr);
+ }
+ mir_free(pszDoc);
+ }
+ }
+ else if (wcsstr((WCHAR*)lParam, L"access_token=")) {
+ DWORD cbCookie = 0;
+
+ pAuth->pszURL = mir_u2a((WCHAR*)lParam);
+
+ /* get_cookie doesn't give us all the necessary cookies, therefore we need to use
+ * InternetGetCookieExA
+ */
+ if (!fpInternetGetCookieExA) {
+ HMODULE hMod = LoadLibrary(_T("wininet.dll"));
+ if (hMod) fpInternetGetCookieExA = (pfnInternetGetCookieExA)GetProcAddress(hMod, "InternetGetCookieExA");
+ }
+ if (fpInternetGetCookieExA &&
+ fpInternetGetCookieExA("https://login.live.com", NULL, NULL, &cbCookie, INTERNET_COOKIE_HTTPONLY, NULL) &&
+ (pAuth->pszCookies = (char*)mir_alloc(cbCookie))) {
+ fpInternetGetCookieExA("https://login.live.com", NULL, pAuth->pszCookies, &cbCookie, INTERNET_COOKIE_HTTPONLY, NULL);
+ }
+ else pAuth->pszCookies = mir_u2a(pAuth->pEmbed->getCookies());
+ PostMessage(hwnd, WM_CLOSE, 0, 0);
+ }
+ else if (wcsstr((WCHAR*)lParam, L"res=cancel")) {
+ PostMessage(hwnd, WM_CLOSE, 0, 0);
+ }
+ return(0);
+ }
+
+ case WM_CLOSE:
+ DestroyWindow(hwnd);
+ PostQuitMessage(0);
+ break;
+
+ case WM_DESTROY:
+ {
+ IEAUTH_PARAM *pAuth = (IEAUTH_PARAM*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+ if (pAuth && pAuth->pEmbed) delete pAuth->pEmbed;
+ return(0);
+ }
+
+ }
+
+ return(DefWindowProc(hwnd, uMsg, wParam, lParam));
+}
+
+
+void __cdecl CMsnProto::msn_IEAuthThread(void *pParam)
+{
+ HWND hWnd;
+ MSG msg;
+ WNDCLASSEX wc={0};
+ static const TCHAR *ClassName = _T("SkypeLoginWindow");
+
+ CoInitialize(NULL);
+
+ wc.cbSize = sizeof(WNDCLASSEX);
+ wc.cbWndExtra = sizeof(void*);
+ wc.hInstance = hInst;
+ wc.lpfnWndProc = AuthWindowProc;
+ wc.lpszClassName = ClassName;
+ RegisterClassEx(&wc);
+
+ if ((hWnd = CreateWindowEx(0, ClassName, _T("MSN Login"), WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT, CW_USEDEFAULT, 640, 480,
+ HWND_DESKTOP, NULL, hInst, pParam))) {
+ ShowWindow( hWnd, SW_SHOW );
+ UpdateWindow( hWnd );
+
+ while( GetMessage(&msg, NULL, 0, 0) )
+ {
+ TranslateMessage( &msg );
+ DispatchMessage( &msg );
+ }
+ }
+
+ UnregisterClass(ClassName, hInst);
+ CoUninitialize();
+}
+
+bool CMsnProto::parseLoginPage(char *pszHTML, NETLIBHTTPREQUEST *nlhr, CMStringA *post)
+{
+ char *pPPFT, *pEnd;
+
+ /* Get PPFT */
+ if ((pPPFT = strstr(pszHTML, "name=\"PPFT\"")) && (pPPFT = strstr(pPPFT, "value=\"")) && (pEnd=strchr(pPPFT+7, '"'))) {
+ *pEnd=0;
+ pPPFT+=7;
+
+ /* Get POST URL if available */
+ if ((nlhr->szUrl = strstr(pszHTML, "urlPost:'")) && (pEnd=strchr(nlhr->szUrl+9, '\''))) {
+ *pEnd=0;
+ nlhr->szUrl += 9;
+ } else nlhr->szUrl = POST_URL;
+
+ /* Create POST data */
+ char szPassword[100];
+ db_get_static(NULL, m_szModuleName, "Password", szPassword, sizeof(szPassword));
+ szPassword[16] = 0;
+ post->Format("PPFT=%s&login=%s&passwd=%s", ptrA(mir_urlEncode(pPPFT)),
+ ptrA(mir_urlEncode(MyOptions.szEmail)), ptrA(mir_urlEncode(szPassword)));
+
+ /* Do the login and get the required tokens */
+ nlhr->dataLength = post->GetLength();
+ nlhr->pData = (char*)post->GetString();
+ return true;
+ }
+ return false;
+}
+
// -1 - Error on login sequence
// 0 - Login failed (invalid username?)
// 1 - Login via Skype login server succeeded
@@ -724,12 +894,14 @@ void CMsnProto::SaveAuthTokensDB(void)
int CMsnProto::MSN_AuthOAuth(void)
{
int retVal = -1;
- const char *pszPostParams = "client_id=00000000480BC46C&scope=service%3A%3Askype.com%3A%3AMBI_SSL&response_type=token&redirect_uri=https%3A%2F%2Flogin.live.com%2Foauth20_desktop.srf";
+ bool bPassportAuth = true;
NETLIBHTTPREQUEST nlhr = { 0 };
NETLIBHTTPREQUEST *nlhrReply;
NETLIBHTTPHEADER headers[3];
time_t t;
+ if (bAskingForAuth) return 0;
+
// Load credentials from DB so that we don't have to do all this stuff if token isn't expired
if (!authTokenExpiretime) LoadAuthTokensDB();
@@ -747,9 +919,7 @@ int CMsnProto::MSN_AuthOAuth(void)
nlhr.headers[0].szValue = (char*)MSN_USER_AGENT;
// Get oauth20 login data
- CMStringA url;
- url.Format("https://login.live.com/oauth20_authorize.srf?%s", pszPostParams);
- nlhr.szUrl = (char*)(const char*)url;
+ nlhr.szUrl = AUTH_URL;
mHttpsTS = clock();
nlhrReply = (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)hNetlibUserHttps, (LPARAM)&nlhr);
mHttpsTS = clock();
@@ -758,35 +928,15 @@ int CMsnProto::MSN_AuthOAuth(void)
hHttpsConnection = nlhrReply->nlc;
if (nlhrReply->resultCode == 200 && nlhrReply->pData) {
- char *pPPFT, *pEnd;
-
- /* Get PPFT */
- if ((pPPFT = strstr(nlhrReply->pData, "name=\"PPFT\"")) && (pPPFT = strstr(pPPFT, "value=\"")) && (pEnd=strchr(pPPFT+7, '"'))) {
- *pEnd=0;
- pPPFT+=7;
-
- /* Get POST URL if available */
- if ((nlhr.szUrl = strstr(nlhrReply->pData, "urlPost:'")) && (pEnd=strchr(nlhr.szUrl+9, '\''))) {
- *pEnd=0;
- nlhr.szUrl += 9;
- } else {
- url.Format("https://login.live.com/ppsecure/post.srf?%s", pszPostParams);
- nlhr.szUrl = (char*)(const char*)url;
- }
+ CMStringA post;
+ /* Get POST-Data and URL */
+ if (parseLoginPage(nlhrReply->pData, &nlhr, &post)) {
/* Get Cookies */
nlhr.headers[1].szValue = (char*)alloca(CopyCookies(nlhrReply, NULL));
CopyCookies(nlhrReply, &nlhr.headers[1]);
if (*nlhr.headers[1].szValue) nlhr.headersCount++;
- /* Create POST data */
- CMStringA post;
- char szPassword[100];
- db_get_static(NULL, m_szModuleName, "Password", szPassword, sizeof(szPassword));
- szPassword[16] = 0;
- post.Format("PPFT=%s&login=%s&passwd=%s", ptrA(mir_urlEncode(pPPFT)),
- ptrA(mir_urlEncode(MyOptions.szEmail)), ptrA(mir_urlEncode(szPassword)));
-
/* Setup headers */
nlhr.headers[nlhr.headersCount].szName = "Content-Type";
nlhr.headers[nlhr.headersCount++].szValue = "application/x-www-form-urlencoded";
@@ -795,126 +945,159 @@ int CMsnProto::MSN_AuthOAuth(void)
nlhr.requestType = REQUEST_POST;
nlhr.flags &= (~NLHRF_REDIRECT);
mHttpsTS = clock();
- nlhr.dataLength = (int)mir_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;
mHttpsTS = clock();
- if (nlhrReply) {
- hHttpsConnection = nlhrReply->nlc;
-
- if (nlhrReply->resultCode == 302) {
- char *pAccessToken;
+ if (nlhrReply2) {
+ char *pszURL=NULL, *pAccessToken, *pEnd;
+ hHttpsConnection = nlhrReply2->nlc;
+ if (nlhrReply2->resultCode == 302) {
/* Extract access_token from Location can be found */
- for (int i = 0; i < nlhrReply->headersCount; i++) {
- if (!mir_strcmpi(nlhrReply->headers[i].szName, "Location") &&
- (pAccessToken = strstr(nlhrReply->headers[i].szValue, "access_token=")) &&
- (pEnd = strchr(pAccessToken + 13, '&'))) {
- char *pRefreshToken, *pExpires, szToken[1024];
- bool bLogin = false;
-
- *pEnd = 0;
- pAccessToken += 13;
- UrlDecode(pAccessToken);
- replaceStr(authAccessToken, pAccessToken);
-
- /* Extract refresh token */
- if ((pRefreshToken = strstr(pEnd + 1, "refresh_token=")) && (pEnd = strchr(pRefreshToken + 14, '&'))) {
- *pEnd = 0;
- pRefreshToken += 14;
- }
- replaceStr(authRefreshToken, pRefreshToken);
-
- /* Extract expire time */
- time(&authTokenExpiretime);
- if ((pExpires = strstr(pEnd + 1, "expires_in=")) && (pEnd = strchr(pExpires + 11, '&'))) {
- *pEnd = 0;
- pExpires += 11;
- authTokenExpiretime += atoi(pExpires);
- }
- else authTokenExpiretime += 86400;
+ for (int i = 0; i < nlhrReply2->headersCount; i++) {
+ if (!mir_strcmpi(nlhrReply2->headers[i].szName, "Location")) {
+ pszURL = nlhrReply2->headers[i].szValue;
+ break;
+ }
+ }
+ }
+ else {
+ /* There may be a problem with login, i.e. M$ security measures. Open up browser
+ * window in order to let user login there. May also be used for 2-factor auth */
+ if (nlhrReply2->resultCode == 200 && nlhrReply2->pData) {
+ UINT uThreadId;
+ IEAUTH_PARAM param = {this, &nlhr, nlhrReply2, NULL, NULL, NULL};
+
+ bAskingForAuth = true;
+ WaitForSingleObject(ForkThreadEx(&CMsnProto::msn_IEAuthThread, &param, &uThreadId), INFINITE);
+ pszURL = param.pszURL;
+ mir_free(authCookies);
+ authCookies = nlhr.headers[1].szValue = param.pszCookies;
+ CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)nlhrReply2);
+ nlhrReply2 = NULL;
+ bAskingForAuth = false;
+ bPassportAuth = false;
+ }
+ }
+ CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)nlhrReply);
+ nlhrReply = nlhrReply2;
+
+ if (pszURL &&
+ (pAccessToken = strstr(pszURL, "access_token=")) &&
+ (pEnd = strchr(pAccessToken + 13, '&'))) {
+ char *pRefreshToken, *pExpires, szToken[1024];
+ bool bLogin = false;
+
+ *pEnd = 0;
+ pAccessToken += 13;
+ UrlDecode(pAccessToken);
+ replaceStr(authAccessToken, pAccessToken);
+
+ /* Extract refresh token */
+ if ((pRefreshToken = strstr(pEnd + 1, "refresh_token=")) && (pEnd = strchr(pRefreshToken + 14, '&'))) {
+ *pEnd = 0;
+ pRefreshToken += 14;
+ }
+ replaceStr(authRefreshToken, pRefreshToken);
+
+ /* Extract expire time */
+ time(&authTokenExpiretime);
+ if ((pExpires = strstr(pEnd + 1, "expires_in=")) && (pEnd = strchr(pExpires + 11, '&'))) {
+ *pEnd = 0;
+ pExpires += 11;
+ authTokenExpiretime += atoi(pExpires);
+ }
+ else authTokenExpiretime += 86400;
- /* Copy auth Cookies to class for other web requests like contact list fetching to avoid ActiveSync */
- mir_free(authCookies);
- authCookies = nlhr.headers[1].szValue = (char*)mir_alloc(CopyCookies(nlhrReply, NULL));
- CopyCookies(nlhrReply, &nlhr.headers[1]);
+ /* Copy auth Cookies to class for other web requests like contact list fetching to avoid ActiveSync */
+ if (nlhrReply) {
+ mir_free(authCookies);
+ authCookies = nlhr.headers[1].szValue = (char*)mir_alloc(CopyCookies(nlhrReply, NULL));
+ CopyCookies(nlhrReply, &nlhr.headers[1]);
+ }
- int loginRet;
- /* Do Login via Skype login server, if not possible switch to SkypeWebExperience login */
- if ((loginRet = LoginSkypeOAuth(pRefreshToken)) < 1) {
- if (loginRet < 0) bLogin = true; else retVal = 0;
- }
- else {
- /* SkyLogin succeeded, request required tokens */
- if (RefreshOAuth(pRefreshToken, "service::ssl.live.com::MBI_SSL", szToken)) {
- replaceStr(authSSLToken, szToken);
+ int loginRet;
+ /* Do Login via Skype login server, if not possible switch to SkypeWebExperience login */
+ if ((loginRet = LoginSkypeOAuth(pRefreshToken)) < 1) {
+ if (loginRet < 0) bLogin = true; else retVal = 0;
+ }
+ else {
+ /* SkyLogin succeeded, request required tokens */
+ if (RefreshOAuth(pRefreshToken, "service::ssl.live.com::MBI_SSL", szToken)) {
+ replaceStr(authSSLToken, szToken);
+ replaceStr(authUser, MyOptions.szEmail);
+ authMethod = retVal = 1;
+ }
+ }
+ mir_free(authSkypeComToken); authSkypeComToken = NULL;
+ mir_free(authSkypeToken); authSkypeToken = NULL;
+
+
+ /* If you need Skypewebexperience login, as i.e. skylogin.dll is not available, we do this here */
+ if (bLogin) {
+ /* Prepare headers*/
+ nlhr.headers[2].szValue = "application/json";
+ nlhr.pData = "{\"trouterurl\":\"https://\",\"connectionid\":\"a\"}";
+ nlhr.dataLength = (int)mir_strlen(nlhr.pData);
+ nlhr.szUrl = "https://skypewebexperience.live.com/v1/User/Initialization";
+ nlhr.nlc = hHttpsConnection;
+
+ /* Request MappingContainer */
+ mHttpsTS = clock();
+ if (nlhrReply) CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)nlhrReply);
+ nlhrReply = (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)hNetlibUserHttps, (LPARAM)&nlhr);
+ mHttpsTS = clock();
+ if (nlhrReply) {
+ hHttpsConnection = nlhrReply->nlc;
+
+ if (nlhrReply->resultCode == 200 && nlhrReply->pData) {
+ /* Parse JSON stuff for MappingContainer */
+ char *pMappingContainer;
+
+ if ((pMappingContainer = strstr(nlhrReply->pData, "\"MappingContainer\":\"")) &&
+ (pEnd = strchr(pMappingContainer + 20, '"'))) {
+ *pEnd = 0;
+ pMappingContainer += 20;
+ UrlDecode(pMappingContainer);
+ replaceStr(authUIC, pMappingContainer);
replaceStr(authUser, MyOptions.szEmail);
- authMethod = retVal = 1;
- }
- }
- mir_free(authSkypeComToken); authSkypeComToken = NULL;
- mir_free(authSkypeToken); authSkypeToken = NULL;
-
-
- /* If you need Skypewebexperience login, as i.e. skylogin.dll is not available, we do this here */
- if (bLogin) {
- /* Prepare headers*/
- nlhr.headers[2].szValue = "application/json";
- nlhr.pData = "{\"trouterurl\":\"https://\",\"connectionid\":\"a\"}";
- nlhr.dataLength = (int)mir_strlen(nlhr.pData);
- nlhr.szUrl = "https://skypewebexperience.live.com/v1/User/Initialization";
- nlhr.nlc = hHttpsConnection;
-
- /* Request MappingContainer */
- mHttpsTS = clock();
- CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)nlhrReply);
- nlhrReply = (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)hNetlibUserHttps, (LPARAM)&nlhr);
- mHttpsTS = clock();
- if (nlhrReply) {
- hHttpsConnection = nlhrReply->nlc;
-
- if (nlhrReply->resultCode == 200 && nlhrReply->pData) {
- /* Parse JSON stuff for MappingContainer */
- char *pMappingContainer;
-
- if ((pMappingContainer = strstr(nlhrReply->pData, "\"MappingContainer\":\"")) &&
- (pEnd = strchr(pMappingContainer + 20, '"'))) {
- *pEnd = 0;
- pMappingContainer += 20;
- UrlDecode(pMappingContainer);
- replaceStr(authUIC, pMappingContainer);
- replaceStr(authUser, MyOptions.szEmail);
- authMethod = retVal = 2;
- }
- else retVal = 0;
- }
- else retVal = 0;
+ authMethod = retVal = 2;
}
- else hHttpsConnection = NULL;
+ else retVal = 0;
}
+ else retVal = 0;
}
+ else hHttpsConnection = NULL;
}
}
- else {
- /* There may be a problem with login, i.e. M$ security measures. Open up browser
- * window with same URL in order to let user correct this */
- if (nlhrReply->resultCode == 200 && nlhrReply->pData) {
- url.Format("https://login.live.com/oauth20_authorize.srf?%s", pszPostParams);
- MSN_ShowPopup(TranslateT("MSN Protocol"),TranslateT(MSN_LOGIN_OAUTH),MSN_ALLOW_MSGBOX,url);
- }
- hHttpsConnection = NULL;
- }
}
+ else hHttpsConnection = NULL;
}
}
if (nlhrReply) CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)nlhrReply);
} else hHttpsConnection = NULL;
if (retVal<=0) authTokenExpiretime=0; else {
- MSN_GetPassportAuth();
+ if (bPassportAuth) {
+ // Fast authentication with just 1 SOAP call supported :)
+ MSN_GetPassportAuth();
+ } else {
+ // Slow authentication required by fetching multiple tokens, i.e. 2-factor auth :(
+ char szToken[1024];
+
+ if (authMethod == 2 && RefreshOAuth(authRefreshToken, "service::chatservice.live.com::MBI_SSL", szToken+2)) {
+ memcpy (szToken, "t=", 2);
+ replaceStr(authStrToken, szToken);
+ }
+ if (RefreshOAuth(authRefreshToken, "service::contacts.msn.com::MBI_SSL", szToken)) {
+ replaceStr(authContactToken, szToken);
+ setString("authContactToken", authContactToken);
+ }
+ if (RefreshOAuth(authRefreshToken, "service::storage.msn.com::MBI_SSL", szToken)) {
+ replaceStr(authStorageToken, szToken);
+ setString("authStorageToken", authStorageToken);
+ }
+ }
SaveAuthTokensDB();
}
return retVal;
diff --git a/protocols/MSN/src/msn_errors.cpp b/protocols/MSN/src/msn_errors.cpp
index 64a79fb45a..2f1e321c0f 100644
--- a/protocols/MSN/src/msn_errors.cpp
+++ b/protocols/MSN/src/msn_errors.cpp
@@ -71,6 +71,7 @@ int CMsnProto::MSN_HandleErrors(ThreadData* info, char* cmdString)
case ERR_SERVER_BUSY:
case ERR_SERVER_UNAVAILABLE:
+ case ERR_TIMEDOUT:
MSN_ShowError("MSN Services are too busy, please try to connect later");
ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGINERR_NOSERVER);
return 1;
diff --git a/protocols/MSN/src/msn_ieembed.cpp b/protocols/MSN/src/msn_ieembed.cpp
new file mode 100644
index 0000000000..ef9ce64285
--- /dev/null
+++ b/protocols/MSN/src/msn_ieembed.cpp
@@ -0,0 +1,365 @@
+/*
+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 <http://www.gnu.org/licenses/>.
+*/
+
+#include "stdafx.h"
+#include <exdispid.h>
+#include "msn_proto.h"
+#include "msn_ieembed.h"
+
+IEEmbedSink::IEEmbedSink(IEEmbed *smptr)
+{
+ ieWindow = smptr;
+}
+
+IEEmbedSink::~IEEmbedSink() {}
+
+STDMETHODIMP IEEmbedSink::QueryInterface(REFIID riid, PVOID *ppv)
+{
+ *ppv = NULL;
+ if (IID_IUnknown == riid)
+ *ppv = (IUnknown *)this;
+
+ if (IID_IDispatch == riid)
+ *ppv = (IDispatch *)this;
+
+ if (DIID_DWebBrowserEvents2 == riid)
+ *ppv = (DWebBrowserEvents2*)this;
+
+ if (NULL != *ppv) {
+ ((LPUNKNOWN)*ppv)->AddRef();
+ return NOERROR;
+ }
+ return E_NOINTERFACE;
+}
+
+STDMETHODIMP_(ULONG) IEEmbedSink::AddRef(void)
+{
+ ++m_cRef;
+ return m_cRef;
+}
+
+STDMETHODIMP_(ULONG) IEEmbedSink::Release(void)
+{
+ --m_cRef;
+ return m_cRef;
+}
+
+STDMETHODIMP IEEmbedSink::GetTypeInfoCount(UINT *) { return E_NOTIMPL; }
+STDMETHODIMP IEEmbedSink::GetTypeInfo(UINT, LCID, LPTYPEINFO*) { return S_OK; }
+STDMETHODIMP IEEmbedSink::GetIDsOfNames(REFIID, LPOLESTR*, UINT, LCID, DISPID*) { return S_OK; }
+
+STDMETHODIMP IEEmbedSink::Invoke(DISPID dispIdMember, REFIID, LCID, WORD, DISPPARAMS* pDispParams, VARIANT*, EXCEPINFO*, UINT*)
+{
+ if (!pDispParams) return E_INVALIDARG;
+ switch (dispIdMember) {
+ case DISPID_DOCUMENTCOMPLETE:
+ DocumentComplete(
+ pDispParams->rgvarg[1].pdispVal,
+ pDispParams->rgvarg[0].pvarVal);
+ return S_OK;
+ }
+
+ return DISP_E_MEMBERNOTFOUND;
+}
+// DWebBrowserEvents2
+
+void IEEmbedSink::StatusTextChange(BSTR) {}
+void IEEmbedSink::ProgressChange(long, long) {}
+void IEEmbedSink::CommandStateChange(long, VARIANT_BOOL) {}
+void IEEmbedSink::DownloadBegin() {}
+void IEEmbedSink::DownloadComplete() {}
+void IEEmbedSink::TitleChange(BSTR) {}
+void IEEmbedSink::PropertyChange(BSTR) {}
+void IEEmbedSink::BeforeNavigate2(IDispatch*, VARIANT* , VARIANT*, VARIANT*, VARIANT*, VARIANT*, VARIANT_BOOL*) { }
+void IEEmbedSink::NewWindow2(IDispatch**, VARIANT_BOOL*) {}
+void IEEmbedSink::NavigateComplete(IDispatch*, VARIANT*) {}
+void IEEmbedSink::DocumentComplete(IDispatch* , VARIANT* url)
+{
+ HWND hWnd;
+ ieWindow->GetWindow(&hWnd);
+ SendMessage(hWnd, UM_DOCCOMPLETE, 0, (LPARAM)url->bstrVal);
+}
+void IEEmbedSink::OnQuit() {}
+void IEEmbedSink::OnVisible(VARIANT_BOOL) {}
+void IEEmbedSink::OnToolBar(VARIANT_BOOL) {}
+void IEEmbedSink::OnMenuBar(VARIANT_BOOL) {}
+void IEEmbedSink::OnStatusBar(VARIANT_BOOL) {}
+void IEEmbedSink::OnFullScreen(VARIANT_BOOL) {}
+void IEEmbedSink::OnTheaterMode(VARIANT_BOOL) {}
+void IEEmbedSink::WindowSetResizable(VARIANT_BOOL) {}
+void IEEmbedSink::WindowSetLeft(long) {}
+void IEEmbedSink::WindowSetTop(long) {}
+void IEEmbedSink::WindowSetWidth(long) {}
+void IEEmbedSink::WindowSetHeight(long) {}
+void IEEmbedSink::WindowClosing(VARIANT_BOOL, VARIANT_BOOL*) {}
+void IEEmbedSink::ClientToHostWindow(long *, long *) {}
+void IEEmbedSink::SetSecureLockIcon(long) {}
+void IEEmbedSink::FileDownload(VARIANT_BOOL*) {}
+
+
+IEEmbed::IEEmbed(HWND _parent)
+{
+ MSG msg;
+ parent = _parent;
+ GetClientRect(_parent, &rcClient);
+ if (SUCCEEDED(pWebBrowser.CoCreateInstance(CLSID_WebBrowser, NULL, CLSCTX_INPROC))) {
+ CComPtr<IOleObject> pOleObject;
+ if (SUCCEEDED(pWebBrowser.QueryInterface(&pOleObject))) {
+ pOleObject->SetClientSite(this);
+ pOleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, &msg, this, 0, this->parent, &rcClient);
+ }
+ else MessageBox(NULL, TranslateT("IID_IOleObject failed."), TranslateT("RESULT"), MB_OK);
+
+ CComPtr<IOleInPlaceObject> pOleInPlace;
+ if (SUCCEEDED(pWebBrowser.QueryInterface(&pOleInPlace)))
+ pOleInPlace->GetWindow(&hwnd);
+ else
+ MessageBox(NULL, TranslateT("IID_IOleInPlaceObject failed."), TranslateT("RESULT"), MB_OK);
+
+ //setBorder();
+ CComPtr<IConnectionPointContainer> pCPContainer;
+ // Step 1: Get a pointer to the connection point container.
+ if (SUCCEEDED(pWebBrowser.QueryInterface(&pCPContainer))) {
+ // m_pConnectionPoint is defined like this:
+ // Step 2: Find the connection point.
+ if (SUCCEEDED(pCPContainer->FindConnectionPoint(DIID_DWebBrowserEvents2, &m_pConnectionPoint))) {
+ // Step 3: Advise the connection point that you
+ // want to sink its events.
+ sink = new IEEmbedSink(this);
+ if (FAILED(m_pConnectionPoint->Advise(sink, &m_dwCookie)))
+ MessageBox(NULL, TranslateT("Failed to Advise"), TranslateT("C++ Event Sink"), MB_OK);
+ }
+ }
+ }
+
+ pWebBrowser->put_RegisterAsDropTarget(VARIANT_FALSE);
+}
+
+IEEmbed::~IEEmbed()
+{
+ CComPtr<IOleObject> pOleObject;
+ if (SUCCEEDED(pWebBrowser.QueryInterface(&pOleObject)))
+ pOleObject->SetClientSite(NULL);
+ else
+ MessageBox(NULL, TranslateT("IID_IOleObject failed."), TranslateT("RESULT"), MB_OK);
+
+ if (m_pConnectionPoint != NULL)
+ m_pConnectionPoint->Unadvise(m_dwCookie);
+
+ if (sink != NULL)
+ delete sink;
+ DestroyWindow(hwnd);
+}
+
+void IEEmbed::ResizeBrowser()
+{
+ CComPtr<IOleInPlaceObject> pOleInPlace;
+
+ GetClientRect(parent, &rcClient);
+ if (SUCCEEDED(pWebBrowser.QueryInterface(&pOleInPlace)))
+ pOleInPlace->SetObjectRects(&rcClient, &rcClient);
+}
+
+
+// IUnknown
+STDMETHODIMP IEEmbed::QueryInterface(REFIID riid, PVOID *ppv)
+{
+ *ppv = NULL;
+ if (IID_IUnknown == riid)
+ *ppv = this;
+ if (IID_IOleClientSite == riid)
+ *ppv = (IOleClientSite*)this;//Unknown)m_pIOleClientSite;
+ if (IID_IOleWindow == riid || IID_IOleInPlaceSite == riid)
+ *ppv = (IOleInPlaceSite*)this;//m_pIOleIPSite;
+
+ if (NULL != *ppv) {
+ ((LPUNKNOWN)*ppv)->AddRef();
+ return NOERROR;
+ }
+ return E_NOINTERFACE;
+}
+
+STDMETHODIMP_(ULONG) IEEmbed::AddRef(void)
+{
+ ++m_cRef;
+ return m_cRef;
+}
+
+STDMETHODIMP_(ULONG) IEEmbed::Release(void)
+{
+ --m_cRef;
+ return m_cRef;
+}
+
+// IDispatch
+STDMETHODIMP IEEmbed::GetTypeInfoCount(UINT *) { return E_NOTIMPL; }
+STDMETHODIMP IEEmbed::GetTypeInfo(UINT, LCID, LPTYPEINFO*) { return S_OK; }
+STDMETHODIMP IEEmbed::GetIDsOfNames(REFIID, LPOLESTR*, UINT, LCID, DISPID*) { return S_OK; }
+STDMETHODIMP IEEmbed::Invoke(DISPID, REFIID, LCID, WORD, DISPPARAMS*, VARIANT*, EXCEPINFO*, UINT*) { return DISP_E_MEMBERNOTFOUND; }
+
+// IOleWindow
+STDMETHODIMP IEEmbed::GetWindow(HWND *phwnd)
+{
+ *phwnd = parent;
+ return S_OK;
+}
+
+STDMETHODIMP IEEmbed::ContextSensitiveHelp(BOOL) { return E_NOTIMPL; }
+STDMETHODIMP IEEmbed::CanInPlaceActivate(void) { return S_OK; }
+STDMETHODIMP IEEmbed::OnInPlaceActivate(void) { return S_OK; }
+STDMETHODIMP IEEmbed::OnUIActivate(void) { return E_NOTIMPL; }
+
+STDMETHODIMP IEEmbed::GetWindowContext(IOleInPlaceFrame **, IOleInPlaceUIWindow **, LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO)
+{
+ lprcPosRect->left = rcClient.left;
+ lprcPosRect->top = rcClient.top;
+ lprcPosRect->right = rcClient.right;
+ lprcPosRect->bottom = rcClient.bottom;
+ lprcClipRect->left = rcClient.left;
+ lprcClipRect->top = rcClient.top;
+ lprcClipRect->right = rcClient.right;
+ lprcClipRect->bottom = rcClient.bottom;
+ return S_OK;
+}
+
+STDMETHODIMP IEEmbed::Scroll(SIZE) { return E_NOTIMPL; }
+STDMETHODIMP IEEmbed::OnUIDeactivate(BOOL) { return E_NOTIMPL; }
+STDMETHODIMP IEEmbed::OnInPlaceDeactivate(void) { return S_OK; }
+STDMETHODIMP IEEmbed::DiscardUndoState(void) { return E_NOTIMPL; }
+STDMETHODIMP IEEmbed::DeactivateAndUndo(void) { return E_NOTIMPL; }
+STDMETHODIMP IEEmbed::OnPosRectChange(LPCRECT) { return E_NOTIMPL; }
+STDMETHODIMP IEEmbed::SaveObject(void) { return E_NOTIMPL; }
+STDMETHODIMP IEEmbed::GetMoniker(DWORD, DWORD, IMoniker **) { return E_NOTIMPL; }
+STDMETHODIMP IEEmbed::GetContainer(IOleContainer **) { return E_NOTIMPL; }
+STDMETHODIMP IEEmbed::ShowObject(void) { return E_NOTIMPL; }
+STDMETHODIMP IEEmbed::OnShowWindow(BOOL) { return E_NOTIMPL; }
+STDMETHODIMP IEEmbed::RequestNewObjectLayout(void) { return E_NOTIMPL; }
+
+
+void IEEmbed::write(const wchar_t *text)
+{
+ CComPtr<IHTMLDocument2> document = getDocument();
+ if (!document) return;
+
+ SAFEARRAY *safe_array = ::SafeArrayCreateVector(VT_VARIANT, 0, 1);
+ if (safe_array != NULL) {
+ VARIANT *variant;
+ ::SafeArrayAccessData(safe_array, (LPVOID *)&variant);
+ variant->vt = VT_BSTR;
+ variant->bstrVal = ::SysAllocString(text);
+ ::SafeArrayUnaccessData(safe_array);
+ document->write(safe_array);
+ // ::SysFreeString(bstr); // don't free it !!!!!!!
+ ::SafeArrayDestroy(safe_array);
+ document->close();
+ }
+}
+
+void IEEmbed::addCookie(const wchar_t *cookieString)
+{
+ CComPtr<IHTMLDocument2> document = getDocument();
+ if (!document) return;
+ BSTR cookie = SysAllocString(cookieString);
+
+ document->put_cookie(cookie);
+
+ SysFreeString(cookie);
+}
+
+BSTR IEEmbed::getCookies()
+{
+ CComPtr<IHTMLDocument2> document = getDocument();
+ BSTR cookie = NULL;
+
+ if (!document) return NULL;
+ document->get_cookie(&cookie);
+ return cookie;
+}
+
+IHTMLDocument2* IEEmbed::getDocument()
+{
+ CComPtr<IDispatch> dispatch;
+ if (SUCCEEDED(pWebBrowser->get_Document(&dispatch)) && dispatch != NULL) {
+ CComPtr<IHTMLDocument2> document;
+ dispatch.QueryInterface(&document);
+ return document.Detach();
+ }
+
+ return NULL;
+}
+
+void IEEmbed::navigate(const wchar_t *url)
+{
+ pWebBrowser->Navigate((WCHAR *)url, NULL, NULL, NULL, NULL);
+}
+
+void IEEmbed::navigate(char *url)
+{
+ wchar_t *pwszUrl = mir_a2u(url);
+ navigate(pwszUrl);
+ mir_free(pwszUrl);
+}
+
+void IEEmbed::navigate(NETLIBHTTPREQUEST *nlhr)
+{
+ WCHAR *szUrl = mir_a2u(nlhr->szUrl);
+ BSTR bstrHeaders;
+ LPSAFEARRAY psa;
+ LPSTR pPostData;
+ VARIANT vPostData = {0}, vHeaders = {0};
+
+ bstrHeaders = SysAllocString(L"Content-Type: application/x-www-form-urlencoded\r\n");
+ V_VT(&vHeaders) = VT_BSTR;
+ V_BSTR(&vHeaders) = bstrHeaders;
+ VariantInit(&vPostData);
+ psa = SafeArrayCreateVector(VT_UI1, 0, nlhr->dataLength);
+ SafeArrayAccessData(psa, (LPVOID*)&pPostData);
+ memcpy(pPostData, nlhr->pData, nlhr->dataLength);
+ SafeArrayUnaccessData(psa);
+ V_VT(&vPostData) = VT_ARRAY | VT_UI1;
+ V_ARRAY(&vPostData) = psa;
+ pWebBrowser->Navigate(szUrl, NULL, NULL, &vPostData, &vHeaders);
+ SysFreeString(bstrHeaders);
+ VariantClear(&vPostData);
+ mir_free(szUrl);
+}
+
+char *IEEmbed::GetHTMLDoc() {
+ CComPtr<IDispatch> spDispDoc;
+ char *pszRet = NULL;
+
+ if (SUCCEEDED(pWebBrowser->get_Document(&spDispDoc))) {
+ CComPtr<IHTMLDocument3> spDoc;
+
+ if (SUCCEEDED(spDispDoc->QueryInterface(IID_IHTMLDocument3, (void**)&spDoc))) {
+ CComPtr<IHTMLElement> spRootElement;
+ if (SUCCEEDED(spDoc->get_documentElement(&spRootElement)))
+ {
+ BSTR bstrDoc;
+ if (SUCCEEDED(spRootElement->get_outerHTML(&bstrDoc)))
+ {
+ pszRet = mir_u2a(bstrDoc);
+ SysFreeString(bstrDoc);
+ }
+ }
+ }
+ }
+ return pszRet;
+}
diff --git a/protocols/MSN/src/msn_ieembed.h b/protocols/MSN/src/msn_ieembed.h
new file mode 100644
index 0000000000..76442b691d
--- /dev/null
+++ b/protocols/MSN/src/msn_ieembed.h
@@ -0,0 +1,140 @@
+/*
+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 <http://www.gnu.org/licenses/>.
+*/
+
+class IEEmbed;
+
+#include <mshtmhst.h>
+#include <mshtml.h>
+#include <exdisp.h>
+
+#include <atlbase.h> // CComPtr
+
+#ifndef IEEMBED_INCLUDED
+#define IEEMBED_INCLUDED
+
+#define UM_DOCCOMPLETE (WM_USER+600)
+
+class IEEmbedSink :public DWebBrowserEvents2 {
+private:
+ int m_cRef;
+ IEEmbed *ieWindow;
+public:
+ IEEmbedSink(IEEmbed *);
+ virtual ~IEEmbedSink();
+ // IDispatch
+ STDMETHODIMP QueryInterface(REFIID riid, PVOID *ppv);
+ STDMETHODIMP_(ULONG) AddRef(void);
+ STDMETHODIMP_(ULONG) Release(void);
+
+ STDMETHOD(GetTypeInfoCount)(UINT*);
+ STDMETHOD(GetTypeInfo)(UINT, LCID, LPTYPEINFO*);
+ STDMETHOD(GetIDsOfNames)(REFIID, LPOLESTR*, UINT, LCID, DISPID*);
+ STDMETHOD(Invoke)(DISPID, REFIID, LCID, WORD, DISPPARAMS*, VARIANT*, EXCEPINFO*, UINT*);
+ // DWebBrowserEvents2
+ STDMETHODIMP_(void)StatusTextChange(BSTR);
+ STDMETHODIMP_(void)ProgressChange(long, long);
+ STDMETHODIMP_(void)CommandStateChange(long, VARIANT_BOOL);
+ STDMETHODIMP_(void)DownloadBegin();
+ STDMETHODIMP_(void)DownloadComplete();
+ STDMETHODIMP_(void)TitleChange(BSTR Text);
+ STDMETHODIMP_(void)PropertyChange(BSTR Text);
+ STDMETHODIMP_(void)BeforeNavigate2(IDispatch*, VARIANT*, VARIANT*, VARIANT*, VARIANT*, VARIANT*, VARIANT_BOOL*);
+ STDMETHODIMP_(void)NewWindow2(IDispatch**, VARIANT_BOOL*);
+ STDMETHODIMP_(void)NavigateComplete(IDispatch*, VARIANT*);
+ STDMETHODIMP_(void)DocumentComplete(IDispatch*, VARIANT*);
+ STDMETHODIMP_(void)OnQuit();
+ STDMETHODIMP_(void)OnVisible(VARIANT_BOOL);
+ STDMETHODIMP_(void)OnToolBar(VARIANT_BOOL);
+ STDMETHODIMP_(void)OnMenuBar(VARIANT_BOOL);
+ STDMETHODIMP_(void)OnStatusBar(VARIANT_BOOL);
+ STDMETHODIMP_(void)OnFullScreen(VARIANT_BOOL);
+ STDMETHODIMP_(void)OnTheaterMode(VARIANT_BOOL);
+ STDMETHODIMP_(void)WindowSetResizable(VARIANT_BOOL);
+ STDMETHODIMP_(void)WindowSetLeft(long);
+ STDMETHODIMP_(void)WindowSetTop(long);
+ STDMETHODIMP_(void)WindowSetWidth(long);
+ STDMETHODIMP_(void)WindowSetHeight(long);
+ STDMETHODIMP_(void)WindowClosing(VARIANT_BOOL, VARIANT_BOOL*);
+ STDMETHODIMP_(void)ClientToHostWindow(long*, long*);
+ STDMETHODIMP_(void)SetSecureLockIcon(long);
+ STDMETHODIMP_(void)FileDownload(VARIANT_BOOL*);
+};
+
+class IEEmbed :public IDispatch, public IOleClientSite, public IOleInPlaceSite //, public IDocHostUIHandler
+{
+public:
+ HWND parent;
+ HWND hwnd;
+ int m_cRef;
+ RECT rcClient;
+ DWORD m_dwCookie;
+ CComPtr<IConnectionPoint> m_pConnectionPoint;
+ CComPtr<IWebBrowser2> pWebBrowser;
+ IEEmbedSink *sink;
+
+ // IUnknown
+ STDMETHODIMP QueryInterface(REFIID riid, PVOID *ppv);
+ STDMETHODIMP_(ULONG) AddRef(void);
+ STDMETHODIMP_(ULONG) Release(void);
+
+ // IDispatch
+ STDMETHOD(GetTypeInfoCount)(UINT*);
+ STDMETHOD(GetTypeInfo)(UINT, LCID, LPTYPEINFO*);
+ STDMETHOD(GetIDsOfNames)(REFIID, LPOLESTR*, UINT, LCID, DISPID*);
+ STDMETHOD(Invoke)(DISPID, REFIID, LCID, WORD, DISPPARAMS*, VARIANT*, EXCEPINFO*, UINT*);
+ // IOleWindow
+ STDMETHOD(GetWindow)(HWND *phwnd);
+ STDMETHOD(ContextSensitiveHelp)(BOOL fEnterMode);
+ // IOleInPlace
+ STDMETHOD(CanInPlaceActivate)(void);
+ STDMETHOD(OnInPlaceActivate)(void);
+ STDMETHOD(OnUIActivate)(void);
+ STDMETHOD(GetWindowContext)(IOleInPlaceFrame **ppFrame, IOleInPlaceUIWindow **ppDoc,
+ LPRECT lprcPosRect, LPRECT lprcClipRect,
+ LPOLEINPLACEFRAMEINFO lpFrameInfo);
+ STDMETHOD(Scroll)(SIZE scrollExtant);
+
+ STDMETHOD(OnUIDeactivate)(BOOL fUndoable);
+ STDMETHOD(OnInPlaceDeactivate)(void);
+ STDMETHOD(DiscardUndoState)(void);
+ STDMETHOD(DeactivateAndUndo)(void);
+ STDMETHOD(OnPosRectChange)(LPCRECT lprcPosRect);
+ // IOleClientSite
+ STDMETHOD(SaveObject)(void);
+ STDMETHOD(GetMoniker)(DWORD dwAssign, DWORD dwWhichMoniker, IMoniker **ppmk);
+ STDMETHOD(GetContainer)(IOleContainer **ppContainer);
+ STDMETHOD(ShowObject)(void);
+ STDMETHOD(OnShowWindow)(BOOL fShow);
+ STDMETHOD(RequestNewObjectLayout)(void);
+
+ IHTMLDocument2 *getDocument();
+ IEEmbed(HWND _parent);
+ virtual ~IEEmbed();
+
+ void ResizeBrowser();
+ void navigate(const wchar_t *);
+ void navigate(char *url);
+ void navigate(NETLIBHTTPREQUEST *nlhr);
+ void write(const wchar_t *text);
+ void addCookie(const wchar_t *cookieString);
+ BSTR getCookies();
+ char* GetHTMLDoc();
+};
+#endif
diff --git a/protocols/MSN/src/msn_proto.h b/protocols/MSN/src/msn_proto.h
index 952c32db05..f5a4fa8358 100644
--- a/protocols/MSN/src/msn_proto.h
+++ b/protocols/MSN/src/msn_proto.h
@@ -118,6 +118,7 @@ struct CMsnProto : public PROTO<CMsnProto>
char *authStorageToken;
char *hotSecretToken, *hotAuthToken;
char *authUser, *authUIC, *authCookies, *authSSLToken, *authAccessToken, *authRefreshToken, *authSkypeComToken, *authSkypeToken;
+ bool bAskingForAuth;
int authMethod;
time_t authTokenExpiretime;
bool bSentBND;
@@ -275,6 +276,7 @@ struct CMsnProto : public PROTO<CMsnProto>
void __cdecl msn_keepAliveThread(void* arg);
void __cdecl msn_loginThread(void* arg);
+ void __cdecl msn_IEAuthThread(void* arg);
void __cdecl MSNServerThread(void* arg);
void __cdecl MsnFileAckThread(void* arg);
@@ -492,6 +494,7 @@ struct CMsnProto : public PROTO<CMsnProto>
char* GenerateLoginBlob(char* challenge);
void LoadAuthTokensDB(void);
void SaveAuthTokensDB(void);
+ bool parseLoginPage(char *pszHTML, NETLIBHTTPREQUEST *nlhr, CMStringA *post);
int LoginSkypeOAuth(const char *pRefreshToken);
bool RefreshOAuth(const char *pszRefreshToken, const char *pszService, char *pszAccessToken, char *pszOutRefreshToken=NULL, time_t *ptExpires=NULL);
int MSN_AuthOAuth(void);
diff --git a/protocols/MSN/src/stdafx.h b/protocols/MSN/src/stdafx.h
index eedae789e9..1f34366308 100644
--- a/protocols/MSN/src/stdafx.h
+++ b/protocols/MSN/src/stdafx.h
@@ -193,12 +193,6 @@ const char MSN_USER_AGENT[] = NETLIB_USER_AGENT;
extern const char sttVoidUid[];
-#define MSN_LOGIN_OAUTH LPGEN("Automatic authentication to MSN failed, possibly due to Captcha-Authentication. \
-Do you want to open a browser window to do a manual login?\n\n\
-This will not log you in to MSN in Miranda, but it allows you to fix potential problems like entering a captcha \
-that gets asked due to location change or to accept new TOS, which are required only once.\n\n\
-Also please note that MSN protocol doesn't support two-factor authentication.")
-
/////////////////////////////////////////////////////////////////////////////////////////
// MSN plugin functions