summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--protocols/MSN/src/msn_auth.cpp87
-rw-r--r--protocols/MSN/src/msn_commands.cpp136
-rw-r--r--protocols/MSN/src/msn_errors.cpp33
-rw-r--r--protocols/MSN/src/msn_global.h4
-rw-r--r--protocols/MSN/src/msn_misc.cpp15
-rw-r--r--protocols/MSN/src/msn_proto.cpp248
-rw-r--r--protocols/MSN/src/msn_proto.h6
-rw-r--r--protocols/MSN/src/msn_threads.cpp6
8 files changed, 438 insertions, 97 deletions
diff --git a/protocols/MSN/src/msn_auth.cpp b/protocols/MSN/src/msn_auth.cpp
index e8282c00bd..47192116cd 100644
--- a/protocols/MSN/src/msn_auth.cpp
+++ b/protocols/MSN/src/msn_auth.cpp
@@ -692,6 +692,18 @@ void CMsnProto::LoadAuthTokensDB(void)
replaceStr(authStorageToken, dbv.pszVal);
db_free(&dbv);
}
+ if (getString("authRefreshToken", &dbv) == 0) {
+ replaceStr(authRefreshToken, dbv.pszVal);
+ db_free(&dbv);
+ }
+ if (getString("authSkypeComToken", &dbv) == 0) {
+ replaceStr(authSkypeComToken, dbv.pszVal);
+ db_free(&dbv);
+ }
+ if (getString("authSkypeToken", &dbv) == 0) {
+ replaceStr(authSkypeToken, dbv.pszVal);
+ db_free(&dbv);
+ }
}
void CMsnProto::SaveAuthTokensDB(void)
@@ -703,6 +715,7 @@ void CMsnProto::SaveAuthTokensDB(void)
setString("authUIC", authUIC);
setString("authCookies", authCookies);
setString("authStrToken", authStrToken);
+ setString("authRefreshToken", authRefreshToken);
}
// -1 - Error on login sequence
@@ -815,6 +828,7 @@ int CMsnProto::MSN_AuthOAuth(void)
*pEnd = 0;
pRefreshToken+=14;
}
+ replaceStr(authRefreshToken, pRefreshToken);
/* Extract expire time */
time(&authTokenExpiretime);
@@ -841,6 +855,8 @@ int CMsnProto::MSN_AuthOAuth(void)
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 */
@@ -920,6 +936,74 @@ const char *CMsnProto::GetMyUsername(int netId)
return MyOptions.szEmail;
}
+const char *CMsnProto::GetSkypeToken(bool bAsAuthHeader)
+{
+ char szToken[1024];
+
+ // Ensure that token isn't expired
+ 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];
+ char szPOST[2048];
+
+ nlhr.cbSize = sizeof(nlhr);
+ nlhr.requestType = REQUEST_POST;
+ nlhr.flags = NLHRF_HTTP11 | NLHRF_DUMPASTEXT | NLHRF_PERSISTENT | NLHRF_REDIRECT;
+ nlhr.nlc = hHttpsConnection;
+ nlhr.headersCount = SIZEOF(headers);
+ 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;
+
+
+ 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) {
+ char *pSkypeToken, *pEnd;
+
+ if ((pSkypeToken = strstr(nlhrReply->pData, "\"skypetoken\":\"")) &&
+ (pEnd=strchr(pSkypeToken+15, '"')))
+ {
+ *pEnd = 0;
+ pSkypeToken+=14;
+ mir_snprintf (szToken, sizeof(szToken), "skype_token %s", pSkypeToken);
+ replaceStr(authSkypeToken, szToken);
+ setString("authSkypeToken", authSkypeToken);
+ }
+
+ }
+ CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)nlhrReply);
+ } else hHttpsConnection = NULL;
+ }
+ if (!bAsAuthHeader && authSkypeToken) {
+ char *pszRet = strchr(authSkypeToken, ' ');
+ if (pszRet) return pszRet+1;
+ }
+ return authSkypeToken;
+}
+
void CMsnProto::FreeAuthTokens(void)
{
mir_free(pAuthToken);
@@ -933,7 +1017,10 @@ void CMsnProto::FreeAuthTokens(void)
mir_free(authUIC);
mir_free(authCookies);
mir_free(authSSLToken);
+ mir_free(authSkypeComToken);
+ mir_free(authSkypeToken);
mir_free(authUser);
mir_free(authAccessToken);
+ mir_free(authRefreshToken);
free(hotAuthToken);
}
diff --git a/protocols/MSN/src/msn_commands.cpp b/protocols/MSN/src/msn_commands.cpp
index d80bddf470..8e51383a71 100644
--- a/protocols/MSN/src/msn_commands.cpp
+++ b/protocols/MSN/src/msn_commands.cpp
@@ -213,6 +213,13 @@ void CMsnProto::MSN_ReceiveMessage(ThreadData* info, char* cmdString, char* para
(!_strnicmp(tContentType, "application/user+xml", 10) && tHeader["Message-Type"] && !strncmp(tHeader["Message-Type"], "RichText", 8))) {
MCONTACT hContact = strncmp(email, "19:", 3)?MSN_HContactFromEmail(email, nick, true, true):NULL;
+ if (!_stricmp(tHeader["Message-Type"], "RichText/UriObject")) {
+ ezxml_t xmli = ezxml_parse_str(msgBody, strlen(msgBody));
+ if (xmli) {
+ MSN_ProcessURIObject(hContact, xmli);
+ ezxml_free(xmli);
+ }
+ } else
if (!_stricmp(tHeader["Message-Type"], "RichText/Contacts")) {
ezxml_t xmli = ezxml_parse_str(msgBody, mir_strlen(msgBody));
if (xmli) {
@@ -359,27 +366,11 @@ void CMsnProto::MSN_ReceiveMessage(ThreadData* info, char* cmdString, char* para
else tContact = MSN_HContactFromEmail(email, nick, true, true);
if (!mir_strcmp(tHeader["Message-Type"], "Nudge"))
NotifyEventHooks(hMSNNudge, (WPARAM)tContact, 0);
-
-#ifdef OBSOLETE
- MimeHeaders tFileInfo;
- tFileInfo.readFromBuffer(msgBody);
-
- const char* id = tFileInfo["ID"];
- if (id != NULL) {
- switch (atol(id)) {
- case 1: // Nudge
- NotifyEventHooks(hMSNNudge, (WPARAM)tContact, 0);
- break;
-
- case 2: // Wink
- break;
-
- case 4: // Action Message
- break;
- }
- }
- }
-#endif
+ /* Other msg types:
+ * Wink
+ * Voice
+ * Data
+ */
}
else if (!_strnicmp(tContentType, "text/x-msmsgsemailnotification", 30))
sttNotificationMessage(msgBody, false);
@@ -421,6 +412,101 @@ void CMsnProto::MSN_ReceiveMessage(ThreadData* info, char* cmdString, char* para
mir_free(newbody);
}
+void CMsnProto::MSN_ProcessURIObject(MCONTACT hContact, ezxml_t xmli)
+{
+ const char *pszSkypeToken;
+
+ if ((pszSkypeToken=GetSkypeToken(true)) && xmli) {
+ /* FIXME: As soon as core has functions to POST images in a conversation AND gives the possibility to supply a
+ * callback for fetching thta image, this may be possible, but currently due to required Auth-Header, this
+ * is not possible and we just send an incoming file transfer
+ const char *thumb = ezxml_attr(xmli, "url_thumbnail");
+ if (thumb && ServiceExists("IEVIEW/NewWindow")) {
+ // Supply callback to detch thumb with auth-header and embed [img] BB-code?
+ }
+ */
+ char *uri = (char*)ezxml_attr(xmli, "uri");
+ if (uri) {
+ // First get HTTP header of file to get content length
+ unsigned __int64 fileSize = 0;
+ NETLIBHTTPHEADER nlbhHeaders[2] = { 0 };
+ nlbhHeaders[0].szName = "User-Agent"; nlbhHeaders[0].szValue = (LPSTR)MSN_USER_AGENT;
+ nlbhHeaders[1].szName = "Authorization"; nlbhHeaders[1].szValue = (char*)pszSkypeToken;
+
+ NETLIBHTTPREQUEST nlhr = { 0 }, *nlhrReply;
+ nlhr.cbSize = sizeof(nlhr);
+ nlhr.requestType = REQUEST_GET;
+ nlhr.flags = NLHRF_GENERATEHOST | NLHRF_PERSISTENT | NLHRF_SMARTAUTHHEADER;
+ nlhr.szUrl = uri;
+ nlhr.headers = (NETLIBHTTPHEADER*)&nlbhHeaders;
+ nlhr.headersCount = SIZEOF(nlbhHeaders);
+ nlhr.nlc = hHttpsConnection;
+
+ mHttpsTS = clock();
+ nlhrReply = (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)hNetlibUserHttps, (LPARAM)&nlhr);
+ mHttpsTS = clock();
+ if (nlhrReply) {
+ hHttpsConnection = nlhrReply->nlc;
+ if (nlhrReply->resultCode == 200) {
+ char *pLength, *pEnd;
+
+ if ((pLength = strstr(nlhrReply->pData, "\"contents\":")) && (pLength = strstr(pLength, "\"imgpsh\"")) &&
+ (pLength = strstr(pLength, "\"length\":")) && (pEnd = strchr(pLength+9, ','))) {
+ pLength+=9;
+ *pEnd = 0;
+ fileSize=_atoi64(pLength);
+ }
+ }
+
+ CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)nlhrReply);
+ } else hHttpsConnection = NULL;
+
+ if (fileSize) {
+ filetransfer* ft = new filetransfer(this);
+ char *pszFile;
+ ezxml_t originalName, desc;
+
+ ft->std.hContact = hContact;
+ ft->tType = SERVER_HTTP;
+ ft->p2p_appID = MSN_APPID_FILE;
+ mir_free(ft->std.tszCurrentFile);
+ if (!((originalName = ezxml_child(xmli, "OriginalName")) && (pszFile = (char*)ezxml_attr(originalName, "v")))) {
+ if ((originalName = ezxml_child(xmli, "meta")))
+ pszFile = (char*)ezxml_attr(originalName, "originalName");
+ }
+ ft->std.tszCurrentFile = mir_utf8decodeT(pszFile);
+ ft->std.totalBytes = ft->std.currentFileSize = fileSize;
+ ft->std.totalFiles = 1;
+ ft->szInvcookie = (char*)mir_calloc(strlen(uri)+16);
+ sprintf(ft->szInvcookie, "%s/content/imgpsh", uri);
+
+ TCHAR tComment[40];
+ mir_sntprintf(tComment, SIZEOF(tComment), TranslateT("%I64u bytes"), ft->std.currentFileSize);
+
+ PROTORECVFILET pre = { 0 };
+ pre.dwFlags = PRFF_TCHAR;
+ pre.fileCount = 1;
+ pre.timestamp = time(NULL);
+ pre.tszDescription = (desc = ezxml_child(xmli, "Description"))?mir_utf8decodeT(desc->txt):tComment;
+ pre.ptszFiles = &ft->std.tszCurrentFile;
+ pre.lParam = (LPARAM)ft;
+ ProtoChainRecvFile(ft->std.hContact, &pre);
+ if (desc) mir_free(pre.tszDescription);
+ } else uri=NULL;
+ }
+
+ if (uri == NULL) {
+ // Fallback: Just filter out the link and post it as a message
+ CallService(MS_PROTO_CONTACTISTYPING, WPARAM(hContact), 0);
+
+ PROTORECVEVENT pre = { 0 };
+ pre.szMessage = (char*)ezxml_txt(xmli);
+ pre.timestamp = (DWORD)time(NULL);
+ ProtoChainRecvMsg(hContact, &pre);
+ }
+ }
+}
+
/////////////////////////////////////////////////////////////////////////////////////////
// Process Yahoo Find
@@ -1032,8 +1118,12 @@ LBL_InvalidCommand:
ezxml_free(xmlact);
}
continue;
- } else if (mir_strcmp(msgtype->txt, "Text")) continue;
- /* TODO: Implement i.e. RichText/Files for announcement of file transfers */
+ } else if (!mir_strcmp(msgtype->txt, "RichText/UriObject")) {
+ if (ezxml_t xmlact = ezxml_parse_str(content->txt, mir_strlen(content->txt))) {
+ MSN_ProcessURIObject(hContact, xmlact);
+ ezxml_free(xmlact);
+ }
+ } else if (mir_strcmp(msgtype->txt, "Text")) continue; /* TODO: Implement i.e. RichText/Files for announcement of file transfers */
}
if (bIsChat) {
diff --git a/protocols/MSN/src/msn_errors.cpp b/protocols/MSN/src/msn_errors.cpp
index 916ce9070e..2a5752f9f7 100644
--- a/protocols/MSN/src/msn_errors.cpp
+++ b/protocols/MSN/src/msn_errors.cpp
@@ -28,6 +28,39 @@ int CMsnProto::MSN_HandleErrors(ThreadData* info, char* cmdString)
int errorCode, packetID = -1;
sscanf(cmdString, "%d %d", &errorCode, &packetID);
+ char* params = "";
+ int trid = -1;
+
+ if (cmdString[3]) {
+ if (isdigit((BYTE)cmdString[4])) {
+ trid = strtol(cmdString + 4, &params, 10);
+ switch (*params) {
+ case ' ': case '\0': case '\t': case '\n':
+ while (*params == ' ' || *params == '\t')
+ params++;
+ break;
+
+ default:
+ params = cmdString + 4;
+ }
+ }
+ else params = cmdString + 4;
+ }
+
+ union {
+ char* tWords[2];
+ struct { char *typeId, *strMsgBytes; } data;
+ };
+
+ if (sttDivideWords(params, SIZEOF(tWords), tWords) < 2) {
+ debugLogA("Invalid %.3s command, ignoring", cmdString);
+ return 0;
+ }
+
+ HReadBuffer buf(info, 0);
+ char* msgBody = (char*)buf.surelyRead(atol(data.strMsgBytes));
+
+
debugLogA("Server error:%s", cmdString);
switch (errorCode) {
diff --git a/protocols/MSN/src/msn_global.h b/protocols/MSN/src/msn_global.h
index 59f8d78cd0..1ce626523e 100644
--- a/protocols/MSN/src/msn_global.h
+++ b/protocols/MSN/src/msn_global.h
@@ -374,7 +374,8 @@ enum TInfoType
SERVER_NOTIFICATION,
SERVER_SWITCHBOARD,
SERVER_FILETRANS,
- SERVER_P2P_DIRECT
+ SERVER_P2P_DIRECT,
+ SERVER_HTTP
};
@@ -400,6 +401,7 @@ struct filetransfer
int fileId; // handle of file being transferring (r/w)
HANDLE hLockHandle;
+ HANDLE hResumeEvt;
ThreadData *info;
TInfoType tType;
diff --git a/protocols/MSN/src/msn_misc.cpp b/protocols/MSN/src/msn_misc.cpp
index f52e6a826e..a0657fec04 100644
--- a/protocols/MSN/src/msn_misc.cpp
+++ b/protocols/MSN/src/msn_misc.cpp
@@ -1112,7 +1112,6 @@ void CMsnProto::MSN_ShowPopup(const MCONTACT hContact, const TCHAR* msg, int fla
/////////////////////////////////////////////////////////////////////////////////////////
// filetransfer class members
-#ifdef OBSOLETE
filetransfer::filetransfer(CMsnProto* prt)
{
memset(this, 0, sizeof(filetransfer));
@@ -1122,6 +1121,7 @@ filetransfer::filetransfer(CMsnProto* prt)
proto = prt;
hLockHandle = CreateMutex(NULL, FALSE, NULL);
+ hResumeEvt = CreateEvent(NULL, FALSE, FALSE, NULL);
}
filetransfer::~filetransfer(void)
@@ -1131,11 +1131,14 @@ filetransfer::~filetransfer(void)
WaitForSingleObject(hLockHandle, 2000);
CloseHandle(hLockHandle);
+ CloseHandle(hResumeEvt);
if (fileId != -1) {
_close(fileId);
- if (p2p_appID != MSN_APPID_FILE && !(std.flags & PFTS_SENDING))
+#ifdef OBSOLETE
+ if (tType != SERVER_HTTP && p2p_appID != MSN_APPID_FILE && !(std.flags & PFTS_SENDING))
proto->p2p_pictureTransferFailed(this);
+#endif
}
if (!bCompleted && p2p_appID == MSN_APPID_FILE) {
@@ -1176,7 +1179,10 @@ void filetransfer::complete(void)
int filetransfer::create(void)
{
- fileId = _topen(std.tszCurrentFile, _O_BINARY | _O_CREAT | _O_TRUNC | _O_WRONLY, _S_IREAD | _S_IWRITE);
+ int flags = _O_BINARY | _O_CREAT | _O_WRONLY | _O_APPEND;
+
+ if (std.currentFileProgress == 0) flags |= _O_TRUNC;
+ fileId = _topen(std.tszCurrentFile, flags, _S_IREAD | _S_IWRITE);
if (fileId == -1)
proto->MSN_ShowError("Cannot create file '%s' during a file transfer", std.tszCurrentFile);
@@ -1225,6 +1231,7 @@ int filetransfer::openNext(void)
return fileId;
}
+#ifdef OBSOLETE
directconnection::directconnection(const char* CallID, const char* Wlid)
{
memset(this, 0, sizeof(directconnection));
@@ -1287,8 +1294,6 @@ void directconnection::xNonceToBin(UUID* nonce)
p[len - 2] = 0;
UuidFromStringA((BYTE*)p, nonce);
}
-#else
-filetransfer::~filetransfer(void) { }
#endif
/////////////////////////////////////////////////////////////////////////////////////////
diff --git a/protocols/MSN/src/msn_proto.cpp b/protocols/MSN/src/msn_proto.cpp
index acf07cc3a4..cc8cf98566 100644
--- a/protocols/MSN/src/msn_proto.cpp
+++ b/protocols/MSN/src/msn_proto.cpp
@@ -458,10 +458,34 @@ HANDLE __cdecl CMsnProto::SearchByEmail(const PROTOCHAR* email)
return SearchBasic(email);
}
-#ifdef OBSOLETE
/////////////////////////////////////////////////////////////////////////////////////////
// MsnFileAllow - starts the file transfer
+// stolen from netlibhttp.cpp
+static void MyNetlibConnFromUrl(const char* szUrl, NETLIBOPENCONNECTION &nloc)
+{
+ bool secur =_strnicmp(szUrl, "https", 5) == 0;
+ const char* phost = strstr(szUrl, "://");
+
+ char* szHost = mir_strdup(phost ? phost + 3 : szUrl);
+
+ char* ppath = strchr(szHost, '/');
+ if (ppath) *ppath = '\0';
+
+ memset(&nloc, 0, sizeof(nloc));
+ nloc.cbSize = sizeof(nloc);
+ nloc.szHost = szHost;
+
+ char* pcolon = strrchr(szHost, ':');
+ if (pcolon) {
+ *pcolon = '\0';
+ nloc.wPort = (WORD)strtol(pcolon+1, NULL, 10);
+ }
+ else nloc.wPort = secur ? 443 : 80;
+ nloc.flags = (secur ? NLOCF_SSL : 0);
+}
+
+
void __cdecl CMsnProto::MsnFileAckThread(void* arg)
{
filetransfer* ft = (filetransfer*)arg;
@@ -470,27 +494,92 @@ void __cdecl CMsnProto::MsnFileAckThread(void* arg)
mir_sntprintf(filefull, SIZEOF(filefull), _T("%s\\%s"), ft->std.tszWorkingDir, ft->std.tszCurrentFile);
replaceStrT(ft->std.tszCurrentFile, filefull);
+ ResetEvent(ft->hResumeEvt);
if (ProtoBroadcastAck(ft->std.hContact, ACKTYPE_FILE, ACKRESULT_FILERESUME, ft, (LPARAM)&ft->std))
- return;
+ WaitForSingleObject(ft->hResumeEvt, INFINITE);
- bool fcrt = ft->create() != -1;
+ ft->create();
- if (ft->p2p_appID != 0) {
- if (fcrt)
- p2p_sendFeedStart(ft);
- p2p_sendStatus(ft, fcrt ? 200 : 603);
+#ifdef OBSOLETE
+ if (ft->tType != SERVER_HTTP) {
+ if (ft->p2p_appID != 0) {
+ if (fcrt)
+ p2p_sendFeedStart(ft);
+ p2p_sendStatus(ft, fcrt ? 200 : 603);
+ }
+ else msnftp_sendAcceptReject(ft, fcrt);
}
- else msnftp_sendAcceptReject(ft, fcrt);
+#endif
ProtoBroadcastAck(ft->std.hContact, ACKTYPE_FILE, ACKRESULT_INITIALISING, ft, 0);
+
+ if (ft->tType == SERVER_HTTP) {
+ const char *pszSkypeToken;
+
+ if (ft->fileId != -1 && (pszSkypeToken=GetSkypeToken(true))) {
+ NETLIBHTTPHEADER nlbhHeaders[3] = { 0 };
+ NETLIBHTTPREQUEST nlhr = { 0 }, *nlhrReply;
+ char szRange[32];
+
+ nlbhHeaders[0].szName = "User-Agent"; nlbhHeaders[0].szValue = (LPSTR)MSN_USER_AGENT;
+ nlbhHeaders[1].szName = "Authorization"; nlbhHeaders[1].szValue = (char*)pszSkypeToken;
+ nlhr.headersCount = 2;
+ if (ft->std.currentFileProgress) {
+ mir_snprintf(szRange, sizeof(szRange), "bytes=%I64d-", ft->std.currentFileProgress);
+ nlbhHeaders[2].szName = "Range";
+ nlbhHeaders[2].szValue = szRange;
+ nlhr.headersCount++;
+ }
+
+ nlhr.cbSize = sizeof(nlhr);
+ nlhr.requestType = REQUEST_GET;
+ nlhr.flags = NLHRF_GENERATEHOST | NLHRF_SMARTREMOVEHOST | NLHRF_SMARTAUTHHEADER | NLHRF_HTTP11;
+ nlhr.szUrl = ft->szInvcookie;
+ nlhr.headers = (NETLIBHTTPHEADER*)&nlbhHeaders;
+
+ NETLIBOPENCONNECTION nloc = { 0 };
+ MyNetlibConnFromUrl(nlhr.szUrl, nloc);
+ nloc.flags |= NLOCF_HTTP;
+ if (nloc.flags & NLOCF_SSL) nlhr.flags |= NLHRF_SSL;
+ HANDLE nlc = (HANDLE)CallService(MS_NETLIB_OPENCONNECTION, (WPARAM)m_hNetlibUser, (LPARAM)&nloc);
+
+ if (nlc && CallService(MS_NETLIB_SENDHTTPREQUEST, (WPARAM)nlc, (LPARAM)&nlhr) != SOCKET_ERROR &&
+ (nlhrReply = (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_RECVHTTPHEADERS, (WPARAM)nlc, 0)))
+ {
+ if (nlhrReply->resultCode == 200 || nlhrReply->resultCode == 206) {
+ INT_PTR dw;
+ char buf[1024];
+
+ ProtoBroadcastAck(ft->std.hContact, ACKTYPE_FILE, ACKRESULT_CONNECTED, ft, 0);
+ while (!ft->bCanceled && ft->std.currentFileProgress < ft->std.currentFileSize &&
+ (dw = Netlib_Recv(nlc, buf, sizeof(buf), MSG_NODUMP))>0 && dw!=SOCKET_ERROR)
+ {
+ _write(ft->fileId, buf, dw);
+ ft->std.totalProgress += dw;
+ ft->std.currentFileProgress += dw;
+ ProtoBroadcastAck(ft->std.hContact, ACKTYPE_FILE, ACKRESULT_DATA, ft, (LPARAM)&ft->std);
+ }
+ if (ft->std.currentFileProgress == ft->std.currentFileSize) ft->std.currentFileNumber++;
+
+ }
+ CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)nlhrReply);
+ }
+ Netlib_CloseHandle(nlc);
+ mir_free((char*)nloc.szHost);
+ if (ft->std.currentFileNumber >= ft->std.totalFiles) ft->complete();
+ }
+ delete ft;
+ }
}
HANDLE __cdecl CMsnProto::FileAllow(MCONTACT, HANDLE hTransfer, const PROTOCHAR* szPath)
{
filetransfer* ft = (filetransfer*)hTransfer;
- if (!msnLoggedIn || !p2p_sessionRegistered(ft))
+#ifdef OBSOLETE
+ if (ft->tType != SERVER_HTTP && (!msnLoggedIn || !p2p_sessionRegistered(ft)))
return 0;
+#endif
if ((ft->std.tszWorkingDir = mir_tstrdup(szPath)) == NULL) {
TCHAR szCurrDir[MAX_PATH];
@@ -515,26 +604,31 @@ int __cdecl CMsnProto::FileCancel(MCONTACT, HANDLE hTransfer)
{
filetransfer* ft = (filetransfer*)hTransfer;
- if (!msnLoggedIn || !p2p_sessionRegistered(ft))
- return 0;
-
- if (!(ft->std.flags & PFTS_SENDING) && ft->fileId == -1) {
- if (ft->p2p_appID != 0)
- p2p_sendStatus(ft, 603);
- else
- msnftp_sendAcceptReject(ft, false);
- }
+ if (ft->tType == SERVER_HTTP) ft->bCanceled = true;
+#ifdef OBSOLETE
else {
- ft->bCanceled = true;
- if (ft->p2p_appID != 0) {
- p2p_sendCancel(ft);
- if (!(ft->std.flags & PFTS_SENDING) && ft->p2p_isV2)
- p2p_sessionComplete(ft);
+ if (!msnLoggedIn || !p2p_sessionRegistered(ft))
+ return 0;
+
+ if (!(ft->std.flags & PFTS_SENDING) && ft->fileId == -1) {
+ if (ft->p2p_appID != 0)
+ p2p_sendStatus(ft, 603);
+ else
+ msnftp_sendAcceptReject(ft, false);
+ }
+ else {
+ ft->bCanceled = true;
+ if (ft->p2p_appID != 0) {
+ p2p_sendCancel(ft);
+ if (!(ft->std.flags & PFTS_SENDING) && ft->p2p_isV2)
+ p2p_sessionComplete(ft);
+ }
}
- }
- ft->std.ptszFiles = NULL;
- ft->std.totalFiles = 0;
+ ft->std.ptszFiles = NULL;
+ ft->std.totalFiles = 0;
+ }
+#endif
return 0;
}
@@ -545,20 +639,25 @@ int __cdecl CMsnProto::FileDeny(MCONTACT, HANDLE hTransfer, const PROTOCHAR* /*s
{
filetransfer* ft = (filetransfer*)hTransfer;
- if (!msnLoggedIn || !p2p_sessionRegistered(ft))
- return 1;
-
- if (!(ft->std.flags & PFTS_SENDING) && ft->fileId == -1) {
- if (ft->p2p_appID != 0)
- p2p_sendStatus(ft, 603);
- else
- msnftp_sendAcceptReject(ft, false);
- }
+ if (ft->tType == SERVER_HTTP) delete ft;
+#ifdef OBSOLETE
else {
- ft->bCanceled = true;
- if (ft->p2p_appID != 0)
- p2p_sendCancel(ft);
+ if (!msnLoggedIn || !p2p_sessionRegistered(ft))
+ return 1;
+
+ if (!(ft->std.flags & PFTS_SENDING) && ft->fileId == -1) {
+ if (ft->p2p_appID != 0)
+ p2p_sendStatus(ft, 603);
+ else
+ msnftp_sendAcceptReject(ft, false);
+ }
+ else {
+ ft->bCanceled = true;
+ if (ft->p2p_appID != 0)
+ p2p_sendCancel(ft);
+ }
}
+#endif
return 0;
}
@@ -570,38 +669,63 @@ int __cdecl CMsnProto::FileResume(HANDLE hTransfer, int* action, const PROTOCHAR
{
filetransfer* ft = (filetransfer*)hTransfer;
- if (!msnLoggedIn || !p2p_sessionRegistered(ft))
- return 1;
+ if (ft->tType == SERVER_HTTP) {
+ switch (*action) {
+ case FILERESUME_SKIP:
+ ft->close();
+ ft->bCanceled = true;
+ break;
+ case FILERESUME_RENAME:
+ replaceStrT(ft->std.tszCurrentFile, *szFilename);
+ break;
+ case FILERESUME_OVERWRITE:
+ ft->std.currentFileProgress = 0;
+ break;
+ case FILERESUME_RESUME:
+ {
+ struct _stati64 statbuf;
+ _tstati64(ft->std.tszCurrentFile, &statbuf);
+ ft->std.currentFileProgress = statbuf.st_size;
+ }
+ break;
+ }
+ SetEvent(ft->hResumeEvt);
+ }
+#ifdef OBSOLETE
+ else {
+ if (!msnLoggedIn || !p2p_sessionRegistered(ft))
+ return 1;
- switch (*action) {
- case FILERESUME_SKIP:
- if (ft->p2p_appID != 0)
- p2p_sendStatus(ft, 603);
- else
- msnftp_sendAcceptReject(ft, false);
- break;
+ switch (*action) {
+ case FILERESUME_SKIP:
+ if (ft->p2p_appID != 0)
+ p2p_sendStatus(ft, 603);
+ else
+ msnftp_sendAcceptReject(ft, false);
+ break;
- case FILERESUME_RENAME:
- replaceStrT(ft->std.tszCurrentFile, *szFilename);
+ case FILERESUME_RENAME:
+ replaceStrT(ft->std.tszCurrentFile, *szFilename);
- default:
- bool fcrt = ft->create() != -1;
- if (ft->p2p_appID != 0) {
- if (fcrt)
- p2p_sendFeedStart(ft);
+ default:
+ bool fcrt = ft->create() != -1;
+ if (ft->p2p_appID != 0) {
+ if (fcrt)
+ p2p_sendFeedStart(ft);
- p2p_sendStatus(ft, fcrt ? 200 : 603);
- }
- else
- msnftp_sendAcceptReject(ft, fcrt);
+ p2p_sendStatus(ft, fcrt ? 200 : 603);
+ }
+ else
+ msnftp_sendAcceptReject(ft, fcrt);
- ProtoBroadcastAck(ft->std.hContact, ACKTYPE_FILE, ACKRESULT_INITIALISING, ft, 0);
- break;
+ ProtoBroadcastAck(ft->std.hContact, ACKTYPE_FILE, ACKRESULT_INITIALISING, ft, 0);
+ break;
+ }
}
+#endif
return 0;
}
-#endif
/////////////////////////////////////////////////////////////////////////////////////////
// MsnGetAwayMsg - reads the current status message for a user
@@ -646,7 +770,7 @@ DWORD_PTR __cdecl CMsnProto::GetCaps(int type, MCONTACT)
case PFLAGNUM_1:
return PF1_IM | PF1_SERVERCLIST | PF1_AUTHREQ | PF1_BASICSEARCH |
PF1_ADDSEARCHRES | PF1_CHAT | PF1_CONTACT |
- /*PF1_FILESEND | PF1_FILERECV | */PF1_URLRECV | PF1_VISLIST | PF1_MODEMSG;
+ /*PF1_FILESEND |*/ PF1_FILERECV | PF1_URLRECV | PF1_VISLIST | PF1_MODEMSG;
case PFLAGNUM_2:
return PF2_ONLINE | PF2_SHORTAWAY | PF2_LIGHTDND | PF2_INVISIBLE | PF2_ONTHEPHONE | PF2_IDLE;
diff --git a/protocols/MSN/src/msn_proto.h b/protocols/MSN/src/msn_proto.h
index f9d238475f..271f6b6100 100644
--- a/protocols/MSN/src/msn_proto.h
+++ b/protocols/MSN/src/msn_proto.h
@@ -40,12 +40,10 @@ struct CMsnProto : public PROTO<CMsnProto>
virtual int __cdecl AuthRecv(MCONTACT hContact, PROTORECVEVENT*);
virtual int __cdecl AuthRequest(MCONTACT hContact, const TCHAR* szMessage);
-#ifdef OBSOLETE
virtual HANDLE __cdecl FileAllow(MCONTACT hContact, HANDLE hTransfer, const PROTOCHAR* szPath);
virtual int __cdecl FileCancel(MCONTACT hContact, HANDLE hTransfer);
virtual int __cdecl FileDeny(MCONTACT hContact, HANDLE hTransfer, const PROTOCHAR* szReason);
virtual int __cdecl FileResume(HANDLE hTransfer, int* action, const PROTOCHAR** szFilename);
-#endif
virtual DWORD_PTR __cdecl GetCaps(int type, MCONTACT hContact = NULL);
@@ -118,7 +116,7 @@ struct CMsnProto : public PROTO<CMsnProto>
char *authContactToken;
char *authStorageToken;
char *hotSecretToken, *hotAuthToken;
- char *authUser, *authUIC, *authCookies, *authSSLToken, *authAccessToken;
+ char *authUser, *authUIC, *authCookies, *authSSLToken, *authAccessToken, *authRefreshToken, *authSkypeComToken, *authSkypeToken;
int authMethod;
time_t authTokenExpiretime;
bool bSentBND;
@@ -222,6 +220,7 @@ struct CMsnProto : public PROTO<CMsnProto>
void MSN_ProcessRemove(char* buf, size_t len);
void MSN_ProcessAdd(char* buf, size_t len);
void MSN_ProcessYFind(char* buf, size_t len);
+ void MSN_ProcessURIObject(MCONTACT hContact, ezxml_t xmli);
void MSN_CustomSmiley(const char* msgBody, char* email, char* nick, int iSmileyType);
void MSN_InviteMessage(ThreadData* info, char* msgBody, char* email, char* nick);
void MSN_SetMirVer(MCONTACT hContact, DWORD dwValue, bool always);
@@ -498,6 +497,7 @@ struct CMsnProto : public PROTO<CMsnProto>
CMStringA HotmailLogin(const char* url);
void FreeAuthTokens(void);
int GetMyNetID(void);
+ const char *GetSkypeToken(bool bAsAuthHeader);
LPCSTR GetMyUsername(int netId);
/////////////////////////////////////////////////////////////////////////////////////////
diff --git a/protocols/MSN/src/msn_threads.cpp b/protocols/MSN/src/msn_threads.cpp
index 41ba2551db..a28e381196 100644
--- a/protocols/MSN/src/msn_threads.cpp
+++ b/protocols/MSN/src/msn_threads.cpp
@@ -616,9 +616,9 @@ void ThreadData::applyGatewayData(HANDLE hConn, bool isPoll)
void ThreadData::getGatewayUrl(char* dest, int destlen, bool isPoll)
{
- static const char openFmtStr[] = "https://%s/gateway/gateway.dll?Action=open&Server=%s&IP=%s";
- static const char pollFmtStr[] = "https://%s/gateway/gateway.dll?Action=poll&SessionID=%s";
- static const char cmdFmtStr[] = "https://%s/gateway/gateway.dll?SessionID=%s";
+ static const char openFmtStr[] = "http://%s/gateway/gateway.dll?Action=open&Server=%s&IP=%s";
+ static const char pollFmtStr[] = "http://%s/gateway/gateway.dll?Action=poll&SessionID=%s";
+ static const char cmdFmtStr[] = "http://%s/gateway/gateway.dll?SessionID=%s";
if (mSessionID[0] == 0) {
const char* svr = mType == SERVER_NOTIFICATION ? "NS" : "SB";