summaryrefslogtreecommitdiff
path: root/plugins/CloudFile/src/file_transfer.h
diff options
context:
space:
mode:
authoraunsane <aunsane@gmail.com>2017-04-16 01:32:19 +0300
committeraunsane <aunsane@gmail.com>2017-04-16 01:32:58 +0300
commit0b9fa1d90f8d0aff7118837ceb1211b578a5a9c8 (patch)
tree3b8be7b839a98a3a52a38d713c2d708ada015510 /plugins/CloudFile/src/file_transfer.h
parent008fb731e3e3b587f596afba1cfe7446de7f0cac (diff)
CloudFile: initial commit
- Dropbox (worked) - Yandex.Disk (worked) - GDrive (not worked)
Diffstat (limited to 'plugins/CloudFile/src/file_transfer.h')
-rw-r--r--plugins/CloudFile/src/file_transfer.h245
1 files changed, 245 insertions, 0 deletions
diff --git a/plugins/CloudFile/src/file_transfer.h b/plugins/CloudFile/src/file_transfer.h
new file mode 100644
index 0000000000..16f515f856
--- /dev/null
+++ b/plugins/CloudFile/src/file_transfer.h
@@ -0,0 +1,245 @@
+#ifndef _FILE_TRANSFER_H_
+#define _FILE_TRANSFER_H_
+
+class FileTransferParam
+{
+private:
+ static ULONG hFileProcess;
+
+ ULONG id;
+ FILE *hFile;
+ PROTOFILETRANSFERSTATUS pfts;
+
+ bool isTerminated;
+
+ const wchar_t* folderName;
+ int relativePathStart;
+
+ CMStringW serverFolder;
+
+ CMStringW data;
+
+public:
+ FileTransferParam(MCONTACT hContact)
+ {
+ hFile = NULL;
+ id = InterlockedIncrement(&hFileProcess);
+
+ isTerminated = false;
+
+ folderName = NULL;
+ relativePathStart = 0;
+
+ pfts.cbSize = sizeof(this->pfts);
+ pfts.flags = PFTS_UNICODE | PFTS_SENDING;
+ pfts.hContact = hContact;
+ pfts.currentFileNumber = -1;
+ pfts.currentFileProgress = 0;
+ pfts.currentFileSize = 0;
+ pfts.currentFileTime = 0;
+ pfts.totalBytes = 0;
+ pfts.totalFiles = 0;
+ pfts.totalProgress = 0;
+ pfts.ptszFiles = (wchar_t**)mir_alloc(sizeof(wchar_t*) * (pfts.totalFiles + 1));
+ pfts.ptszFiles[pfts.totalFiles] = NULL;
+ pfts.tszWorkingDir = NULL;
+ pfts.tszCurrentFile = NULL;
+
+ ProtoBroadcastAck(MODULE, pfts.hContact, ACKTYPE_FILE, ACKRESULT_INITIALISING, (HANDLE)id, 0);
+ }
+
+ ~FileTransferParam()
+ {
+ CloseCurrentFile();
+
+ if (pfts.tszWorkingDir)
+ mir_free(pfts.tszWorkingDir);
+
+ if (pfts.pszFiles)
+ {
+ for (int i = 0; pfts.pszFiles[i]; i++)
+ {
+ if (pfts.pszFiles[i]) mir_free(pfts.pszFiles[i]);
+ }
+ mir_free(pfts.pszFiles);
+ }
+ }
+
+ ULONG GetId() const
+ {
+ return id;
+ }
+
+ MCONTACT GetHContact() const
+ {
+ return pfts.hContact;
+ }
+
+ const wchar_t* GetData() const
+ {
+ if (data.IsEmpty())
+ return NULL;
+ return data;
+ }
+
+ void Terminate()
+ {
+ isTerminated = true;
+ }
+
+ void SetWorkingDirectory(const wchar_t *path)
+ {
+ relativePathStart = wcsrchr(path, '\\') - path + 1;
+ pfts.tszWorkingDir = (wchar_t*)mir_calloc(sizeof(wchar_t) * relativePathStart);
+ mir_wstrncpy(pfts.tszWorkingDir, path, relativePathStart);
+ if (PathIsDirectory(path))
+ folderName = wcsrchr(path, '\\') + 1;
+ }
+
+ void SetServerFolder(const wchar_t *path)
+ {
+ if (path)
+ serverFolder = path;
+ }
+
+ const wchar_t* GetServerFolder() const
+ {
+ if (serverFolder.IsEmpty())
+ return NULL;
+ return serverFolder;
+ }
+
+ const wchar_t* GetFolderName() const
+ {
+ return folderName;
+ }
+
+ void AddFile(const wchar_t *path)
+ {
+ pfts.ptszFiles = (wchar_t**)mir_realloc(pfts.ptszFiles, sizeof(wchar_t*) * (pfts.totalFiles + 2));
+ pfts.ptszFiles[pfts.totalFiles++] = mir_wstrdup(path);
+ pfts.ptszFiles[pfts.totalFiles] = NULL;
+
+ FILE *file = _wfopen(path, L"rb");
+ if (file != NULL) {
+ _fseeki64(file, 0, SEEK_END);
+ pfts.totalBytes += _ftelli64(file);
+ fclose(file);
+ }
+ }
+
+ void AppendFormatData(const wchar_t *format, ...)
+ {
+ va_list args;
+ va_start(args, format);
+ data.AppendFormatV(format, args);
+ va_end(args);
+ }
+
+ const wchar_t* GetCurrentFilePath() const
+ {
+ return pfts.ptszFiles[pfts.currentFileNumber];
+ }
+
+ const wchar_t* GetCurrentRelativeFilePath() const
+ {
+ return &GetCurrentFilePath()[relativePathStart];
+ }
+
+ const wchar_t* GetCurrentFileName() const
+ {
+ return wcsrchr(pfts.ptszFiles[pfts.currentFileNumber], '\\') + 1;
+ }
+
+ void OpenCurrentFile()
+ {
+ hFile = _wfopen(GetCurrentFilePath(), L"rb");
+ if (!hFile)
+ throw Exception("Unable to open file");
+ _fseeki64(hFile, 0, SEEK_END);
+ pfts.currentFileSize = _ftelli64(hFile);
+ rewind(hFile);
+ }
+
+ size_t ReadCurrentFile(void *buffer, size_t count)
+ {
+ return fread(buffer, sizeof(char), count, hFile);
+ }
+
+ void CheckCurrentFile()
+ {
+ if (ferror(hFile))
+ throw Exception("Error while file sending");
+
+ if (isTerminated)
+ throw Exception("Transfer was terminated");
+ }
+
+ void CloseCurrentFile()
+ {
+ if (hFile != NULL)
+ {
+ fclose(hFile);
+ hFile = NULL;
+ }
+ }
+
+ const uint64_t GetCurrentFileSize() const
+ {
+ return pfts.currentFileSize;
+ }
+
+ const uint64_t GetCurrentFileChunkSize() const
+ {
+ int chunkSize = 1024 * 1024;
+ if (pfts.currentFileSize < chunkSize)
+ chunkSize = min(pfts.currentFileSize, chunkSize / 4);
+ else if (pfts.currentFileSize > 20 * chunkSize)
+ chunkSize = chunkSize * 4;
+ return chunkSize;
+ }
+
+ void Progress(size_t count)
+ {
+ pfts.currentFileProgress += count;
+ pfts.totalProgress += count;
+ ProtoBroadcastAck(MODULE, pfts.hContact, ACKTYPE_FILE, ACKRESULT_DATA, (HANDLE)id, (LPARAM)&pfts);
+ }
+
+ void FirstFile()
+ {
+ CloseCurrentFile();
+
+ pfts.currentFileNumber = 0;
+ pfts.currentFileProgress = 0;
+ pfts.tszCurrentFile = wcsrchr(pfts.ptszFiles[pfts.currentFileNumber], '\\') + 1;
+ ProtoBroadcastAck(MODULE, pfts.hContact, ACKTYPE_FILE, ACKRESULT_DATA, (HANDLE)id, (LPARAM)&pfts);
+
+ OpenCurrentFile();
+ CheckCurrentFile();
+ }
+
+ bool NextFile()
+ {
+ CloseCurrentFile();
+
+ if (++pfts.currentFileNumber == pfts.totalFiles)
+ return false;
+
+ pfts.currentFileProgress = 0;
+ pfts.tszCurrentFile = wcsrchr(pfts.ptszFiles[pfts.currentFileNumber], '\\') + 1;
+ ProtoBroadcastAck(MODULE, pfts.hContact, ACKTYPE_FILE, ACKRESULT_NEXTFILE, (HANDLE)id, 0);
+
+ OpenCurrentFile();
+ CheckCurrentFile();
+
+ return true;
+ }
+
+ void SetStatus(int status, LPARAM param = 0)
+ {
+ ProtoBroadcastAck(MODULE, pfts.hContact, ACKTYPE_FILE, status, (HANDLE)id, param);
+ }
+};
+
+#endif //_FILE_TRANSFER_H_ \ No newline at end of file