summaryrefslogtreecommitdiff
path: root/plugins/Dropbox/src
diff options
context:
space:
mode:
authorKirill Volinsky <mataes2007@gmail.com>2014-02-19 13:33:46 +0000
committerKirill Volinsky <mataes2007@gmail.com>2014-02-19 13:33:46 +0000
commit36df84a13018c6c26e7cd1bb8e093dc54393aed7 (patch)
treebe220c6dd21741370af430e066486143a4cc747f /plugins/Dropbox/src
parenta8934644810474ad6f367759ee0ea14da12909de (diff)
folder rename
git-svn-id: http://svn.miranda-ng.org/main/trunk@8179 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/Dropbox/src')
-rw-r--r--plugins/Dropbox/src/common.h39
-rw-r--r--plugins/Dropbox/src/dropbox.cpp128
-rw-r--r--plugins/Dropbox/src/dropbox.h110
-rw-r--r--plugins/Dropbox/src/dropbox_dialogs.cpp62
-rw-r--r--plugins/Dropbox/src/dropbox_events.cpp40
-rw-r--r--plugins/Dropbox/src/dropbox_icons.cpp33
-rw-r--r--plugins/Dropbox/src/dropbox_menus.cpp17
-rw-r--r--plugins/Dropbox/src/dropbox_services.cpp82
-rw-r--r--plugins/Dropbox/src/dropbox_transfers.cpp210
-rw-r--r--plugins/Dropbox/src/dropbox_utils.cpp26
-rw-r--r--plugins/Dropbox/src/http_request.h92
-rw-r--r--plugins/Dropbox/src/main.cpp52
-rw-r--r--plugins/Dropbox/src/resource.hbin0 -> 1370 bytes
-rw-r--r--plugins/Dropbox/src/version.h15
14 files changed, 906 insertions, 0 deletions
diff --git a/plugins/Dropbox/src/common.h b/plugins/Dropbox/src/common.h
new file mode 100644
index 0000000000..d3b14a3e15
--- /dev/null
+++ b/plugins/Dropbox/src/common.h
@@ -0,0 +1,39 @@
+#ifndef _COMMON_H_
+#define _COMMON_H_
+
+#include <windows.h>
+#include <Shlwapi.h>
+#include <time.h>
+
+#include <newpluginapi.h>
+
+#include <m_options.h>
+#include <m_database.h>
+#include <m_clist.h>
+#include <m_skin.h>
+#include <m_icolib.h>
+#include <m_popup.h>
+
+#include <m_protoint.h>
+#include <m_protomod.h>
+#include <m_protosvc.h>
+
+#include <m_netlib.h>
+
+#include <m_json.h>
+#include <m_langpack.h>
+#include <m_string.h>
+
+#include "version.h"
+#include "resource.h"
+
+#define MODULE "Dropbox"
+
+class CDropbox;
+
+extern HINSTANCE g_hInstance;
+extern CDropbox *g_dropbox;
+
+HANDLE CreateProtoServiceFunctionObj(const char *szModule, const char *szService, MIRANDASERVICEOBJ serviceProc, void* obj);
+
+#endif //_COMMON_H_ \ No newline at end of file
diff --git a/plugins/Dropbox/src/dropbox.cpp b/plugins/Dropbox/src/dropbox.cpp
new file mode 100644
index 0000000000..35f9a7b832
--- /dev/null
+++ b/plugins/Dropbox/src/dropbox.cpp
@@ -0,0 +1,128 @@
+#include "dropbox.h"
+
+CDropbox::CDropbox()
+{
+ PROTOCOLDESCRIPTOR pd = { PROTOCOLDESCRIPTOR_V3_SIZE };
+ pd.szName = MODULE;
+ pd.type = PROTOTYPE_VIRTUAL;
+ CallService(MS_PROTO_REGISTERMODULE, 0, (LPARAM)&pd);
+
+ HookEvent(ME_OPT_INITIALISE, OnOptionsInit);
+ HookEvent(ME_SYSTEM_MODULESLOADED, CDropbox::OnModulesLoaded);
+
+ CreateProtoServiceFunction(MODULE, PS_GETCAPS, CDropbox::GetCaps);
+ CreateProtoServiceFunction(MODULE, PSS_FILE, CDropbox::SendFile);
+ CreateProtoServiceFunction(MODULE, PSS_MESSAGE, CDropbox::SendMessage);
+
+ InitIcons();
+ InitMenus();
+}
+
+MCONTACT CDropbox::GetDefaultContact()
+{
+ return db_find_first(MODULE);
+}
+
+bool CDropbox::HasAccessToken()
+{
+ return db_get_sa(NULL, MODULE, "TokenSecret") != NULL;
+}
+
+void CDropbox::RequestAcceessToken()
+{
+ ShellExecuteA(NULL, "open", DROPBOX_WWW_URL "/" DROPBOX_API_VER "/oauth2/authorize?response_type=code&client_id=" DROPBOX_API_KEY, NULL, NULL, SW_SHOWDEFAULT);
+
+ char request_token[128] = { 0 };
+ //request_token[0] = 0;
+
+ if (DialogBoxParam(
+ g_hInstance,
+ MAKEINTRESOURCE(IDD_TOKEN_REQUEST),
+ NULL,
+ CDropbox::TokenRequestProc,
+ (LPARAM)&request_token) == IDOK)
+ {
+ char data[64];
+ mir_snprintf(
+ data,
+ SIZEOF(data),
+ "client_id=%s&client_secret=%s",
+ DROPBOX_API_KEY,
+ DROPBOX_API_SECRET);
+
+ HttpRequest *request = new HttpRequest(hNetlibUser, REQUEST_POST, DROPBOX_API_URL "/oauth2/token");
+ request->AddParameter("grant_type", "authorization_code");
+ request->AddParameter("code", request_token);
+ request->AddHeader("Content-Type", "application/x-www-form-urlencoded");
+ request->pData = mir_strdup(data);
+ request->dataLength = strlen(data);
+
+ NETLIBHTTPREQUEST *response = request->Send();
+
+ delete request;
+
+ if (response)
+ {
+ if (response->resultCode == HttpStatus::OK)
+ {
+ JSONNODE *root = json_parse(response->pData);
+ if (root != NULL)
+ {
+ JSONNODE *node = json_get(root, "access_token");
+ ptrA access_token = ptrA(mir_u2a(json_as_string(node)));
+ db_set_s(NULL, MODULE, "TokenSecret", access_token);
+
+ MCONTACT hContact = GetDefaultContact();
+ if (hContact)
+ {
+ node = json_get(root, "uid");
+ wchar_t *uid = json_as_string(node);
+ db_set_ws(hContact, MODULE, "uid", uid);
+ if (db_get_w(hContact, MODULE, "Status", ID_STATUS_OFFLINE) == ID_STATUS_OFFLINE)
+ db_set_w(hContact, MODULE, "Status", ID_STATUS_ONLINE);
+ }
+
+ CDropbox::ShowNotification(TranslateT("Access request"), TranslateT("Access granted"), MB_ICONINFORMATION);
+
+ delete node;
+ delete root;
+ }
+ }
+ else
+ {
+ JSONNODE *root = json_parse(response->pData);
+ if (root != NULL)
+ {
+ JSONNODE *node = json_get(root, "error_description");
+ wchar_t *error_description = json_as_string(node);
+
+ CDropbox::ShowNotification(TranslateT("Access request"), error_description, MB_ICONERROR);
+
+ delete node;
+ delete root;
+ }
+ }
+
+ mir_free(response);
+ }
+ }
+}
+
+void CDropbox::DestroyAcceessToken()
+{
+
+ HttpRequest *request = new HttpRequest(hNetlibUser, REQUEST_POST, DROPBOX_API_URL "/disable_access_token");
+ //request->SendAsync(&CDropboxProto::AsyncFunc);
+ NETLIBHTTPREQUEST *response = request->Send();
+
+ delete request;
+ mir_free(response);
+
+ db_unset(NULL, MODULE, "TokenSecret");
+ MCONTACT hContact = GetDefaultContact();
+ if (hContact)
+ {
+ if (db_get_w(hContact, MODULE, "Status", ID_STATUS_ONLINE) == ID_STATUS_ONLINE)
+ db_set_w(hContact, MODULE, "Status", ID_STATUS_OFFLINE);
+ }
+} \ No newline at end of file
diff --git a/plugins/Dropbox/src/dropbox.h b/plugins/Dropbox/src/dropbox.h
new file mode 100644
index 0000000000..ba400d90d0
--- /dev/null
+++ b/plugins/Dropbox/src/dropbox.h
@@ -0,0 +1,110 @@
+#ifndef _Dropbox_PROTO_H_
+#define _Dropbox_PROTO_H_
+
+//#include "common.h"
+#include "http_request.h"
+
+#define DROPBOX_API_VER "1"
+#define DROPBOX_API_ROOT "sandbox"
+#define DROPBOX_WWW_URL "https://www.dropbox.com/"
+#define DROPBOX_API_URL "https://api.dropbox.com/" DROPBOX_API_VER
+#define DROPBOX_APICONTENT_URL "https://api-content.dropbox.com/" DROPBOX_API_VER
+
+#define DROPBOX_API_KEY "fa8du7gkf2q8xzg"
+#include "..\..\..\Dropbox\secret_key.h"
+
+#define DROPBOX_FILE_CHUNK_SIZE 1024 * 1024 //1 MB
+
+enum
+{
+ CMI_API_ACCESS_REQUERIED,
+ CMI_URL_OPEN_ROOT,
+ CMI_MAX // this item shall be the last one
+};
+
+struct FileTransferParam
+{
+ HANDLE hProcess;
+ PROTOFILETRANSFERSTATUS pfts;
+
+ FileTransferParam()
+ {
+ pfts.cbSize = sizeof(this->pfts);
+ pfts.flags = PFTS_UTF;
+ pfts.currentFileNumber = 0;
+ pfts.currentFileProgress = 0;
+ pfts.currentFileSize = 0;
+ pfts.currentFileTime = 0;
+ pfts.totalBytes = 0;
+ pfts.totalFiles = 0;
+ pfts.totalProgress = 0;
+ pfts.tszWorkingDir = NULL;
+ pfts.wszCurrentFile = NULL;
+ }
+
+ ~FileTransferParam()
+ {
+ for (int i = 0; pfts.pszFiles[pfts.totalFiles]; i++)
+ {
+ delete pfts.pszFiles[i];
+ }
+ delete pfts.pszFiles;
+ }
+};
+
+class CDropbox
+{
+public:
+ CDropbox();
+ ~CDropbox() { }
+
+private:
+ HANDLE hNetlibUser;
+ ULONG hFileProcess;
+
+ static HGENMENU ContactMenuItems[CMI_MAX];
+
+ // hooks
+ static int OnModulesLoaded(WPARAM wParam, LPARAM lParam);
+ static int OnOptionsInit(WPARAM wParam, LPARAM lParam);
+
+ // services
+ static INT_PTR GetCaps(WPARAM wParam, LPARAM lParam);
+ static INT_PTR SendFile(WPARAM wParam, LPARAM lParam);
+ static INT_PTR SendMessage(WPARAM wParam, LPARAM lParam);
+
+ static INT_PTR RequeriedApiAccess(WPARAM wParam, LPARAM lParam);
+
+ // access token
+ static bool HasAccessToken();
+
+ void RequestAcceessToken();
+ void DestroyAcceessToken();
+
+ // 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);
+
+ static void _cdecl SendFileAsync(void *arg);
+
+ // contacts
+ static MCONTACT GetDefaultContact();
+
+ // icons
+ static void InitIcons();
+
+ // menus
+ static void InitMenus();
+
+ // 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
+ 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);
+};
+
+#endif //_Dropbox_PROTO_H_ \ No newline at end of file
diff --git a/plugins/Dropbox/src/dropbox_dialogs.cpp b/plugins/Dropbox/src/dropbox_dialogs.cpp
new file mode 100644
index 0000000000..1bbe8af20c
--- /dev/null
+++ b/plugins/Dropbox/src/dropbox_dialogs.cpp
@@ -0,0 +1,62 @@
+#include "dropbox.h"
+
+INT_PTR CALLBACK CDropbox::TokenRequestProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ char *token = reinterpret_cast<char*>(::GetWindowLongPtr(hwndDlg, GWLP_USERDATA));
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+
+ token = (char*)lParam;
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam);
+ {
+ //::SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)CSkypeProto::IconList[0].Handle);
+ //::SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)CSkypeProto::IconList[0].Handle);
+
+ /*wchar_t title[MAX_PATH];
+ ::mir_sntprintf(
+ title,
+ MAX_PATH,
+ ::TranslateT("Enter a password for %s:"),
+ param->login);*/
+ //::SetDlgItemText(hwndDlg, IDC_INSTRUCTION, title);
+
+ SendDlgItemMessage(hwndDlg, IDC_TOKEN, EM_LIMITTEXT, 128 - 1, 0);
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hwndDlg, 0);
+ break;
+
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDOK:
+ {
+ char data[128];
+ GetDlgItemTextA(hwndDlg, IDC_TOKEN, data, SIZEOF(data));
+ strcpy(token, data);
+
+ EndDialog(hwndDlg, IDOK);
+ }
+ break;
+
+ case IDCANCEL:
+ EndDialog(hwndDlg, IDCANCEL);
+ break;
+ }
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+INT_PTR CALLBACK CDropbox::MainOptionsProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ return FALSE;
+} \ No newline at end of file
diff --git a/plugins/Dropbox/src/dropbox_events.cpp b/plugins/Dropbox/src/dropbox_events.cpp
new file mode 100644
index 0000000000..83ee861712
--- /dev/null
+++ b/plugins/Dropbox/src/dropbox_events.cpp
@@ -0,0 +1,40 @@
+#include "dropbox.h"
+
+int CDropbox::OnModulesLoaded(WPARAM wParam, LPARAM lParam)
+{
+ NETLIBUSER nlu = { sizeof(nlu) };
+ nlu.flags = NUF_INCOMING | NUF_OUTGOING | NUF_HTTPCONNS | NUF_TCHAR;
+ nlu.szSettingsModule = MODULE;
+ nlu.szSettingsModule = MODULE;
+ nlu.ptszDescriptiveName = L"Dropbox";
+
+ g_dropbox->hNetlibUser = (HANDLE)CallService(MS_NETLIB_REGISTERUSER, 0, (LPARAM)&nlu);
+
+ MCONTACT hContact = GetDefaultContact();
+ if (!hContact)
+ {
+ hContact = (MCONTACT)CallService(MS_DB_CONTACT_ADD, 0, 0);
+ if (!CallService(MS_PROTO_ADDTOCONTACT, hContact, (LPARAM)MODULE))
+ {
+ db_set_s(hContact, MODULE, "Nick", MODULE);
+ }
+ }
+
+ return 0;
+}
+
+int CDropbox::OnOptionsInit(WPARAM wParam, LPARAM lParam)
+{
+ OPTIONSDIALOGPAGE odp = { sizeof(odp) };
+ odp.position = 100000000;
+ odp.hInstance = g_hInstance;
+ odp.flags = ODPF_BOLDGROUPS;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONS_MAIN);
+ odp.pszGroup = LPGEN("Network");
+ odp.pszTitle = LPGEN("Dropbox");
+ odp.pfnDlgProc = MainOptionsProc;
+
+ //Options_AddPage(wParam, &odp);
+
+ return 0;
+} \ No newline at end of file
diff --git a/plugins/Dropbox/src/dropbox_icons.cpp b/plugins/Dropbox/src/dropbox_icons.cpp
new file mode 100644
index 0000000000..c781369f8e
--- /dev/null
+++ b/plugins/Dropbox/src/dropbox_icons.cpp
@@ -0,0 +1,33 @@
+#include "dropbox.h"
+
+void CDropbox::InitIcons()
+{
+ wchar_t filePath[MAX_PATH];
+ GetModuleFileName(g_hInstance, filePath, MAX_PATH);
+
+ wchar_t sectionName[100];
+ mir_sntprintf(
+ sectionName,
+ SIZEOF(sectionName),
+ _T("%s/%s"),
+ LPGENT("Protocols"),
+ LPGENT(MODULE));
+
+ char settingName[100];
+ mir_snprintf(
+ settingName,
+ SIZEOF(settingName),
+ "%s_%s",
+ MODULE,
+ "main");
+
+ SKINICONDESC sid = {0};
+ sid.cbSize = sizeof(SKINICONDESC);
+ sid.flags = SIDF_ALL_TCHAR;
+ sid.ptszDefaultFile = filePath;
+ sid.pszName = settingName;
+ sid.ptszSection = sectionName;
+ sid.ptszDescription = LPGENT("Protocol icon");
+ sid.iDefaultIndex = -IDI_DROPBOX;
+ /*HANDLE hIcon = */Skin_AddIcon(&sid);
+} \ No newline at end of file
diff --git a/plugins/Dropbox/src/dropbox_menus.cpp b/plugins/Dropbox/src/dropbox_menus.cpp
new file mode 100644
index 0000000000..fe20bddf1d
--- /dev/null
+++ b/plugins/Dropbox/src/dropbox_menus.cpp
@@ -0,0 +1,17 @@
+#include "dropbox.h"
+
+HGENMENU CDropbox::ContactMenuItems[CMI_MAX];
+
+void CDropbox::InitMenus()
+{
+ CLISTMENUITEM mi = { 0 };
+ mi.cbSize = sizeof(CLISTMENUITEM);
+ mi.flags = CMIF_TCHAR;
+
+ mi.pszService = MODULE"/RequeriedAccess";
+ mi.ptszName = LPGENT("Requeried access");
+ mi.position = -201001000 + CMI_API_ACCESS_REQUERIED;
+ mi.icolibItem = LoadSkinnedIconHandle(SKINICON_AUTH_REVOKE);
+ ContactMenuItems[CMI_API_ACCESS_REQUERIED] = Menu_AddContactMenuItem(&mi);
+ CreateServiceFunction(mi.pszService, RequeriedApiAccess);
+} \ No newline at end of file
diff --git a/plugins/Dropbox/src/dropbox_services.cpp b/plugins/Dropbox/src/dropbox_services.cpp
new file mode 100644
index 0000000000..0524cff1c7
--- /dev/null
+++ b/plugins/Dropbox/src/dropbox_services.cpp
@@ -0,0 +1,82 @@
+#include "dropbox.h"
+
+INT_PTR CDropbox::GetCaps(WPARAM wParam, LPARAM lParam)
+{
+ switch(wParam)
+ {
+ case PFLAGNUM_1:
+ return PF1_IM | PF1_FILESEND | PF1_AUTHREQ;
+ case PFLAGNUM_2:
+ return PF2_ONLINE;
+ case PFLAGNUM_4:
+ return PF4_FORCEAUTH;
+ case PFLAG_UNIQUEIDTEXT:
+ return (INT_PTR)MODULE " ID";
+ case PFLAG_UNIQUEIDSETTING:
+ return (DWORD_PTR)"uid";
+ }
+
+ return 0;
+}
+
+INT_PTR CDropbox::SendFile(WPARAM wParam, LPARAM lParam)
+{
+ CCSDATA *pccsd = (CCSDATA*)lParam;
+
+ FileTransferParam *ftp = new FileTransferParam();
+ ftp->pfts.flags = PFTS_SENDING | PFTS_UTF;
+ ftp->pfts.hContact = pccsd->hContact;
+
+ char **files = (char**)pccsd->lParam;
+
+ for (int i = 0; files[i]; i++)
+ {
+ if (PathIsDirectoryA(files[i]))
+ continue;
+ ftp->pfts.totalFiles++;
+ }
+
+ ftp->pfts.pszFiles = new char*[ftp->pfts.totalFiles + 1];
+ ftp->pfts.pszFiles[ftp->pfts.totalFiles] = NULL;
+ for (int i = 0, j = 0; files[i]; i++)
+ {
+ if (PathIsDirectoryA(files[i]))
+ continue;
+
+ ftp->pfts.pszFiles[j] = mir_strdup(files[i]);
+
+ FILE *file = fopen(files[j], "rb");
+ if (file != NULL)
+ {
+ fseek(file, 0, SEEK_END);
+ ftp->pfts.totalBytes += ftell(file);
+ fseek(file, 0, SEEK_SET);
+ fclose(file);
+ }
+
+ j++;
+ }
+ ULONG fileId = InterlockedIncrement(&g_dropbox->hFileProcess);
+ ftp->hProcess = (HANDLE)fileId;
+
+ mir_forkthread(CDropbox::SendFileAsync, ftp);
+
+ return fileId;
+}
+
+INT_PTR CDropbox::SendMessage( WPARAM wParam, LPARAM lParam)
+{
+ return 0;
+}
+
+INT_PTR CDropbox::RequeriedApiAccess(WPARAM wParam, LPARAM lParam)
+{
+ int result = MessageBox(NULL, TranslateT("Are you sure you want to requeried access?"), TranslateT("Requeried access"), MB_YESNO | MB_ICONQUESTION);
+ if (result == IDYES && g_dropbox->HasAccessToken())
+ {
+ g_dropbox->DestroyAcceessToken();
+ g_dropbox->RequestAcceessToken();
+ }
+
+ return 0;
+} \ No newline at end of file
diff --git a/plugins/Dropbox/src/dropbox_transfers.cpp b/plugins/Dropbox/src/dropbox_transfers.cpp
new file mode 100644
index 0000000000..550e6b7e64
--- /dev/null
+++ b/plugins/Dropbox/src/dropbox_transfers.cpp
@@ -0,0 +1,210 @@
+#include "dropbox.h"
+
+HttpRequest *CDropbox::CreateFileSendChunkedRequest(const char *data, int length)
+{
+ HttpRequest *request = new HttpRequest(hNetlibUser, REQUEST_PUT, DROPBOX_APICONTENT_URL "/chunked_upload");
+ request->AddParameter("access_token", 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;
+ }
+
+ 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)
+ {
+ JSONNODE *root = json_parse(response->pData);
+ if (root != NULL)
+ {
+ JSONNODE *node = json_get(root, "upload_id");
+ strcpy(uploadId, mir_u2a(json_as_string(node)));
+
+ node = json_get(root, "offset");
+ offset = json_as_int(node);
+
+ delete node;
+ delete root;
+ }
+ }
+
+ mir_free(response);
+ }
+}
+
+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);
+
+ NETLIBHTTPREQUEST *response = request->Send();
+
+ delete request;
+
+ if (response)
+ {
+ if (response->resultCode == HttpStatus::OK)
+ {
+ JSONNODE *root = json_parse(response->pData);
+ if (root != NULL)
+ {
+ JSONNODE *node = json_get(root, "offset");
+ offset = json_as_int(node);
+
+ delete node;
+ delete root;
+ }
+ }
+
+ mir_free(response);
+ }
+}
+
+void CDropbox::SendFileChunkedLast(const char *fileName, const char *uploadId, MCONTACT hContact)
+{
+ char url[MAX_PATH];
+ mir_snprintf(
+ url,
+ SIZEOF(url),
+ "%s/commit_chunked_upload/%s/%s",
+ DROPBOX_APICONTENT_URL,
+ DROPBOX_API_ROOT,
+ fileName);
+
+ HttpRequest *request = new HttpRequest(hNetlibUser, REQUEST_POST, url);
+ request->AddParameter("upload_id", uploadId);
+ request->AddParameter("access_token", db_get_sa(NULL, MODULE, "TokenSecret"));
+
+ NETLIBHTTPREQUEST *response = request->Send();
+
+ delete request;
+
+ if (response && response->resultCode == HttpStatus::OK)
+ {
+ mir_snprintf(
+ url,
+ SIZEOF(url),
+ "%s/shares/%s/%s",
+ DROPBOX_API_URL,
+ DROPBOX_API_ROOT,
+ fileName);
+
+ request = new HttpRequest(hNetlibUser, REQUEST_POST, url);
+ request->AddParameter("access_token", db_get_sa(NULL, MODULE, "TokenSecret"));
+
+ mir_free(response);
+
+ response = request->Send();
+
+ if (response)
+ {
+ if (response->resultCode == HttpStatus::OK)
+ {
+ JSONNODE *root = json_parse(response->pData);
+ if (root != NULL)
+ {
+ JSONNODE *node = json_get(root, "url");
+ char message[1024];
+ mir_snprintf(
+ message,
+ SIZEOF(message),
+ Translate("Link to download file \"%s\": %s"),
+ 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);
+
+ delete node;
+ delete root;
+ }
+ }
+
+ mir_free(response);
+ }
+ }
+}
+
+void _cdecl CDropbox::SendFileAsync(void *arg)
+{
+ FileTransferParam *ftp = (FileTransferParam *)arg;
+
+ ProtoBroadcastAck(MODULE, ftp->pfts.hContact, ACKTYPE_FILE, ACKRESULT_INITIALISING, ftp->hProcess, 0);
+
+ for (int i = 0; ftp->pfts.pszFiles[i]; i++)
+ {
+ FILE *file = fopen(ftp->pfts.pszFiles[i], "rb");
+ if (file != NULL)
+ {
+ int offset = 0;
+ char *uploadId = new char[32];
+
+ const char *fileName = strrchr(ftp->pfts.pszFiles[i], '\\') + 1;
+
+ fseek(file, 0, SEEK_END);
+ DWORD fileSize = ftell(file);
+ fseek(file, 0, SEEK_SET);
+
+ ftp->pfts.currentFileNumber = i;
+ ftp->pfts.currentFileSize = fileSize;
+ ftp->pfts.currentFileProgress = 0;
+ ftp->pfts.szCurrentFile = strrchr(ftp->pfts.pszFiles[i], '\\') + 1;
+
+ ProtoBroadcastAck(MODULE, ftp->pfts.hContact, ACKTYPE_FILE, ACKRESULT_DATA, ftp->hProcess, (LPARAM)&ftp->pfts);
+
+ while (!feof(file) && !ferror(file))
+ {
+ int chunkSize = DROPBOX_FILE_CHUNK_SIZE;
+ if (fileSize < 1024*1024)
+ chunkSize = DROPBOX_FILE_CHUNK_SIZE / 5;
+ else if (fileSize > 20*1024*1024)
+ chunkSize = DROPBOX_FILE_CHUNK_SIZE * 4;
+
+ char *data = new char[chunkSize + 1];
+ size_t count = fread(data, sizeof(char), chunkSize, file);
+
+ if (!offset)
+ g_dropbox->SendFileChunkedFirst(data, count, uploadId, offset);
+ else
+ g_dropbox->SendFileChunkedNext(data, count, uploadId, offset);
+
+ ftp->pfts.currentFileProgress += count;
+ ftp->pfts.totalProgress += count;
+
+ ProtoBroadcastAck(MODULE, ftp->pfts.hContact, ACKTYPE_FILE, ACKRESULT_DATA, ftp->hProcess, (LPARAM)&ftp->pfts);
+ }
+
+ fclose(file);
+
+ g_dropbox->SendFileChunkedLast(fileName, uploadId, ftp->pfts.hContact);
+ ftp->pfts.currentFileProgress = ftp->pfts.currentFileSize;
+
+ if (i < ftp->pfts.totalFiles - 1)
+ ProtoBroadcastAck(MODULE, ftp->pfts.hContact, ACKTYPE_FILE, ACKRESULT_NEXTFILE, ftp->hProcess, 0);
+ }
+ }
+
+ ProtoBroadcastAck(MODULE, ftp->pfts.hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, ftp->hProcess, 0);
+
+ delete ftp;
+} \ No newline at end of file
diff --git a/plugins/Dropbox/src/dropbox_utils.cpp b/plugins/Dropbox/src/dropbox_utils.cpp
new file mode 100644
index 0000000000..caf4d9c980
--- /dev/null
+++ b/plugins/Dropbox/src/dropbox_utils.cpp
@@ -0,0 +1,26 @@
+#include "dropbox.h"
+
+void CDropbox::ShowNotification(const wchar_t *caption, const wchar_t *message, int flags, MCONTACT hContact)
+{
+ if (Miranda_Terminated()) return;
+
+ if (ServiceExists(MS_POPUP_ADDPOPUPT) && db_get_b(NULL, "Popup", "ModuleIsEnabled", 1))
+ {
+ POPUPDATAW ppd = {0};
+ ppd.lchContact = hContact;
+ wcsncpy(ppd.lpwzContactName, caption, MAX_CONTACTNAME);
+ wcsncpy(ppd.lpwzText, message, MAX_SECONDLINE);
+ ppd.lchIcon = Skin_GetIcon("Skype_main");
+
+ if (!PUAddPopupW(&ppd))
+ return;
+
+ }
+
+ MessageBox(NULL, message, caption, MB_OK | flags);
+}
+
+void CDropbox::ShowNotification(const wchar_t *message, int flags, MCONTACT hContact)
+{
+ ShowNotification(TranslateT(MODULE), message, flags, hContact);
+} \ No newline at end of file
diff --git a/plugins/Dropbox/src/http_request.h b/plugins/Dropbox/src/http_request.h
new file mode 100644
index 0000000000..b17ef16b58
--- /dev/null
+++ b/plugins/Dropbox/src/http_request.h
@@ -0,0 +1,92 @@
+#ifndef _HTTP_REQUEST_H_
+#define _HTTP_REQUEST_H_
+
+#include "common.h"
+
+enum HttpStatus
+{
+ OK = 200
+};
+
+class HttpRequest : public NETLIBHTTPREQUEST, public MZeroedObject
+{
+public:
+ HttpRequest(HANDLE hNetlibUser, int requestType, LPCSTR url)
+ {
+ cbSize = sizeof(NETLIBHTTPREQUEST);
+ flags = NLHRF_HTTP11;
+ this->requestType = requestType;
+
+ m_hNetlibUser = hNetlibUser;
+ m_szUrl = mir_strdup(url);
+ }
+
+ ~HttpRequest()
+ {
+ for (int i=0; i < headersCount; i++)
+ {
+ mir_free(headers[i].szName);
+ mir_free(headers[i].szValue);
+ }
+ mir_free(headers);
+ mir_free(pData);
+ }
+
+
+ void AddHeader(LPCSTR szName, LPCSTR szValue)
+ {
+ headers = (NETLIBHTTPHEADER*)mir_realloc(headers, sizeof(NETLIBHTTPHEADER)*(headersCount+1));
+ headers[headersCount].szName = mir_strdup(szName);
+ headers[headersCount].szValue = mir_strdup(szValue);
+ headersCount++;
+ }
+
+ void AddParameter(LPCSTR szName, LPCSTR szValue)
+ {
+ if(m_szUrl.Find('?') == -1)
+ m_szUrl.AppendFormat("?%s=%s", szName, szValue);
+ else
+ m_szUrl.AppendFormat("&%s=%s", szName, szValue);
+ }
+
+ void AddParameter(LPCSTR szName, int value)
+ {
+ if(m_szUrl.Find('?') == -1)
+ m_szUrl.AppendFormat("?%s=%i", szName, value);
+ else
+ m_szUrl.AppendFormat("&%s=%i", szName, value);
+ }
+
+ NETLIBHTTPREQUEST *Send()
+ {
+ szUrl = m_szUrl.GetBuffer();
+ return (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)m_hNetlibUser, (LPARAM)this);
+ }
+
+ //void SendAsync(typename CBaseProto<T>::AsyncHttpRequest callback)
+ //{
+ // szUrl = m_szUrl.GetBuffer();
+ // AsyncParam param = { this, proto, callback };
+ // /*HANDLE hThread = */mir_forkthread(SendAsync, &param);
+ // //WaitForSingleObject(hThread, INFINITE);
+ //}
+
+private:
+
+ CMStringA m_szUrl;
+ HANDLE m_hNetlibUser;
+
+ /*static void SendAsync(void *arg)
+ {
+ AsyncParam *param = (AsyncParam*)arg;
+ NETLIBHTTPREQUEST* response = (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)param->m_proto->m_hNetlibUser, (LPARAM)param->m_request);
+
+ CBaseProto<T> *proto = param->m_proto;
+ AsyncRequestCallback callback = param->m_callback;
+ proto->*callback(response);
+
+ delete response;
+ }*/
+};
+
+#endif //_HTTP_REQUEST_H_ \ No newline at end of file
diff --git a/plugins/Dropbox/src/main.cpp b/plugins/Dropbox/src/main.cpp
new file mode 100644
index 0000000000..da1ccca07f
--- /dev/null
+++ b/plugins/Dropbox/src/main.cpp
@@ -0,0 +1,52 @@
+//#include "common.h"
+#include "dropbox.h"
+
+int hLangpack;
+HINSTANCE g_hInstance;
+CDropbox *g_dropbox;
+
+PLUGININFOEX pluginInfo =
+{
+ sizeof(PLUGININFOEX),
+ __PLUGIN_NAME,
+ PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
+ __DESCRIPTION,
+ __AUTHOR,
+ __AUTHOREMAIL,
+ __COPYRIGHT,
+ __AUTHORWEB,
+ UNICODE_AWARE,
+ // {B908773A-86F7-4A91-8674-6A20BA0E67D1}
+ {0xb908773a, 0x86f7, 0x4a91, {0x86, 0x74, 0x6a, 0x20, 0xba, 0xe, 0x67, 0xd1}}
+
+};
+
+DWORD WINAPI DllMain(HINSTANCE hInstance, DWORD, LPVOID)
+{
+ g_hInstance = hInstance;
+
+ return TRUE;
+}
+
+extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion)
+{
+ return &pluginInfo;
+}
+
+extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = {MIID_PROTOCOL, MIID_LAST};
+
+extern "C" int __declspec(dllexport) Load(void)
+{
+ mir_getLP(&pluginInfo);
+
+ g_dropbox = new CDropbox();
+
+ return 0;
+}
+
+extern "C" int __declspec(dllexport) Unload(void)
+{
+ delete g_dropbox;
+
+ return 0;
+} \ No newline at end of file
diff --git a/plugins/Dropbox/src/resource.h b/plugins/Dropbox/src/resource.h
new file mode 100644
index 0000000000..50deccd319
--- /dev/null
+++ b/plugins/Dropbox/src/resource.h
Binary files differ
diff --git a/plugins/Dropbox/src/version.h b/plugins/Dropbox/src/version.h
new file mode 100644
index 0000000000..178ef67ee7
--- /dev/null
+++ b/plugins/Dropbox/src/version.h
@@ -0,0 +1,15 @@
+#define __MAJOR_VERSION 0
+#define __MINOR_VERSION 11
+#define __RELEASE_NUM 0
+#define __BUILD_NUM 1
+
+#include <stdver.h>
+
+#define __PLUGIN_NAME "Dropbox"
+#define __INTERNAL_NAME "Dropbox"
+#define __FILENAME "Dropbox.dll"
+#define __DESCRIPTION "Provides ability to upload files on Dropbox."
+#define __AUTHOR "unsane"
+#define __AUTHOREMAIL ""
+#define __AUTHORWEB "http://miranda-ng.org/p/Dropbox/"
+#define __COPYRIGHT "© 2014 Miranda NG project"