diff options
-rw-r--r-- | protocols/SkypeWeb/SkypeWeb.vcxproj | 1 | ||||
-rw-r--r-- | protocols/SkypeWeb/SkypeWeb.vcxproj.filters | 3 | ||||
-rw-r--r-- | protocols/SkypeWeb/src/requests/files.h | 67 | ||||
-rw-r--r-- | protocols/SkypeWeb/src/skype_files.cpp | 120 | ||||
-rw-r--r-- | protocols/SkypeWeb/src/skype_proto.h | 5 | ||||
-rw-r--r-- | protocols/SkypeWeb/src/skype_utils.h | 17 | ||||
-rw-r--r-- | protocols/SkypeWeb/src/stdafx.h | 1 |
7 files changed, 99 insertions, 115 deletions
diff --git a/protocols/SkypeWeb/SkypeWeb.vcxproj b/protocols/SkypeWeb/SkypeWeb.vcxproj index 0ee9f1eac3..4bf088ab26 100644 --- a/protocols/SkypeWeb/SkypeWeb.vcxproj +++ b/protocols/SkypeWeb/SkypeWeb.vcxproj @@ -55,7 +55,6 @@ <ClInclude Include="src\requests\chatrooms.h" />
<ClInclude Include="src\requests\contacts.h" />
<ClInclude Include="src\requests\endpoint.h" />
- <ClInclude Include="src\requests\files.h" />
<ClInclude Include="src\requests\history.h" />
<ClInclude Include="src\requests\login.h" />
<ClInclude Include="src\requests\messages.h" />
diff --git a/protocols/SkypeWeb/SkypeWeb.vcxproj.filters b/protocols/SkypeWeb/SkypeWeb.vcxproj.filters index e52040b257..dd8efdbab3 100644 --- a/protocols/SkypeWeb/SkypeWeb.vcxproj.filters +++ b/protocols/SkypeWeb/SkypeWeb.vcxproj.filters @@ -90,9 +90,6 @@ <ClInclude Include="src\requests\endpoint.h">
<Filter>Header Files\Requests</Filter>
</ClInclude>
- <ClInclude Include="src\requests\files.h">
- <Filter>Header Files\Requests</Filter>
- </ClInclude>
<ClInclude Include="src\requests\history.h">
<Filter>Header Files\Requests</Filter>
</ClInclude>
diff --git a/protocols/SkypeWeb/src/requests/files.h b/protocols/SkypeWeb/src/requests/files.h deleted file mode 100644 index 7c04baabfb..0000000000 --- a/protocols/SkypeWeb/src/requests/files.h +++ /dev/null @@ -1,67 +0,0 @@ -#pragma once - -struct ASMObjectCreateRequest : public AsyncHttpRequest -{ - ASMObjectCreateRequest(CSkypeProto *ppro, CFileUploadParam *fup) : - AsyncHttpRequest(REQUEST_POST, HOST_OTHER, "https://api.asm.skype.com/v1/objects", &CSkypeProto::OnASMObjectCreated) - { - flags &= (~NLHRF_DUMPASTEXT); - pUserInfo = fup; - - AddHeader("Authorization", CMStringA(FORMAT, "skype_token %s", ppro->m_szApiToken.get())); - AddHeader("Content-Type", "application/json"); - AddHeader("X-Client-Version", "0/0.0.0.0"); - - CMStringA szContact(ppro->getId(fup->hContact)); - T2Utf uszFileName(fup->tszFileName); - const char *szFileName = strrchr(uszFileName.get() + 1, '\\'); - - JSONNode node; - if (fup->isPicture) - node << CHAR_PARAM("type", "pish/image"); - else - node << CHAR_PARAM("type", "sharing/file"); - - JSONNode jPermission(JSON_ARRAY); jPermission.set_name(szContact.c_str()); jPermission << CHAR_PARAM("", "read"); - JSONNode jPermissions; jPermissions.set_name("permissions"); jPermissions << jPermission; - node << CHAR_PARAM("filename", szFileName) << jPermissions; - m_szParam = node.write().c_str(); - } -}; - -struct ASMObjectUploadRequest : public AsyncHttpRequest -{ - ASMObjectUploadRequest(CSkypeProto *ppro, const char *szObject, const uint8_t *data, int size, CFileUploadParam *fup) : - AsyncHttpRequest(REQUEST_PUT, HOST_OTHER, 0, &CSkypeProto::OnASMObjectUploaded) - { - m_szUrl.AppendFormat("https://api.asm.skype.com/v1/objects/%s/content/%s", - szObject, fup->isPicture ? "imgpsh" : "original"); - pUserInfo = fup; - - AddHeader("Authorization", CMStringA(FORMAT, "skype_token %s", ppro->m_szApiToken.get())); - AddHeader("Content-Type", fup->isPicture ? "application" : "application/octet-stream"); - - m_szParam.Truncate(size); - memcpy(m_szParam.GetBuffer(), data, size); - } -}; - -struct SendFileRequest : public AsyncHttpRequest -{ - SendFileRequest(CFileUploadParam *fup, const char *username, const char *message) : - AsyncHttpRequest(REQUEST_POST, HOST_DEFAULT, 0, &CSkypeProto::OnMessageSent) - { - m_szUrl.AppendFormat("/users/ME/conversations/%s/messages", mir_urlEncode(username).c_str()); - - JSONNode ref(JSON_ARRAY); ref.set_name("amsreferences"); ref << CHAR_PARAM("", fup->uid); - - JSONNode node; - if (fup->isPicture) - node << CHAR_PARAM("messagetype", "RichText/UriObject"); - else - node << CHAR_PARAM("messagetype", "RichText/Media_GenericFile"); - - node << INT64_PARAM("clientmessageid", time(0)) << CHAR_PARAM("contenttype", "text") << CHAR_PARAM("content", message) << ref; - m_szParam = node.write().c_str(); - } -}; diff --git a/protocols/SkypeWeb/src/skype_files.cpp b/protocols/SkypeWeb/src/skype_files.cpp index 24f279a600..6d3f6646db 100644 --- a/protocols/SkypeWeb/src/skype_files.cpp +++ b/protocols/SkypeWeb/src/skype_files.cpp @@ -101,37 +101,48 @@ INT_PTR CSkypeProto::SvcOfflineFile(WPARAM param, LPARAM) #define FILETRANSFER_FAILED(fup) { ProtoBroadcastAck(fup->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, (HANDLE)fup); delete fup; fup = nullptr;}
-HANDLE CSkypeProto::SendFile(MCONTACT hContact, const wchar_t *szDescription, wchar_t **ppszFiles)
-{
- if (IsOnline()) {
- CFileUploadParam *fup = new CFileUploadParam(hContact, szDescription, ppszFiles);
- ForkThread(&CSkypeProto::SendFileThread, (void*)fup);
- return (HANDLE)fup;
- }
- return INVALID_HANDLE_VALUE;
-}
-
-void CSkypeProto::SendFileThread(void *p)
+void CSkypeProto::SendFile(CFileUploadParam *fup)
{
- CFileUploadParam *fup = (CFileUploadParam *)p;
- if (!IsOnline()) {
- FILETRANSFER_FAILED(fup);
- return;
- }
- if (!fup->IsAccess()) {
+ auto *pwszFileName = &fup->arFileName[0];
+ if (!IsOnline() || _waccess(pwszFileName, 0)) {
FILETRANSFER_FAILED(fup);
return;
}
- if (auto *pBitmap = FreeImage_LoadU(FreeImage_GetFIFFromFilenameU(fup->tszFileName), fup->tszFileName)) {
+ if (auto *pBitmap = FreeImage_LoadU(FreeImage_GetFIFFromFilenameU(pwszFileName), pwszFileName)) {
fup->isPicture = true;
fup->width = FreeImage_GetWidth(pBitmap);
fup->height = FreeImage_GetHeight(pBitmap);
FreeImage_Unload(pBitmap);
}
+ else fup->isPicture = false;
ProtoBroadcastAck(fup->hContact, ACKTYPE_FILE, ACKRESULT_CONNECTING, (HANDLE)fup);
- PushRequest(new ASMObjectCreateRequest(this, fup));
+
+ // create upload slot
+ auto *pReq = new AsyncHttpRequest(REQUEST_POST, HOST_OTHER, "https://api.asm.skype.com/v1/objects", &CSkypeProto::OnASMObjectCreated);
+ pReq->flags &= (~NLHRF_DUMPASTEXT);
+ pReq->pUserInfo = fup;
+
+ pReq->AddHeader("Authorization", CMStringA(FORMAT, "skype_token %s", m_szApiToken.get()));
+ pReq->AddHeader("Content-Type", "application/json");
+ pReq->AddHeader("X-Client-Version", "0/0.0.0.0");
+
+ CMStringA szContact(getId(fup->hContact));
+ T2Utf uszFileName(&fup->arFileName[0]);
+ const char *szFileName = strrchr(uszFileName.get() + 1, '\\');
+
+ JSONNode node;
+ if (fup->isPicture)
+ node << CHAR_PARAM("type", "pish/image");
+ else
+ node << CHAR_PARAM("type", "sharing/file");
+
+ JSONNode jPermission(JSON_ARRAY); jPermission.set_name(szContact.c_str()); jPermission << CHAR_PARAM("", "read");
+ JSONNode jPermissions; jPermissions.set_name("permissions"); jPermissions << jPermission;
+ node << CHAR_PARAM("filename", szFileName) << jPermissions;
+ pReq->m_szParam = node.write().c_str();
+ PushRequest(pReq);
}
void CSkypeProto::OnASMObjectCreated(MHttpResponse *response, AsyncHttpRequest *pRequest)
@@ -156,8 +167,9 @@ LBL_Error: }
fup->uid = mir_strdup(strObjectId.c_str());
- FILE *pFile = _wfopen(fup->tszFileName, L"rb");
- if (pFile == nullptr) return;
+ FILE *pFile = _wfopen(&fup->arFileName[0], L"rb");
+ if (pFile == nullptr)
+ goto LBL_Error;
fseek(pFile, 0, SEEK_END);
long lFileLen = ftell(pFile);
@@ -170,25 +182,37 @@ LBL_Error: mir_ptr<uint8_t> pData((uint8_t*)mir_alloc(lFileLen));
long lBytes = (long)fread(pData, sizeof(uint8_t), lFileLen, pFile);
- if (lBytes != lFileLen) {
- fclose(pFile);
+ fclose(pFile);
+
+ if (lBytes != lFileLen)
goto LBL_Error;
- }
+
fup->size = lBytes;
ProtoBroadcastAck(fup->hContact, ACKTYPE_FILE, ACKRESULT_INITIALISING, (HANDLE)fup);
- PushRequest(new ASMObjectUploadRequest(this, strObjectId.c_str(), pData, lBytes, fup));
- fclose(pFile);
+
+ // upload file to the previously created slot
+ auto *pReq = new AsyncHttpRequest(REQUEST_PUT, HOST_OTHER, 0, &CSkypeProto::OnASMObjectUploaded);
+ pReq->m_szUrl.Format("https://api.asm.skype.com/v1/objects/%s/content/%s",
+ strObjectId.c_str(), fup->isPicture ? "imgpsh" : "original");
+ pReq->pUserInfo = fup;
+
+ pReq->AddHeader("Authorization", CMStringA(FORMAT, "skype_token %s", m_szApiToken.get()));
+ pReq->AddHeader("Content-Type", fup->isPicture ? "application" : "application/octet-stream");
+
+ pReq->m_szParam.Truncate(lBytes);
+ memcpy(pReq->m_szParam.GetBuffer(), pData, lBytes);
+ PushRequest(pReq);
}
void CSkypeProto::OnASMObjectUploaded(MHttpResponse *response, AsyncHttpRequest *pRequest)
{
- auto *fup = (CFileUploadParam*)pRequest->pUserInfo;
+ auto *fup = (CFileUploadParam *)pRequest->pUserInfo;
if (response == nullptr) {
FILETRANSFER_FAILED(fup);
return;
}
- wchar_t *tszFile = wcsrchr(fup->tszFileName, L'\\') + 1;
+ wchar_t *tszFile = wcsrchr(&fup->arFileName[0], L'\\') + 1;
TiXmlDocument doc;
auto *pRoot = doc.NewElement("URIObject");
@@ -224,7 +248,7 @@ void CSkypeProto::OnASMObjectUploaded(MHttpResponse *response, AsyncHttpRequest auto *xmlSize = doc.NewElement("FileSize"); xmlSize->SetAttribute("v", (int)fup->size); pRoot->InsertEndChild(xmlSize);
if (fup->isPicture) {
- auto xmlMeta = doc.NewElement("meta");
+ auto xmlMeta = doc.NewElement("meta");
xmlMeta->SetAttribute("type", "photo"); xmlMeta->SetAttribute("originalName", tszFile);
pRoot->InsertEndChild(xmlMeta);
}
@@ -236,11 +260,43 @@ void CSkypeProto::OnASMObjectUploaded(MHttpResponse *response, AsyncHttpRequest Utils_GetRandom(&hMessage, sizeof(hMessage));
hMessage &= ~0x80000000;
- auto *pReq = new SendFileRequest(fup, getId(fup->hContact), printer.CStr());
+ // create a new file transfer event using previously filled slot
+ auto *pReq = new AsyncHttpRequest(REQUEST_POST, HOST_DEFAULT, 0, &CSkypeProto::OnMessageSent);
+ pReq->m_szUrl.AppendFormat("/users/ME/conversations/%s/messages", mir_urlEncode(getId(fup->hContact)).c_str());
pReq->hContact = fup->hContact;
pReq->pUserInfo = (HANDLE)hMessage;
+
+ JSONNode ref(JSON_ARRAY); ref.set_name("amsreferences"); ref << CHAR_PARAM("", fup->uid);
+
+ JSONNode node;
+ if (fup->isPicture)
+ node << CHAR_PARAM("messagetype", "RichText/UriObject");
+ else
+ node << CHAR_PARAM("messagetype", "RichText/Media_GenericFile");
+
+ node << INT64_PARAM("clientmessageid", time(0)) << CHAR_PARAM("contenttype", "text") << CHAR_PARAM("content", printer.CStr()) << ref;
+ pReq->m_szParam = node.write().c_str();
+
PushRequest(pReq);
- ProtoBroadcastAck(fup->hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, (HANDLE)fup);
- delete fup;
+ // if that's last file in the queue, finish file transfer, or proceed with the next file
+ if (fup->arFileName.getCount() == 1) {
+ ProtoBroadcastAck(fup->hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, (HANDLE)fup);
+ delete fup;
+ }
+ else {
+ fup->arFileName.remove(int(0));
+ ProtoBroadcastAck(fup->hContact, ACKTYPE_FILE, ACKRESULT_NEXTFILE, (HANDLE)fup);
+ SendFile(fup);
+ }
+}
+
+HANDLE CSkypeProto::SendFile(MCONTACT hContact, const wchar_t *szDescription, wchar_t **ppszFiles)
+{
+ if (!IsOnline())
+ return INVALID_HANDLE_VALUE;
+
+ CFileUploadParam *fup = new CFileUploadParam(hContact, ppszFiles, szDescription);
+ SendFile(fup);
+ return fup;
}
diff --git a/protocols/SkypeWeb/src/skype_proto.h b/protocols/SkypeWeb/src/skype_proto.h index da73290f6e..b1feccf602 100644 --- a/protocols/SkypeWeb/src/skype_proto.h +++ b/protocols/SkypeWeb/src/skype_proto.h @@ -94,9 +94,6 @@ public: // search
void __cdecl SearchBasicThread(void *param);
- // threads
- void __cdecl CSkypeProto::SendFileThread(void *p);
-
//////////////////////////////////////////////////////////////////////////////////////
// services
@@ -251,6 +248,8 @@ private: MCONTACT GetContactFromAuthEvent(MEVENT hEvent);
// files
+ void SendFile(CFileUploadParam *fup);
+
void __cdecl ReceiveFileThread(void *param);
INT_PTR __cdecl SvcOfflineFile(WPARAM, LPARAM);
diff --git a/protocols/SkypeWeb/src/skype_utils.h b/protocols/SkypeWeb/src/skype_utils.h index 8c9d73b1b0..feef9b8883 100644 --- a/protocols/SkypeWeb/src/skype_utils.h +++ b/protocols/SkypeWeb/src/skype_utils.h @@ -49,7 +49,7 @@ public: struct CFileUploadParam : public MZeroedObject
{
- ptrW tszFileName;
+ OBJLIST<wchar_t> arFileName;
ptrW tszDesc;
ptrA atr;
ptrA fname;
@@ -59,13 +59,14 @@ struct CFileUploadParam : public MZeroedObject MCONTACT hContact;
bool isPicture;
- __forceinline CFileUploadParam(MCONTACT _hContact, const wchar_t* _desc, wchar_t** _files) :
+ CFileUploadParam(MCONTACT _hContact, wchar_t **_files, const wchar_t* _desc) :
+ arFileName(1),
hContact(_hContact),
- tszDesc(mir_wstrdup(_desc)),
- tszFileName(mir_wstrdup(_files[0]))
- {};
-
- __forceinline bool IsAccess() { return ::_waccess(tszFileName, 0) == 0; }
+ tszDesc(mir_wstrdup(_desc))
+ {
+ for (auto p = _files; *p != 0; p++)
+ arFileName.insert(newStrW(*p));
+ }
};
class JsonReply
@@ -81,4 +82,4 @@ public: __forceinline int error() const { return m_errorCode; }
};
-#endif //_UTILS_H_
\ No newline at end of file +#endif //_UTILS_H_
diff --git a/protocols/SkypeWeb/src/stdafx.h b/protocols/SkypeWeb/src/stdafx.h index 6d77964566..162b708a77 100644 --- a/protocols/SkypeWeb/src/stdafx.h +++ b/protocols/SkypeWeb/src/stdafx.h @@ -117,7 +117,6 @@ struct AsyncHttpRequest : public MTHttpRequest<CSkypeProto> #include "requests/chatrooms.h"
#include "requests/contacts.h"
#include "requests/endpoint.h"
-#include "requests/files.h"
#include "requests/history.h"
#include "requests/login.h"
#include "requests/messages.h"
|