summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--plugins/CloudFile/res/resource.rc19
-rw-r--r--plugins/CloudFile/src/Services/dropbox_api.h18
-rw-r--r--plugins/CloudFile/src/Services/dropbox_service.cpp59
-rw-r--r--plugins/CloudFile/src/Services/dropbox_service.h6
-rw-r--r--plugins/CloudFile/src/Services/google_api.h10
-rw-r--r--plugins/CloudFile/src/Services/google_service.cpp87
-rw-r--r--plugins/CloudFile/src/Services/google_service.h8
-rw-r--r--plugins/CloudFile/src/Services/microsoft_api.h31
-rw-r--r--plugins/CloudFile/src/Services/microsoft_service.cpp54
-rw-r--r--plugins/CloudFile/src/Services/microsoft_service.h6
-rw-r--r--plugins/CloudFile/src/Services/yandex_api.h24
-rw-r--r--plugins/CloudFile/src/Services/yandex_service.cpp93
-rw-r--r--plugins/CloudFile/src/Services/yandex_service.h5
-rw-r--r--plugins/CloudFile/src/cloud_service.cpp74
-rw-r--r--plugins/CloudFile/src/cloud_service.h37
-rw-r--r--plugins/CloudFile/src/events.cpp46
-rw-r--r--plugins/CloudFile/src/file_transfer.h16
-rw-r--r--plugins/CloudFile/src/main.cpp10
-rw-r--r--plugins/CloudFile/src/menus.cpp45
-rw-r--r--plugins/CloudFile/src/options.cpp76
-rw-r--r--plugins/CloudFile/src/options.h10
-rw-r--r--plugins/CloudFile/src/resource.h16
-rw-r--r--plugins/CloudFile/src/srmm.cpp38
-rw-r--r--plugins/CloudFile/src/stdafx.h4
-rw-r--r--plugins/CloudFile/src/utils.cpp62
-rw-r--r--plugins/CloudFile/src/version.h2
26 files changed, 471 insertions, 385 deletions
diff --git a/plugins/CloudFile/res/resource.rc b/plugins/CloudFile/res/resource.rc
index 93713dece3..b071d664f7 100644
--- a/plugins/CloudFile/res/resource.rc
+++ b/plugins/CloudFile/res/resource.rc
@@ -83,15 +83,20 @@ STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
EXSTYLE WS_EX_CONTROLPARENT
FONT 8, "MS Shell Dlg", 0, 0, 0x1
BEGIN
- GROUPBOX "Download link",IDC_STATIC,5,5,297,57
+ GROUPBOX "Download link",IDC_STATIC,5,100,297,57
CONTROL "Autosend download link to contact",IDC_URL_AUTOSEND,
- "Button",BS_AUTORADIOBUTTON,11,19,282,10
+ "Button",BS_AUTORADIOBUTTON,11,114,282,10
CONTROL "Paste download link into message input area",IDC_URL_COPYTOMIA,
- "Button",BS_AUTORADIOBUTTON,11,32,282,10
+ "Button",BS_AUTORADIOBUTTON,11,127,282,10
CONTROL "Copy download link to clipboard",IDC_URL_COPYTOCB,
- "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,45,282,10
- GROUPBOX "Services",IDC_STATIC,5,65,297,96
- CONTROL "",IDC_SERVICES,"SysListView32",LVS_REPORT | LVS_ALIGNLEFT | LVS_NOCOLUMNHEADER | WS_BORDER | WS_TABSTOP,11,76,285,76
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,140,282,10
+ GROUPBOX "General",IDC_STATIC,5,5,297,33
+ COMBOBOX IDC_DEFAULTSERVICE,102,17,194,12,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Default service",IDC_STATIC,11,19,85,8
+ GROUPBOX "On conflict when upload",IDC_STATIC,5,41,297,56
+ CONTROL "Try to rename",IDC_RENAMEONCONFLICT,"Button",BS_AUTORADIOBUTTON,11,67,285,10
+ CONTROL "Try to replace",IDC_REPLACEONCONFLICT,"Button",BS_AUTORADIOBUTTON,11,80,285,10
+ CONTROL "Nothing",IDC_DONOTHING,"Button",BS_AUTORADIOBUTTON,11,54,41,10
END
IDD_OAUTH DIALOGEX 0, 0, 193, 83
@@ -138,6 +143,8 @@ BEGIN
LEFTMARGIN, 5
RIGHTMARGIN, 302
VERTGUIDE, 11
+ VERTGUIDE, 96
+ VERTGUIDE, 102
VERTGUIDE, 296
TOPMARGIN, 5
BOTTOMMARGIN, 229
diff --git a/plugins/CloudFile/src/Services/dropbox_api.h b/plugins/CloudFile/src/Services/dropbox_api.h
index 3db69250e8..890ff420f6 100644
--- a/plugins/CloudFile/src/Services/dropbox_api.h
+++ b/plugins/CloudFile/src/Services/dropbox_api.h
@@ -58,23 +58,23 @@ namespace DropboxAPI
}
};
- class StartUploadSessionRequest : public HttpRequest
+ class CreateUploadSessionRequest : public HttpRequest
{
public:
- StartUploadSessionRequest(const char *token, const char *data, size_t size) :
+ CreateUploadSessionRequest(const char *token, const char *chunk, size_t chunkSize) :
HttpRequest(REQUEST_POST, DROPBOX_API_CU "/files/upload_session/start")
{
AddBearerAuthHeader(token);
AddHeader("Content-Type", "application/octet-stream");
- SetData(data, size);
+ SetData(chunk, chunkSize);
}
};
- class AppendToUploadSessionRequest : public HttpRequest
+ class UploadFileChunkRequest : public HttpRequest
{
public:
- AppendToUploadSessionRequest(const char *token, const char *sessionId, size_t offset, const char *data, size_t size) :
+ UploadFileChunkRequest(const char *token, const char *sessionId, size_t offset, const char *chunk, size_t chunkSize) :
HttpRequest(REQUEST_POST, DROPBOX_API_CU "/files/upload_session/append_v2")
{
AddBearerAuthHeader(token);
@@ -92,14 +92,14 @@ namespace DropboxAPI
AddHeader("Dropbox-API-Arg", param.write().c_str());
- SetData(data, size);
+ SetData(chunk, chunkSize);
}
};
- class FinishUploadSessionRequest : public HttpRequest
+ class CommitUploadSessionRequest : public HttpRequest
{
public:
- FinishUploadSessionRequest(const char *token, const char *sessionId, size_t offset, const char *path, const char *data, size_t size) :
+ CommitUploadSessionRequest(const char *token, const char *sessionId, size_t offset, const char *path, const char *chunk, size_t chunkSize) :
HttpRequest(REQUEST_POST, DROPBOX_API_CU "/files/upload_session/finish")
{
AddBearerAuthHeader(token);
@@ -124,7 +124,7 @@ namespace DropboxAPI
AddHeader("Dropbox-API-Arg", params.write().c_str());
- SetData(data, size);
+ SetData(chunk, chunkSize);
}
};
diff --git a/plugins/CloudFile/src/Services/dropbox_service.cpp b/plugins/CloudFile/src/Services/dropbox_service.cpp
index 409494e9d3..fdd904e5e3 100644
--- a/plugins/CloudFile/src/Services/dropbox_service.cpp
+++ b/plugins/CloudFile/src/Services/dropbox_service.cpp
@@ -119,10 +119,10 @@ char* CDropboxService::UploadFile(const char *data, size_t size, char *path)
return path;
}
-void CDropboxService::StartUploadSession(const char *data, size_t size, char *sessionId)
+void CDropboxService::CreateUploadSession(const char *chunk, size_t chunkSize, char *sessionId)
{
ptrA token(db_get_sa(NULL, GetModule(), "TokenSecret"));
- DropboxAPI::StartUploadSessionRequest request(token, data, size);
+ DropboxAPI::CreateUploadSessionRequest request(token, chunk, chunkSize);
NLHR_PTR response(request.Send(hConnection));
JSONNode root = GetJsonResponse(response);
@@ -130,19 +130,19 @@ void CDropboxService::StartUploadSession(const char *data, size_t size, char *se
mir_strcpy(sessionId, node.as_string().c_str());
}
-void CDropboxService::AppendToUploadSession(const char *data, size_t size, const char *sessionId, size_t offset)
+void CDropboxService::UploadFileChunk(const char *chunk, size_t chunkSize, const char *sessionId, size_t offset)
{
ptrA token(db_get_sa(NULL, GetModule(), "TokenSecret"));
- DropboxAPI::AppendToUploadSessionRequest request(token, sessionId, offset, data, size);
+ DropboxAPI::UploadFileChunkRequest request(token, sessionId, offset, chunk, chunkSize);
NLHR_PTR response(request.Send(hConnection));
GetJsonResponse(response);
}
-char* CDropboxService::FinishUploadSession(const char *data, size_t size, const char *sessionId, size_t offset, char *path)
+char* CDropboxService::CommitUploadSession(const char *data, size_t size, const char *sessionId, size_t offset, char *path)
{
ptrA token(db_get_sa(NULL, GetModule(), "TokenSecret"));
- DropboxAPI::FinishUploadSessionRequest request(token, sessionId, offset, path, data, size);
+ DropboxAPI::CommitUploadSessionRequest request(token, sessionId, offset, path, data, size);
NLHR_PTR response(request.Send(hConnection));
JSONNode root = GetJsonResponse(response);
@@ -214,62 +214,57 @@ UINT CDropboxService::Upload(FileTransferParam *ftp)
Login();
try {
- const wchar_t *folderName = ftp->GetFolderName();
- if (folderName) {
- char path[MAX_PATH], url[MAX_PATH];
+ if (ftp->IsFolder()) {
+ T2Utf folderName(ftp->GetFolderName());
+
+ char path[MAX_PATH];
PreparePath(folderName, path);
CreateFolder(path);
- CreateSharedLink(path, url);
- ftp->AppendFormatData(L"%s\r\n", ptrW(mir_utf8decodeW(url)));
+
+ char link[MAX_PATH];
+ CreateSharedLink(path, link);
+ ftp->AppendFormatData(L"%s\r\n", ptrW(mir_utf8decodeW(link)));
}
ftp->FirstFile();
do
{
- const wchar_t *fileName = ftp->GetCurrentRelativeFilePath();
+ T2Utf fileName(ftp->GetCurrentRelativeFilePath());
uint64_t fileSize = ftp->GetCurrentFileSize();
int chunkSize = ftp->GetCurrentFileChunkSize();
mir_ptr<char>data((char*)mir_calloc(chunkSize));
- size_t size = ftp->ReadCurrentFile(data, chunkSize);
- size_t offset = 0;
char sessionId[64];
- StartUploadSession(data, size, sessionId);
+ size_t size = ftp->ReadCurrentFile(data, chunkSize);
+ CreateUploadSession(data, size, sessionId);
- offset += size;
ftp->Progress(size);
- for (size_t chunk = 0; chunk < (fileSize / chunkSize) - 1; chunk++)
+ size_t offset = size;
+ size_t chunkCount = ceil(fileSize / chunkSize) - 2;
+ while (chunkCount--)
{
ftp->CheckCurrentFile();
size = ftp->ReadCurrentFile(data, chunkSize);
- AppendToUploadSession(data, size, sessionId, offset);
+ UploadFileChunk(data, size, sessionId, offset);
offset += size;
ftp->Progress(size);
}
- if (offset < fileSize)
- size = ftp->ReadCurrentFile(data, fileSize - offset);
- else
- size = 0;
+ size = offset < fileSize
+ ? ftp->ReadCurrentFile(data, fileSize - offset)
+ : 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);
- FinishUploadSession(data, size, sessionId, offset, path);
+ PreparePath(fileName, path);
+ CommitUploadSession(data, size, sessionId, offset, path);
ftp->Progress(size);
- if (!wcschr(fileName, L'\\')) {
+ if (!ftp->IsFolder()) {
char url[MAX_PATH];
CreateSharedLink(path, url);
ftp->AppendFormatData(L"%s\r\n", ptrW(mir_utf8decodeW(url)));
diff --git a/plugins/CloudFile/src/Services/dropbox_service.h b/plugins/CloudFile/src/Services/dropbox_service.h
index 362a9751fc..c498b52178 100644
--- a/plugins/CloudFile/src/Services/dropbox_service.h
+++ b/plugins/CloudFile/src/Services/dropbox_service.h
@@ -10,9 +10,9 @@ private:
void HandleJsonError(JSONNode &node);
char* UploadFile(const char *data, size_t size, char *path);
- void StartUploadSession(const char *data, size_t size, char *sessionId);
- void AppendToUploadSession(const char *data, size_t size, const char *sessionId, size_t offset);
- char* FinishUploadSession(const char *data, size_t size, const char *sessionId, size_t offset, char *path);
+ void CreateUploadSession(const char *chunk, size_t chunkSize, char *sessionId);
+ void UploadFileChunk(const char *chunk, size_t chunkSize, const char *sessionId, size_t offset);
+ char* CommitUploadSession(const char *chunk, size_t chunkSize, const char *sessionId, size_t offset, char *path);
void CreateFolder(const char *path);
void CreateSharedLink(const char *path, char *url);
diff --git a/plugins/CloudFile/src/Services/google_api.h b/plugins/CloudFile/src/Services/google_api.h
index b609507caa..c73124cdad 100644
--- a/plugins/CloudFile/src/Services/google_api.h
+++ b/plugins/CloudFile/src/Services/google_api.h
@@ -54,7 +54,7 @@ namespace GDriveAPI
class UploadFileRequest : public HttpRequest
{
public:
- UploadFileRequest(const char *token, const char *name, const char *data, size_t size) :
+ UploadFileRequest(const char *token, const char *parentId, const char *name, const char *data, size_t size) :
HttpRequest(REQUEST_POST, GDRIVE_UPLOAD)
{
AddBearerAuthHeader(token);
@@ -67,6 +67,8 @@ namespace GDriveAPI
body.AppendChar(0x0A);
body.Append("{");
body.AppendFormat("\"name\": \"%s\"", name);
+ if (parentId)
+ body.AppendFormat("\"parents\": [\"%s\"]", parentId);
body.Append("}");
body.AppendChar(0x0A);
body.AppendChar(0x0A);
@@ -86,7 +88,7 @@ namespace GDriveAPI
class CreateUploadSessionRequest : public HttpRequest
{
public:
- CreateUploadSessionRequest(const char *token, const char *name) :
+ CreateUploadSessionRequest(const char *token, const char *parentId, const char *name) :
HttpRequest(REQUEST_POST, GDRIVE_UPLOAD)
{
AddUrlParameter("uploadType=resumable");
@@ -94,8 +96,12 @@ namespace GDriveAPI
AddBearerAuthHeader(token);
AddHeader("Content-Type", "application/json");
+ JSONNode parents(JSON_ARRAY);
+ parents << JSONNode("", parentId);
+
JSONNode params(JSON_NODE);
params << JSONNode("name", name);
+ params << parents;
json_string data = params.write();
SetData(data.c_str(), data.length());
diff --git a/plugins/CloudFile/src/Services/google_service.cpp b/plugins/CloudFile/src/Services/google_service.cpp
index bf6c7de90e..ac1d71b0f1 100644
--- a/plugins/CloudFile/src/Services/google_service.cpp
+++ b/plugins/CloudFile/src/Services/google_service.cpp
@@ -80,14 +80,14 @@ unsigned CGDriveService::RequestAccessTokenThread(void *owner, void *param)
: service->HttpStatusToError(response->resultCode);
Netlib_Logf(service->hConnection, "%s: %s", service->GetModule(), error);
- ShowNotification(TranslateT("server does not respond"), MB_ICONERROR);
+ //ShowNotification(TranslateT("server does not respond"), MB_ICONERROR);
return 0;
}
JSONNode root = JSONNode::parse(response->pData);
if (root.empty()) {
Netlib_Logf(service->hConnection, "%s: %s", service->GetModule(), service->HttpStatusToError(response->resultCode));
- ShowNotification(TranslateT("server does not respond"), MB_ICONERROR);
+ //ShowNotification(TranslateT("server does not respond"), MB_ICONERROR);
return 0;
}
@@ -95,7 +95,7 @@ unsigned CGDriveService::RequestAccessTokenThread(void *owner, void *param)
if (!node.isnull()) {
ptrW error_description(mir_a2u_cp(node.as_string().c_str(), CP_UTF8));
Netlib_Logf(service->hConnection, "%s: %s", service->GetModule(), service->HttpStatusToError(response->resultCode));
- ShowNotification((wchar_t*)error_description, MB_ICONERROR);
+ //ShowNotification((wchar_t*)error_description, MB_ICONERROR);
return 0;
}
@@ -136,10 +136,10 @@ void CGDriveService::HandleJsonError(JSONNode &node)
}
}
-void CGDriveService::UploadFile(const char *name, const char *data, size_t size, char *fileId)
+void CGDriveService::UploadFile(const char *parentId, const char *name, const char *data, size_t size, char *fileId)
{
ptrA token(db_get_sa(NULL, GetModule(), "TokenSecret"));
- GDriveAPI::UploadFileRequest request(token, name, data, size);
+ GDriveAPI::UploadFileRequest request(token, parentId, name, data, size);
NLHR_PTR response(request.Send(hConnection));
JSONNode root = GetJsonResponse(response);
@@ -147,14 +147,13 @@ void CGDriveService::UploadFile(const char *name, const char *data, size_t size,
mir_strcpy(fileId, node.as_string().c_str());
}
-void CGDriveService::CreateUploadSession(char *uploadUri, const char *name)
+void CGDriveService::CreateUploadSession(const char *parentId, const char *name, char *uploadUri)
{
ptrA token(db_get_sa(NULL, GetModule(), "TokenSecret"));
- GDriveAPI::CreateUploadSessionRequest request(token, name);
+ GDriveAPI::CreateUploadSessionRequest request(token, parentId, name);
NLHR_PTR response(request.Send(hConnection));
- if (response == NULL)
- throw Exception(HttpStatusToError());
+ HandleHttpError(response);
if (HTTP_CODE_SUCCESS(response->resultCode)) {
for (int i = 0; i < response->headersCount; i++)
@@ -167,9 +166,7 @@ void CGDriveService::CreateUploadSession(char *uploadUri, const char *name)
}
}
- if (response->dataLength)
- throw Exception(response->pData);
- throw Exception(HttpStatusToError(response->resultCode));
+ HttpResponseToError(response);
}
void CGDriveService::UploadFileChunk(const char *uploadUri, const char *chunk, size_t chunkSize, uint64_t offset, uint64_t fileSize, char *fileId)
@@ -177,8 +174,7 @@ void CGDriveService::UploadFileChunk(const char *uploadUri, const char *chunk, s
GDriveAPI::UploadFileChunkRequest request(uploadUri, chunk, chunkSize, offset, fileSize);
NLHR_PTR response(request.Send(hConnection));
- if (response == NULL)
- throw Exception(HttpStatusToError());
+ HandleHttpError(response);
if (response->resultCode == HTTP_CODE_PERMANENT_REDIRECT)
return;
@@ -190,38 +186,35 @@ void CGDriveService::UploadFileChunk(const char *uploadUri, const char *chunk, s
return;
}
- if (response->dataLength)
- throw Exception(response->pData);
- throw Exception(HttpStatusToError(response->resultCode));
+ HttpResponseToError(response);
}
-void CGDriveService::CreateFolder(const char *path)
+void CGDriveService::CreateFolder(const char *path, char *folderId)
{
ptrA token(db_get_sa(NULL, GetModule(), "TokenSecret"));
GDriveAPI::CreateFolderRequest request(token, path);
NLHR_PTR response(request.Send(hConnection));
- GetJsonResponse(response);
+ JSONNode root = GetJsonResponse(response);
+ JSONNode node = root.at("id");
+ mir_strcpy(folderId, node.as_string().c_str());
}
-void CGDriveService::CreateSharedLink(const char *fileId, char *url)
+void CGDriveService::CreateSharedLink(const char *itemId, char *url)
{
ptrA token(db_get_sa(NULL, GetModule(), "TokenSecret"));
- GDriveAPI::GrantPermissionsRequest request(token, fileId);
+ GDriveAPI::GrantPermissionsRequest request(token, itemId);
NLHR_PTR response(request.Send(hConnection));
- if (response == NULL)
- throw Exception(HttpStatusToError());
+ HandleHttpError(response);
if (HTTP_CODE_SUCCESS(response->resultCode)) {
- CMStringA sharedUrl(CMStringDataFormat::FORMAT, GDRIVE_SHARE, fileId);
+ CMStringA sharedUrl(CMStringDataFormat::FORMAT, GDRIVE_SHARE, itemId);
mir_strcpy(url, sharedUrl);
return;
}
- if (response->dataLength)
- throw Exception(response->pData);
- throw Exception(HttpStatusToError(response->resultCode));
+ HttpResponseToError(response);
}
UINT CGDriveService::Upload(FileTransferParam *ftp)
@@ -235,22 +228,23 @@ UINT CGDriveService::Upload(FileTransferParam *ftp)
return ACKRESULT_FAILED;
}
- const wchar_t *folderName = ftp->GetFolderName();
- if (folderName) {
- char path[MAX_PATH], link[MAX_PATH];
- PreparePath(folderName, path);
- CreateFolder(path);
- CreateSharedLink(path, link);
+ char folderId[32] = { 0 };
+ if (ftp->IsFolder()) {
+ T2Utf folderName(ftp->GetFolderName());
+
+ CreateFolder(folderName, folderId);
+ char link[MAX_PATH];
+
+ CreateSharedLink(folderId, link);
ftp->AppendFormatData(L"%s\r\n", ptrW(mir_utf8decodeW(link)));
}
ftp->FirstFile();
do
{
- const wchar_t *fileName = ftp->GetCurrentRelativeFilePath();
+ T2Utf fileName(ftp->GetCurrentRelativeFilePath());
uint64_t fileSize = ftp->GetCurrentFileSize();
- uint64_t offset = 0;
char fileId[32];
size_t chunkSize = ftp->GetCurrentFileChunkSize();
@@ -259,24 +253,21 @@ UINT CGDriveService::Upload(FileTransferParam *ftp)
if (chunkSize == fileSize)
{
ftp->CheckCurrentFile();
-
size_t size = ftp->ReadCurrentFile(chunk, chunkSize);
- UploadFile(chunk, T2Utf(fileName), size, fileId);
+ UploadFile(folderId, fileName, chunk, size, fileId);
}
else
{
char uploadUri[1024];
- CreateUploadSession(uploadUri, T2Utf(fileName));
+ CreateUploadSession(uploadUri, folderId, fileName);
- size_t size = 0;
- for (size_t i = 0; i < (fileSize / chunkSize); i++)
+ uint64_t offset = 0;
+ size_t chunkCount = ceil(fileSize / chunkSize);
+ while (chunkCount--)
{
ftp->CheckCurrentFile();
-
- size = ftp->ReadCurrentFile(chunk, chunkSize);
- if (size == 0)
- break;
+ size_t size = ftp->ReadCurrentFile(chunk, chunkSize);
UploadFileChunk(uploadUri, chunk, size, offset, fileSize, fileId);
@@ -285,10 +276,10 @@ UINT CGDriveService::Upload(FileTransferParam *ftp)
}
}
- if (!wcschr(fileName, L'\\')) {
- char url[MAX_PATH];
- CreateSharedLink(fileId, url);
- ftp->AppendFormatData(L"%s\r\n", ptrW(mir_utf8decodeW(url)));
+ if (!ftp->IsFolder()) {
+ char link[MAX_PATH];
+ CreateSharedLink(fileId, link);
+ ftp->AppendFormatData(L"%s\r\n", ptrW(mir_utf8decodeW(link)));
}
} while (ftp->NextFile());
}
diff --git a/plugins/CloudFile/src/Services/google_service.h b/plugins/CloudFile/src/Services/google_service.h
index 1da21b5fef..878fa8f442 100644
--- a/plugins/CloudFile/src/Services/google_service.h
+++ b/plugins/CloudFile/src/Services/google_service.h
@@ -9,11 +9,11 @@ private:
void HandleJsonError(JSONNode &node);
- void UploadFile(const char *name, const char *data, size_t size, char *fileId);
- void CreateUploadSession(char *uploadUri, const char *name);
+ void UploadFile(const char *parentId, const char *name, const char *data, size_t size, char *fileId);
+ void CreateUploadSession(const char *parentId, const char *name, char *uploadUri);
void UploadFileChunk(const char *uploadUri, const char *chunk, size_t chunkSize, uint64_t offset, uint64_t fileSize, char *fileId);
- void CreateFolder(const char *path);
- void CreateSharedLink(const char *fileId, char *url);
+ void CreateFolder(const char *path, char *folderId);
+ void CreateSharedLink(const char *itemId, char *url);
public:
CGDriveService(HNETLIBUSER hConnection);
diff --git a/plugins/CloudFile/src/Services/microsoft_api.h b/plugins/CloudFile/src/Services/microsoft_api.h
index 395d6e434d..cc27a80756 100644
--- a/plugins/CloudFile/src/Services/microsoft_api.h
+++ b/plugins/CloudFile/src/Services/microsoft_api.h
@@ -40,20 +40,26 @@ namespace OneDriveAPI
class UploadFileRequest : public HttpRequest
{
public:
- UploadFileRequest(const char *token, const char *name, const char *data, size_t size) :
+ UploadFileRequest(const char *token, const char *name, const char *data, size_t size, OnConflict strategy = NONE) :
HttpRequest(REQUEST_PUT, FORMAT, ONEDRIVE_API "/special/approot:/%s:/content", ptrA(mir_urlEncode(name)))
{
- AddUrlParameter("@microsoft.graph.conflictBehavior=rename");
+ if (strategy == OnConflict::RENAME)
+ AddUrlParameter("@microsoft.graph.conflictBehavior=rename");
+ else if (strategy == OnConflict::REPLACE)
+ AddUrlParameter("@microsoft.graph.conflictBehavior=replace");
AddBearerAuthHeader(token);
SetData(data, size);
}
- UploadFileRequest(const char *token, const char *parentId, const char *name, const char *data, size_t size) :
+ UploadFileRequest(const char *token, const char *parentId, const char *name, const char *data, size_t size, OnConflict strategy = NONE) :
HttpRequest(REQUEST_PUT, FORMAT, ONEDRIVE_API "/items/{parent-id}:/{filename}:/content", parentId, ptrA(mir_urlEncode(name)))
{
- AddUrlParameter("@microsoft.graph.conflictBehavior=rename");
+ if (strategy == OnConflict::RENAME)
+ AddUrlParameter("@microsoft.graph.conflictBehavior=rename");
+ else if (strategy == OnConflict::REPLACE)
+ AddUrlParameter("@microsoft.graph.conflictBehavior=replace");
AddBearerAuthHeader(token);
@@ -64,7 +70,7 @@ namespace OneDriveAPI
class CreateUploadSessionRequest : public HttpRequest
{
public:
- CreateUploadSessionRequest(const char *token, const char *name) :
+ CreateUploadSessionRequest(const char *token, const char *name, OnConflict strategy = NONE) :
HttpRequest(REQUEST_POST, FORMAT, ONEDRIVE_API "/special/approot:/%s:/createUploadSession", ptrA(mir_urlEncode(name)))
{
AddBearerAuthHeader(token);
@@ -72,8 +78,10 @@ namespace OneDriveAPI
JSONNode item(JSON_NODE);
item.set_name("item");
- item
- << JSONNode("@microsoft.graph.conflictBehavior", "rename");
+ if (strategy == OnConflict::RENAME)
+ item << JSONNode("@microsoft.graph.conflictBehavior", "rename");
+ if (strategy == OnConflict::REPLACE)
+ item << JSONNode("@microsoft.graph.conflictBehavior", "replace");
JSONNode params(JSON_NODE);
params << item;
@@ -82,7 +90,7 @@ namespace OneDriveAPI
SetData(data.c_str(), data.length());
}
- CreateUploadSessionRequest(const char *token, const char *parentId, const char *name) :
+ CreateUploadSessionRequest(const char *token, const char *parentId, const char *name, OnConflict strategy = NONE) :
HttpRequest(REQUEST_POST, FORMAT, ONEDRIVE_API "/items/%s:/%s:/createUploadSession", parentId, name)
{
AddBearerAuthHeader(token);
@@ -90,9 +98,10 @@ namespace OneDriveAPI
JSONNode item(JSON_NODE);
item.set_name("item");
- item
- << JSONNode("@microsoft.graph.conflictBehavior", "rename")
- << JSONNode("name", name);
+ if (strategy == OnConflict::RENAME)
+ item << JSONNode("@microsoft.graph.conflictBehavior", "rename");
+ if (strategy == OnConflict::REPLACE)
+ item << JSONNode("@microsoft.graph.conflictBehavior", "replace");
JSONNode params(JSON_NODE);
params << item;
diff --git a/plugins/CloudFile/src/Services/microsoft_service.cpp b/plugins/CloudFile/src/Services/microsoft_service.cpp
index 0cf41eb738..77919574e0 100644
--- a/plugins/CloudFile/src/Services/microsoft_service.cpp
+++ b/plugins/CloudFile/src/Services/microsoft_service.cpp
@@ -82,14 +82,14 @@ unsigned COneDriveService::RequestAccessTokenThread(void *owner, void *param)
: service->HttpStatusToError(response->resultCode);
Netlib_Logf(service->hConnection, "%s: %s", service->GetModule(), error);
- ShowNotification(TranslateT("server does not respond"), MB_ICONERROR);
+ //ShowNotification(TranslateT("server does not respond"), MB_ICONERROR);
return 0;
}
JSONNode root = JSONNode::parse(response->pData);
if (root.empty()) {
Netlib_Logf(service->hConnection, "%s: %s", service->GetModule(), service->HttpStatusToError(response->resultCode));
- ShowNotification(TranslateT("server does not respond"), MB_ICONERROR);
+ //ShowNotification(TranslateT("server does not respond"), MB_ICONERROR);
return 0;
}
@@ -97,7 +97,7 @@ unsigned COneDriveService::RequestAccessTokenThread(void *owner, void *param)
if (!node.isnull()) {
ptrW error_description(mir_a2u_cp(node.as_string().c_str(), CP_UTF8));
Netlib_Logf(service->hConnection, "%s: %s", service->GetModule(), service->HttpStatusToError(response->resultCode));
- ShowNotification((wchar_t*)error_description, MB_ICONERROR);
+ //ShowNotification((wchar_t*)error_description, MB_ICONERROR);
return 0;
}
@@ -141,7 +141,7 @@ void COneDriveService::UploadFile(const char *parentId, const char *name, const
mir_strcpy(fileId, node.as_string().c_str());
}
-void COneDriveService::CreateUploadSession(char *uploadUri, const char *name, const char *parentId)
+void COneDriveService::CreateUploadSession(const char *parentId, const char *name, char *uploadUri)
{
ptrA token(db_get_sa(NULL, GetModule(), "TokenSecret"));
OneDriveAPI::CreateUploadSessionRequest *request = mir_strlen(parentId)
@@ -155,13 +155,12 @@ void COneDriveService::CreateUploadSession(char *uploadUri, const char *name, co
mir_strcpy(uploadUri, node.as_string().c_str());
}
-void COneDriveService::UploadFileChunk(const char *uploadUri, const char *chunk, size_t chunkSize, uint64_t offset, uint64_t fileSize, char *itemId)
+void COneDriveService::UploadFileChunk(const char *uploadUri, const char *chunk, size_t chunkSize, uint64_t offset, uint64_t fileSize, char *fileId)
{
OneDriveAPI::UploadFileChunkRequest request(uploadUri, chunk, chunkSize, offset, fileSize);
NLHR_PTR response(request.Send(hConnection));
- if (response == NULL)
- throw Exception(HttpStatusToError());
+ HandleHttpError(response);
if (response->resultCode == HTTP_CODE_ACCEPTED)
return;
@@ -169,16 +168,14 @@ void COneDriveService::UploadFileChunk(const char *uploadUri, const char *chunk,
if (HTTP_CODE_SUCCESS(response->resultCode)) {
JSONNode root = GetJsonResponse(response);
JSONNode node = root.at("id");
- mir_strcpy(itemId, node.as_string().c_str());
+ mir_strcpy(fileId, node.as_string().c_str());
return;
}
- if (response->dataLength)
- throw Exception(response->pData);
- throw Exception(HttpStatusToError(response->resultCode));
+ HttpResponseToError(response);
}
-void COneDriveService::CreateFolder(const char *path, char *itemId)
+void COneDriveService::CreateFolder(const char *path, char *folderId)
{
ptrA token(db_get_sa(NULL, GetModule(), "TokenSecret"));
OneDriveAPI::CreateFolderRequest request(token, path);
@@ -186,7 +183,7 @@ void COneDriveService::CreateFolder(const char *path, char *itemId)
JSONNode root = GetJsonResponse(response);
JSONNode node = root.at("id");
- mir_strcpy(itemId, node.as_string().c_str());
+ mir_strcpy(folderId, node.as_string().c_str());
}
void COneDriveService::CreateSharedLink(const char *itemId, char *url)
@@ -213,11 +210,14 @@ UINT COneDriveService::Upload(FileTransferParam *ftp)
}
char folderId[32] = { 0 };
- const wchar_t *folderName = ftp->GetFolderName();
- if (folderName) {
- char path[MAX_PATH], link[MAX_PATH];
+ if (ftp->IsFolder()) {
+ T2Utf folderName(ftp->GetFolderName());
+
+ char path[MAX_PATH];
PreparePath(folderName, path);
CreateFolder(path, folderId);
+
+ char link[MAX_PATH];
CreateSharedLink(path, link);
ftp->AppendFormatData(L"%s\r\n", ptrW(mir_utf8decodeW(link)));
}
@@ -225,10 +225,9 @@ UINT COneDriveService::Upload(FileTransferParam *ftp)
ftp->FirstFile();
do
{
- const wchar_t *fileName = ftp->GetCurrentRelativeFilePath();
+ T2Utf fileName(ftp->GetCurrentRelativeFilePath());
uint64_t fileSize = ftp->GetCurrentFileSize();
- uint64_t offset = 0;
char fileId[32];
size_t chunkSize = ftp->GetCurrentFileChunkSize();
@@ -237,7 +236,6 @@ UINT COneDriveService::Upload(FileTransferParam *ftp)
if (chunkSize == fileSize)
{
ftp->CheckCurrentFile();
-
size_t size = ftp->ReadCurrentFile(chunk, chunkSize);
UploadFile(folderId, T2Utf(fileName), chunk, size, fileId);
@@ -247,14 +245,10 @@ UINT COneDriveService::Upload(FileTransferParam *ftp)
char uploadUri[1024];
CreateUploadSession(uploadUri, T2Utf(fileName), folderId);
- size_t size = 0;
- for (size_t i = 0; i < (fileSize / chunkSize); i++)
- {
+ uint64_t offset = 0;
+ for (size_t i = 0; i < (fileSize / chunkSize); i++) {
ftp->CheckCurrentFile();
-
- size = ftp->ReadCurrentFile(chunk, chunkSize);
- if (size == 0)
- break;
+ size_t size = ftp->ReadCurrentFile(chunk, chunkSize);
UploadFileChunk(uploadUri, chunk, size, offset, fileSize, fileId);
@@ -263,10 +257,10 @@ UINT COneDriveService::Upload(FileTransferParam *ftp)
}
}
- if (!wcschr(fileName, L'\\')) {
- char url[MAX_PATH];
- CreateSharedLink(fileId, url);
- ftp->AppendFormatData(L"%s\r\n", ptrW(mir_utf8decodeW(url)));
+ if (!ftp->IsFolder()) {
+ char link[MAX_PATH];
+ CreateSharedLink(fileId, link);
+ ftp->AppendFormatData(L"%s\r\n", ptrW(mir_utf8decodeW(link)));
}
} while (ftp->NextFile());
}
diff --git a/plugins/CloudFile/src/Services/microsoft_service.h b/plugins/CloudFile/src/Services/microsoft_service.h
index 3b49e1f6f3..cdd9d53976 100644
--- a/plugins/CloudFile/src/Services/microsoft_service.h
+++ b/plugins/CloudFile/src/Services/microsoft_service.h
@@ -9,9 +9,9 @@ private:
void HandleJsonError(JSONNode &node);
void UploadFile(const char *parentId, const char *name, const char *data, size_t size, char *fileId);
- void CreateUploadSession(char *uploadUri, const char *name, const char *parentId = NULL);
- void UploadFileChunk(const char *uploadUri, const char *chunk, size_t chunkSize, uint64_t offset, uint64_t fileSize, char *itemId);
- void CreateFolder(const char *path, char *itemId);
+ void CreateUploadSession(const char *parentId, const char *name, char *uploadUri);
+ void UploadFileChunk(const char *uploadUri, const char *chunk, size_t chunkSize, uint64_t offset, uint64_t fileSize, char *fileId);
+ void CreateFolder(const char *path, char *folderId);
void CreateSharedLink(const char *itemId, char *url);
public:
diff --git a/plugins/CloudFile/src/Services/yandex_api.h b/plugins/CloudFile/src/Services/yandex_api.h
index 2a83abb634..56d77feb8c 100644
--- a/plugins/CloudFile/src/Services/yandex_api.h
+++ b/plugins/CloudFile/src/Services/yandex_api.h
@@ -52,27 +52,41 @@ namespace YandexAPI
class GetUploadUrlRequest : public HttpRequest
{
public:
- GetUploadUrlRequest(const char *token, const char *path) :
+ GetUploadUrlRequest(const char *token, const char *path, OnConflict strategy = NONE) :
HttpRequest(REQUEST_GET, YADISK_API "/upload")
{
AddOAuthHeader(token);
AddUrlParameter("path=%s", ptrA(mir_urlEncode(path)));
- AddUrlParameter("overwrite=true");
+ if (strategy == OnConflict::REPLACE)
+ AddUrlParameter("overwrite=true");
}
};
class UploadFileRequest : public HttpRequest
{
public:
- UploadFileRequest(const char *token, const char *url, const char *data, size_t size) :
+ UploadFileRequest(const char *url, const char *data, size_t size) :
HttpRequest(REQUEST_PUT, url)
{
- AddOAuthHeader(token);
-
SetData(data, size);
}
};
+ class UploadFileChunkRequest : public HttpRequest
+ {
+ public:
+ UploadFileChunkRequest(const char *url, const char *chunk, size_t chunkSize, uint64_t offset, uint64_t fileSize) :
+ HttpRequest(REQUEST_PUT, url)
+ {
+ uint64_t rangeMin = offset;
+ uint64_t rangeMax = offset + chunkSize - 1;
+ CMStringA range(CMStringDataFormat::FORMAT, "bytes %I64u-%I64u/%I64u", rangeMin, rangeMax, fileSize);
+ AddHeader("Content-Range", range);
+
+ SetData(chunk, chunkSize);
+ }
+ };
+
class CreateFolderRequest : public HttpRequest
{
public:
diff --git a/plugins/CloudFile/src/Services/yandex_service.cpp b/plugins/CloudFile/src/Services/yandex_service.cpp
index 1b8abecf96..bce62324a1 100644
--- a/plugins/CloudFile/src/Services/yandex_service.cpp
+++ b/plugins/CloudFile/src/Services/yandex_service.cpp
@@ -83,14 +83,14 @@ unsigned CYandexService::RequestAccessTokenThread(void *owner, void *param)
: service->HttpStatusToError(response->resultCode);
Netlib_Logf(service->hConnection, "%s: %s", service->GetModule(), error);
- ShowNotification(TranslateT("server does not respond"), MB_ICONERROR);
+ //ShowNotification(TranslateT("server does not respond"), MB_ICONERROR);
return 0;
}
JSONNode root = JSONNode::parse(response->pData);
if (root.empty()) {
Netlib_Logf(service->hConnection, "%s: %s", service->GetModule(), service->HttpStatusToError(response->resultCode));
- ShowNotification(TranslateT("server does not respond"), MB_ICONERROR);
+ //ShowNotification(TranslateT("server does not respond"), MB_ICONERROR);
return 0;
}
@@ -98,7 +98,7 @@ unsigned CYandexService::RequestAccessTokenThread(void *owner, void *param)
if (!node.isnull()) {
ptrW error_description(mir_a2u_cp(node.as_string().c_str(), CP_UTF8));
Netlib_Logf(service->hConnection, "%s: %s", service->GetModule(), service->HttpStatusToError(response->resultCode));
- ShowNotification((wchar_t*)error_description, MB_ICONERROR);
+ //ShowNotification((wchar_t*)error_description, MB_ICONERROR);
return 0;
}
@@ -139,7 +139,7 @@ void CYandexService::HandleJsonError(JSONNode &node)
}
}
-void CYandexService::GetUploadUrl(char *path, char *url)
+void CYandexService::CreateUploadSession(const char *path, char *uploadUri)
{
ptrA token(db_get_sa(NULL, GetModule(), "TokenSecret"));
YandexAPI::GetUploadUrlRequest request(token, path);
@@ -147,26 +147,34 @@ void CYandexService::GetUploadUrl(char *path, char *url)
JSONNode root = GetJsonResponse(response);
JSONNode node = root.at("href");
- mir_strcpy(url, node.as_string().c_str());
+ mir_strcpy(uploadUri, node.as_string().c_str());
}
-void CYandexService::UploadFile(const char *url, const char *data, size_t size)
+void CYandexService::UploadFile(const char *uploadUri, const char *data, size_t size)
{
- ptrA token(db_get_sa(NULL, GetModule(), "TokenSecret"));
- YandexAPI::UploadFileRequest request(token, url, data, size);
+ YandexAPI::UploadFileRequest request(uploadUri, data, size);
NLHR_PTR response(request.Send(hConnection));
- if (response == NULL)
- throw Exception(HttpStatusToError());
+ HandleHttpError(response);
- if (response->resultCode >= HTTP_CODE_OK &&
- response->resultCode <= HTTP_CODE_MULTIPLE_CHOICES) {
+ if (response->resultCode == HTTP_CODE_CREATED)
return;
- }
- if (response->dataLength)
- throw Exception(response->pData);
- throw Exception(HttpStatusToError(response->resultCode));
+ HttpResponseToError(response);
+}
+
+void CYandexService::UploadFileChunk(const char *uploadUri, const char *chunk, size_t chunkSize, uint64_t offset, uint64_t fileSize)
+{
+ YandexAPI::UploadFileChunkRequest request(uploadUri, chunk, chunkSize, offset, fileSize);
+ NLHR_PTR response(request.Send(hConnection));
+
+ HandleHttpError(response);
+
+ if (response->resultCode == HTTP_CODE_ACCEPTED ||
+ response->resultCode == HTTP_CODE_CREATED)
+ return;
+
+ HttpResponseToError(response);
}
void CYandexService::CreateFolder(const char *path)
@@ -206,11 +214,14 @@ UINT CYandexService::Upload(FileTransferParam *ftp)
return ACKRESULT_FAILED;
}
- const wchar_t *folderName = ftp->GetFolderName();
- if (folderName) {
- char path[MAX_PATH], link[MAX_PATH];
+ if (ftp->IsFolder()) {
+ T2Utf folderName(ftp->GetFolderName());
+
+ char path[MAX_PATH];
PreparePath(folderName, path);
CreateFolder(path);
+
+ char link[MAX_PATH];
CreateSharedLink(path, link);
ftp->AppendFormatData(L"%s\r\n", ptrW(mir_utf8decodeW(link)));
}
@@ -218,28 +229,40 @@ UINT CYandexService::Upload(FileTransferParam *ftp)
ftp->FirstFile();
do
{
- const wchar_t *fileName = ftp->GetCurrentRelativeFilePath();
+ T2Utf fileName(ftp->GetCurrentRelativeFilePath());
uint64_t fileSize = ftp->GetCurrentFileSize();
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);
- char url[MAX_PATH];
- GetUploadUrl(path, url);
+ PreparePath(fileName, path);
+
+ char uploadUri[1024];
+ CreateUploadSession(path, uploadUri);
+
+ size_t chunkSize = ftp->GetCurrentFileChunkSize();
+ mir_ptr<char>chunk((char*)mir_calloc(chunkSize));
- mir_ptr<char>data((char*)mir_calloc(fileSize));
- size_t size = ftp->ReadCurrentFile(data, fileSize);
- UploadFile(url, data, size);
+ if (chunkSize == fileSize) {
+ ftp->CheckCurrentFile();
+ size_t size = ftp->ReadCurrentFile(chunk, chunkSize);
- ftp->Progress(size);
+ UploadFile(uploadUri, chunk, size);
+ }
+ else {
+ uint64_t offset = 0;
+ size_t chunkCount = ceil(fileSize / chunkSize);
+ while (chunkCount--)
+ {
+ ftp->CheckCurrentFile();
+ size_t size = ftp->ReadCurrentFile(chunk, chunkSize);
+
+ UploadFileChunk(uploadUri, chunk, size, offset, fileSize);
+
+ offset += size;
+ ftp->Progress(size);
+ }
+ }
- if (!wcschr(fileName, L'\\')) {
+ if (!ftp->IsFolder()) {
char url[MAX_PATH];
CreateSharedLink(path, url);
ftp->AppendFormatData(L"%s\r\n", ptrW(mir_utf8decodeW(url)));
diff --git a/plugins/CloudFile/src/Services/yandex_service.h b/plugins/CloudFile/src/Services/yandex_service.h
index e3b122ffa1..85c0ad12de 100644
--- a/plugins/CloudFile/src/Services/yandex_service.h
+++ b/plugins/CloudFile/src/Services/yandex_service.h
@@ -9,8 +9,9 @@ private:
void HandleJsonError(JSONNode &node);
- void GetUploadUrl(char *path, char *url);
- void UploadFile(const char *url, const char *data, size_t size);
+ void CreateUploadSession(const char *path, char *uploadUri);
+ void UploadFile(const char *uploadUri, const char *data, size_t size);
+ void UploadFileChunk(const char *uploadUri, const char *chunk, size_t chunkSize, uint64_t offset, uint64_t fileSize);
void CreateFolder(const char *path);
void CreateSharedLink(const char *path, char *url);
diff --git a/plugins/CloudFile/src/cloud_service.cpp b/plugins/CloudFile/src/cloud_service.cpp
index f8b8b1e976..3ad83d1e2f 100644
--- a/plugins/CloudFile/src/cloud_service.cpp
+++ b/plugins/CloudFile/src/cloud_service.cpp
@@ -20,23 +20,21 @@ void InitServices()
for (size_t i = 0; i < count; i++) {
CCloudService *service = Services[i];
- if (!db_get_b(NULL, service->GetModule(), "IsEnable", TRUE))
- continue;
-
- CMStringA moduleName(CMStringDataFormat::FORMAT, "%s/%s", MODULE, service->GetModule());
+ CMStringA moduleName = MODULE;
+ moduleName.AppendFormat("/%s", service->GetModule());
pd.type = PROTOTYPE_VIRTUAL;
pd.szName = moduleName.GetBuffer();
Proto_RegisterModule(&pd);
- CMStringA serviceName(CMStringDataFormat::FORMAT, "%s%s", moduleName, PSS_FILE);
+ CMStringA serviceName = moduleName + PSS_FILE;
CreateServiceFunctionObj(serviceName, ProtoSendFile, service);
- moduleName = CMStringA(CMStringDataFormat::FORMAT, "%s/%s/Interceptor", MODULE, service->GetModule());
+ moduleName += "/Interceptor";
pd.szName = moduleName.GetBuffer();
pd.type = PROTOTYPE_FILTER;
Proto_RegisterModule(&pd);
- serviceName = CMStringA(CMStringDataFormat::FORMAT, "%s%s", moduleName, PSS_FILE);
+ serviceName = moduleName + PSS_FILE;
CreateServiceFunctionObj(serviceName, ProtoSendFileInterceptor, service);
}
}
@@ -46,6 +44,16 @@ CCloudService::CCloudService(HNETLIBUSER hConnection)
{
}
+const wchar_t* CCloudService::GetText() const
+{
+ return _A2T(GetModule());
+}
+
+int CCloudService::GetIconId() const
+{
+ return 0;
+}
+
void CCloudService::OpenUploadDialog(MCONTACT hContact)
{
char *proto = GetContactProto(hContact);
@@ -62,44 +70,6 @@ void CCloudService::OpenUploadDialog(MCONTACT hContact)
SetActiveWindow(it->second);
}
-void CCloudService::SendToContact(MCONTACT hContact, const wchar_t *data)
-{
- const char *szProto = GetContactProto(hContact);
- if (db_get_b(hContact, szProto, "ChatRoom", 0) == TRUE) {
- ptrW tszChatRoom(db_get_wsa(hContact, szProto, "ChatRoomID"));
- Chat_SendUserMessage(szProto, tszChatRoom, data);
- return;
- }
-
- char *message = mir_utf8encodeW(data);
- if (ProtoChainSend(hContact, PSS_MESSAGE, 0, (LPARAM)message) != ACKRESULT_FAILED)
- AddEventToDb(hContact, EVENTTYPE_MESSAGE, DBEF_UTF | DBEF_SENT, (DWORD)mir_strlen(message), (PBYTE)message);
-}
-
-void CCloudService::PasteToInputArea(MCONTACT hContact, const wchar_t *data)
-{
- CallService(MS_MSG_SENDMESSAGEW, hContact, (LPARAM)data);
-}
-
-void CCloudService::PasteToClipboard(const wchar_t *data)
-{
- if (OpenClipboard(NULL)) {
- EmptyClipboard();
-
- size_t size = sizeof(wchar_t) * (mir_wstrlen(data) + 1);
- HGLOBAL hClipboardData = GlobalAlloc(NULL, size);
- if (hClipboardData) {
- wchar_t *pchData = (wchar_t*)GlobalLock(hClipboardData);
- if (pchData) {
- memcpy(pchData, (wchar_t*)data, size);
- GlobalUnlock(hClipboardData);
- SetClipboardData(CF_UNICODETEXT, hClipboardData);
- }
- }
- CloseClipboard();
- }
-}
-
void CCloudService::Report(MCONTACT hContact, const wchar_t *data)
{
if (db_get_b(NULL, MODULE, "UrlAutoSend", 1))
@@ -157,16 +127,20 @@ char* CCloudService::HttpStatusToError(int status)
return "Unknown error";
}
+void CCloudService::HttpResponseToError(NETLIBHTTPREQUEST *response)
+{
+ if (response->dataLength)
+ throw Exception(response->pData);
+ throw Exception(HttpStatusToError(response->resultCode));
+}
+
void CCloudService::HandleHttpError(NETLIBHTTPREQUEST *response)
{
if (response == NULL)
throw Exception(HttpStatusToError());
- if (!HTTP_CODE_SUCCESS(response->resultCode)) {
- if (response->dataLength)
- throw Exception(response->pData);
- throw Exception(HttpStatusToError(response->resultCode));
- }
+ if (!HTTP_CODE_SUCCESS(response->resultCode))
+ HttpResponseToError(response);
}
JSONNode CCloudService::GetJsonResponse(NETLIBHTTPREQUEST *response)
diff --git a/plugins/CloudFile/src/cloud_service.h b/plugins/CloudFile/src/cloud_service.h
index ed35961cd6..edc4cdd90d 100644
--- a/plugins/CloudFile/src/cloud_service.h
+++ b/plugins/CloudFile/src/cloud_service.h
@@ -1,6 +1,13 @@
#ifndef _CLOUD_SERVICE_H_
#define _CLOUD_SERVICE_H_
+enum OnConflict
+{
+ NONE,
+ RENAME,
+ REPLACE,
+};
+
class CCloudService
{
protected:
@@ -12,6 +19,7 @@ protected:
char* PreparePath(const wchar_t *oldPath, char *newPath);
virtual char* HttpStatusToError(int status = 0);
+ virtual void HttpResponseToError(NETLIBHTTPREQUEST *response);
virtual void HandleHttpError(NETLIBHTTPREQUEST *response);
virtual void HandleJsonError(JSONNode &node) = 0;
@@ -23,8 +31,8 @@ public:
CCloudService(HNETLIBUSER hConnection);
virtual const char* GetModule() const = 0;
- virtual const wchar_t* GetText() const = 0;
- virtual int GetIconId() const = 0;
+ virtual const wchar_t* GetText() const;
+ virtual int GetIconId() const;
virtual bool IsLoggedIn() = 0;
virtual void Login() = 0;
@@ -34,11 +42,28 @@ public:
virtual UINT Upload(FileTransferParam *ftp) = 0;
- void SendToContact(MCONTACT hContact, const wchar_t *data);
- void PasteToInputArea(MCONTACT hContact, const wchar_t *data);
- void PasteToClipboard(const wchar_t *data);
-
void Report(MCONTACT hContact, const wchar_t *data);
};
+class CCloudServiceSearch : public CCloudService
+{
+private:
+ const char *m_search;
+
+protected:
+ void HandleJsonError(JSONNode&) { }
+
+public:
+ CCloudServiceSearch(const char *search)
+ : CCloudService(NULL), m_search(search) { }
+
+ const char* GetModule() const { return m_search; }
+
+ bool IsLoggedIn() { return false; }
+ void Login() { }
+ void Logout() { }
+
+ UINT Upload(FileTransferParam*) { return 0; }
+};
+
#endif //_CLOUD_SERVICE_H_ \ No newline at end of file
diff --git a/plugins/CloudFile/src/events.cpp b/plugins/CloudFile/src/events.cpp
index df71721dfb..248397b8f4 100644
--- a/plugins/CloudFile/src/events.cpp
+++ b/plugins/CloudFile/src/events.cpp
@@ -2,16 +2,6 @@
int OnModulesLoaded(WPARAM, LPARAM)
{
- // init
- InitServices();
- InitializeIcons();
- InitializeMenus();
- // netlib
- NETLIBUSER nlu = {};
- nlu.flags = NUF_INCOMING | NUF_OUTGOING | NUF_HTTPCONNS | NUF_UNICODE;
- nlu.szSettingsModule = MODULE;
- nlu.szDescriptiveName.w = _A2W("MODULE");
- hNetlibConnection = Netlib_RegisterUser(&nlu);
// options
HookEvent(ME_OPT_INITIALISE, OnOptionsInitialized);
// srfile
@@ -35,27 +25,21 @@ int OnProtoAck(WPARAM, LPARAM lParam)
{
ACKDATA *ack = (ACKDATA*)lParam;
- if (!mir_strcmp(ack->szModule, MODULE))
- return 0; // don't rebroadcast our own acks
-
- if (ack->type == ACKTYPE_STATUS) {
- WORD status = ack->lParam;
- bool canSendOffline = (CallProtoService(ack->szModule, PS_GETCAPS, PFLAGNUM_4, 0) & PF4_IMSENDOFFLINE) > 0;
-
- for (MCONTACT hContact = db_find_first(ack->szModule); hContact; hContact = db_find_next(hContact, ack->szModule)) {
- MessageWindowData msgw;
- if (!Srmm_GetWindowData(hContact, msgw) && msgw.uState & MSG_WINDOW_STATE_EXISTS) {
- BBButton bbd = {};
- bbd.pszModuleName = MODULE;
- bbd.dwButtonID = BBB_ID_FILE_SEND;
- bbd.bbbFlags = BBSF_RELEASED;
-
- if (status == ID_STATUS_OFFLINE && !canSendOffline)
- bbd.bbbFlags = BBSF_DISABLED;
-
- Srmm_SetButtonState(hContact, &bbd);
- }
- }
+ if (ack->type != ACKTYPE_STATUS)
+ return 0;
+
+ for (MCONTACT hContact = db_find_first(ack->szModule); hContact; hContact = db_find_next(hContact, ack->szModule)) {
+ MessageWindowData msgw;
+ if (Srmm_GetWindowData(hContact, msgw) || !(msgw.uState & MSG_WINDOW_STATE_EXISTS))
+ continue;
+
+ BBButton bbd = {};
+ bbd.pszModuleName = MODULE;
+ bbd.dwButtonID = BBB_ID_FILE_SEND;
+ bbd.bbbFlags = CanSendToContact(hContact)
+ ? BBSF_RELEASED
+ : BBSF_DISABLED;
+ Srmm_SetButtonState(hContact, &bbd);
}
return 0;
diff --git a/plugins/CloudFile/src/file_transfer.h b/plugins/CloudFile/src/file_transfer.h
index 700988eaf4..cdf4475aeb 100644
--- a/plugins/CloudFile/src/file_transfer.h
+++ b/plugins/CloudFile/src/file_transfer.h
@@ -14,9 +14,7 @@ private:
const wchar_t* folderName;
int relativePathStart;
-
- CMStringW serverFolder;
-
+
CMStringW data;
public:
@@ -96,17 +94,9 @@ public:
folderName = wcsrchr(path, '\\') + 1;
}
- void SetServerFolder(const wchar_t *path)
- {
- if (path)
- serverFolder = path;
- }
-
- const wchar_t* GetServerFolder() const
+ const wchar_t* IsFolder() const
{
- if (serverFolder.IsEmpty())
- return NULL;
- return serverFolder;
+ return folderName;
}
const wchar_t* GetFolderName() const
diff --git a/plugins/CloudFile/src/main.cpp b/plugins/CloudFile/src/main.cpp
index a95c9db056..40a660a490 100644
--- a/plugins/CloudFile/src/main.cpp
+++ b/plugins/CloudFile/src/main.cpp
@@ -39,6 +39,16 @@ extern "C" int __declspec(dllexport) Load(void)
HookEvent(ME_PROTO_ACK, OnProtoAck);
HookEvent(ME_SYSTEM_MODULESLOADED, OnModulesLoaded);
+ NETLIBUSER nlu = {};
+ nlu.flags = NUF_INCOMING | NUF_OUTGOING | NUF_HTTPCONNS | NUF_UNICODE;
+ nlu.szSettingsModule = MODULE;
+ nlu.szDescriptiveName.w = _A2W("MODULE");
+ hNetlibConnection = Netlib_RegisterUser(&nlu);
+
+ InitServices();
+ InitializeIcons();
+ InitializeMenus();
+
return 0;
}
diff --git a/plugins/CloudFile/src/menus.cpp b/plugins/CloudFile/src/menus.cpp
index 235ed4e196..13791c13de 100644
--- a/plugins/CloudFile/src/menus.cpp
+++ b/plugins/CloudFile/src/menus.cpp
@@ -15,25 +15,40 @@ void InitializeMenus()
{
CMenuItem mi;
SET_UID(mi, 0x93d4495b, 0x259b, 0x4fba, 0xbc, 0x14, 0xf9, 0x46, 0x2c, 0xda, 0xfc, 0x6d);
- mi.name.a = LPGEN("Upload files to...");
- mi.position = -2000020001;
+ mi.name.a = LPGEN("Upload to ...");
+
+ ptrA defaultService(db_get_sa(NULL, MODULE, "DefaultService"));
+ if (defaultService) {
+ CCloudServiceSearch search(defaultService);
+ CCloudService *service = Services.find(&search);
+ if (service) {
+ mi.name.a = LPGEN("Upload");
+ mi.pszService = MODULE "/Default/Upload";
+ CreateServiceFunctionObj(mi.pszService, UploadMenuCommand, service);
+ }
+ }
+
+ mi.position = -2000019999;
mi.hIcon = LoadIconEx(IDI_UPLOAD);
hContactMenu = Menu_AddContactMenuItem(&mi);
+ if (defaultService)
+ return;
+
UNSET_UID(mi);
- mi.flags |= CMIF_SYSTEM | CMIF_UNICODE;
+
mi.root = hContactMenu;
size_t count = Services.getCount();
+
for (size_t i = 0; i < count; i++) {
CCloudService *service = Services[i];
- if (!db_get_b(NULL, service->GetModule(), "IsEnable", TRUE))
- continue;
-
- CMStringA serviceName(CMStringDataFormat::FORMAT, "%s/%s/Upload", MODULE, service->GetModule());
-
+ CMStringA serviceName = MODULE;
+ serviceName.AppendFormat("/%s/Upload", service->GetModule());
mi.pszService = serviceName.GetBuffer();
+
+ mi.flags = CMIF_SYSTEM | CMIF_UNICODE;
mi.name.w = (wchar_t*)service->GetText();
mi.position = i;
mi.hIcolibItem = GetIconHandle(Services[i]->GetIconId());
@@ -44,19 +59,7 @@ void InitializeMenus()
int OnPrebuildContactMenu(WPARAM hContact, LPARAM)
{
- bool bShow = false;
- char *proto = GetContactProto(hContact);
- if (proto) {
- bool bHasIM = (CallProtoService(proto, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_IMSEND) != 0;
- if (bHasIM) {
- bool isProtoOnline = CallProtoService(proto, PS_GETSTATUS, 0, 0) > ID_STATUS_OFFLINE;
- WORD status = db_get_w(hContact, proto, "Status", ID_STATUS_OFFLINE);
- bool canSendOffline = (CallProtoService(proto, PS_GETCAPS, PFLAGNUM_4, 0) & PF4_IMSENDOFFLINE) > 0;
- if (isProtoOnline && (status != ID_STATUS_OFFLINE || canSendOffline))
- bShow = true;
- }
- }
- Menu_ShowItem(hContactMenu, bShow);
+ Menu_ShowItem(hContactMenu, CanSendToContact(hContact));
return 0;
} \ No newline at end of file
diff --git a/plugins/CloudFile/src/options.cpp b/plugins/CloudFile/src/options.cpp
index e09b659bc1..ca9a860962 100644
--- a/plugins/CloudFile/src/options.cpp
+++ b/plugins/CloudFile/src/options.cpp
@@ -2,11 +2,18 @@
COptionsMain::COptionsMain()
: CPluginDlgBase(hInstance, IDD_OPTIONS_MAIN, MODULE),
+ m_defaultService(this, IDC_DEFAULTSERVICE),
+ m_renameOnConflict(this, IDC_RENAMEONCONFLICT),
+ m_repalceOnConflict(this, IDC_REPLACEONCONFLICT),
m_urlAutoSend(this, IDC_URL_AUTOSEND),
m_urlPasteToMessageInputArea(this, IDC_URL_COPYTOMIA),
- m_urlCopyToClipboard(this, IDC_URL_COPYTOCB),
- m_services(this, IDC_SERVICES), isServiceListInit(false)
+ m_urlCopyToClipboard(this, IDC_URL_COPYTOCB)
{
+ /*CreateLink(m_defaultService, "DefaultService", L"");
+
+ CreateLink(m_renameOnConflict, "RenameOnConflict", DBVT_BYTE, 1);
+ CreateLink(m_repalceOnConflict, "RepalceOnConflict", DBVT_BYTE, 0);*/
+
CreateLink(m_urlAutoSend, "UrlAutoSend", DBVT_BYTE, 1);
CreateLink(m_urlPasteToMessageInputArea, "UrlPasteToMessageInputArea", DBVT_BYTE, 0);
CreateLink(m_urlCopyToClipboard, "UrlCopyToClipboard", DBVT_BYTE, 0);
@@ -16,58 +23,41 @@ void COptionsMain::OnInitDialog()
{
CDlgBase::OnInitDialog();
- m_services.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES | LVS_EX_INFOTIP);
-
- m_services.AddColumn(0, TranslateT("Account name"), 50);
+ ptrA defaultService(db_get_sa(NULL, MODULE, "DefaultService"));
+ int iItem = m_defaultService.AddString(TranslateT("No"));
+ m_defaultService.SetCurSel(iItem);
size_t count = Services.getCount();
for (size_t i = 0; i < count; i++) {
CCloudService *service = Services[i];
- int iItem = m_services.AddItem(mir_wstrdup(service->GetText()), -1, (LPARAM)service);
- //m_services.SetItem(iItem, 1, mir_a2u(service->GetModule));
- int isEnable = db_get_b(NULL, service->GetModule(), "IsEnable", TRUE);
- m_services.SetCheckState(iItem, isEnable);
+ iItem = m_defaultService.AddString(mir_wstrdup(service->GetText()), (LPARAM)service);
+ if (!mir_strcmpi(service->GetModule(), defaultService))
+ m_defaultService.SetCurSel(iItem);
}
- m_services.SetColumnWidth(0, LVSCW_AUTOSIZE_USEHEADER);
-
- isServiceListInit = true;
+ BYTE strategy = db_get_b(NULL, MODULE, "ConflictStrategy", OnConflict::NONE);
+ if (strategy == OnConflict::RENAME)
+ m_renameOnConflict.SetState(TRUE);
+ else if (strategy == OnConflict::REPLACE)
+ m_repalceOnConflict.SetState(TRUE);
}
void COptionsMain::OnApply()
{
- int count = m_services.GetItemCount();
- for (int iItem = 0; iItem < count; iItem++)
- {
- CCloudService *service = (CCloudService*)m_services.GetItemData(iItem);
-
- int isEnable = m_services.GetCheckState(iItem);
- db_set_b(NULL, service->GetModule(), "IsEnable", isEnable);
- }
-}
-
-INT_PTR COptionsMain::DlgProc(UINT msg, WPARAM wParam, LPARAM lParam)
-{
- switch (msg)
- {
- case WM_NOTIFY:
- {
- LPNMHDR lpnmHdr = (LPNMHDR)lParam;
- if (lpnmHdr->idFrom == (UINT_PTR)m_services.GetCtrlId() && lpnmHdr->code == LVN_ITEMCHANGED)
- {
- LPNMLISTVIEW pnmv = (LPNMLISTVIEW)lParam;
- if (pnmv->uChanged & LVIF_STATE && pnmv->uNewState & LVIS_STATEIMAGEMASK)
- {
- if (isServiceListInit)
- NotifyChange();
- }
- }
- }
- break;
- }
-
- return CDlgBase::DlgProc(msg, wParam, lParam);
+ int iItem = m_defaultService.GetCurSel();
+ CCloudService *service = (CCloudService*)m_defaultService.GetItemData(iItem);
+ if (service)
+ db_set_s(NULL, MODULE, "DefaultService", service->GetModule());
+ else
+ db_unset(NULL, MODULE, "DefaultService");
+
+ if (m_renameOnConflict.GetState())
+ db_set_b(NULL, MODULE, "ConflictStrategy", OnConflict::RENAME);
+ else if (m_repalceOnConflict.GetState())
+ db_set_b(NULL, MODULE, "ConflictStrategy", OnConflict::REPLACE);
+ else
+ db_unset(NULL, MODULE, "ConflictStrategy");
}
/////////////////////////////////////////////////////////////////////////////////
diff --git a/plugins/CloudFile/src/options.h b/plugins/CloudFile/src/options.h
index d6f5e7caaf..a0fd102c7d 100644
--- a/plugins/CloudFile/src/options.h
+++ b/plugins/CloudFile/src/options.h
@@ -4,19 +4,19 @@
class COptionsMain : public CPluginDlgBase
{
private:
+ CCtrlCombo m_defaultService;
+
+ CCtrlCheck m_renameOnConflict;
+ CCtrlCheck m_repalceOnConflict;
+
CCtrlCheck m_urlAutoSend;
CCtrlCheck m_urlPasteToMessageInputArea;
CCtrlCheck m_urlCopyToClipboard;
- bool isServiceListInit;
- CCtrlListView m_services;
-
protected:
void OnInitDialog();
void OnApply();
- INT_PTR DlgProc(UINT msg, WPARAM wParam, LPARAM lParam);
-
public:
COptionsMain();
};
diff --git a/plugins/CloudFile/src/resource.h b/plugins/CloudFile/src/resource.h
index 4360fd84b5..90d32f5162 100644
--- a/plugins/CloudFile/src/resource.h
+++ b/plugins/CloudFile/src/resource.h
@@ -13,12 +13,14 @@
#define IDC_OAUTH_CODE 121
#define IDC_OAUTH_AUTHORIZE 122
#define IDD_OPTIONS_MAIN 1000
-#define IDC_URL_ISTEMPORARY 1001
-#define IDC_URL_COPYTOCB 1002
-#define IDC_URL_COPYTOMIA 1003
-#define IDC_URL_AUTOSEND 1004
-#define IDC_ACCOUNTS 1011
-#define IDC_SERVICES 1011
+#define IDC_DEFAULTSERVICE 1001
+#define IDC_DONOTHING 1010
+#define IDC_RENAMEONCONFLICT 1011
+#define IDC_REPLACEONCONFLICT 1012
+#define IDC_URL_ISTEMPORARY 1021
+#define IDC_URL_COPYTOCB 1022
+#define IDC_URL_COPYTOMIA 1023
+#define IDC_URL_AUTOSEND 1024
// Next default values for new objects
//
@@ -26,7 +28,7 @@
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 130
#define _APS_NEXT_COMMAND_VALUE 40001
-#define _APS_NEXT_CONTROL_VALUE 1013
+#define _APS_NEXT_CONTROL_VALUE 1030
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
diff --git a/plugins/CloudFile/src/srmm.cpp b/plugins/CloudFile/src/srmm.cpp
index 8781479c1b..58d8ef9708 100644
--- a/plugins/CloudFile/src/srmm.cpp
+++ b/plugins/CloudFile/src/srmm.cpp
@@ -4,9 +4,9 @@ int OnSrmmToolbarLoaded(WPARAM, LPARAM)
{
BBButton bbd = {};
bbd.pszModuleName = MODULE;
- bbd.bbbFlags = BBBF_ISIMBUTTON | BBBF_ISCHATBUTTON | BBBF_ISRSIDEBUTTON;
+ bbd.bbbFlags = BBBF_ISIMBUTTON | BBBF_ISCHATBUTTON | BBBF_ISRSIDEBUTTON | BBBF_ISARROWBUTTON;
- CMStringW tooltip(CMStringDataFormat::FORMAT, TranslateT("Upload files to..."));
+ CMStringW tooltip(FORMAT, TranslateT("Upload files to..."));
bbd.pwszTooltip = tooltip;
bbd.hIcon = GetIconHandle(IDI_UPLOAD);
bbd.dwButtonID = BBB_ID_FILE_SEND;
@@ -20,18 +20,12 @@ int OnSrmmWindowOpened(WPARAM, LPARAM lParam)
{
MessageWindowEventData *ev = (MessageWindowEventData*)lParam;
if (ev->uType == MSG_WINDOW_EVT_OPENING && ev->hContact) {
- char *proto = GetContactProto(ev->hContact);
- bool isProtoOnline = CallProtoService(proto, PS_GETSTATUS, 0, 0) > ID_STATUS_OFFLINE;
- WORD status = db_get_w(ev->hContact, proto, "Status", ID_STATUS_OFFLINE);
- bool canSendOffline = (CallProtoService(proto, PS_GETCAPS, PFLAGNUM_4, 0) & PF4_IMSENDOFFLINE) > 0;
-
BBButton bbd = {};
bbd.pszModuleName = MODULE;
bbd.dwButtonID = BBB_ID_FILE_SEND;
- bbd.bbbFlags = BBSF_RELEASED;
- if (!isProtoOnline || (status == ID_STATUS_OFFLINE && !canSendOffline))
- bbd.bbbFlags = BBSF_DISABLED;
-
+ bbd.bbbFlags = CanSendToContact(ev->hContact)
+ ? BBSF_RELEASED
+ : BBSF_DISABLED;
Srmm_SetButtonState(ev->hContact, &bbd);
}
@@ -48,23 +42,31 @@ int OnSrmmButtonPressed(WPARAM, LPARAM lParam)
if (cbc->dwButtonId != BBB_ID_FILE_SEND)
return 0;
+ if (cbc->flags != BBCF_ARROWCLICKED) {
+ ptrA defaultService(db_get_sa(NULL, MODULE, "DefaultService"));
+ if (defaultService) {
+ CCloudServiceSearch search(defaultService);
+ CCloudService *service = Services.find(&search);
+ if (service)
+ service->OpenUploadDialog(cbc->hContact);
+ return 0;
+ }
+ }
+
HMENU hMenu = CreatePopupMenu();
size_t count = Services.getCount();
for (size_t i = 0; i < count; i++) {
CCloudService *service = Services[i];
- if (!db_get_b(NULL, service->GetModule(), "IsEnable", TRUE))
- continue;
-
- InsertMenu(hMenu, i, MF_STRING, i + 1, TranslateW(service->GetText()));
+ InsertMenu(hMenu, i, MF_STRING | MF_BYPOSITION, i + 1,TranslateW(service->GetText()));
//HBITMAP hBitmap = (HBITMAP)LoadImage(hInstance, MAKEINTRESOURCE(service->GetIconId()), IMAGE_ICON, 16, 16, 0);
//SetMenuItemBitmaps(hMenu, i, MF_BITMAP, hBitmap, hBitmap);
}
- int ind = TrackPopupMenu(hMenu, TPM_RETURNCMD, cbc->pt.x, cbc->pt.y, 0, cbc->hwndFrom, NULL);
- if (ind > 0) {
- CCloudService *service = Services[ind - 1];
+ int pos = TrackPopupMenu(hMenu, TPM_RETURNCMD, cbc->pt.x, cbc->pt.y, 0, cbc->hwndFrom, NULL);
+ if (pos > 0) {
+ CCloudService *service = Services[pos - 1];
service->OpenUploadDialog(cbc->hContact);
}
diff --git a/plugins/CloudFile/src/stdafx.h b/plugins/CloudFile/src/stdafx.h
index e74711a96a..a002e334c2 100644
--- a/plugins/CloudFile/src/stdafx.h
+++ b/plugins/CloudFile/src/stdafx.h
@@ -108,5 +108,9 @@ UINT UploadAndReportProgressThread(void *owner, void *arg);
void ShowNotification(const wchar_t *caption, const wchar_t *message, int flags, MCONTACT hContact = NULL);
void ShowNotification(const wchar_t *message, int flags, MCONTACT hContact = NULL);
MEVENT AddEventToDb(MCONTACT hContact, WORD type, DWORD flags, DWORD cbBlob, PBYTE pBlob);
+bool CanSendToContact(MCONTACT hContact);
+void SendToContact(MCONTACT hContact, const wchar_t *data);
+void PasteToInputArea(MCONTACT hContact, const wchar_t *data);
+void PasteToClipboard(const wchar_t *data);
#endif //_COMMON_H_ \ No newline at end of file
diff --git a/plugins/CloudFile/src/utils.cpp b/plugins/CloudFile/src/utils.cpp
index cabcd7de97..e4846baf31 100644
--- a/plugins/CloudFile/src/utils.cpp
+++ b/plugins/CloudFile/src/utils.cpp
@@ -38,3 +38,65 @@ MEVENT AddEventToDb(MCONTACT hContact, WORD type, DWORD flags, DWORD cbBlob, PBY
dbei.flags = flags;
return db_event_add(hContact, &dbei);
}
+
+bool CanSendToContact(MCONTACT hContact)
+{
+ if (!hContact)
+ return false;
+
+ const char *proto = GetContactProto(hContact);
+ if (!proto)
+ return false;
+
+ bool canSend = (CallProtoService(proto, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_IMSEND) != 0;
+ if (!canSend)
+ return false;
+
+ bool isProtoOnline = CallProtoService(proto, PS_GETSTATUS, 0, 0) > ID_STATUS_OFFLINE;
+ if (isProtoOnline)
+ return true;
+
+ bool isContactOnline = db_get_w(hContact, proto, "Status", ID_STATUS_OFFLINE) > ID_STATUS_OFFLINE;
+ if (isContactOnline)
+ return true;
+
+ return CallProtoService(proto, PS_GETCAPS, PFLAGNUM_4, 0) & PF4_IMSENDOFFLINE;
+}
+
+void SendToContact(MCONTACT hContact, const wchar_t *data)
+{
+ const char *szProto = GetContactProto(hContact);
+ if (db_get_b(hContact, szProto, "ChatRoom", 0) == TRUE) {
+ ptrW tszChatRoom(db_get_wsa(hContact, szProto, "ChatRoomID"));
+ Chat_SendUserMessage(szProto, tszChatRoom, data);
+ return;
+ }
+
+ char *message = mir_utf8encodeW(data);
+ if (ProtoChainSend(hContact, PSS_MESSAGE, 0, (LPARAM)message) != ACKRESULT_FAILED)
+ AddEventToDb(hContact, EVENTTYPE_MESSAGE, DBEF_UTF | DBEF_SENT, (DWORD)mir_strlen(message), (PBYTE)message);
+}
+
+void PasteToInputArea(MCONTACT hContact, const wchar_t *data)
+{
+ CallService(MS_MSG_SENDMESSAGEW, hContact, (LPARAM)data);
+}
+
+void PasteToClipboard(const wchar_t *data)
+{
+ if (OpenClipboard(NULL)) {
+ EmptyClipboard();
+
+ size_t size = sizeof(wchar_t) * (mir_wstrlen(data) + 1);
+ HGLOBAL hClipboardData = GlobalAlloc(NULL, size);
+ if (hClipboardData) {
+ wchar_t *pchData = (wchar_t*)GlobalLock(hClipboardData);
+ if (pchData) {
+ memcpy(pchData, (wchar_t*)data, size);
+ GlobalUnlock(hClipboardData);
+ SetClipboardData(CF_UNICODETEXT, hClipboardData);
+ }
+ }
+ CloseClipboard();
+ }
+}
diff --git a/plugins/CloudFile/src/version.h b/plugins/CloudFile/src/version.h
index 1f08a3d35b..9c733ab819 100644
--- a/plugins/CloudFile/src/version.h
+++ b/plugins/CloudFile/src/version.h
@@ -1,7 +1,7 @@
#define __MAJOR_VERSION 0
#define __MINOR_VERSION 11
#define __RELEASE_NUM 0
-#define __BUILD_NUM 1
+#define __BUILD_NUM 2
#include <stdver.h>