summaryrefslogtreecommitdiff
path: root/plugins/Dropbox
diff options
context:
space:
mode:
authorAlexander Lantsev <aunsane@gmail.com>2014-02-19 19:07:45 +0000
committerAlexander Lantsev <aunsane@gmail.com>2014-02-19 19:07:45 +0000
commitfc46c19a61d26fb610d173bb8fc5420eea966caa (patch)
tree0d388af6d8a53eb4ef56dcdb96fe44d56bccb63d /plugins/Dropbox
parent3ced66e7eac9a8a0867073553db2b2bd74729b09 (diff)
Dropbox:
- global object replaced by singleton - added ability to upload folders git-svn-id: http://svn.miranda-ng.org/main/trunk@8183 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/Dropbox')
-rw-r--r--plugins/Dropbox/Dropbox_11.vcxproj1
-rw-r--r--plugins/Dropbox/Dropbox_11.vcxproj.filters3
-rw-r--r--plugins/Dropbox/src/common.h5
-rw-r--r--plugins/Dropbox/src/dropbox.cpp25
-rw-r--r--plugins/Dropbox/src/dropbox.h53
-rw-r--r--plugins/Dropbox/src/dropbox_events.cpp2
-rw-r--r--plugins/Dropbox/src/dropbox_services.cpp58
-rw-r--r--plugins/Dropbox/src/dropbox_transfers.cpp122
-rw-r--r--plugins/Dropbox/src/http_request.h25
-rw-r--r--plugins/Dropbox/src/main.cpp8
-rw-r--r--plugins/Dropbox/src/singleton.h29
11 files changed, 210 insertions, 121 deletions
diff --git a/plugins/Dropbox/Dropbox_11.vcxproj b/plugins/Dropbox/Dropbox_11.vcxproj
index 8f52177702..86a93e74c5 100644
--- a/plugins/Dropbox/Dropbox_11.vcxproj
+++ b/plugins/Dropbox/Dropbox_11.vcxproj
@@ -190,6 +190,7 @@
<ClInclude Include="src\dropbox.h" />
<ClInclude Include="src\http_request.h" />
<ClInclude Include="src\resource.h" />
+ <ClInclude Include="src\singleton.h" />
<ClInclude Include="src\version.h" />
</ItemGroup>
<ItemGroup>
diff --git a/plugins/Dropbox/Dropbox_11.vcxproj.filters b/plugins/Dropbox/Dropbox_11.vcxproj.filters
index d5d53e93d6..1393a38512 100644
--- a/plugins/Dropbox/Dropbox_11.vcxproj.filters
+++ b/plugins/Dropbox/Dropbox_11.vcxproj.filters
@@ -45,6 +45,9 @@
<ClInclude Include="src\dropbox.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="src\singleton.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="Header Files">
diff --git a/plugins/Dropbox/src/common.h b/plugins/Dropbox/src/common.h
index d3b14a3e15..89afef0c2c 100644
--- a/plugins/Dropbox/src/common.h
+++ b/plugins/Dropbox/src/common.h
@@ -29,11 +29,6 @@
#define MODULE "Dropbox"
-class CDropbox;
-
extern HINSTANCE g_hInstance;
-extern CDropbox *g_dropbox;
-
-HANDLE CreateProtoServiceFunctionObj(const char *szModule, const char *szService, MIRANDASERVICEOBJ serviceProc, void* obj);
#endif //_COMMON_H_ \ No newline at end of file
diff --git a/plugins/Dropbox/src/dropbox.cpp b/plugins/Dropbox/src/dropbox.cpp
index fa2d5cbc86..ed705d6dea 100644
--- a/plugins/Dropbox/src/dropbox.cpp
+++ b/plugins/Dropbox/src/dropbox.cpp
@@ -1,6 +1,6 @@
#include "dropbox.h"
-CDropbox::CDropbox()
+void CDropbox::Init()
{
PROTOCOLDESCRIPTOR pd = { PROTOCOLDESCRIPTOR_V3_SIZE };
pd.szName = MODULE;
@@ -28,7 +28,7 @@ bool CDropbox::HasAccessToken()
return db_get_sa(NULL, MODULE, "TokenSecret") != NULL;
}
-void CDropbox::RequestAcceessToken()
+void CDropbox::RequestAcceessToken(MCONTACT hContact)
{
ShellExecuteA(NULL, "open", DROPBOX_WWW_URL DROPBOX_API_VER "/oauth2/authorize?response_type=code&client_id=" DROPBOX_API_KEY, NULL, NULL, SW_SHOWDEFAULT);
@@ -71,7 +71,6 @@ void CDropbox::RequestAcceessToken()
ptrA access_token = ptrA(mir_u2a(json_as_string(node)));
db_set_s(NULL, MODULE, "TokenSecret", access_token);
- MCONTACT hContact = GetDefaultContact();
if (hContact)
{
node = json_get(root, "uid");
@@ -107,20 +106,34 @@ void CDropbox::RequestAcceessToken()
}
}
-void CDropbox::DestroyAcceessToken()
+void CDropbox::DestroyAcceessToken(MCONTACT hContact)
{
HttpRequest *request = new HttpRequest(hNetlibUser, REQUEST_POST, DROPBOX_API_URL "/disable_access_token");
- //request->SendAsync(&CDropboxProto::AsyncFunc);
NETLIBHTTPREQUEST *response = request->Send();
delete request;
mir_free(response);
db_unset(NULL, MODULE, "TokenSecret");
- MCONTACT hContact = GetDefaultContact();
if (hContact)
{
if (db_get_w(hContact, MODULE, "Status", ID_STATUS_ONLINE) == ID_STATUS_ONLINE)
db_set_w(hContact, MODULE, "Status", ID_STATUS_OFFLINE);
}
+}
+
+void CDropbox::RequeriedAccessAsync(void *arg)
+{
+ MCONTACT hContact = (MCONTACT)arg;
+
+ if (hContact && MessageBox(
+ NULL,
+ TranslateT("Are you sure you want to requeried access?"),
+ TranslateT("Requeried access"),
+ MB_YESNO | MB_ICONQUESTION) == IDYES)
+ {
+ if (HasAccessToken())
+ Singleton<CDropbox>::GetInstance()->DestroyAcceessToken(hContact);
+ Singleton<CDropbox>::GetInstance()->RequestAcceessToken(hContact);
+ }
} \ No newline at end of file
diff --git a/plugins/Dropbox/src/dropbox.h b/plugins/Dropbox/src/dropbox.h
index ba400d90d0..0789f508c7 100644
--- a/plugins/Dropbox/src/dropbox.h
+++ b/plugins/Dropbox/src/dropbox.h
@@ -1,7 +1,7 @@
-#ifndef _Dropbox_PROTO_H_
-#define _Dropbox_PROTO_H_
+#ifndef _DROPBOX_PROTO_H_
+#define _DROPBOX_PROTO_H_
-//#include "common.h"
+#include "singleton.h"
#include "http_request.h"
#define DROPBOX_API_VER "1"
@@ -18,7 +18,6 @@
enum
{
CMI_API_ACCESS_REQUERIED,
- CMI_URL_OPEN_ROOT,
CMI_MAX // this item shall be the last one
};
@@ -27,36 +26,56 @@ struct FileTransferParam
HANDLE hProcess;
PROTOFILETRANSFERSTATUS pfts;
- FileTransferParam()
+ int totalFolders;
+ char **pszFolders;
+ int relativePathStart;
+
+ FileTransferParam()
{
+ totalFolders = 0;
+ pszFolders = NULL;
+ relativePathStart = 0;
+
pfts.cbSize = sizeof(this->pfts);
pfts.flags = PFTS_UTF;
pfts.currentFileNumber = 0;
pfts.currentFileProgress = 0;
pfts.currentFileSize = 0;
- pfts.currentFileTime = 0;
pfts.totalBytes = 0;
pfts.totalFiles = 0;
pfts.totalProgress = 0;
+ pfts.pszFiles = NULL;
pfts.tszWorkingDir = NULL;
pfts.wszCurrentFile = NULL;
}
- ~FileTransferParam()
+ ~FileTransferParam()
{
- for (int i = 0; pfts.pszFiles[pfts.totalFiles]; i++)
+ /*if (pfts.pszFiles)
{
- delete pfts.pszFiles[i];
+ for (int i = 0; pfts.pszFiles[i]; i++)
+ {
+ if (pfts.pszFiles[i]) delete pfts.pszFiles[i];
+ }
+ delete pfts.pszFiles;
}
- delete pfts.pszFiles;
+
+ if (pszFolders)
+ {
+ for (int i = 0; pszFolders[i]; i++)
+ {
+ if (pszFolders[i]) delete pszFolders[i];
+ }
+ delete pszFolders;
+ }*/
}
};
class CDropbox
{
public:
- CDropbox();
- ~CDropbox() { }
+ void Init();
+ void Uninit() { };
private:
HANDLE hNetlibUser;
@@ -78,8 +97,10 @@ private:
// access token
static bool HasAccessToken();
- void RequestAcceessToken();
- void DestroyAcceessToken();
+ void RequestAcceessToken(MCONTACT hContact);
+ void DestroyAcceessToken(MCONTACT hContact);
+
+ static void RequeriedAccessAsync(void *arg);
// transrers
HttpRequest *CreateFileSendChunkedRequest(const char *data, int length);
@@ -87,6 +108,8 @@ private:
void SendFileChunkedNext(const char *data, int length, const char *uploadId, int &offset);
void SendFileChunkedLast(const char *fileName, const char *uploadId, MCONTACT hContact);
+ void CreateFolder(const char *folderName);
+
static void _cdecl SendFileAsync(void *arg);
// contacts
@@ -107,4 +130,4 @@ private:
void ShowNotification(const wchar_t *message, int flags = 0, MCONTACT hContact = NULL);
};
-#endif //_Dropbox_PROTO_H_ \ No newline at end of file
+#endif //_DROPBOX_PROTO_H_ \ No newline at end of file
diff --git a/plugins/Dropbox/src/dropbox_events.cpp b/plugins/Dropbox/src/dropbox_events.cpp
index 83ee861712..62684d66d5 100644
--- a/plugins/Dropbox/src/dropbox_events.cpp
+++ b/plugins/Dropbox/src/dropbox_events.cpp
@@ -8,7 +8,7 @@ int CDropbox::OnModulesLoaded(WPARAM wParam, LPARAM lParam)
nlu.szSettingsModule = MODULE;
nlu.ptszDescriptiveName = L"Dropbox";
- g_dropbox->hNetlibUser = (HANDLE)CallService(MS_NETLIB_REGISTERUSER, 0, (LPARAM)&nlu);
+ Singleton<CDropbox>::GetInstance()->hNetlibUser = (HANDLE)CallService(MS_NETLIB_REGISTERUSER, 0, (LPARAM)&nlu);
MCONTACT hContact = GetDefaultContact();
if (!hContact)
diff --git a/plugins/Dropbox/src/dropbox_services.cpp b/plugins/Dropbox/src/dropbox_services.cpp
index b61f9c54ad..0389021920 100644
--- a/plugins/Dropbox/src/dropbox_services.cpp
+++ b/plugins/Dropbox/src/dropbox_services.cpp
@@ -32,31 +32,53 @@ INT_PTR CDropbox::SendFile(WPARAM wParam, LPARAM lParam)
for (int i = 0; files[i]; i++)
{
if (PathIsDirectoryA(files[i]))
- continue;
- ftp->pfts.totalFiles++;
+ ftp->totalFolders++;
+ else
+ ftp->pfts.totalFiles++;
}
+ ftp->pszFolders = new char*[ftp->totalFolders + 1];
+ ftp->pszFolders[ftp->totalFolders] = NULL;
+
ftp->pfts.pszFiles = new char*[ftp->pfts.totalFiles + 1];
ftp->pfts.pszFiles[ftp->pfts.totalFiles] = NULL;
- for (int i = 0, j = 0; files[i]; i++)
+
+ for (int i = 0, j = 0, k = 0; files[i]; i++)
{
if (PathIsDirectoryA(files[i]))
- continue;
+ {
+ if (!ftp->relativePathStart)
+ {
+ char *rootFolder = files[j];
+ char *relativePath = strrchr(rootFolder, '\\') + 1;
+ ftp->relativePathStart = relativePath - rootFolder;
+ }
- ftp->pfts.pszFiles[j] = mir_strdup(files[i]);
+ ftp->pszFolders[j] = mir_strdup(&files[i][ftp->relativePathStart]);
- FILE *file = fopen(files[j], "rb");
- if (file != NULL)
- {
- fseek(file, 0, SEEK_END);
- ftp->pfts.totalBytes += ftell(file);
- fseek(file, 0, SEEK_SET);
- fclose(file);
+ j++;
}
+ else
+ {
+ //if (!relativePathStart)
+ ftp->pfts.pszFiles[k] = mir_strdup(files[i]);
+ /*else
+ {
+ ftp->pfts.pszFiles[k] = mir_strdup(&files[i][relativePathStart]);
+ }*/
- j++;
+ FILE *file = fopen(files[i], "rb");
+ if (file != NULL)
+ {
+ fseek(file, 0, SEEK_END);
+ ftp->pfts.totalBytes += ftell(file);
+ fseek(file, 0, SEEK_SET);
+ fclose(file);
+ }
+ k++;
+ }
}
- ULONG fileId = InterlockedIncrement(&g_dropbox->hFileProcess);
+ ULONG fileId = InterlockedIncrement(&Singleton<CDropbox>::GetInstance()->hFileProcess);
ftp->hProcess = (HANDLE)fileId;
mir_forkthread(CDropbox::SendFileAsync, ftp);
@@ -71,13 +93,7 @@ INT_PTR CDropbox::SendMessage( WPARAM wParam, LPARAM lParam)
INT_PTR CDropbox::RequeriedApiAccess(WPARAM wParam, LPARAM lParam)
{
- int result = MessageBox(NULL, TranslateT("Are you sure you want to requeried access?"), TranslateT("Requeried access"), MB_YESNO | MB_ICONQUESTION);
- if (result == IDYES)
- {
- if (HasAccessToken())
- g_dropbox->DestroyAcceessToken();
- g_dropbox->RequestAcceessToken();
- }
+ mir_forkthread(CDropbox::RequeriedAccessAsync, (void*)wParam);
return 0;
} \ No newline at end of file
diff --git a/plugins/Dropbox/src/dropbox_transfers.cpp b/plugins/Dropbox/src/dropbox_transfers.cpp
index 550e6b7e64..6a0d885894 100644
--- a/plugins/Dropbox/src/dropbox_transfers.cpp
+++ b/plugins/Dropbox/src/dropbox_transfers.cpp
@@ -76,14 +76,23 @@ void CDropbox::SendFileChunkedNext(const char *data, int length, const char *upl
void CDropbox::SendFileChunkedLast(const char *fileName, const char *uploadId, MCONTACT hContact)
{
- char url[MAX_PATH];
+ /*char url[MAX_PATH];
mir_snprintf(
url,
SIZEOF(url),
"%s/commit_chunked_upload/%s/%s",
DROPBOX_APICONTENT_URL,
DROPBOX_API_ROOT,
+ fileName);*/
+
+ CMStringA url;
+ url.AppendFormat(
+ "%s/commit_chunked_upload/%s/%s",
+ DROPBOX_APICONTENT_URL,
+ DROPBOX_API_ROOT,
fileName);
+ url.Replace('\\', '/');
+
HttpRequest *request = new HttpRequest(hNetlibUser, REQUEST_POST, url);
request->AddParameter("upload_id", uploadId);
@@ -93,55 +102,76 @@ void CDropbox::SendFileChunkedLast(const char *fileName, const char *uploadId, M
delete request;
- if (response && response->resultCode == HttpStatus::OK)
+ if (response)
{
- mir_snprintf(
- url,
- SIZEOF(url),
- "%s/shares/%s/%s",
- DROPBOX_API_URL,
- DROPBOX_API_ROOT,
- fileName);
+ if (response->resultCode == HttpStatus::OK)
+ {
+ url.Replace(DROPBOX_APICONTENT_URL, DROPBOX_API_URL);
+ url.Replace("commit_chunked_upload", "shares");
- request = new HttpRequest(hNetlibUser, REQUEST_POST, url);
- request->AddParameter("access_token", db_get_sa(NULL, MODULE, "TokenSecret"));
+ request = new HttpRequest(hNetlibUser, REQUEST_POST, url);
+ request->AddParameter("access_token", db_get_sa(NULL, MODULE, "TokenSecret"));
- mir_free(response);
+ mir_free(response);
- response = request->Send();
+ response = request->Send();
- if (response)
- {
- if (response->resultCode == HttpStatus::OK)
+ if (response)
{
- JSONNODE *root = json_parse(response->pData);
- if (root != NULL)
+ if (response->resultCode == HttpStatus::OK)
{
- JSONNODE *node = json_get(root, "url");
- char message[1024];
- mir_snprintf(
- message,
- SIZEOF(message),
- Translate("Link to download file \"%s\": %s"),
- fileName,
- mir_utf8encodeW(json_as_string(node)));
-
- DBEVENTINFO dbei = { sizeof(dbei) };
- dbei.szModule = MODULE;
- dbei.timestamp = time(NULL);
- dbei.eventType = EVENTTYPE_MESSAGE;
- dbei.cbBlob = strlen(message);
- dbei.pBlob = (PBYTE)mir_strdup(message);
- dbei.flags = DBEF_UTF;
- ::db_event_add(hContact, &dbei);
-
- delete node;
- delete root;
+ JSONNODE *root = json_parse(response->pData);
+ if (root != NULL)
+ {
+ JSONNODE *node = json_get(root, "url");
+ char message[1024];
+ mir_snprintf(
+ message,
+ SIZEOF(message),
+ Translate("Link to download file \"%s\": %s"),
+ fileName,
+ mir_utf8encodeW(json_as_string(node)));
+
+ DBEVENTINFO dbei = { sizeof(dbei) };
+ dbei.szModule = MODULE;
+ dbei.timestamp = time(NULL);
+ dbei.eventType = EVENTTYPE_MESSAGE;
+ dbei.cbBlob = strlen(message);
+ dbei.pBlob = (PBYTE)mir_strdup(message);
+ dbei.flags = DBEF_UTF;
+ ::db_event_add(hContact, &dbei);
+
+ delete node;
+ delete root;
+ }
}
- }
- mir_free(response);
+ mir_free(response);
+ }
}
+ else
+ mir_free(response);
+ }
+}
+
+void CDropbox::CreateFolder(const char *folderName)
+{
+ HttpRequest *request = new HttpRequest(hNetlibUser, REQUEST_POST, DROPBOX_API_URL "/fileops/create_folder");
+ request->AddParameter("root", DROPBOX_API_ROOT);
+ request->AddParameter("path", folderName);
+ request->AddParameter("access_token", db_get_sa(NULL, MODULE, "TokenSecret"));
+
+ NETLIBHTTPREQUEST *response = request->Send();
+
+ delete request;
+
+ if (response)
+ {
+ /*if (response->resultCode == HttpStatus::OK)
+ {
+ }*/
+
+ mir_free(response);
}
}
@@ -151,6 +181,9 @@ void _cdecl CDropbox::SendFileAsync(void *arg)
ProtoBroadcastAck(MODULE, ftp->pfts.hContact, ACKTYPE_FILE, ACKRESULT_INITIALISING, ftp->hProcess, 0);
+ for (int i = 0; ftp->pszFolders[i]; i++)
+ Singleton<CDropbox>::GetInstance()->CreateFolder(ftp->pszFolders[i]);
+
for (int i = 0; ftp->pfts.pszFiles[i]; i++)
{
FILE *file = fopen(ftp->pfts.pszFiles[i], "rb");
@@ -159,7 +192,8 @@ void _cdecl CDropbox::SendFileAsync(void *arg)
int offset = 0;
char *uploadId = new char[32];
- const char *fileName = strrchr(ftp->pfts.pszFiles[i], '\\') + 1;
+ //const char *fileName = strrchr(ftp->pfts.pszFiles[i], '\\') + 1;
+ const char *fileName = &ftp->pfts.pszFiles[i][ftp->relativePathStart];
fseek(file, 0, SEEK_END);
DWORD fileSize = ftell(file);
@@ -184,9 +218,9 @@ void _cdecl CDropbox::SendFileAsync(void *arg)
size_t count = fread(data, sizeof(char), chunkSize, file);
if (!offset)
- g_dropbox->SendFileChunkedFirst(data, count, uploadId, offset);
+ Singleton<CDropbox>::GetInstance()->SendFileChunkedFirst(data, count, uploadId, offset);
else
- g_dropbox->SendFileChunkedNext(data, count, uploadId, offset);
+ Singleton<CDropbox>::GetInstance()->SendFileChunkedNext(data, count, uploadId, offset);
ftp->pfts.currentFileProgress += count;
ftp->pfts.totalProgress += count;
@@ -196,7 +230,7 @@ void _cdecl CDropbox::SendFileAsync(void *arg)
fclose(file);
- g_dropbox->SendFileChunkedLast(fileName, uploadId, ftp->pfts.hContact);
+ Singleton<CDropbox>::GetInstance()->SendFileChunkedLast(fileName, uploadId, ftp->pfts.hContact);
ftp->pfts.currentFileProgress = ftp->pfts.currentFileSize;
if (i < ftp->pfts.totalFiles - 1)
diff --git a/plugins/Dropbox/src/http_request.h b/plugins/Dropbox/src/http_request.h
index b17ef16b58..43b1b311ec 100644
--- a/plugins/Dropbox/src/http_request.h
+++ b/plugins/Dropbox/src/http_request.h
@@ -43,7 +43,7 @@ public:
void AddParameter(LPCSTR szName, LPCSTR szValue)
{
- if(m_szUrl.Find('?') == -1)
+ if (m_szUrl.Find('?') == -1)
m_szUrl.AppendFormat("?%s=%s", szName, szValue);
else
m_szUrl.AppendFormat("&%s=%s", szName, szValue);
@@ -51,7 +51,7 @@ public:
void AddParameter(LPCSTR szName, int value)
{
- if(m_szUrl.Find('?') == -1)
+ if (m_szUrl.Find('?') == -1)
m_szUrl.AppendFormat("?%s=%i", szName, value);
else
m_szUrl.AppendFormat("&%s=%i", szName, value);
@@ -63,30 +63,9 @@ public:
return (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)m_hNetlibUser, (LPARAM)this);
}
- //void SendAsync(typename CBaseProto<T>::AsyncHttpRequest callback)
- //{
- // szUrl = m_szUrl.GetBuffer();
- // AsyncParam param = { this, proto, callback };
- // /*HANDLE hThread = */mir_forkthread(SendAsync, &param);
- // //WaitForSingleObject(hThread, INFINITE);
- //}
-
private:
-
CMStringA m_szUrl;
HANDLE m_hNetlibUser;
-
- /*static void SendAsync(void *arg)
- {
- AsyncParam *param = (AsyncParam*)arg;
- NETLIBHTTPREQUEST* response = (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)param->m_proto->m_hNetlibUser, (LPARAM)param->m_request);
-
- CBaseProto<T> *proto = param->m_proto;
- AsyncRequestCallback callback = param->m_callback;
- proto->*callback(response);
-
- delete response;
- }*/
};
#endif //_HTTP_REQUEST_H_ \ No newline at end of file
diff --git a/plugins/Dropbox/src/main.cpp b/plugins/Dropbox/src/main.cpp
index da1ccca07f..c5bfbd358a 100644
--- a/plugins/Dropbox/src/main.cpp
+++ b/plugins/Dropbox/src/main.cpp
@@ -1,9 +1,7 @@
-//#include "common.h"
#include "dropbox.h"
int hLangpack;
HINSTANCE g_hInstance;
-CDropbox *g_dropbox;
PLUGININFOEX pluginInfo =
{
@@ -33,20 +31,18 @@ extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD miranda
return &pluginInfo;
}
-extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = {MIID_PROTOCOL, MIID_LAST};
-
extern "C" int __declspec(dllexport) Load(void)
{
mir_getLP(&pluginInfo);
- g_dropbox = new CDropbox();
+ Singleton<CDropbox>::GetInstance()->Init();
return 0;
}
extern "C" int __declspec(dllexport) Unload(void)
{
- delete g_dropbox;
+ Singleton<CDropbox>::GetInstance()->Uninit();
return 0;
} \ No newline at end of file
diff --git a/plugins/Dropbox/src/singleton.h b/plugins/Dropbox/src/singleton.h
new file mode 100644
index 0000000000..432e2ed7f0
--- /dev/null
+++ b/plugins/Dropbox/src/singleton.h
@@ -0,0 +1,29 @@
+#ifndef _SINGLETON_H_
+#define _SINGLETON_H_
+
+template<typename T>
+class Singleton
+{
+public:
+ static T *GetInstance()
+ {
+ if (!instance)
+ instance = new T;
+ return instance;
+ }
+
+private:
+ static T* instance;
+
+ Singleton();
+ Singleton(Singleton const&);
+
+ ~Singleton();
+
+ Singleton &operator=(Singleton const&);
+};
+
+template <typename T> T *Singleton<T>::instance = 0;
+
+
+#endif //_SINGLETON_H_ \ No newline at end of file