From 71846c4e387e27164ffde6b2e8a188b3bc21b2eb Mon Sep 17 00:00:00 2001 From: Alexander Lantsev Date: Wed, 13 May 2015 14:29:47 +0000 Subject: Dropbox: refactoring of http requests git-svn-id: http://svn.miranda-ng.org/main/trunk@13570 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/Dropbox/src/api/account.h | 38 ++++++++ plugins/Dropbox/src/api/operations.h | 60 +++++++++++++ plugins/Dropbox/src/api/upload.h | 47 ++++++++++ plugins/Dropbox/src/dropbox.cpp | 106 +++++++++------------- plugins/Dropbox/src/dropbox.h | 6 +- plugins/Dropbox/src/dropbox_commands.cpp | 143 +++++++++++++++--------------- plugins/Dropbox/src/dropbox_transfers.cpp | 114 ++++++------------------ plugins/Dropbox/src/dropbox_utils.cpp | 2 - plugins/Dropbox/src/http_request.h | 104 +++++++++++++++++----- plugins/Dropbox/src/stdafx.h | 6 +- plugins/Dropbox/src/version.h | 4 +- 11 files changed, 380 insertions(+), 250 deletions(-) create mode 100644 plugins/Dropbox/src/api/account.h create mode 100644 plugins/Dropbox/src/api/operations.h create mode 100644 plugins/Dropbox/src/api/upload.h (limited to 'plugins/Dropbox/src') diff --git a/plugins/Dropbox/src/api/account.h b/plugins/Dropbox/src/api/account.h new file mode 100644 index 0000000000..4db79622d2 --- /dev/null +++ b/plugins/Dropbox/src/api/account.h @@ -0,0 +1,38 @@ +#ifndef _DROPBOX_API_ACCOUNT_H_ +#define _DROPBOX_API_ACCOUNT_H_ + +class GetAccessTokenRequest : public HttpRequest +{ +public: + GetAccessTokenRequest(const char *requestToken) : + HttpRequest(REQUEST_POST, DROPBOX_API_URL "/oauth2/token") + { + AddBasicAuthHeader(DROPBOX_APP_KEY, DROPBOX_API_SECRET); + AddHeader("Content-Type", "application/x-www-form-urlencoded"); + + CMStringA data(CMStringDataFormat::FORMAT, "grant_type=authorization_code&code=%s", requestToken); + pData = data.GetBuffer(); + dataLength = data.GetLength(); + } +}; + +class DisableAccessTokenRequest : public HttpRequest +{ +public: + DisableAccessTokenRequest() : + HttpRequest(REQUEST_POST, DROPBOX_API_URL "/disable_access_token") + { + } +}; + +class GetAccountInfoRequest : public HttpRequest +{ +public: + GetAccountInfoRequest(const char *token) : + HttpRequest(REQUEST_GET, DROPBOX_API_URL "/account/info") + { + AddBearerAuthHeader(token); + } +}; + +#endif //_DROPBOX_API_ACCOUNT_H_ diff --git a/plugins/Dropbox/src/api/operations.h b/plugins/Dropbox/src/api/operations.h new file mode 100644 index 0000000000..1ff7d50230 --- /dev/null +++ b/plugins/Dropbox/src/api/operations.h @@ -0,0 +1,60 @@ +#ifndef _DROPBOX_API_OPERATIONS_H_ +#define _DROPBOX_API_OPERATIONS_H_ + +class ShareRequest : public HttpRequest +{ +public: + ShareRequest(const char *token, const char *path, bool useShortUrl = true) : + HttpRequest(REQUEST_POST, FORMAT, DROPBOX_API_URL "/shares/auto/%s", path) + { + if (!useShortUrl) + AddUrlParameter("short_url=false"); + + AddBearerAuthHeader(token); + AddHeader("Content-Type", "application/x-www-form-urlencoded"); + } +}; + +class DeleteRequest : public HttpRequest +{ +public: + DeleteRequest(const char *token, const char *path) : + HttpRequest(REQUEST_POST, DROPBOX_API_URL "/fileops/delete") + { + AddBearerAuthHeader(token); + AddHeader("Content-Type", "application/x-www-form-urlencoded"); + + CMStringA data(CMStringDataFormat::FORMAT, "root=auto&path=%s", path); + data.Replace('\\', '/'); + pData = data.GetBuffer(); + dataLength = data.GetLength(); + } +}; + +class CreateFolderRequest : public HttpRequest +{ +public: + CreateFolderRequest(const char *token, const char *path) : + HttpRequest(REQUEST_POST, DROPBOX_API_URL "/fileops/create_folder") + { + AddBearerAuthHeader(token); + AddHeader("Content-Type", "application/x-www-form-urlencoded"); + + CMStringA data(CMStringDataFormat::FORMAT, "root=auto&path=%s", path); + data.Replace('\\', '/'); + pData = data.GetBuffer(); + dataLength = data.GetLength(); + } +}; + +class GetMetadataRequest : public HttpRequest +{ +public: + GetMetadataRequest(const char *token, const char *path) : + HttpRequest(REQUEST_GET, FORMAT, DROPBOX_API_URL "/metadata/auto/%s", path) + { + AddBearerAuthHeader(token); + } +}; + +#endif //_DROPBOX_API_OPERATIONS_H_ diff --git a/plugins/Dropbox/src/api/upload.h b/plugins/Dropbox/src/api/upload.h new file mode 100644 index 0000000000..323bf907a5 --- /dev/null +++ b/plugins/Dropbox/src/api/upload.h @@ -0,0 +1,47 @@ +#ifndef _DROPBOX_API_UPLOAD_H_ +#define _DROPBOX_API_UPLOAD_H_ + +class UploadFileRequest : public HttpRequest +{ +public: + UploadFileRequest(const char *token, const char *fileName, const char *data, int length) : + HttpRequest(REQUEST_PUT, FORMAT, DROPBOX_APICONTENT_URL "/files_put/auto/%s", fileName) + { + AddBearerAuthHeader(token); + pData = (char*)data; + dataLength = length; + } +}; + +class UploadFileChunkRequest : public HttpRequest +{ +public: + UploadFileChunkRequest(const char *token, const char *data, int length) : + HttpRequest(REQUEST_PUT, DROPBOX_APICONTENT_URL "/chunked_upload") + { + AddBearerAuthHeader(token); + AddHeader("Content-Type", "application/octet-stream"); + pData = (char*)data; + dataLength = length; + } + + UploadFileChunkRequest(const char *token, const char *uploadId, size_t offset, const char *data, int length) : + HttpRequest(REQUEST_PUT, FORMAT, DROPBOX_APICONTENT_URL "/chunked_upload?upload_id=%s&offset=%i", uploadId, offset) + { + AddBearerAuthHeader(token); + AddHeader("Content-Type", "application/octet-stream"); + pData = (char*)data; + dataLength = length; + } + + UploadFileChunkRequest(const char *token, const char *uploadId, const char *path) : + HttpRequest(REQUEST_POST, FORMAT, DROPBOX_APICONTENT_URL "/commit_chunked_upload/auto/%s", path) + { + AddBearerAuthHeader(token); + AddHeader("Content-Type", "application/x-www-form-urlencoded"); + + AddUrlParameter("upload_id=%s", uploadId); + } +}; + +#endif //_DROPBOX_API_UPLOAD_H_ diff --git a/plugins/Dropbox/src/dropbox.cpp b/plugins/Dropbox/src/dropbox.cpp index 52fd2314ac..5649bec56e 100644 --- a/plugins/Dropbox/src/dropbox.cpp +++ b/plugins/Dropbox/src/dropbox.cpp @@ -65,14 +65,11 @@ bool CDropbox::HasAccessToken() void CDropbox::RequestAccountInfo() { - HttpRequest *request = new HttpRequest(hNetlibConnection, REQUEST_GET, DROPBOX_API_URL "/account/info"); - request->AddBearerAuthHeader(db_get_sa(NULL, MODULE, "TokenSecret")); - mir_ptr response(request->Send()); - - delete request; - MCONTACT hContact = CDropbox::GetDefaultContact(); + ptrA token(db_get_sa(NULL, MODULE, "TokenSecret")); + GetAccountInfoRequest request(token); + mir_ptr response(request.Send(hNetlibConnection)); HandleHttpResponseError(response); JSONROOT root(response->pData); @@ -137,14 +134,11 @@ void CDropbox::RequestAccountInfo() void CDropbox::DestroyAccessToken() { - HttpRequest *request = new HttpRequest(hNetlibConnection, REQUEST_POST, DROPBOX_API_URL "/disable_access_token"); - mir_ptr response(request->Send()); - - delete request; - - MCONTACT hContact = CDropbox::GetDefaultContact(); + DisableAccessTokenRequest request; + mir_ptr response(request.Send(hNetlibConnection)); db_unset(NULL, MODULE, "TokenSecret"); + MCONTACT hContact = CDropbox::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); @@ -164,73 +158,59 @@ UINT CDropbox::RequestAccessTokenAsync(void *owner, void *param) char requestToken[128]; GetDlgItemTextA(hwndDlg, IDC_REQUEST_CODE, requestToken, SIZEOF(requestToken)); - char data[1024]; - mir_snprintf( - data, - SIZEOF(data), - "grant_type=authorization_code&code=%s", - requestToken); - - HttpRequest *request = new HttpRequest(instance->hNetlibConnection, REQUEST_POST, DROPBOX_API_URL "/oauth2/token"); - request->AddBasicAuthHeader(DROPBOX_APP_KEY, DROPBOX_API_SECRET); - request->AddHeader("Content-Type", "application/x-www-form-urlencoded"); - request->pData = mir_strdup(data); - request->dataLength = (int)strlen(data); - - mir_ptr response(request->Send()); - - delete request; - - MCONTACT hContact = instance->GetDefaultContact(); + GetAccessTokenRequest request(requestToken); + mir_ptr response(request.Send(instance->hNetlibConnection)); if (response == NULL) { + Netlib_Logf(instance->hNetlibConnection, "%s: %s", MODULE, HttpStatusToText(HTTP_STATUS_ERROR)); if (hwndDlg) SetDlgItemText(hwndDlg, IDC_AUTH_STATUS, TranslateT("server does not respond")); /*else ShowNotification(TranslateT("server does not respond"), MB_ICONERROR);*/ + return 0; } + JSONROOT root(response->pData); - if (root) + if (root == NULL) { - if (response->resultCode == HTTP_STATUS_OK) - { - 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); + JSONNODE *node = json_get(root, "error_description"); + ptrW error_description(json_as_string(node)); - if (hContact) { - if (db_get_w(hContact, MODULE, "Status", ID_STATUS_OFFLINE) == ID_STATUS_OFFLINE) - db_set_w(hContact, MODULE, "Status", ID_STATUS_ONLINE); - } + Netlib_Logf(instance->hNetlibConnection, "%s: %s", MODULE, Netlib_Logf(instance->hNetlibConnection, "%s: %s", MODULE, HttpStatusToText((HTTP_STATUS)response->resultCode))); + if (hwndDlg) + SetDlgItemText(hwndDlg, IDC_AUTH_STATUS, error_description); + /*else + ShowNotification((TCHAR*)error_description, MB_ICONERROR);*/ + return 0; + } - try - { - instance->RequestAccountInfo(); - } - catch (TransferException &ex) - { - Netlib_Logf(instance->hNetlibConnection, "%s: %s", MODULE, ex.what()); - return 0; - } + 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); - if (hwndDlg) - SetDlgItemText(hwndDlg, IDC_AUTH_STATUS, TranslateT("you have been authorized")); - /*else - ShowNotification(TranslateT("you have been authorized"), MB_ICONINFORMATION);*/ - } - else - { - JSONNODE *node = json_get(root, "error_description"); - ptrW error_description(json_as_string(node)); + MCONTACT hContact = instance->GetDefaultContact(); + if (hContact) + { + if (db_get_w(hContact, MODULE, "Status", ID_STATUS_OFFLINE) == ID_STATUS_OFFLINE) + db_set_w(hContact, MODULE, "Status", ID_STATUS_ONLINE); + } - if (hwndDlg) - SetDlgItemText(hwndDlg, IDC_AUTH_STATUS, error_description); - /*else - ShowNotification((TCHAR*)error_description, MB_ICONERROR);*/ - } + try + { + instance->RequestAccountInfo(); + } + catch (TransferException &ex) + { + Netlib_Logf(instance->hNetlibConnection, "%s: %s", MODULE, ex.what()); + return 0; } + if (hwndDlg) + SetDlgItemText(hwndDlg, IDC_AUTH_STATUS, TranslateT("you have been authorized")); + /*else + ShowNotification(TranslateT("you have been authorized"), MB_ICONINFORMATION);*/ + SetDlgItemTextA(hwndDlg, IDC_REQUEST_CODE, ""); return 0; diff --git a/plugins/Dropbox/src/dropbox.h b/plugins/Dropbox/src/dropbox.h index c8e38234ba..8c46fcc55b 100644 --- a/plugins/Dropbox/src/dropbox.h +++ b/plugins/Dropbox/src/dropbox.h @@ -97,12 +97,12 @@ private: void RequestAccountInfo(); // transfers - void SendFile(const char *fileName, const char *data, int length); + void SendFile(const char *path, const char *data, int length); void SendFileChunkedFirst(const char *data, int length, char *uploadId, size_t &offset); void SendFileChunkedNext(const char *data, int length, const char *uploadId, size_t &offset); - void SendFileChunkedLast(const char *fileName, const char *uploadId); + void SendFileChunkedLast(const char *path, const char *uploadId); - void CreateFolder(const char *folderName); + void CreateFolder(const char *encodedPath); void CreateDownloadUrl(const char *path, char *url); diff --git a/plugins/Dropbox/src/dropbox_commands.cpp b/plugins/Dropbox/src/dropbox_commands.cpp index 5b992fd45e..3ce87a7c3b 100644 --- a/plugins/Dropbox/src/dropbox_commands.cpp +++ b/plugins/Dropbox/src/dropbox_commands.cpp @@ -17,49 +17,56 @@ void CDropbox::CommandContent(void *arg) { CommandParam *param = (CommandParam*)arg; - char *name = (char*)param->data; - - CMStringA url(DROPBOX_API_URL "/metadata/" DROPBOX_API_ROOT); - if (name) - url.AppendFormat("/%s", ptrA(mir_utf8encode(name))); - - HttpRequest *request = new HttpRequest(param->instance->hNetlibConnection, REQUEST_GET, url); - request->AddBearerAuthHeader(db_get_sa(NULL, MODULE, "TokenSecret")); - - mir_ptr response(request->Send()); - - delete request; - - if (response && response->resultCode == HTTP_STATUS_OK) { - CMStringA message; - - JSONROOT root(response->pData); - if (root) { - JSONNODE *node = json_get(root, "is_dir"); - bool isDir = json_as_bool(node) > 0; - if (!isDir) - message.AppendFormat("\"%s\" %s", name, Translate("is file")); - else { - JSONNODE *content = json_as_array(json_get(root, "contents")); - for (int i = 0;; i++) { - JSONNODE *item = json_at(content, i); - if (item == NULL) { - if (i == 0) - message.AppendFormat("\"%s\" %s", name, Translate("is empty")); - break; - } + char *path = (char*)param->data; + if (path) + { + ptrA token(db_get_sa(NULL, MODULE, "TokenSecret")); + ptrA encodedPath(mir_utf8encode(path)); + GetMetadataRequest request(token, encodedPath); + mir_ptr response(request.Send(param->instance->hNetlibConnection)); + + if (response && response->resultCode == HTTP_STATUS_OK) + { + CMStringA message; - ptrA subName(mir_u2a(json_as_string(json_get(item, "path")))); - message.AppendFormat("%s\n", (subName[0] == '/') ? &subName[1] : subName); + JSONROOT root(response->pData); + if (root) + { + JSONNODE *node = json_get(root, "is_dir"); + bool isDir = json_as_bool(node) > 0; + if (!isDir) + message.AppendFormat("\"%s\" %s", path, Translate("is file")); + else + { + JSONNODE *content = json_as_array(json_get(root, "contents")); + for (int i = 0;; i++) { + JSONNODE *item = json_at(content, i); + if (item == NULL) { + if (i == 0) + message.AppendFormat("\"%s\" %s", path, Translate("is empty")); + break; + } + + ptrA subName(mir_u2a(json_as_string(json_get(item, "path")))); + message.AppendFormat("%s\n", (subName[0] == '/') ? &subName[1] : subName); + } } - } - ProtoBroadcastAck(MODULE, param->hContact, ACKTYPE_MESSAGE, ACKRESULT_SUCCESS, param->hProcess, 0); - CallContactService(param->instance->GetDefaultContact(), PSR_MESSAGE, 0, (LPARAM)message.GetBuffer()); + ProtoBroadcastAck(MODULE, param->hContact, ACKTYPE_MESSAGE, ACKRESULT_SUCCESS, param->hProcess, 0); + CallContactService(param->instance->GetDefaultContact(), PSR_MESSAGE, 0, (LPARAM)message.GetBuffer()); - return; + return; + } } } + else + { + CMStringA error(FORMAT, Translate("\"%s\" command has invalid parameter.\nUse \"/help\" for more info."), "/content"); + ProtoBroadcastAck(MODULE, param->hContact, ACKTYPE_MESSAGE, ACKRESULT_SUCCESS, param->hProcess, 0); + CallContactService(param->instance->GetDefaultContact(), PSR_MESSAGE, 0, (LPARAM)error.GetBuffer()); + + return; + } ProtoBroadcastAck(MODULE, param->hContact, ACKTYPE_MESSAGE, ACKRESULT_FAILED, param->hProcess, 0); } @@ -68,24 +75,22 @@ void CDropbox::CommandShare(void *arg) { CommandParam *param = (CommandParam*)arg; - char *name = (char*)param->data; - if (name) { - CMStringA url(DROPBOX_API_URL "/shares/" DROPBOX_API_ROOT); - if (name) - url.AppendFormat("/%s", ptrA(mir_utf8encode(name))); - - HttpRequest *request = new HttpRequest(param->instance->hNetlibConnection, REQUEST_POST, url); - request->AddBearerAuthHeader(db_get_sa(NULL, MODULE, "TokenSecret")); - - mir_ptr response(request->Send()); - - delete request; - - if (response && response->resultCode == HTTP_STATUS_OK) { + char *path = (char*)param->data; + if (path) + { + ptrA token(db_get_sa(NULL, MODULE, "TokenSecret")); + ptrA encodedPath(mir_utf8encode(path)); + bool useShortUrl = db_get_b(NULL, MODULE, "UseSortLinks", 1) > 0; + ShareRequest request(token, encodedPath, useShortUrl); + mir_ptr response(request.Send(param->instance->hNetlibConnection)); + + if (response && response->resultCode == HTTP_STATUS_OK) + { CMStringA link; JSONROOT root(response->pData); - if (root) { + if (root) + { JSONNODE *node = json_get(root, "url"); link = mir_u2a(json_as_string(node)); ProtoBroadcastAck(MODULE, param->hContact, ACKTYPE_MESSAGE, ACKRESULT_SUCCESS, param->hProcess, 0); @@ -95,7 +100,8 @@ void CDropbox::CommandShare(void *arg) } } } - else { + else + { CMStringA error(FORMAT, Translate("\"%s\" command has invalid parameter.\nUse \"/help\" for more info."), "/share"); ProtoBroadcastAck(MODULE, param->hContact, ACKTYPE_MESSAGE, ACKRESULT_SUCCESS, param->hProcess, 0); CallContactService(param->instance->GetDefaultContact(), PSR_MESSAGE, 0, (LPARAM)error.GetBuffer()); @@ -110,33 +116,30 @@ void CDropbox::CommandDelete(void *arg) { CommandParam *param = (CommandParam*)arg; - char *name = (char*)param->data; - if (name) { - CMStringA pparam = CMStringA("root=" DROPBOX_API_ROOT "&path=") + ptrA(mir_utf8encode(name)); - - HttpRequest *request = new HttpRequest(param->instance->hNetlibConnection, REQUEST_POST, DROPBOX_API_URL "/fileops/delete"); - request->AddBearerAuthHeader(db_get_sa(NULL, MODULE, "TokenSecret")); - request->AddHeader("Content-Type", "application/x-www-form-urlencoded"); - request->pData = mir_strdup(pparam); - request->dataLength = pparam.GetLength(); - - mir_ptr response(request->Send()); - - delete request; + char *path = (char*)param->data; + if (path) + { + ptrA token(db_get_sa(NULL, MODULE, "TokenSecret")); + ptrA encodedPath(mir_utf8encode(path)); + DeleteRequest request(token, encodedPath); + mir_ptr response(request.Send(param->instance->hNetlibConnection)); - if (response && response->resultCode == HTTP_STATUS_OK) { + if (response && response->resultCode == HTTP_STATUS_OK) + { JSONROOT root(response->pData); - if (root) { + if (root) + { JSONNODE *node = json_get(root, "is_deleted"); bool isDeleted = json_as_bool(node) > 0; - CMStringA message(FORMAT, "%s %s", name, !isDeleted ? Translate("is not deleted") : Translate("is deleted")); + CMStringA message(FORMAT, "%s %s", path, !isDeleted ? Translate("is not deleted") : Translate("is deleted")); ProtoBroadcastAck(MODULE, param->hContact, ACKTYPE_MESSAGE, ACKRESULT_SUCCESS, param->hProcess, 0); CallContactService(param->instance->GetDefaultContact(), PSR_MESSAGE, 0, (LPARAM)message.GetBuffer()); return; } } } - else { + else + { CMStringA error(FORMAT, Translate("\"%s\" command has invalid parameter.\nUse \"/help\" for more info."), "/delete"); ProtoBroadcastAck(MODULE, param->hContact, ACKTYPE_MESSAGE, ACKRESULT_SUCCESS, param->hProcess, 0); CallContactService(param->instance->GetDefaultContact(), PSR_MESSAGE, 0, (LPARAM)error.GetBuffer()); diff --git a/plugins/Dropbox/src/dropbox_transfers.cpp b/plugins/Dropbox/src/dropbox_transfers.cpp index f9bcce0bb4..f7d10463e3 100644 --- a/plugins/Dropbox/src/dropbox_transfers.cpp +++ b/plugins/Dropbox/src/dropbox_transfers.cpp @@ -1,38 +1,20 @@ #include "stdafx.h" -void CDropbox::SendFile(const char *fileName, const char *data, int length) +void CDropbox::SendFile(const char *path, const char *data, int length) { - CMStringA url(FORMAT, DROPBOX_APICONTENT_URL "/files_put/%s/%s", DROPBOX_API_ROOT, ptrA(mir_utf8encode(fileName))); - url.Replace('\\', '/'); - - HttpRequest *request = new HttpRequest(hNetlibConnection, REQUEST_PUT, DROPBOX_APICONTENT_URL "/files_put"); - request->AddBearerAuthHeader(ptrA(db_get_sa(NULL, MODULE, "TokenSecret"))); - request->pData = (char*)mir_alloc(sizeof(char)* length); - memcpy(request->pData, data, length); - request->dataLength = length; - - mir_ptr response(request->Send()); - - delete request; - + ptrA token(db_get_sa(NULL, MODULE, "TokenSecret")); + ptrA encodedPath(mir_utf8encode(path)); + UploadFileRequest request(token, encodedPath, data, length); + mir_ptr response(request.Send(hNetlibConnection)); HandleHttpResponseError(response); } void CDropbox::SendFileChunkedFirst(const char *data, int length, char *uploadId, size_t &offset) { - HttpRequest *request = new HttpRequest(hNetlibConnection, REQUEST_PUT, DROPBOX_APICONTENT_URL "/chunked_upload"); - request->AddBearerAuthHeader(ptrA(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; - - mir_ptr response(request->Send()); - - delete request; - + ptrA token(db_get_sa(NULL, MODULE, "TokenSecret")); + UploadFileChunkRequest request(token, data, length); + mir_ptr response(request.Send(hNetlibConnection)); HandleHttpResponseError(response); - JSONROOT root(response->pData); if (root) { @@ -46,22 +28,10 @@ void CDropbox::SendFileChunkedFirst(const char *data, int length, char *uploadId void CDropbox::SendFileChunkedNext(const char *data, int length, const char *uploadId, size_t &offset) { - CMStringA url(DROPBOX_APICONTENT_URL "/chunked_upload"); - url.AppendFormat("?upload_id=%s&offset=%i", uploadId, offset); - - HttpRequest *request = new HttpRequest(hNetlibConnection, REQUEST_PUT, url); - request->AddBearerAuthHeader(ptrA(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; - - mir_ptr response(request->Send()); - - delete request; - + ptrA token(db_get_sa(NULL, MODULE, "TokenSecret")); + UploadFileChunkRequest request(token, uploadId, offset, data, length); + mir_ptr response(request.Send(hNetlibConnection)); HandleHttpResponseError(response); - JSONROOT root(response->pData); if (root) { @@ -70,42 +40,21 @@ void CDropbox::SendFileChunkedNext(const char *data, int length, const char *upl } } -void CDropbox::SendFileChunkedLast(const char *fileName, const char *uploadId) +void CDropbox::SendFileChunkedLast(const char *path, const char *uploadId) { - CMStringA url(FORMAT, "%s/commit_chunked_upload/%s/%s", DROPBOX_APICONTENT_URL, DROPBOX_API_ROOT, fileName); - url.Replace('\\', '/'); - - CMStringA data(FORMAT, "upload_id=%s", uploadId); - - HttpRequest *request = new HttpRequest(hNetlibConnection, REQUEST_POST, url); - request->AddBearerAuthHeader(ptrA(db_get_sa(NULL, MODULE, "TokenSecret"))); - request->AddHeader("Content-Type", "application/x-www-form-urlencoded"); - request->pData = data.GetBuffer(); - request->dataLength = data.GetLength(); - - mir_ptr response(request->Send()); - - delete request; - + ptrA token(db_get_sa(NULL, MODULE, "TokenSecret")); + ptrA encodedPath(mir_utf8encode(path)); + UploadFileChunkRequest request(token, uploadId, (char*)encodedPath); + mir_ptr response(request.Send(hNetlibConnection)); HandleHttpResponseError(response); } -void CDropbox::CreateFolder(const char *folderName) +void CDropbox::CreateFolder(const char *path) { - CMStringA folder(folderName); - folder.Replace('\\', '/'); - - CMStringA data(FORMAT, "root=%s&path=%s", DROPBOX_API_ROOT, folder); - - HttpRequest *request = new HttpRequest(hNetlibConnection, REQUEST_POST, DROPBOX_API_URL "/fileops/create_folder"); - request->AddBearerAuthHeader(ptrA(db_get_sa(NULL, MODULE, "TokenSecret"))); - request->AddHeader("Content-Type", "application/x-www-form-urlencoded"); - request->pData = data.GetBuffer(); - request->dataLength = data.GetLength(); - - mir_ptr response(request->Send()); - - delete request; + ptrA token(db_get_sa(NULL, MODULE, "TokenSecret")); + ptrA encodedPath(mir_utf8encode(path)); + CreateFolderRequest request(token, encodedPath); + mir_ptr response(request.Send(hNetlibConnection)); // forder exists on server if (response->resultCode == HTTP_STATUS_FORBIDDEN) @@ -116,26 +65,17 @@ void CDropbox::CreateFolder(const char *folderName) void CDropbox::CreateDownloadUrl(const char *path, char *url) { - CMStringA api_url(DROPBOX_API_URL); - api_url.AppendFormat("/shares/%s/%s", DROPBOX_API_ROOT, path); - - if (!db_get_b(NULL, MODULE, "UseSortLinks", 1)) - api_url += "?short_url=false"; - - HttpRequest *request = new HttpRequest(hNetlibConnection, REQUEST_POST, api_url); - request->AddBearerAuthHeader(ptrA(db_get_sa(NULL, MODULE, "TokenSecret"))); - - mir_ptr response(request->Send()); - - delete request; - + ptrA token(db_get_sa(NULL, MODULE, "TokenSecret")); + ptrA encodedPath(mir_utf8encode(path)); + bool useShortUrl = db_get_b(NULL, MODULE, "UseSortLinks", 1) > 0; + ShareRequest request(token, encodedPath, useShortUrl); + mir_ptr response(request.Send(hNetlibConnection)); HandleHttpResponseError(response); - JSONROOT root(response->pData); if (root) { JSONNODE *node = json_get(root, "url"); - mir_strcpy(url, ptrA(mir_urlEncode(_T2A(json_as_string(node))))); + mir_strcpy(url, _T2A(json_as_string(node))); } } diff --git a/plugins/Dropbox/src/dropbox_utils.cpp b/plugins/Dropbox/src/dropbox_utils.cpp index 28eff5049f..17fe9eb919 100644 --- a/plugins/Dropbox/src/dropbox_utils.cpp +++ b/plugins/Dropbox/src/dropbox_utils.cpp @@ -29,8 +29,6 @@ char* CDropbox::HttpStatusToText(HTTP_STATUS status) return "Unknown error"; } - - void CDropbox::HandleHttpResponseError(NETLIBHTTPREQUEST *response) { if (response == NULL) diff --git a/plugins/Dropbox/src/http_request.h b/plugins/Dropbox/src/http_request.h index 3b41344776..79f6c09a65 100644 --- a/plugins/Dropbox/src/http_request.h +++ b/plugins/Dropbox/src/http_request.h @@ -15,33 +15,50 @@ enum HTTP_STATUS HTTP_STATUS_INSUFICIENTE_STORAGE = 507 }; -class HttpRequest : public NETLIBHTTPREQUEST, public MZeroedObject +class HttpRequestException { + CMStringA message; + public: - HttpRequest(HANDLE hNetlibConnection, int requestType, LPCSTR url) + HttpRequestException(const char *message) : + message(message) { - cbSize = sizeof(NETLIBHTTPREQUEST); - flags = NLHRF_HTTP11; - this->requestType = requestType; + } - m_hNetlibConnection = hNetlibConnection; - m_szUrl = mir_strdup(url); + const char* what() const throw() + { + return message.c_str(); } +}; - ~HttpRequest() +class HttpRequest : protected NETLIBHTTPREQUEST//, public MZeroedObject +{ +private: + CMStringA m_szUrl; + va_list formatArgs; + + void Init(int type) { - for (int i = 0; i < headersCount; i++) { - mir_free(headers[i].szName); - mir_free(headers[i].szValue); - } - mir_free(headers); - mir_free(pData); + cbSize = sizeof(NETLIBHTTPREQUEST); + requestType = type; + flags = NLHRF_HTTP11 | NLHRF_SSL | NLHRF_NODUMPSEND | NLHRF_DUMPASTEXT; + szUrl = NULL; + headers = NULL; + headersCount = 0; + pData = NULL; + dataLength = 0; + resultCode = 0; + szResultDescr = NULL; + nlc = NULL; + timeout = 0; } +protected: + enum HttpRequestUrlFormat { FORMAT }; void AddHeader(LPCSTR szName, LPCSTR szValue) { - headers = (NETLIBHTTPHEADER*)mir_realloc(headers, sizeof(NETLIBHTTPHEADER)*(headersCount + 1)); + headers = (NETLIBHTTPHEADER*)mir_realloc(headers, sizeof(NETLIBHTTPHEADER) * (headersCount + 1)); headers[headersCount].szName = mir_strdup(szName); headers[headersCount].szValue = mir_strdup(szValue); headersCount++; @@ -89,15 +106,60 @@ public: headersCount++; } - NETLIBHTTPREQUEST *Send() + void AddUrlParameter(const char *urlFormat, ...) { - szUrl = m_szUrl.GetBuffer(); - return (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)m_hNetlibConnection, (LPARAM)this); + va_list urlArgs; + va_start(urlArgs, urlFormat); + m_szUrl += m_szUrl.Find('?') == -1 ? '?' : '&'; + m_szUrl.AppendFormatV(urlFormat, urlArgs); + va_end(urlArgs); } -private: - CMStringA m_szUrl; - HANDLE m_hNetlibConnection; + /*void SetData(const char *data, size_t size) + { + if (pData != NULL) + mir_free(pData); + + dataLength = (int)size; + pData = (char*)mir_alloc(size + 1); + memcpy(pData, data, size); + pData[size] = 0; + }*/ + +public: + HttpRequest(int type, LPCSTR url) + { + Init(type); + + m_szUrl = url; + } + + HttpRequest(int type, HttpRequestUrlFormat, LPCSTR urlFormat, ...) + { + Init(type); + + va_list formatArgs; + va_start(formatArgs, urlFormat); + m_szUrl.AppendFormatV(urlFormat, formatArgs); + va_end(formatArgs); + } + + ~HttpRequest() + { + for (int i = 0; i < headersCount; i++) + { + mir_free(headers[i].szName); + mir_free(headers[i].szValue); + } + mir_free(headers); + } + + NETLIBHTTPREQUEST* Send(HANDLE hNetlibConnection) + { + m_szUrl.Replace('\\', '/'); + szUrl = m_szUrl.GetBuffer(); + return (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)hNetlibConnection, (LPARAM)this); + } }; #endif //_HTTP_REQUEST_H_ \ No newline at end of file diff --git a/plugins/Dropbox/src/stdafx.h b/plugins/Dropbox/src/stdafx.h index 7e8420b896..c2eca7328b 100644 --- a/plugins/Dropbox/src/stdafx.h +++ b/plugins/Dropbox/src/stdafx.h @@ -29,6 +29,10 @@ #include #include +#include "dropbox.h" +#include "api\account.h" +#include "api\upload.h" +#include "api\operations.h" #include "version.h" #include "resource.h" @@ -37,8 +41,6 @@ extern HINSTANCE g_hInstance; -#include "dropbox.h" - // icons void InitializeIcons(); HANDLE GetIconHandle(int iconId); diff --git a/plugins/Dropbox/src/version.h b/plugins/Dropbox/src/version.h index 27323bf19e..f1cd12cd17 100644 --- a/plugins/Dropbox/src/version.h +++ b/plugins/Dropbox/src/version.h @@ -1,14 +1,14 @@ #define __MAJOR_VERSION 0 #define __MINOR_VERSION 12 #define __RELEASE_NUM 0 -#define __BUILD_NUM 2 +#define __BUILD_NUM 3 #include #define __PLUGIN_NAME "Dropbox" #define __FILENAME "Dropbox.dll" #define __DESCRIPTION "Allows you to transfer files via Dropbox." -#define __AUTHOR "unsane" +#define __AUTHOR "Miranda NG Team" #define __AUTHOREMAIL "" #define __AUTHORWEB "http://miranda-ng.org/p/Dropbox/" #define __COPYRIGHT "© 2014-15 Miranda NG project" -- cgit v1.2.3