From e62bc2a6f28f6a7b7fcb3996e9fab86fae3239f7 Mon Sep 17 00:00:00 2001 From: Alexander Lantsev Date: Mon, 24 Feb 2014 17:38:35 +0000 Subject: Dropbox: - added ability to send files to contacts of other protocols - many other little improvements git-svn-id: http://svn.miranda-ng.org/main/trunk@8263 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/Dropbox/Dropbox_11.vcxproj | 1 + plugins/Dropbox/Dropbox_11.vcxproj.filters | 3 + plugins/Dropbox/src/common.h | 10 +-- plugins/Dropbox/src/dropbox.cpp | 31 +++++++-- plugins/Dropbox/src/dropbox.h | 70 ++++++-------------- plugins/Dropbox/src/dropbox_events.cpp | 65 +++++++++++++++++- plugins/Dropbox/src/dropbox_menus.cpp | 39 ++++++++++- plugins/Dropbox/src/dropbox_services.cpp | 100 +++++++++++----------------- plugins/Dropbox/src/dropbox_transfers.cpp | 102 +++++++++++++---------------- plugins/Dropbox/src/dropbox_utils.cpp | 31 ++++++++- plugins/Dropbox/src/file_transfer.h | 57 ++++++++++++++++ plugins/Dropbox/src/http_request.h | 16 +++-- 12 files changed, 336 insertions(+), 189 deletions(-) create mode 100644 plugins/Dropbox/src/file_transfer.h (limited to 'plugins') diff --git a/plugins/Dropbox/Dropbox_11.vcxproj b/plugins/Dropbox/Dropbox_11.vcxproj index cdd3d7aae4..16db020481 100644 --- a/plugins/Dropbox/Dropbox_11.vcxproj +++ b/plugins/Dropbox/Dropbox_11.vcxproj @@ -188,6 +188,7 @@ + diff --git a/plugins/Dropbox/Dropbox_11.vcxproj.filters b/plugins/Dropbox/Dropbox_11.vcxproj.filters index ad97939cf2..6f2103fb99 100644 --- a/plugins/Dropbox/Dropbox_11.vcxproj.filters +++ b/plugins/Dropbox/Dropbox_11.vcxproj.filters @@ -51,6 +51,9 @@ Header Files + + Header Files + diff --git a/plugins/Dropbox/src/common.h b/plugins/Dropbox/src/common.h index d30863a33b..faa1e30302 100644 --- a/plugins/Dropbox/src/common.h +++ b/plugins/Dropbox/src/common.h @@ -13,6 +13,12 @@ #include #include #include +#include +#include +#include +#include +#include +#include #include #include @@ -20,10 +26,6 @@ #include -#include -#include -#include - #include "version.h" #include "resource.h" #include "dropbox.h" diff --git a/plugins/Dropbox/src/dropbox.cpp b/plugins/Dropbox/src/dropbox.cpp index 9bbee6b9f5..41c53d22a4 100644 --- a/plugins/Dropbox/src/dropbox.cpp +++ b/plugins/Dropbox/src/dropbox.cpp @@ -9,6 +9,8 @@ void CDropbox::Init() HookEvent(ME_OPT_INITIALISE, OnOptionsInit); HookEvent(ME_SYSTEM_MODULESLOADED, CDropbox::OnModulesLoaded); + HookEvent(ME_DB_CONTACT_DELETED, CDropbox::OnContactDeleted); + HookEvent(ME_CLIST_PREBUILDCONTACTMENU, CDropbox::OnPrebuildContactMenu); CreateProtoServiceFunction(MODULE, PS_GETCAPS, CDropbox::ProtoGetCaps); CreateProtoServiceFunction(MODULE, PSS_FILE, CDropbox::ProtoSendFile); @@ -16,11 +18,18 @@ void CDropbox::Init() InitIcons(); InitMenus(); + + INSTANCE->hContactTransfer = 0; } +MCONTACT CDropbox::hContactDefault = 0; + MCONTACT CDropbox::GetDefaultContact() { - return db_find_first(MODULE); + if (!hContactDefault) + hContactDefault = db_find_first(MODULE); + + return hContactDefault; } bool CDropbox::HasAccessToken() @@ -41,9 +50,17 @@ void CDropbox::RequestAcceessToken(MCONTACT hContact) CDropbox::TokenRequestProc, (LPARAM)&request_token) == IDOK) { + char data[1024]; + mir_snprintf( + data, + SIZEOF(data), + Translate("grant_type=authorization_code&code=%s"), + request_token); + HttpRequest *request = new HttpRequest(hNetlibUser, REQUEST_POST, DROPBOX_API_URL "/oauth2/token"); - request->AddParameter("grant_type", "authorization_code"); - request->AddParameter("code", request_token); + request->pData = mir_strdup(data); + request->dataLength = strlen(data); + request->AddHeader("Content-Type", "application/x-www-form-urlencoded"); request->AddBasicAuthHeader(DROPBOX_API_KEY, DROPBOX_API_SECRET); NETLIBHTTPREQUEST *response = request->Send(); @@ -52,7 +69,7 @@ void CDropbox::RequestAcceessToken(MCONTACT hContact) if (response) { - if (response->resultCode == HttpStatus::OK) + if (response->resultCode == HTTP_STATUS::OK) { JSONNODE *root = json_parse(response->pData); if (root != NULL) @@ -122,9 +139,9 @@ void CDropbox::RequestApiAuthorizationAsync(void *arg) TranslateT("Request athorization"), MB_YESNO | MB_ICONQUESTION) == IDYES) { - Singleton::GetInstance()->DestroyAcceessToken(hContact); - Singleton::GetInstance()->RequestAcceessToken(hContact); + INSTANCE->DestroyAcceessToken(hContact); + INSTANCE->RequestAcceessToken(hContact); } else - Singleton::GetInstance()->RequestAcceessToken(hContact); + INSTANCE->RequestAcceessToken(hContact); } \ No newline at end of file diff --git a/plugins/Dropbox/src/dropbox.h b/plugins/Dropbox/src/dropbox.h index 09f162302f..72af0114ee 100644 --- a/plugins/Dropbox/src/dropbox.h +++ b/plugins/Dropbox/src/dropbox.h @@ -1,8 +1,10 @@ #ifndef _DROPBOX_PROTO_H_ #define _DROPBOX_PROTO_H_ +#include #include "singleton.h" #include "http_request.h" +#include "file_transfer.h" #define DROPBOX_API_VER "1" #define DROPBOX_API_ROOT "sandbox" @@ -15,6 +17,10 @@ #define DROPBOX_FILE_CHUNK_SIZE 1024 * 1024 //1 MB +#define BBB_ID_FILE_SEND 10001 + +#define INSTANCE Singleton::GetInstance() + enum { CMI_API_REQUEST_AUTH, @@ -22,56 +28,6 @@ enum CMI_MAX // this item shall be the last one }; -struct FileTransferParam -{ - HANDLE hProcess; - PROTOFILETRANSFERSTATUS pfts; - - int totalFolders; - char **pszFolders; - int relativePathStart; - - FileTransferParam() - { - totalFolders = 0; - pszFolders = NULL; - relativePathStart = 0; - - pfts.cbSize = sizeof(this->pfts); - pfts.flags = PFTS_UTF; - pfts.currentFileNumber = 0; - pfts.currentFileProgress = 0; - pfts.currentFileSize = 0; - pfts.totalBytes = 0; - pfts.totalFiles = 0; - pfts.totalProgress = 0; - pfts.pszFiles = NULL; - pfts.tszWorkingDir = NULL; - pfts.wszCurrentFile = NULL; - } - - ~FileTransferParam() - { - if (pfts.pszFiles) - { - for (int i = 0; pfts.pszFiles[i]; i++) - { - if (pfts.pszFiles[i]) mir_free(pfts.pszFiles[i]); - } - delete pfts.pszFiles; - } - - if (pszFolders) - { - for (int i = 0; pszFolders[i]; i++) - { - if (pszFolders[i]) mir_free(pszFolders[i]); - } - delete pszFolders; - } - } -}; - class CDropbox { public: @@ -81,12 +37,22 @@ public: private: HANDLE hNetlibUser; ULONG hFileProcess; + MCONTACT hContactTransfer; + + static MCONTACT hContactDefault; + static std::map dcftp; static HGENMENU ContactMenuItems[CMI_MAX]; // hooks static int OnModulesLoaded(WPARAM wParam, LPARAM lParam); static int OnOptionsInit(WPARAM wParam, LPARAM lParam); + static int OnContactDeleted(WPARAM wParam, LPARAM lParam); + static int OnPrebuildContactMenu(WPARAM wParam, LPARAM); + static int OnSrmmWindowOpened(WPARAM wParam, LPARAM); + static int OnSrmmButtonPressed(WPARAM wParam, LPARAM); + static int OnFileDoalogCancelled(WPARAM wParam, LPARAM); + static int OnFileDoalogSuccessed(WPARAM wParam, LPARAM); // services static INT_PTR ProtoGetCaps(WPARAM wParam, LPARAM lParam); @@ -106,7 +72,6 @@ private: static void RequestApiAuthorizationAsync(void *arg); // transrers - HttpRequest *CreateFileSendChunkedRequest(const char *data, int length); void SendFileChunkedFirst(const char *data, int length, char *uploadId, int &offset); void SendFileChunkedNext(const char *data, int length, const char *uploadId, int &offset); void SendFileChunkedLast(const char *fileName, const char *uploadId, MCONTACT hContact); @@ -123,12 +88,15 @@ private: // menus static void InitMenus(); + static void Menu_DisableItem(HGENMENU hMenuItem, BOOL bDisable); // dialogs static INT_PTR CALLBACK TokenRequestProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); static INT_PTR CALLBACK MainOptionsProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); // utils + static wchar_t *HttpStatusToText(HTTP_STATUS status); + void ShowNotification(const wchar_t *caption, const wchar_t *message, int flags = 0, MCONTACT hContact = NULL); void ShowNotification(const wchar_t *message, int flags = 0, MCONTACT hContact = NULL); }; diff --git a/plugins/Dropbox/src/dropbox_events.cpp b/plugins/Dropbox/src/dropbox_events.cpp index 02e2a788bd..b670370ae2 100644 --- a/plugins/Dropbox/src/dropbox_events.cpp +++ b/plugins/Dropbox/src/dropbox_events.cpp @@ -2,13 +2,16 @@ int CDropbox::OnModulesLoaded(WPARAM wParam, LPARAM lParam) { + HookEvent(ME_FILEDLG_CANCELED, CDropbox::OnFileDoalogCancelled); + HookEvent(ME_FILEDLG_SUCCEEDED, CDropbox::OnFileDoalogSuccessed); + NETLIBUSER nlu = { sizeof(nlu) }; nlu.flags = NUF_INCOMING | NUF_OUTGOING | NUF_HTTPCONNS | NUF_TCHAR; nlu.szSettingsModule = MODULE; nlu.szSettingsModule = MODULE; nlu.ptszDescriptiveName = L"Dropbox"; - Singleton::GetInstance()->hNetlibUser = (HANDLE)CallService(MS_NETLIB_REGISTERUSER, 0, (LPARAM)&nlu); + INSTANCE->hNetlibUser = (HANDLE)CallService(MS_NETLIB_REGISTERUSER, 0, (LPARAM)&nlu); MCONTACT hContact = GetDefaultContact(); if (!hContact) @@ -20,6 +23,22 @@ int CDropbox::OnModulesLoaded(WPARAM wParam, LPARAM lParam) } } + if (ServiceExists(MS_BB_ADDBUTTON)) + { + BBButton bbd = { sizeof(bbd) }; + bbd.pszModuleName = MODULE; + + bbd.bbbFlags = BBBF_ISIMBUTTON | BBBF_ISRSIDEBUTTON; + bbd.ptszTooltip = TranslateT("Send files to Dropbox"); + bbd.hIcon = LoadSkinnedIconHandle(SKINICON_EVENT_FILE); + bbd.dwButtonID = BBB_ID_FILE_SEND; + bbd.dwDefPos = 100 + bbd.dwButtonID; + CallService(MS_BB_ADDBUTTON, 0, (LPARAM)&bbd); + + HookEvent(ME_MSG_WINDOWEVENT, CDropbox::OnSrmmWindowOpened); + HookEvent(ME_MSG_BUTTONPRESSED, CDropbox::OnSrmmButtonPressed); + } + return 0; } @@ -37,4 +56,48 @@ int CDropbox::OnOptionsInit(WPARAM wParam, LPARAM lParam) //Options_AddPage(wParam, &odp); return 0; +} + +int CDropbox::OnContactDeleted(WPARAM hContact, LPARAM lParam) +{ + if (lstrcmpiA(GetContactProto(hContact), MODULE) == 0) + { + if (INSTANCE->HasAccessToken()) + INSTANCE->DestroyAcceessToken(hContact); + } + + return 0; +} + +int CDropbox::OnSrmmWindowOpened(WPARAM hContact, LPARAM lParam) +{ + MessageWindowEventData *ev = (MessageWindowEventData*)lParam; + if (ev->uType == MSG_WINDOW_EVT_OPENING && ev->hContact) + { + WORD status = CallContactService(hContact, PS_GETSTATUS, 0, 0); + + BBButton bbd = { sizeof(bbd) }; + bbd.pszModuleName = MODULE; + bbd.bbbFlags = (ev->hContact != INSTANCE->GetDefaultContact() || status == ID_STATUS_OFFLINE) ? 0 : BBSF_HIDDEN | BBSF_DISABLED; + + bbd.dwButtonID = BBB_ID_FILE_SEND; + CallService(MS_BB_SETBUTTONSTATE, (WPARAM)ev->hContact, (LPARAM)&bbd); + } + + return 0; +} + +int CDropbox::OnSrmmButtonPressed(WPARAM hContact, LPARAM lParam) +{ + CustomButtonClickData *cbc = (CustomButtonClickData *)lParam; + if (!strcmp(cbc->pszModule, MODULE) && cbc->dwButtonId == BBB_ID_FILE_SEND && hContact) + { + INSTANCE->hContactTransfer = hContact; + + HWND hwnd = (HWND)CallService(MS_FILE_SENDFILE, INSTANCE->GetDefaultContact(), 0); + + dcftp[hwnd] = hContact; + } + + return 0; } \ No newline at end of file diff --git a/plugins/Dropbox/src/dropbox_menus.cpp b/plugins/Dropbox/src/dropbox_menus.cpp index aff00f4187..f510858240 100644 --- a/plugins/Dropbox/src/dropbox_menus.cpp +++ b/plugins/Dropbox/src/dropbox_menus.cpp @@ -8,12 +8,12 @@ void CDropbox::InitMenus() mi.cbSize = sizeof(CLISTMENUITEM); mi.flags = CMIF_TCHAR; - /*mi.pszService = MODULE"/SendFilesToDropbox"; + mi.pszService = MODULE"/SendFilesToDropbox"; mi.ptszName = LPGENT("Send files to Dropbox"); - mi.position = -201000000 + CMI_SEND_FILES; + mi.position = -201002000 + CMI_SEND_FILES; mi.icolibItem = LoadSkinnedIconHandle(SKINICON_EVENT_FILE); ContactMenuItems[CMI_SEND_FILES] = Menu_AddContactMenuItem(&mi); - CreateServiceFunction(mi.pszService, SendFilesToDropbox);*/ + CreateServiceFunction(mi.pszService, SendFilesToDropbox); mi.pszService = MODULE"/RequestAuthorization"; mi.ptszName = LPGENT("Request Authorization"); @@ -21,4 +21,37 @@ void CDropbox::InitMenus() mi.icolibItem = LoadSkinnedIconHandle(SKINICON_AUTH_REQUEST); ContactMenuItems[CMI_API_REQUEST_AUTH] = Menu_AddContactMenuItem(&mi); CreateServiceFunction(mi.pszService, RequestApiAuthorization); +} + +void CDropbox::Menu_DisableItem(HGENMENU hMenuItem, BOOL bDisable) +{ + CLISTMENUITEM clmi = { sizeof(clmi) }; + clmi.cbSize = sizeof(CLISTMENUITEM); + clmi.flags = CMIM_FLAGS; + if (bDisable) + clmi.flags |= CMIF_GRAYED; + + Menu_ModifyItem(hMenuItem, &clmi); +} + +int CDropbox::OnPrebuildContactMenu(WPARAM hContact, LPARAM lParam) +{ + if ( !hContact) + return 0; + + //bool ctrlPressed = (GetKeyState(VK_CONTROL) & 0x8000) != 0; + WORD status = CallContactService(hContact, PS_GETSTATUS, 0, 0); + + if (hContact == INSTANCE->GetDefaultContact() || status == ID_STATUS_OFFLINE) + Menu_ShowItem(INSTANCE->ContactMenuItems[CMI_SEND_FILES], FALSE); + else + { + Menu_DisableItem(INSTANCE->ContactMenuItems[CMI_SEND_FILES], INSTANCE->hContactTransfer); + if (strcmp(GetContactProto(hContact), MODULE)) + { + Menu_ShowItem(INSTANCE->ContactMenuItems[CMI_API_REQUEST_AUTH], FALSE); + } + } + + return 0; } \ No newline at end of file diff --git a/plugins/Dropbox/src/dropbox_services.cpp b/plugins/Dropbox/src/dropbox_services.cpp index c485779737..1ce493c25a 100644 --- a/plugins/Dropbox/src/dropbox_services.cpp +++ b/plugins/Dropbox/src/dropbox_services.cpp @@ -23,9 +23,11 @@ INT_PTR CDropbox::ProtoSendFile(WPARAM wParam, LPARAM lParam) { CCSDATA *pccsd = (CCSDATA*)lParam; - FileTransferParam *ftp = new FileTransferParam(); + FileTransfer *ftp = new FileTransfer(); ftp->pfts.flags = PFTS_SENDING | PFTS_UTF; ftp->pfts.hContact = pccsd->hContact; + ftp->hContact = (INSTANCE->hContactTransfer) ? INSTANCE->hContactTransfer : pccsd->hContact; + INSTANCE->hContactTransfer = 0; char **files = (char**)pccsd->lParam; @@ -73,7 +75,8 @@ INT_PTR CDropbox::ProtoSendFile(WPARAM wParam, LPARAM lParam) k++; } } - ULONG fileId = InterlockedIncrement(&Singleton::GetInstance()->hFileProcess); + + ULONG fileId = InterlockedIncrement(&INSTANCE->hFileProcess); ftp->hProcess = (HANDLE)fileId; mir_forkthread(CDropbox::SendFileAsync, ftp); @@ -83,6 +86,19 @@ INT_PTR CDropbox::ProtoSendFile(WPARAM wParam, LPARAM lParam) INT_PTR CDropbox::ProtoSendMessage( WPARAM wParam, LPARAM lParam) { + CCSDATA *pccsd = (CCSDATA*)lParam; + + char *message = (char*)pccsd->lParam; + + DBEVENTINFO dbei = { sizeof(dbei) }; + dbei.szModule = MODULE; + dbei.timestamp = time(NULL); + dbei.eventType = EVENTTYPE_MESSAGE; + dbei.cbBlob = strlen(message); + dbei.pBlob = (PBYTE)mir_strdup(message); + //dbei.flags = DBEF_UTF; + db_event_add(pccsd->hContact, &dbei); + return 0; } @@ -93,73 +109,33 @@ INT_PTR CDropbox::RequestApiAuthorization(WPARAM wParam, LPARAM lParam) return 0; } -INT_PTR CDropbox::SendFilesToDropbox(WPARAM wParam, LPARAM lParam) -{ - TCHAR filter[128], *pfilter; - wchar_t buffer[4096] = {0}; - - OPENFILENAME ofn = {0}; - ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400; - //ofn.hwndOwner = hwndDlg; - lstrcpy(filter, TranslateT("All files")); - lstrcat(filter, _T(" (*)")); - pfilter = filter + lstrlen(filter)+1; - lstrcpy(pfilter, _T("*")); - pfilter = filter + lstrlen(filter)+1; - pfilter[ 0 ] = '\0'; - ofn.lpstrFilter = filter; - ofn.lpstrFile = buffer; - ofn.nMaxFile = 4096; - ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_ALLOWMULTISELECT | OFN_EXPLORER | OFN_NOCHANGEDIR | OFN_HIDEREADONLY | OFN_DONTADDTORECENT; - if (GetOpenFileName(&ofn)) - { - wchar_t **files = NULL; +std::map CDropbox::dcftp; - if (buffer[ofn.nFileOffset - 1] != '\0') - { - // Single-Select - files = (wchar_t**)mir_alloc(sizeof(wchar_t*) * 2); +INT_PTR CDropbox::SendFilesToDropbox(WPARAM hContact, LPARAM lParam) +{ + INSTANCE->hContactTransfer = hContact; - files[0] = mir_wstrdup(buffer); - files[1] = NULL; - } - else - { - // Multi-Select - int i = 0; - wchar_t *p = buffer; + HWND hwnd = (HWND)CallService(MS_FILE_SENDFILE, INSTANCE->GetDefaultContact(), 0); - while (*p) - { - p += lstrlen(p) + 1; - i++; - } + dcftp[hwnd] = hContact; - files = (wchar_t**)mir_alloc(sizeof(wchar_t*) * i); - p = buffer; i = 0; + return 0; +} - while (*p) - { - p += lstrlen(p) + 1; - if (lstrlen(p) > 0) - { - int len = lstrlen(buffer) + lstrlen(p) + 1; - files[i] = (wchar_t*)mir_alloc(sizeof(wchar_t) * len); - lstrcpy(files[i], buffer); - lstrcat(files[i], L"\\"); - lstrcat(files[i], p); - files[i++][len] = '\0'; - } - } - files[i] = NULL; - } +int CDropbox::OnFileDoalogCancelled(WPARAM hContact, LPARAM lParam) +{ + HWND hwnd = (HWND)lParam; + if (INSTANCE->hContactTransfer == dcftp[hwnd]) + dcftp.erase((HWND)lParam); - /*char *cHandle = (char*)wParam; - char hHandle[16]= { 0 }; - strcat(&hHandle[1], cHandle);*/ + return 0; +} - CallContactService(wParam, PSS_FILET, wParam, (LPARAM)files); - } +int CDropbox::OnFileDoalogSuccessed(WPARAM hContact, LPARAM lParam) +{ + HWND hwnd = (HWND)lParam; + if (INSTANCE->hContactTransfer == dcftp[hwnd]) + dcftp.erase((HWND)lParam); return 0; } \ No newline at end of file diff --git a/plugins/Dropbox/src/dropbox_transfers.cpp b/plugins/Dropbox/src/dropbox_transfers.cpp index 4d5dd7c2e6..c87d06fe15 100644 --- a/plugins/Dropbox/src/dropbox_transfers.cpp +++ b/plugins/Dropbox/src/dropbox_transfers.cpp @@ -1,31 +1,21 @@ #include "common.h" -HttpRequest *CDropbox::CreateFileSendChunkedRequest(const char *data, int length) +void CDropbox::SendFileChunkedFirst(const char *data, int length, char *uploadId, int &offset) { HttpRequest *request = new HttpRequest(hNetlibUser, REQUEST_PUT, DROPBOX_APICONTENT_URL "/chunked_upload"); request->AddBearerAuthHeader(db_get_sa(NULL, MODULE, "TokenSecret")); - if (length > 0) - { - request->AddHeader("Content-Type", "application/octet-stream"); - request->dataLength = length; - request->pData = (char*)mir_alloc(sizeof(char) * (length + 1)); - memcpy(request->pData, data, length); - request->pData[length] = 0; - } + request->AddHeader("Content-Type", "application/octet-stream"); + request->pData = (char*)mir_alloc(sizeof(char) * length ); + memcpy(request->pData, data, length); + request->dataLength = length; - return request; -} - -void CDropbox::SendFileChunkedFirst(const char *data, int length, char *uploadId, int &offset) -{ - HttpRequest *request = CreateFileSendChunkedRequest(data, length); NETLIBHTTPREQUEST *response = request->Send(); delete request; if (response) { - if (response->resultCode == HttpStatus::OK) + if (response->resultCode == HTTP_STATUS::OK) { JSONNODE *root = json_parse(response->pData); if (root != NULL) @@ -47,9 +37,15 @@ void CDropbox::SendFileChunkedFirst(const char *data, int length, char *uploadId void CDropbox::SendFileChunkedNext(const char *data, int length, const char *uploadId, int &offset) { - HttpRequest *request = CreateFileSendChunkedRequest(data, length); - request->AddParameter("upload_id", uploadId); - request->AddParameter("offset", offset); + CMStringA url = DROPBOX_APICONTENT_URL "/chunked_upload"; + url.AppendFormat("?upload_id=%s&offset=%i", uploadId, offset); + + HttpRequest *request = new HttpRequest(hNetlibUser, REQUEST_PUT, url); + request->AddBearerAuthHeader(db_get_sa(NULL, MODULE, "TokenSecret")); + request->AddHeader("Content-Type", "application/octet-stream"); + request->pData = (char*)mir_alloc(sizeof(char) * length); + memcpy(request->pData, data, length); + request->dataLength = length; NETLIBHTTPREQUEST *response = request->Send(); @@ -57,7 +53,7 @@ void CDropbox::SendFileChunkedNext(const char *data, int length, const char *upl if (response) { - if (response->resultCode == HttpStatus::OK) + if (response->resultCode == HTTP_STATUS::OK) { JSONNODE *root = json_parse(response->pData); if (root != NULL) @@ -84,9 +80,13 @@ void CDropbox::SendFileChunkedLast(const char *fileName, const char *uploadId, M fileName); url.Replace('\\', '/'); + CMStringA param = CMStringA("upload_id=") + uploadId; + HttpRequest *request = new HttpRequest(hNetlibUser, REQUEST_POST, url); - request->AddParameter("upload_id", uploadId); request->AddBearerAuthHeader(db_get_sa(NULL, MODULE, "TokenSecret")); + request->AddHeader("Content-Type", "application/x-www-form-urlencoded"); + request->pData = mir_strdup(param); + request->dataLength = param.GetLength(); NETLIBHTTPREQUEST *response = request->Send(); @@ -94,7 +94,7 @@ void CDropbox::SendFileChunkedLast(const char *fileName, const char *uploadId, M if (response) { - if (response->resultCode == HttpStatus::OK && !strchr(fileName, '\\')) + if (response->resultCode == HTTP_STATUS::OK && !strchr(fileName, '\\')) { url.Replace(DROPBOX_APICONTENT_URL, DROPBOX_API_URL); url.Replace("commit_chunked_upload", "shares"); @@ -108,12 +108,13 @@ void CDropbox::SendFileChunkedLast(const char *fileName, const char *uploadId, M if (response) { - if (response->resultCode == HttpStatus::OK) + if (response->resultCode == HTTP_STATUS::OK) { JSONNODE *root = json_parse(response->pData); if (root != NULL) { JSONNODE *node = json_get(root, "url"); + char message[1024]; mir_snprintf( message, @@ -122,14 +123,7 @@ void CDropbox::SendFileChunkedLast(const char *fileName, const char *uploadId, M fileName, mir_utf8encodeW(json_as_string(node))); - DBEVENTINFO dbei = { sizeof(dbei) }; - dbei.szModule = MODULE; - dbei.timestamp = time(NULL); - dbei.eventType = EVENTTYPE_MESSAGE; - dbei.cbBlob = strlen(message); - dbei.pBlob = (PBYTE)mir_strdup(message); - dbei.flags = DBEF_UTF; - ::db_event_add(hContact, &dbei); + CallContactService(hContact, PSS_MESSAGE, 0, (LPARAM)&message); delete node; delete root; @@ -149,10 +143,16 @@ void CDropbox::CreateFolder(const char *folderName, MCONTACT hContact) CMStringA folder = folderName; folder.Replace('\\', '/'); + CMStringA param; + param.AppendFormat("root=%s&path=%s", + DROPBOX_API_ROOT, + folder); + HttpRequest *request = new HttpRequest(hNetlibUser, REQUEST_POST, DROPBOX_API_URL "/fileops/create_folder"); - request->AddParameter("root", DROPBOX_API_ROOT); - request->AddParameter("path", folderName); request->AddBearerAuthHeader(db_get_sa(NULL, MODULE, "TokenSecret")); + request->AddHeader("Content-Type", "application/x-www-form-urlencoded"); + request->pData = mir_strdup(param); + request->dataLength = param.GetLength(); NETLIBHTTPREQUEST *response = request->Send(); @@ -160,16 +160,12 @@ void CDropbox::CreateFolder(const char *folderName, MCONTACT hContact) if (response) { - if (response->resultCode == HttpStatus::OK && !strchr(folderName, '\\')) + if (response->resultCode == HTTP_STATUS::OK && !strchr(folderName, '\\')) { - char url[MAX_PATH]; - mir_snprintf( - url, - SIZEOF(url), - "%s/shares/%s/%s", - DROPBOX_API_URL, + CMStringA url = DROPBOX_API_URL; + url.AppendFormat("/shares/%s/%s", DROPBOX_API_ROOT, - folder.GetBuffer()); + folder); request = new HttpRequest(hNetlibUser, REQUEST_POST, url); request->AddBearerAuthHeader(db_get_sa(NULL, MODULE, "TokenSecret")); @@ -180,7 +176,7 @@ void CDropbox::CreateFolder(const char *folderName, MCONTACT hContact) if (response) { - if (response->resultCode == HttpStatus::OK) + if (response->resultCode == HTTP_STATUS::OK) { JSONNODE *root = json_parse(response->pData); if (root != NULL) @@ -194,14 +190,7 @@ void CDropbox::CreateFolder(const char *folderName, MCONTACT hContact) folderName, mir_utf8encodeW(json_as_string(node))); - DBEVENTINFO dbei = { sizeof(dbei) }; - dbei.szModule = MODULE; - dbei.timestamp = time(NULL); - dbei.eventType = EVENTTYPE_MESSAGE; - dbei.cbBlob = strlen(message); - dbei.pBlob = (PBYTE)mir_strdup(message); - dbei.flags = DBEF_UTF; - ::db_event_add(hContact, &dbei); + CallContactService(hContact, PSS_MESSAGE, 0, (LPARAM)&message); delete node; delete root; @@ -218,12 +207,12 @@ void CDropbox::CreateFolder(const char *folderName, MCONTACT hContact) void _cdecl CDropbox::SendFileAsync(void *arg) { - FileTransferParam *ftp = (FileTransferParam *)arg; + FileTransfer *ftp = (FileTransfer*)arg; ProtoBroadcastAck(MODULE, ftp->pfts.hContact, ACKTYPE_FILE, ACKRESULT_INITIALISING, ftp->hProcess, 0); for (int i = 0; ftp->pszFolders[i]; i++) - Singleton::GetInstance()->CreateFolder(ftp->pszFolders[i], ftp->pfts.hContact); + INSTANCE->CreateFolder(ftp->pszFolders[i], ftp->hContact); for (int i = 0; ftp->pfts.pszFiles[i]; i++) { @@ -262,9 +251,9 @@ void _cdecl CDropbox::SendFileAsync(void *arg) int count = fread(data, sizeof(char), chunkSize, file); if (!offset) - Singleton::GetInstance()->SendFileChunkedFirst(data, count, uploadId, offset); + INSTANCE->SendFileChunkedFirst(data, count, uploadId, offset); else - Singleton::GetInstance()->SendFileChunkedNext(data, count, uploadId, offset); + INSTANCE->SendFileChunkedNext(data, count, uploadId, offset); ftp->pfts.currentFileProgress += count; ftp->pfts.totalProgress += count; @@ -274,7 +263,7 @@ void _cdecl CDropbox::SendFileAsync(void *arg) fclose(file); - Singleton::GetInstance()->SendFileChunkedLast(fileName, uploadId, ftp->pfts.hContact); + INSTANCE->SendFileChunkedLast(fileName, uploadId, ftp->hContact); ftp->pfts.currentFileProgress = ftp->pfts.currentFileSize; if (i < ftp->pfts.totalFiles - 1) @@ -282,6 +271,9 @@ void _cdecl CDropbox::SendFileAsync(void *arg) } } + if (INSTANCE->hContactTransfer) + INSTANCE->hContactTransfer = 0; + ProtoBroadcastAck(MODULE, ftp->pfts.hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, ftp->hProcess, 0); delete ftp; diff --git a/plugins/Dropbox/src/dropbox_utils.cpp b/plugins/Dropbox/src/dropbox_utils.cpp index eaed860e19..cba5442ba9 100644 --- a/plugins/Dropbox/src/dropbox_utils.cpp +++ b/plugins/Dropbox/src/dropbox_utils.cpp @@ -1,5 +1,32 @@ #include "common.h" +wchar_t *CDropbox::HttpStatusToText(HTTP_STATUS status) +{ + switch (status) + { + case OK: + return TranslateT("Ok"); + case BAD_REQUEST: + return TranslateT("Bad input parameter. Error message should indicate which one and why"); + case UNAUTHORIZED: + return TranslateT("Bad or expired token. This can happen if the user or Dropbox revoked or expired an access token. To fix, you should re-authenticate the user"); + case FORBIDDEN: + return TranslateT("Bad OAuth request (wrong consumer key, bad nonce, expired timestamp...). Unfortunately, re-authenticating the user won't help here"); + case NOT_FOUND: + return TranslateT("File or folder not found at the specified path"); + case METHOD_NOT_ALLOWED: + return TranslateT("Request method not expected (generally should be GET or POST)"); + case TOO_MANY_REQUESTS: + return TranslateT("Your app is making too many requests and is being rate limited. 429s can trigger on a per-app or per-user basis"); + case SERVICE_UNAVAILABLE: + return TranslateT("If the response includes the Retry-After header, this means your OAuth 1.0 app is being rate limited. Otherwise, this indicates a transient server error, and your app should retry its request."); + case INSUFICIENTE_STORAGE: + return TranslateT("User is over Dropbox storage quota"); + } + + return TranslateT("Unknown"); +} + void CDropbox::ShowNotification(const wchar_t *caption, const wchar_t *message, int flags, MCONTACT hContact) { if (Miranda_Terminated()) return; @@ -14,9 +41,9 @@ void CDropbox::ShowNotification(const wchar_t *caption, const wchar_t *message, if (!PUAddPopupW(&ppd)) return; - + } - + MessageBox(NULL, message, caption, MB_OK | flags); } diff --git a/plugins/Dropbox/src/file_transfer.h b/plugins/Dropbox/src/file_transfer.h new file mode 100644 index 0000000000..1c0a511e47 --- /dev/null +++ b/plugins/Dropbox/src/file_transfer.h @@ -0,0 +1,57 @@ +#ifndef _FILE_TRANSFER_H_ +#define _FILE_TRANSFER_H_ + +#include "common.h" + +struct FileTransfer +{ + HANDLE hProcess; + MCONTACT hContact; + PROTOFILETRANSFERSTATUS pfts; + + int totalFolders; + char **pszFolders; + int relativePathStart; + + FileTransfer() + { + totalFolders = 0; + pszFolders = NULL; + relativePathStart = 0; + + pfts.cbSize = sizeof(this->pfts); + pfts.flags = PFTS_UTF; + pfts.currentFileNumber = 0; + pfts.currentFileProgress = 0; + pfts.currentFileSize = 0; + pfts.totalBytes = 0; + pfts.totalFiles = 0; + pfts.totalProgress = 0; + pfts.pszFiles = NULL; + pfts.tszWorkingDir = NULL; + pfts.wszCurrentFile = NULL; + } + + ~FileTransfer() + { + if (pfts.pszFiles) + { + for (int i = 0; pfts.pszFiles[i]; i++) + { + if (pfts.pszFiles[i]) mir_free(pfts.pszFiles[i]); + } + delete pfts.pszFiles; + } + + if (pszFolders) + { + for (int i = 0; pszFolders[i]; i++) + { + if (pszFolders[i]) mir_free(pszFolders[i]); + } + delete pszFolders; + } + } +}; + +#endif //_FILE_TRANSFER_H_ \ No newline at end of file diff --git a/plugins/Dropbox/src/http_request.h b/plugins/Dropbox/src/http_request.h index 81a6dcd99d..79882053e3 100644 --- a/plugins/Dropbox/src/http_request.h +++ b/plugins/Dropbox/src/http_request.h @@ -3,9 +3,17 @@ #include "common.h" -enum HttpStatus +enum HTTP_STATUS { - OK = 200 + OK = 200, + BAD_REQUEST = 400, + UNAUTHORIZED = 401, + FORBIDDEN = 403, + NOT_FOUND = 404, + METHOD_NOT_ALLOWED = 405, + TOO_MANY_REQUESTS = 429, + SERVICE_UNAVAILABLE = 503, + INSUFICIENTE_STORAGE = 507 }; class HttpRequest : public NETLIBHTTPREQUEST, public MZeroedObject @@ -83,7 +91,7 @@ public: headersCount++; } - void AddParameter(LPCSTR szName, LPCSTR szValue) + /*void AddParameter(LPCSTR szName, LPCSTR szValue) { if (m_szUrl.Find('?') == -1) m_szUrl.AppendFormat("?%s=%s", szName, szValue); @@ -97,7 +105,7 @@ public: m_szUrl.AppendFormat("?%s=%i", szName, value); else m_szUrl.AppendFormat("&%s=%i", szName, value); - } + }*/ NETLIBHTTPREQUEST *Send() { -- cgit v1.2.3