#include "stdafx.h" char* CDropbox::UploadFile(const char *data, size_t size, char *path) { ptrA token(db_get_sa(NULL, MODULE, "TokenSecret")); ptrA encodedPath(mir_utf8encode(path)); UploadFileRequest request(token, encodedPath, data, size); NLHR_PTR response(request.Send(hNetlibConnection)); JSONNode root = HandleJsonResponse(response); JSONNode node = root.at("path_lower"); mir_strcpy(path, node.as_string().c_str()); return path; } void CDropbox::StartUploadSession(const char *data, size_t size, char *sessionId) { ptrA token(db_get_sa(NULL, MODULE, "TokenSecret")); StartUploadSessionRequest request(token, data, size); NLHR_PTR response(request.Send(hNetlibConnection)); JSONNode root = HandleJsonResponse(response); JSONNode node = root.at("session_id"); mir_strcpy(sessionId, node.as_string().c_str()); } void CDropbox::AppendToUploadSession(const char *data, size_t size, const char *sessionId, size_t offset) { ptrA token(db_get_sa(NULL, MODULE, "TokenSecret")); AppendToUploadSessionRequest request(token, sessionId, offset, data, size); NLHR_PTR response(request.Send(hNetlibConnection)); HandleJsonResponse(response); } char* CDropbox::FinishUploadSession(const char *data, size_t size, const char *sessionId, size_t offset, char *path) { ptrA token(db_get_sa(NULL, MODULE, "TokenSecret")); FinishUploadSessionRequest request(token, sessionId, offset, path, data, size); NLHR_PTR response(request.Send(hNetlibConnection)); JSONNode root = HandleJsonResponse(response); JSONNode node = root.at("path_lower"); mir_strcpy(path, node.as_string().c_str()); return path; } void CDropbox::CreateFolder(const char *path) { ptrA token(db_get_sa(NULL, MODULE, "TokenSecret")); CreateFolderRequest request(token, path); NLHR_PTR response(request.Send(hNetlibConnection)); // forder exists on server if (response->resultCode == HTTP_STATUS_FORBIDDEN) return; HandleJsonResponse(response); } void CDropbox::CreateDownloadUrl(const char *path, char *url) { ptrA token(db_get_sa(NULL, MODULE, "TokenSecret")); if (db_get_b(NULL, MODULE, "UrlIsTemporary", 0)) { GetTemporaryLinkRequest request(token, path); NLHR_PTR response(request.Send(hNetlibConnection)); JSONNode root = HandleJsonResponse(response); JSONNode link = root.at("link"); mir_strcpy(url, link.as_string().c_str()); return; } CreateSharedLinkRequest shareRequest(token, path); NLHR_PTR response(shareRequest.Send(hNetlibConnection)); HandleHttpResponse(response); JSONNode root = JSONNode::parse(response->pData); if (root.isnull()) throw DropboxException(HttpStatusToText(HTTP_STATUS_ERROR)); JSONNode error = root.at("error"); if (error.isnull()) { JSONNode link = root.at("url"); mir_strcpy(url, link.as_string().c_str()); return; } json_string tag = error.at(".tag").as_string(); if (tag != "shared_link_already_exists") throw DropboxException(tag.c_str()); GetSharedLinkRequest getRequest(token, path); response = getRequest.Send(hNetlibConnection); root = HandleJsonResponse(response); JSONNode links = root.at("links").as_array(); const JSONNode &link = (*links.begin()).at("url"); mir_strcpy(url, link.as_string().c_str()); } UINT CDropbox::UploadToDropbox(void *owner, void *arg) { CDropbox *instance = (CDropbox*)owner; FileTransferParam *ftp = (FileTransferParam*)arg; try { const wchar_t *folderName = ftp->GetFolderName(); if (folderName) { char path[MAX_PATH], url[MAX_PATH]; PreparePath(folderName, path); instance->CreateFolder(path); instance->CreateDownloadUrl(path, url); ftp->AppendFormatData(L"%s\r\n", ptrW(mir_utf8decodeW(url))); } ftp->FirstFile(); do { const wchar_t *fileName = ftp->GetCurrentRelativeFilePath(); uint64_t fileSize = ftp->GetCurrentFileSize(); int chunkSize = ftp->GetCurrentFileChunkSize(); mir_ptrdata((char*)mir_calloc(chunkSize)); size_t size = ftp->ReadCurrentFile(data, chunkSize); size_t offset = 0; char sessionId[64]; instance->StartUploadSession(data, size, sessionId); offset += size; ftp->Progress(size); for (size_t chunk = 0; chunk < (fileSize / chunkSize) - 1; chunk++) { ftp->CheckCurrentFile(); size = ftp->ReadCurrentFile(data, chunkSize); instance->AppendToUploadSession(data, size, sessionId, offset); offset += size; ftp->Progress(size); } if (offset < fileSize) size = ftp->ReadCurrentFile(data, fileSize - offset); else size = 0; char path[MAX_PATH]; const wchar_t *serverFolder = ftp->GetServerFolder(); if (serverFolder) { wchar_t serverPath[MAX_PATH] = { 0 }; mir_snwprintf(serverPath, L"%s\\%s", serverFolder, fileName); PreparePath(serverPath, path); } else PreparePath(fileName, path); instance->FinishUploadSession(data, size, sessionId, offset, path); ftp->Progress(size); if (!wcschr(fileName, L'\\')) { char url[MAX_PATH]; instance->CreateDownloadUrl(path, url); ftp->AppendFormatData(L"%s\r\n", ptrW(mir_utf8decodeW(url))); } } while (ftp->NextFile()); } catch (DropboxException &ex) { Netlib_Logf(instance->hNetlibConnection, "%s: %s", MODULE, ex.what()); ftp->SetStatus(ACKRESULT_FAILED); return ACKRESULT_FAILED; } ftp->SetStatus(ACKRESULT_SUCCESS); return ACKRESULT_SUCCESS; } UINT CDropbox::UploadAndReportProgress(void *owner, void *arg) { CDropbox *instance = (CDropbox*)owner; FileTransferParam *ftp = (FileTransferParam*)arg; int res = UploadToDropbox(owner, arg); if (res == ACKRESULT_SUCCESS) instance->Report(ftp->GetHContact(), ftp->GetData()); instance->transfers.remove(ftp); delete ftp; return res; } UINT CDropbox::UploadAndRaiseEvent(void *owner, void *arg) { CDropbox *instance = (CDropbox*)owner; FileTransferParam *ftp = (FileTransferParam*)arg; int res = UploadToDropbox(owner, arg); DropboxUploadResult ur = { 0 }; ur.hProcess = (HANDLE)ftp->GetId(); ur.status = res; ur.data = T2Utf(ftp->GetData()); NotifyEventHooks(instance->hUploadedEventHook, ftp->GetHContact(), (LPARAM)&ur); instance->transfers.remove(ftp); delete ftp; return res; }