summaryrefslogtreecommitdiff
path: root/protocols/ICQCorp/src/transfer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/ICQCorp/src/transfer.cpp')
-rw-r--r--protocols/ICQCorp/src/transfer.cpp505
1 files changed, 505 insertions, 0 deletions
diff --git a/protocols/ICQCorp/src/transfer.cpp b/protocols/ICQCorp/src/transfer.cpp
new file mode 100644
index 0000000000..eb1a8dbf7b
--- /dev/null
+++ b/protocols/ICQCorp/src/transfer.cpp
@@ -0,0 +1,505 @@
+/*
+ ICQ Corporate protocol plugin for Miranda IM.
+ Copyright (C) 2003-2005 Eugene Tarasenko <zlyden13@inbox.ru>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "corp.h"
+
+std::vector <ICQTransfer *> icqTransfers;
+
+///////////////////////////////////////////////////////////////////////////////
+
+void WINAPI transferTimerProc(HWND hWnd, UINT Msg, UINT_PTR hTimer, DWORD Time)
+{
+ unsigned int i;
+
+ KillTimer(NULL, hTimer);
+ for (i=0; i<icqTransfers.size(); i++) if (hTimer == icqTransfers[i]->hTimer) icqTransfers[i]->process();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+ICQTransfer::ICQTransfer(ICQUser *u, unsigned int theSequence) :
+ socket(WM_NETEVENT_TRANSFER)
+{
+ uin = u->uin;
+ hContact = u->hContact;
+ sequence = theSequence;
+ files = NULL;
+ description = NULL;
+ path = NULL;
+ sending = 0;
+ speed = 100;
+ count = 0;
+ current = -1;
+ fileName = NULL;
+ fileSize = 0;
+ fileProgress = 0;
+ totalSize = 0;
+ totalProgress = 0;
+ lastNotify = 0;
+ hTimer = NULL;
+ hFile = INVALID_HANDLE_VALUE;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+ICQTransfer::~ICQTransfer()
+{
+ closeFile();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQTransfer::processTcpPacket(Packet &packet)
+{
+ unsigned int /*i,*/ status, junkLong;
+ //unsigned short junkShort;
+ unsigned char cmd/*, junkChar*/;
+ char *name = NULL, *directoryName = NULL;
+
+ packet >> cmd;
+ switch (cmd)
+ {
+ case 0x00:
+ T("[tcp] recieve initialising file transfer\n");
+ packet >> junkLong
+ >> count
+ >> totalSize
+ >> speed
+ >> name;
+
+ files = new char*[count + 1];
+ ZeroMemory(files, (count+1)*sizeof(char*));
+
+ ack(ACKRESULT_INITIALISING);
+ sendPacket0x01();
+ break;
+
+ case 0x01:
+ T("[tcp] ack initialising\n");
+ packet >> speed
+ >> name;
+
+ ack(ACKRESULT_INITIALISING);
+ sendPacket0x02();
+ break;
+
+ case 0x02:
+ T("[tcp] recieve next file\n");
+ packet >> directory
+ >> files[++current]
+ >> directoryName
+ >> fileSize
+ >> fileDate
+ >> speed;
+
+ if (directoryName[0])
+ {
+ char *fullName = new char[strlen(directoryName) + strlen(files[current]) + 2];
+ sprintf(fullName, "%s\\%s", directoryName, files[current]);
+ delete [] files[current];
+ files[current] = fullName;
+ }
+
+ if (directory) createDirectory();
+ else openFile();
+ ack(ACKRESULT_NEXTFILE);
+
+ if (fileProgress) ack(ACKRESULT_FILERESUME);
+ else sendPacket0x03();
+ break;
+
+ case 0x03:
+ T("[tcp] ack next file\n");
+ packet >> fileProgress
+ >> status
+ >> speed;
+
+ totalProgress += fileProgress;
+ setFilePosition();
+ ack(ACKRESULT_NEXTFILE);
+
+ if (status != 0)
+ {
+ totalProgress += fileSize - fileProgress;
+ fileProgress = fileSize;
+ closeFile();
+ ack(ACKRESULT_DATA);
+ }
+
+ process();
+ break;
+
+ case 0x04:
+ T("[tcp] recieve stop file\n");
+ packet >> junkLong;
+
+ totalProgress += fileSize - fileProgress;
+ fileProgress = fileSize;
+ closeFile();
+ ack(ACKRESULT_DATA);
+ break;
+
+ case 0x05:
+ T("[tcp] recieve new speed\n");
+ packet >> speed;
+ break;
+
+ case 0x06:
+ unsigned long result;
+
+ WriteFile(hFile, packet.data(), packet.dataSize(), &result, NULL);
+
+ fileProgress += result;
+ totalProgress += result;
+
+ if (fileProgress >= fileSize) closeFile();
+ ack(ACKRESULT_DATA);
+ break;
+
+ default:
+ T("[tcp] unknown packet:\n%s", packet.print());
+ packet.reset();
+ }
+
+ delete [] directoryName;
+ delete [] name;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQTransfer::sendPacket0x00()
+{
+ char nick[1] = { 0 };
+
+ sending = true;
+
+ Packet packet;
+ packet << (unsigned char)0x00
+ << (unsigned int)0x00
+ << count
+ << totalSize
+ << speed
+ << nick;
+
+ T("[tcp] send packet 0x00\n");
+ socket.sendPacket(packet);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQTransfer::sendPacket0x01()
+{
+ char nick[1] = { 0 };
+
+ Packet packet;
+ packet << (unsigned char)0x01
+ << speed
+ << nick;
+
+ T("[tcp] send packet 0x01\n");
+ socket.sendPacket(packet);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQTransfer::sendPacket0x02()
+{
+ char *directoryName, *p;
+
+ current++;
+ openFile();
+
+ directoryName = _strdup(fileName);
+ p = strrchr(directoryName, '\\');
+ p[0] = 0;
+ p[1] = 0;
+
+ Packet packet;
+ packet << (unsigned char)0x02
+ << directory
+ << (strrchr(fileName, '\\') + 1)
+ << (directoryName + strlen(path) + 1)
+ << fileSize
+ << fileDate
+ << speed;
+
+ T("[tcp] send packet 0x02\n");
+ socket.sendPacket(packet);
+ ack(ACKRESULT_NEXTFILE);
+
+ free(directoryName);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQTransfer::sendPacket0x03()
+{
+ Packet packet;
+ packet << (unsigned char)0x03
+ << fileProgress
+ << (unsigned int)0x00
+ << speed;
+
+ setFilePosition();
+
+ T("[tcp] send packet 0x03\n");
+ socket.sendPacket(packet);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQTransfer::sendPacket0x04()
+{
+ T("[tcp] send packet 0x04\n");
+/*
+ icq_PacketAppend8(p, 0x04);
+ icq_PacketAppend32(p, filenum);
+*/
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQTransfer::sendPacket0x05()
+{
+ T("[tcp] send packet 0x05\n");
+/*
+ icq_PacketAppend8(p, 0x05);
+ icq_PacketAppend32(p, speed);
+*/
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQTransfer::sendPacket0x06()
+{
+ unsigned long result;
+
+ Packet packet;
+ packet << (unsigned char)0x06;
+
+ ReadFile(hFile, packet.data(), 2048, &result, NULL);
+ if (result == 0) return;
+ packet.add(result);
+
+// T("[tcp] send packet 0x06\n");
+ socket.sendPacket(packet);
+
+ fileProgress += result;
+ totalProgress += result;
+
+ if (fileProgress >= fileSize) closeFile();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQTransfer::ack(unsigned int result)
+{
+ PROTOFILETRANSFERSTATUS fts;
+
+ if (result == ACKRESULT_DATA && GetTickCount() < lastNotify+250 && fileProgress < fileSize) return;
+
+ fts.cbSize = sizeof(fts);
+ fts.hContact = hContact;
+ //fts.sending = sending;
+ fts.pszFiles = files;
+ fts.totalFiles = count;
+ fts.currentFileNumber = current;
+ fts.totalBytes = totalSize;
+ fts.totalProgress = totalProgress;
+ fts.szWorkingDir = path;
+ fts.szCurrentFile = fileName;
+ fts.currentFileSize = fileSize;
+ fts.currentFileProgress = fileProgress;
+ fts.currentFileTime = CallService(MS_DB_TIME_TIMESTAMPTOLOCAL, fileDate, 0);
+/*
+ switch (session->status)
+ {
+ case FILE_STATUS_LISTENING: result = ACKRESULT_SENTREQUEST; break;
+ case FILE_STATUS_CONNECTED: result = ACKRESULT_CONNECTED; break;
+ case FILE_STATUS_CONNECTING: result = ACKRESULT_CONNECTING; break;
+ case FILE_STATUS_INITIALIZING: result = ACKRESULT_INITIALISING; break;
+ case FILE_STATUS_NEXT_FILE: result = ACKRESULT_NEXTFILE; break;
+ case FILE_STATUS_SENDING:
+ case FILE_STATUS_RECEIVING: result=ACKRESULT_DATA; break;
+ }
+*/
+ ProtoBroadcastAck(protoName, hContact, ACKTYPE_FILE, result, this, (LPARAM)&fts);
+ lastNotify = GetTickCount();
+
+ if (result == ACKRESULT_DATA && current >= count-1 && fileProgress >= fileSize)
+ {
+ ProtoBroadcastAck(protoName, hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, this, 0);
+ socket.closeConnection();
+
+ unsigned int i;
+ for (i=0; i<icqTransfers.size(); i++)
+ {
+ if (icqTransfers[i] == this)
+ {
+ delete icqTransfers[i];
+ icqTransfers[i] = icqTransfers[icqTransfers.size() - 1];
+ icqTransfers.pop_back();
+ break;
+ }
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQTransfer::process()
+{
+ unsigned int /*i, */startTime;
+
+ hTimer = NULL;
+ if (current >= count) return;
+
+ startTime = GetTickCount();
+ while (fileProgress < fileSize && GetTickCount() < startTime+100) sendPacket0x06();
+ ack(ACKRESULT_DATA);
+
+ if (fileProgress < fileSize) hTimer = SetTimer(NULL, 0, 1, (TIMERPROC)transferTimerProc);
+ else if (current < count-1) sendPacket0x02();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQTransfer::resume(int action, const char *newName)
+{
+ switch (action)
+ {
+ case FILERESUME_OVERWRITE:
+ T("[ ] overwrite existing file\n");
+ fileProgress = 0;
+ break;
+
+ case FILERESUME_RESUME:
+ T("[ ] file resume\n");
+ break;
+
+ case FILERESUME_RENAME:
+ T("[ ] rename file\n");
+ delete [] fileName;
+ fileName = new char[strlen(newName) + 1];
+ strcpy(fileName, newName);
+ files[current] = fileName;
+
+ openFile();
+ fileProgress = 0;
+ break;
+
+ case FILERESUME_SKIP:
+ T("[ ] skip file\n");
+ fileProgress = fileSize;
+ break;
+ }
+
+ totalProgress += fileProgress;
+
+ sendPacket0x03();
+ ack(ACKRESULT_NEXTFILE);
+
+ if (fileProgress) ack(ACKRESULT_DATA);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQTransfer::openFile()
+{
+ HANDLE hFind;
+ WIN32_FIND_DATA findData;
+ __int64 fileTime;
+
+ if (hFile != INVALID_HANDLE_VALUE) closeFile();
+ if (path) SetCurrentDirectory(path);
+
+ fileName = files[current];
+
+ hFind = FindFirstFile(fileName, &findData);
+ if (hFind != INVALID_HANDLE_VALUE)
+ {
+ FindClose(hFind);
+ if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ {
+ T("open directory %s\n", fileName);
+ directory = 1;
+ fileProgress = 0;
+ fileSize = 0;
+ fileDate = *(__int64*)(&findData.ftLastWriteTime) / 10000000 - 11644473600i64;
+ return;
+ }
+ }
+ directory = 0;
+
+ hFile = CreateFile(fileName, sending ? GENERIC_READ : GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, NULL);
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ char msg[2048];
+
+ T("can't open file %s\n", fileName);
+ sprintf(msg, "%s\n%s", sending ? Translate("Your file transfer has been aborted because one of the files that you selected to send is no longer readable from the disk. You may have deleted or moved it.") : Translate("Your file receive has been aborted because Miranda could not open the destination file in order to write to it. You may be trying to save to a read-only folder."), fileName);
+ MessageBox(NULL, msg, Translate(protoName), MB_ICONWARNING|MB_OK);
+ return;
+ }
+
+ if (sending)
+ {
+ fileProgress = 0;
+ fileSize = GetFileSize(hFile, NULL);
+
+ GetFileTime(hFile, NULL, NULL, (LPFILETIME)&fileTime);
+ fileDate = fileTime / 10000000 - 11644473600i64;
+ }
+ else
+ {
+ fileProgress = GetFileSize(hFile, NULL);
+
+ fileTime = (11644473600i64 + (__int64)fileDate) * 10000000;
+ SetFileTime(hFile, NULL, NULL, (LPFILETIME)&fileTime);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQTransfer::closeFile()
+{
+ CloseHandle(hFile);
+ hFile = INVALID_HANDLE_VALUE;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQTransfer::setFilePosition()
+{
+ if (hFile != INVALID_HANDLE_VALUE) SetFilePointer(hFile, fileProgress, NULL, FILE_BEGIN);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQTransfer::createDirectory()
+{
+ if (path) SetCurrentDirectory(path);
+
+ fileName = files[current];
+ CreateDirectory(fileName, NULL);
+
+ fileProgress = 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////