diff options
Diffstat (limited to 'protocols/CloudFile/src/cloud_file.cpp')
-rw-r--r-- | protocols/CloudFile/src/cloud_file.cpp | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/protocols/CloudFile/src/cloud_file.cpp b/protocols/CloudFile/src/cloud_file.cpp new file mode 100644 index 0000000000..f6019f8196 --- /dev/null +++ b/protocols/CloudFile/src/cloud_file.cpp @@ -0,0 +1,197 @@ +#include "stdafx.h" + +CCloudService::CCloudService(const char *protoName, const wchar_t *userName, HPLUGIN pPlugin) + : PROTO<CCloudService>(protoName, userName), + m_pPlugin(pPlugin) +{ + NETLIBUSER nlu = {}; + nlu.flags = NUF_OUTGOING | NUF_HTTPCONNS | NUF_UNICODE; + nlu.szSettingsModule = (char*)protoName; + nlu.szDescriptiveName.w = (wchar_t*)userName; + m_hConnection = Netlib_RegisterUser(&nlu); + + CreateProtoService(PS_CREATEACCMGRUI, &CCloudService::OnAccountManagerInit); +} + +CCloudService::~CCloudService() +{ + Netlib_CloseHandle(m_hConnection); + m_hConnection = nullptr; +} + +void CCloudService::OnErase() +{ + KillModuleMenus(m_pPlugin); +} + +HPLUGIN CCloudService::GetId() const +{ + return m_pPlugin; +} + +const char* CCloudService::GetAccountName() const +{ + return m_szModuleName; +} + +const wchar_t* CCloudService::GetUserName() const +{ + return m_tszUserName; +} + +INT_PTR CCloudService::GetCaps(int type, MCONTACT) +{ + switch (type) { + case PFLAGNUM_1: + return PF1_FILESEND; + case PFLAGNUM_2: + case PFLAGNUM_5: + return PF2_NONE; + default: + return 0; + } +} + +int CCloudService::FileCancel(MCONTACT, HANDLE hTransfer) +{ + FileTransferParam *ftp = Transfers.find((FileTransferParam*)&hTransfer); + if (ftp) + ftp->Terminate(); + + return 0; +} + +HANDLE CCloudService::SendFile(MCONTACT hContact, const wchar_t *description, wchar_t **paths) +{ + FileTransferParam *ftp = new FileTransferParam(hContact); + ftp->SetDescription(description); + ftp->SetWorkingDirectory(paths[0]); + for (int i = 0; paths[i]; i++) { + if (PathIsDirectory(paths[i])) + continue; + ftp->AddFile(paths[i]); + } + Transfers.insert(ftp); + mir_forkthreadowner(UploadAndReportProgressThread, this, ftp); + return (HANDLE)ftp->GetId(); +} + +void CCloudService::OpenUploadDialog(MCONTACT hContact) +{ + char *proto = GetContactProto(hContact); + if (!mir_strcmpi(proto, META_PROTO)) + hContact = db_mc_getMostOnline(hContact); + + auto it = InterceptedContacts.find(hContact); + if (it == InterceptedContacts.end()) { + HWND hwnd = (HWND)CallService(MS_FILE_SENDFILE, hContact, 0); + InterceptedContacts[hContact] = hwnd; + } + else + SetActiveWindow(it->second); +} + +INT_PTR CCloudService::OnAccountManagerInit(WPARAM, LPARAM lParam) +{ + CAccountManagerDlg *page = new CAccountManagerDlg(this); + page->SetParent((HWND)lParam); + page->Show(); + return (INT_PTR)page->GetHwnd(); +} + +std::string CCloudService::PreparePath(const std::string &path) const +{ + std::string newPath = path; + if (newPath[0] != '/') + newPath.insert(0, "/"); + std::replace(newPath.begin(), newPath.end(), '\\', '/'); + size_t pos = newPath.find("//"); + while (pos != std::string::npos) { + newPath.replace(pos, 2, "/"); + pos = newPath.find("//", pos + 1); + } + return newPath; +} + +char* CCloudService::HttpStatusToError(int status) +{ + switch (status) { + case HTTP_CODE_OK: + return "OK"; + case HTTP_CODE_BAD_REQUEST: + return "Bad input parameter. Error message should indicate which one and why"; + case HTTP_CODE_UNAUTHORIZED: + return "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 HTTP_CODE_FORBIDDEN: + return "Bad OAuth request (wrong consumer key, bad nonce, expired timestamp...). Unfortunately, re-authenticating the user won't help here"; + case HTTP_CODE_NOT_FOUND: + return "File or folder not found at the specified path"; + case HTTP_CODE_METHOD_NOT_ALLOWED: + return "Request method not expected (generally should be GET or POST)"; + case HTTP_CODE_TOO_MANY_REQUESTS: + return "Your app is making too many requests and is being rate limited. 429s can trigger on a per-app or per-user basis"; + case HTTP_CODE_SERVICE_UNAVAILABLE: + return "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."; + } + + return "Unknown error"; +} + +void CCloudService::HttpResponseToError(NETLIBHTTPREQUEST *response) +{ + if (response == nullptr) + throw Exception(HttpStatusToError()); + if (response->dataLength) + throw Exception(response->pData); + throw Exception(HttpStatusToError(response->resultCode)); +} + +void CCloudService::HandleHttpError(NETLIBHTTPREQUEST *response) +{ + if (response == nullptr) + throw Exception(HttpStatusToError()); + + if (HTTP_CODE_SUCCESS(response->resultCode)) + return; + + if (response->resultCode == HTTP_CODE_UNAUTHORIZED) + delSetting("TokenSecret"); + + HttpResponseToError(response); +} + +JSONNode CCloudService::GetJsonResponse(NETLIBHTTPREQUEST *response) +{ + HandleHttpError(response); + + JSONNode root = JSONNode::parse(response->pData); + if (root.isnull()) + throw Exception(HttpStatusToError()); + + HandleJsonError(root); + + return root; +} + +UINT CCloudService::Upload(CCloudService *service, FileTransferParam *ftp) +{ + try { + if (!service->IsLoggedIn()) + service->Login(); + + if (!service->IsLoggedIn()) { + ftp->SetStatus(ACKRESULT_FAILED); + return ACKRESULT_FAILED; + } + + service->Upload(ftp); + } + catch (Exception &ex) { + service->debugLogA("%s: %s", service->GetModuleName(), ex.what()); + ftp->SetStatus(ACKRESULT_FAILED); + return ACKRESULT_FAILED; + } + + ftp->SetStatus(ACKRESULT_SUCCESS); + return ACKRESULT_SUCCESS; +}
\ No newline at end of file |