summaryrefslogtreecommitdiff
path: root/protocols/Yahoo/file_transfer.cpp
diff options
context:
space:
mode:
authorVadim Dashevskiy <watcherhd@gmail.com>2012-05-15 10:38:20 +0000
committerVadim Dashevskiy <watcherhd@gmail.com>2012-05-15 10:38:20 +0000
commit48540940b6c28bb4378abfeb500ec45a625b37b6 (patch)
tree2ef294c0763e802f91d868bdef4229b6868527de /protocols/Yahoo/file_transfer.cpp
parent5c350913f011e119127baeb32a6aedeb4f0d33bc (diff)
initial commit
git-svn-id: http://svn.miranda-ng.org/main/trunk@2 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'protocols/Yahoo/file_transfer.cpp')
-rw-r--r--protocols/Yahoo/file_transfer.cpp908
1 files changed, 908 insertions, 0 deletions
diff --git a/protocols/Yahoo/file_transfer.cpp b/protocols/Yahoo/file_transfer.cpp
new file mode 100644
index 0000000000..c18ef4c22b
--- /dev/null
+++ b/protocols/Yahoo/file_transfer.cpp
@@ -0,0 +1,908 @@
+/*
+ * $Id: file_transfer.cpp 13893 2011-10-23 19:29:28Z borkra $
+ *
+ * myYahoo Miranda Plugin
+ *
+ * Authors: Gennady Feldman (aka Gena01)
+ * Laurent Marechal (aka Peorth)
+ *
+ * This code is under GPL and is based on AIM, MSN and Miranda source code.
+ * I want to thank Robert Rainwater and George Hazan for their code and support
+ * and for answering some of my questions during development of this plugin.
+ */
+#include <time.h>
+#include <sys/stat.h>
+
+#include "yahoo.h"
+#include <m_protosvc.h>
+#include "file_transfer.h"
+
+YList *file_transfers=NULL;
+
+static y_filetransfer* new_ft(CYahooProto* ppro, int id, HANDLE hContact, const char *who, const char *msg,
+ const char *url, const char *ft_token, int y7, YList *fs, int sending)
+{
+ yahoo_file_info * fi;
+ int i=0;
+ YList *l=fs;
+
+ LOG(("[new_ft] id: %d, who: %s, msg: %s, ft_token: %s, y7: %d, sending: %d", id, who, msg, ft_token, y7, sending));
+
+ y_filetransfer* ft = (y_filetransfer*) calloc(1, sizeof(y_filetransfer));
+ ft->ppro = ppro;
+ ft->id = id;
+ ft->who = strdup(who);
+ ft->hWaitEvent = INVALID_HANDLE_VALUE;
+
+ ft->hContact = hContact;
+ ft->files = fs;
+
+ ft->url = (url == NULL) ? NULL : strdup(url);
+ ft->ftoken = (ft_token == NULL) ? NULL : strdup(ft_token);
+ ft->msg = (msg != NULL) ? strdup(msg) : strdup("[no description given]");
+
+ ft->cancel = 0;
+ ft->y7 = y7;
+
+ ft->hWaitEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
+
+ ft->pfts.cbSize = sizeof(PROTOFILETRANSFERSTATUS);
+ ft->pfts.hContact = hContact;
+ ft->pfts.flags = PFTS_TCHAR;
+ ft->pfts.flags |= (sending != 0 ) ? PFTS_SENDING : PFTS_RECEIVING;
+
+ ft->pfts.tszWorkingDir = NULL;
+ ft->pfts.currentFileTime = 0;
+
+ ft->pfts.totalFiles = y_list_length(fs);
+
+ ft->pfts.ptszFiles = (TCHAR**) mir_calloc(ft->pfts.totalFiles * sizeof(TCHAR *));
+ ft->pfts.totalBytes = 0;
+
+ while(l) {
+ fi = ( yahoo_file_info* )l->data;
+
+ ft->pfts.ptszFiles[i++] = mir_utf8decodeT(fi->filename);
+ ft->pfts.totalBytes += fi->filesize;
+
+ l=l->next;
+ }
+
+ ft->pfts.currentFileNumber = 0;
+
+ fi = ( yahoo_file_info* )fs->data;
+ ft->pfts.tszCurrentFile = _tcsdup(ft->pfts.ptszFiles[ft->pfts.currentFileNumber]);
+ ft->pfts.currentFileSize = fi->filesize;
+
+ file_transfers = y_list_prepend(file_transfers, ft);
+
+ LOG(("[/new_ft]"));
+
+ return ft;
+}
+
+y_filetransfer* find_ft(const char *ft_token, const char *who)
+{
+ YList *l;
+ y_filetransfer* f;
+ LOG(("[find_ft] Searching for: %s", ft_token));
+
+ for(l = file_transfers; l; l = y_list_next(l)) {
+ f = (y_filetransfer* )l->data;
+ if (lstrcmpA(f->ftoken, ft_token) == 0 && lstrcmpA(f->who, who) == 0) {
+ LOG(("[find_ft] Got it!"));
+ return f;
+ }
+ }
+
+ LOG(("[find_ft] FT not found?"));
+ return NULL;
+}
+
+static void free_ft(y_filetransfer* ft)
+{
+ YList *l;
+ int i;
+
+ LOG(("[free_ft] token: %s", ft->ftoken));
+
+ for(l = file_transfers; l; l = y_list_next(l)) {
+ if (l->data == ft){
+ LOG(("[free_ft] Ft found and removed from the list"));
+ file_transfers = y_list_remove_link(file_transfers, l);
+ y_list_free_1(l);
+ break;
+ }
+ }
+
+ if ( ft->hWaitEvent != INVALID_HANDLE_VALUE )
+ CloseHandle( ft->hWaitEvent );
+
+ FREE(ft->who);
+ FREE(ft->msg);
+ FREE(ft->url);
+ FREE(ft->ftoken);
+ FREE(ft->relay);
+
+ LOG(("[free_ft] About to free the File List."));
+
+ while(ft->files) {
+ YList *tmp = ft->files;
+ yahoo_file_info * c = ( yahoo_file_info* )ft->files->data;
+ FREE(c->filename);
+ FREE(c);
+ ft->files = y_list_remove_link(ft->files, ft->files);
+ y_list_free_1(tmp);
+ }
+
+ LOG(("[free_ft] About to free PFTS."));
+
+ for (i=0; i< ft->pfts.totalFiles; i++)
+ mir_free(ft->pfts.ptszFiles[i]);
+
+ mir_free(ft->pfts.ptszFiles);
+ FREE(ft->pfts.tszCurrentFile);
+ FREE(ft->pfts.tszWorkingDir);
+ FREE(ft);
+
+ LOG(("[/free_ft]"));
+}
+
+static void upload_file(int id, int fd, int error, void *data)
+{
+ y_filetransfer *sf = (y_filetransfer*) data;
+ struct yahoo_file_info *fi = (struct yahoo_file_info *)sf->files->data;
+ char buf[1024];
+ unsigned long size = 0;
+ DWORD dw = 0;
+ int rw = 0;
+
+ if (fd < 0) {
+ LOG(("[get_fd] Connect Failed!"));
+ error = 1;
+ }
+
+ if(!error) {
+ HANDLE myhFile = CreateFile(sf->pfts.tszCurrentFile,
+ GENERIC_READ,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
+ 0);
+
+ if(myhFile !=INVALID_HANDLE_VALUE) {
+ DWORD lNotify = GetTickCount();
+
+ LOG(("proto: %s, hContact: %p", sf->ppro->m_szModuleName, sf->hContact));
+
+ LOG(("Sending file: %s", fi->filename));
+ //ProtoBroadcastAck(m_szModuleName, sf->hContact, ACKTYPE_FILE, ACKRESULT_CONNECTING, sf, 0);
+ //ProtoBroadcastAck(m_szModuleName, sf->hContact, ACKTYPE_FILE, ACKRESULT_NEXTFILE, sf, 0);
+ ProtoBroadcastAck(sf->ppro->m_szModuleName, sf->hContact, ACKTYPE_FILE, ACKRESULT_CONNECTED, sf, 0);
+ //ProtoBroadcastAck(m_szModuleName, sf->hContact, ACKTYPE_FILE, ACKRESULT_SENTREQUEST, sf, 0);
+ //ProtoBroadcastAck(m_szModuleName, sf->hContact, ACKTYPE_FILE, ACKRESULT_INITIALISING, sf, 0);
+
+ do {
+ ReadFile(myhFile, buf, sizeof(buf), &dw, NULL);
+
+ if (dw) {
+ rw = Netlib_Send((HANDLE)fd, buf, dw, MSG_NODUMP);
+
+ if (rw < 1) {
+ LOG(("Upload Failed. Send error? Got: %d", rw));
+ error = 1;
+ break;
+ } else
+ size += rw;
+
+ if(GetTickCount() >= lNotify + 500 || rw < 1024 || size == fi->filesize) {
+ LOG(("DOING UI Notify. Got %lu/%lu", size, fi->filesize));
+ sf->pfts.totalProgress = size;
+ sf->pfts.currentFileProgress = size;
+
+ ProtoBroadcastAck(sf->ppro->m_szModuleName, sf->hContact, ACKTYPE_FILE, ACKRESULT_DATA, sf, (LPARAM) & sf->pfts);
+ lNotify = GetTickCount();
+ }
+
+ }
+
+ if (sf->cancel) {
+ LOG(("Upload Cancelled! "));
+ error = 1;
+ break;
+ }
+ } while ( rw > 0 && dw > 0 && !error);
+
+ CloseHandle(myhFile);
+
+ sf->pfts.totalProgress = size;
+ sf->pfts.currentFileProgress = size;
+
+ ProtoBroadcastAck(sf->ppro->m_szModuleName, sf->hContact, ACKTYPE_FILE, ACKRESULT_DATA, sf, (LPARAM) & sf->pfts);
+
+ }
+ }
+
+ if (fd > 0) {
+ int tr = 0;
+
+ do {
+ rw = Netlib_Recv((HANDLE)fd, buf, sizeof(buf), 0);
+ LOG(("Got: %d bytes", rw));
+
+ if (tr == 0) {
+ //"HTTP/1.1 999" 12
+ // 012345678901
+ if (rw > 12) {
+ if (buf[9] != '2' || buf[10] != '0' || buf[11] != '0') {
+ LOG(("File Transfer Failed: %c%c%c", buf[9], buf[10], buf[11]));
+ error=1;
+ }
+ }
+ }
+ tr +=rw;
+ } while (rw > 0);
+
+ Netlib_CloseHandle((HANDLE)fd);
+ }
+
+ LOG(("File send complete!"));
+
+ if (! error) {
+ sf->pfts.currentFileNumber++;
+
+ if (sf->pfts.currentFileNumber >= sf->pfts.totalFiles) {
+ ProtoBroadcastAck(sf->ppro->m_szModuleName, sf->hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, sf, 0);
+ } else {
+ YList *l;
+ struct yahoo_file_info * fi;
+
+ // Do Next file
+ FREE(sf->pfts.tszCurrentFile);
+
+ l = sf->files;
+
+ fi = ( yahoo_file_info* )l->data;
+ FREE(fi->filename);
+ FREE(fi);
+
+ sf->files = y_list_remove_link(sf->files, l);
+ y_list_free_1(l);
+
+ // need to move to the next file on the list and fill the file information
+ fi = ( yahoo_file_info* )sf->files->data;
+ sf->pfts.tszCurrentFile = _tcsdup(sf->pfts.ptszFiles[sf->pfts.currentFileNumber]);
+ sf->pfts.currentFileSize = fi->filesize;
+ sf->pfts.currentFileProgress = 0;
+
+ ProtoBroadcastAck(sf->ppro->m_szModuleName, sf->hContact, ACKTYPE_FILE, ACKRESULT_NEXTFILE, sf, 0);
+ LOG(("Waiting for next file request packet..."));
+ }
+
+ } else {
+ ProtoBroadcastAck(sf->ppro->m_szModuleName, sf->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, sf, 0);
+ }
+}
+
+static void dl_file(int id, int fd, int error, const char *filename, unsigned long size, void *data)
+{
+ y_filetransfer *sf = (y_filetransfer*) data;
+ struct yahoo_file_info *fi = (struct yahoo_file_info *)sf->files->data;
+ char buf[1024];
+ unsigned long rsize = 0;
+ DWORD dw, c;
+
+ if (fd < 0) {
+ LOG(("[get_url] Connect Failed!"));
+
+ if (sf->ftoken != NULL) {
+ LOG(("[get_url] DC Detected: asking sender to upload to Yahoo FileServers!"));
+ yahoo_ftdc_deny(id, sf->who, fi->filename, sf->ftoken, 3);
+ }
+
+ error = 1;
+ }
+
+ if(!error) {
+ HANDLE myhFile;
+ TCHAR filefull[MAX_PATH];
+
+ /*
+ * We need FULL Path for File Resume to work properly!!!
+ *
+ * Don't rely on workingDir to be right, since it's not used to check if file exists.
+ */
+ mir_sntprintf(filefull, MAX_PATH, _T("%s\\%s"), sf->pfts.tszWorkingDir, sf->pfts.tszCurrentFile);
+ FREE(sf->pfts.tszCurrentFile);
+ sf->pfts.tszCurrentFile = _tcsdup(filefull);
+
+ ResetEvent(sf->hWaitEvent);
+
+ if ( sf->ppro->SendBroadcast( sf->hContact, ACKTYPE_FILE, ACKRESULT_FILERESUME, sf, ( LPARAM )&sf->pfts )) {
+ WaitForSingleObject( sf->hWaitEvent, INFINITE );
+
+ LOG(("[dl_file] Got action: %ld", sf->action));
+
+ switch(sf->action){
+ case FILERESUME_RENAME:
+ case FILERESUME_OVERWRITE:
+ case FILERESUME_RESUME:
+ // no action needed at this point, just break out of the switch statement
+ break;
+
+ case FILERESUME_CANCEL :
+ sf->cancel = 1;
+ break;
+
+ case FILERESUME_SKIP :
+ default:
+ sf->cancel = 2;
+ break;
+ }
+ }
+
+
+
+ if (! sf->cancel) {
+
+ myhFile = CreateFile(sf->pfts.tszCurrentFile,
+ GENERIC_WRITE,
+ FILE_SHARE_WRITE,
+ NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
+
+ if(myhFile !=INVALID_HANDLE_VALUE) {
+ DWORD lNotify = GetTickCount();
+
+ SetEndOfFile(myhFile);
+
+ LOG(("proto: %s, hContact: %p", sf->ppro->m_szModuleName, sf->hContact));
+
+ ProtoBroadcastAck(sf->ppro->m_szModuleName, sf->hContact, ACKTYPE_FILE, ACKRESULT_CONNECTED, sf, 0);
+
+ do {
+ dw = Netlib_Recv((HANDLE)fd, buf, 1024, MSG_NODUMP);
+
+ if (dw > 0) {
+ WriteFile(myhFile, buf, dw, &c, NULL);
+ rsize += dw;
+ sf->pfts.totalProgress += dw;
+ sf->pfts.currentFileProgress += dw;
+
+ if(GetTickCount() >= lNotify + 500 || dw <= 0 || rsize == size) {
+
+ LOG(("DOING UI Notify. Got %lu/%lu", rsize, size));
+
+ ProtoBroadcastAck(sf->ppro->m_szModuleName, sf->hContact, ACKTYPE_FILE, ACKRESULT_DATA, sf, (LPARAM) & sf->pfts);
+ lNotify = GetTickCount();
+ }
+
+ } else {
+ LOG(("Recv Failed! Socket Error?"));
+ error = 1;
+ break;
+ }
+
+ if (sf->cancel) {
+ LOG(("Recv Cancelled! "));
+ error = 1;
+ break;
+ }
+ } while ( dw > 0 && rsize < size);
+
+ while (dw > 0 && ! sf->cancel && ! error) {
+ dw = Netlib_Recv((HANDLE)fd, buf, 1024, MSG_NODUMP);
+ LOG(("Ack."));
+ }
+
+ ProtoBroadcastAck(sf->ppro->m_szModuleName, sf->hContact, ACKTYPE_FILE, ACKRESULT_DATA, sf, (LPARAM) & sf->pfts);
+
+ LOG(("[Finished DL] Got %lu/%lu", rsize, size));
+ CloseHandle(myhFile);
+
+ } else {
+ LOG(("Can not open file for writing: %s", buf));
+ error = 1;
+ }
+
+ }
+ }
+
+ if (fd > 0) {
+ LOG(("Closing connection: %d", fd));
+ Netlib_CloseHandle((HANDLE)fd);
+
+ if (sf->cancel || error) {
+ /* abort FT transfer */
+ yahoo_ft7dc_abort(id, sf->who, sf->ftoken);
+ }
+ }
+
+ if (! error) {
+ sf->pfts.currentFileNumber++;
+
+ LOG(("File %d/%d download complete!", sf->pfts.currentFileNumber, sf->pfts.totalFiles));
+
+ if (sf->pfts.currentFileNumber >= sf->pfts.totalFiles) {
+ ProtoBroadcastAck(sf->ppro->m_szModuleName, sf->hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, sf, 0);
+ } else {
+ YList *l;
+ struct yahoo_file_info * fi;
+
+ // Do Next file
+ yahoo_ft7dc_nextfile(id, sf->who, sf->ftoken);
+ FREE(sf->pfts.tszCurrentFile);
+
+ l = sf->files;
+
+ fi = ( yahoo_file_info* )l->data;
+ FREE(fi->filename);
+ FREE(fi);
+
+ sf->files = y_list_remove_link(sf->files, l);
+ y_list_free_1(l);
+
+ // need to move to the next file on the list and fill the file information
+ fi = ( yahoo_file_info* )sf->files->data;
+ sf->pfts.tszCurrentFile = _tcsdup(sf->pfts.ptszFiles[sf->pfts.currentFileNumber]);
+ sf->pfts.currentFileSize = fi->filesize;
+ sf->pfts.currentFileProgress = 0;
+
+ ProtoBroadcastAck(sf->ppro->m_szModuleName, sf->hContact, ACKTYPE_FILE, ACKRESULT_NEXTFILE, sf, 0);
+ }
+ } else {
+ LOG(("File download failed!"));
+
+ ProtoBroadcastAck(sf->ppro->m_szModuleName, sf->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, sf, 0);
+ }
+}
+
+//=======================================================
+//File Transfer
+//=======================================================
+void __cdecl CYahooProto::recv_filethread(void *psf)
+{
+ y_filetransfer *sf = ( y_filetransfer* )psf;
+ struct yahoo_file_info *fi = (struct yahoo_file_info *)sf->files->data;
+
+ ProtoBroadcastAck(m_szModuleName, sf->hContact, ACKTYPE_FILE, ACKRESULT_CONNECTING, sf, 0);
+
+ DebugLog("[yahoo_recv_filethread] who: %s, msg: %s, filename: %s ", sf->who, sf->msg, fi->filename);
+
+
+ yahoo_get_url_handle(m_id, sf->url, &dl_file, sf);
+
+ if (sf->pfts.currentFileNumber >= sf->pfts.totalFiles)
+ free_ft(sf);
+ else
+ DebugLog("[yahoo_recv_filethread] More files coming?");
+}
+
+void CYahooProto::ext_got_file(const char *me, const char *who, const char *url, long expires, const char *msg, const char *fname, unsigned long fesize, const char *ft_token, int y7)
+{
+ HANDLE hContact;
+ char *szBlob;
+ y_filetransfer *ft;
+ char fn[1024];
+ struct yahoo_file_info *fi;
+ YList *files=NULL;
+
+ LOG(("[ext_yahoo_got_file] ident:%s, who: %s, url: %s, expires: %lu, msg: %s, fname: %s, fsize: %lu ftoken: %s y7: %d", me, who, url, expires, msg, fname, fesize, ft_token == NULL ? "NULL" : ft_token, y7));
+
+ hContact = getbuddyH(who);
+ if (hContact == NULL)
+ hContact = add_buddy(who, who, 0 /* NO FT for other IMs */, PALF_TEMPORARY);
+
+ ZeroMemory(fn, 1024);
+
+ if (fname != NULL)
+ lstrcpynA(fn, fname, 1024);
+ else {
+ char *start, *end;
+
+ /* based on how gaim does this */
+ start = ( char* )strrchr(url, '/');
+ if (start)
+ start++;
+
+ end = ( char* )strrchr(url, '?');
+
+ if (start && *start && end) {
+ lstrcpynA(fn, start, end-start+1);
+ } else
+ lstrcpyA(fn, "filename.ext");
+ }
+
+ fi = y_new(struct yahoo_file_info,1);
+ fi->filename = strdup(fn);
+ fi->filesize = fesize;
+
+ files = y_list_append(files, fi);
+
+ ft = new_ft(this, m_id, hContact, who, msg, url, ft_token, y7, files, 0 /* downloading */);
+ if (ft == NULL) {
+ DebugLog("SF IS NULL!!!");
+ return;
+ }
+
+ // blob is DWORD(*ft), ASCIIZ(filenames), ASCIIZ(description)
+ szBlob = (char *) malloc(sizeof(DWORD) + lstrlenA(fn) + lstrlenA(ft->msg) + 2);
+ *((PDWORD) szBlob) = 0;
+ strcpy(szBlob + sizeof(DWORD), fn);
+ strcpy(szBlob + sizeof(DWORD) + lstrlenA(fn) + 1, ft->msg);
+
+ PROTORECVEVENT pre;
+ pre.flags = PREF_UTF;
+ pre.timestamp = (DWORD)time(NULL);
+ pre.szMessage = szBlob;
+ pre.lParam = (LPARAM)ft;
+
+ CCSDATA ccs;
+ ccs.szProtoService = PSR_FILE;
+ ccs.hContact = hContact;
+ ccs.wParam = 0;
+ ccs.lParam = (LPARAM) & pre;
+ CallService(MS_PROTO_CHAINRECV, 0, (LPARAM) & ccs);
+ free(szBlob);
+}
+
+void CYahooProto::ext_got_files(const char *me, const char *who, const char *ft_token, int y7, YList* files)
+{
+ HANDLE hContact;
+ char *szBlob;
+ y_filetransfer *ft;
+ YList *f;
+ char fn[4096];
+ int fc = 0;
+
+ LOG(("[ext_yahoo_got_files] ident:%s, who: %s, ftoken: %s ", me, who, ft_token == NULL ? "NULL" : ft_token));
+
+ hContact = getbuddyH(who);
+ if (hContact == NULL)
+ hContact = add_buddy(who, who, 0 /* NO FT for other IMs */, PALF_TEMPORARY);
+
+ ft = new_ft(this, m_id, hContact, who, NULL, NULL, ft_token, y7, files, 0 /* downloading */);
+ if (ft == NULL) {
+ DebugLog("SF IS NULL!!!");
+ return;
+ }
+
+ fn[0] = '\0';
+ for (f=files; f; f = y_list_next(f)) {
+ char z[1024];
+ struct yahoo_file_info *fi = (struct yahoo_file_info *) f->data;
+
+ snprintf(z, 1024, "%s (%lu)\r\n", fi->filename, fi->filesize);
+ lstrcatA(fn, z);
+ fc++;
+ }
+
+ if (fc > 1) {
+ /* multiple files */
+
+ }
+
+ // blob is DWORD(*ft), ASCIIZ(filenames), ASCIIZ(description)
+ szBlob = (char *) malloc(sizeof(DWORD) + lstrlenA(fn) + 2);
+ *((PDWORD) szBlob) = 0;
+ strcpy(szBlob + sizeof(DWORD), fn);
+ strcpy(szBlob + sizeof(DWORD) + lstrlenA(fn) + 1, "");
+
+ PROTORECVEVENT pre;
+ pre.flags = PREF_UTF;
+ pre.timestamp = (DWORD)time(NULL);
+ pre.szMessage = szBlob;
+ pre.lParam = (LPARAM)ft;
+
+ CCSDATA ccs;
+ ccs.szProtoService = PSR_FILE;
+ ccs.hContact = ft->hContact;
+ ccs.wParam = 0;
+ ccs.lParam = (LPARAM)&pre;
+ CallService(MS_PROTO_CHAINRECV, 0, (LPARAM) & ccs);
+ free(szBlob);
+}
+
+void CYahooProto::ext_got_file7info(const char *me, const char *who, const char *url, const char *fname, const char *ft_token)
+{
+ y_filetransfer *ft;
+
+ LOG(("[ext_yahoo_got_file7info] ident:%s, who: %s, url: %s, fname: %s, ft_token: %s", me, who, url, fname, ft_token));
+
+ ft = find_ft(ft_token, who);
+
+ if (ft == NULL) {
+ LOG(("ERROR: Can't find the token: %s in my file transfers list...", ft_token));
+ return;
+ }
+
+ ProtoBroadcastAck(m_szModuleName, ft->hContact, ACKTYPE_GETINFO, ACKRESULT_SUCCESS, (HANDLE) 1, 0);
+
+ FREE(ft->url);
+
+ ft->url = strdup(url);
+
+ YForkThread(&CYahooProto::recv_filethread, ft);
+}
+
+void ext_yahoo_send_file7info(int id, const char *me, const char *who, const char *ft_token)
+{
+ y_filetransfer *ft;
+ yahoo_file_info *fi;
+
+ char *c;
+ LOG(("[ext_yahoo_send_file7info] id: %i, ident:%s, who: %s, ft_token: %s", id, me, who, ft_token));
+
+ ft = find_ft(ft_token, who);
+
+ if (ft == NULL) {
+ LOG(("ERROR: Can't find the token: %s in my file transfers list...", ft_token));
+ return;
+ }
+
+ fi = (yahoo_file_info *) ft->files->data;
+
+ c = strrchr(fi->filename, '\\');
+ if (c != NULL ) {
+ c++;
+ } else {
+ c = fi->filename;
+ }
+
+ LOG(("Resolving relay.msg.yahoo.com..."));
+ PHOSTENT he = gethostbyname("relay.msg.yahoo.com");
+
+ if (he) {
+ ft->relay = strdup( inet_ntoa(*( PIN_ADDR )he->h_addr_list[0]) );
+ LOG(("Got Relay IP: %s", ft->relay));
+ } else {
+ ft->relay = strdup( "98.136.112.33" );
+ LOG(("DNS Lookup failed. Using Relay IP: %s", ft->relay));
+ }
+
+ yahoo_send_file7info(id, me, who, ft_token, c, ft->relay );
+}
+
+struct _sfs{
+ char *me;
+ char *token;
+ y_filetransfer *sf;
+};
+
+void CYahooProto::ext_ft7_send_file(const char *me, const char *who, const char *filename, const char *token, const char *ft_token)
+{
+ y_filetransfer *sf;
+ struct _sfs *s;
+
+ LOG(("[ext_yahoo_send_file7info] ident:%s, who: %s, ft_token: %s", me, who, ft_token));
+
+ sf = find_ft(ft_token, who);
+
+ if (sf == NULL) {
+ LOG(("ERROR: Can't find the token: %s in my file transfers list...", ft_token));
+ return;
+ }
+
+ s = (struct _sfs *) malloc( sizeof( struct _sfs ));
+
+ s->me = strdup(me);
+ s->token = strdup(token);
+ s->sf = sf;
+
+ YForkThread(&CYahooProto::send_filethread, s);
+}
+
+/**************** Send File ********************/
+
+void __cdecl CYahooProto::send_filethread(void *psf)
+{
+ struct _sfs *s = ( struct _sfs * )psf;
+ y_filetransfer *sf = s->sf;
+ struct yahoo_file_info *fi = (struct yahoo_file_info *)sf->files->data;
+
+ ProtoBroadcastAck(m_szModuleName, sf->hContact, ACKTYPE_FILE, ACKRESULT_CONNECTING, sf, 0);
+
+ LOG(("who %s, msg: %s, filename: %s filesize: %ld", sf->who, sf->msg, fi->filename, fi->filesize));
+
+ yahoo_send_file_y7(sf->id, s->me, sf->who, sf->relay, fi->filesize, s->token, &upload_file, sf);
+
+ FREE(s->me);
+ FREE(s->token);
+ FREE(s);
+
+ if (sf->pfts.currentFileNumber >= sf->pfts.totalFiles) {
+ free_ft(sf);
+ } else {
+ DebugLog("[yahoo_send_filethread] More files coming?");
+ }
+
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+// SendFile - sends a file
+
+HANDLE __cdecl CYahooProto::SendFile( HANDLE hContact, const PROTOCHAR* szDescription, PROTOCHAR** ppszFiles )
+{
+ DBVARIANT dbv;
+ y_filetransfer *sf;
+
+ LOG(("[YahooSendFile]"));
+
+ if ( !m_bLoggedIn )
+ return 0;
+
+ /*DebugLog("Getting Files");
+
+ if ( ppszFiles[1] != NULL ){
+ MessageBoxA(NULL, "YAHOO protocol allows only one file to be sent at a time", "Yahoo", MB_OK | MB_ICONINFORMATION);
+ return 0;
+ }
+
+ DebugLog("Getting Yahoo ID");
+ */
+
+ if (!DBGetContactSettingString(hContact, m_szModuleName, YAHOO_LOGINID, &dbv)) {
+ long tFileSize = 0;
+ struct _stat statbuf;
+ struct yahoo_file_info *fi;
+ YList *fs=NULL;
+ int i=0;
+ char *s;
+
+ while (ppszFiles[i] != NULL) {
+ if ( _tstat( ppszFiles[i], &statbuf ) == 0 )
+ tFileSize = statbuf.st_size;
+
+ fi = y_new(struct yahoo_file_info,1);
+
+ /**
+ * Need to use regular memory allocator/deallocator, since this is how things are build w/ libyahoo2
+ */
+ s = mir_utf8encodeT(ppszFiles[i]);
+ fi->filename = strdup(s);
+ mir_free(s);
+
+ fi->filesize = tFileSize;
+
+ fs = y_list_append(fs, fi);
+ i++;
+ }
+
+ sf = new_ft(this, m_id, hContact, dbv.pszVal, ( char* )szDescription,
+ NULL, NULL, 0, fs, 1 /* sending */);
+
+ DBFreeVariant(&dbv);
+
+ if (sf == NULL) {
+ DebugLog("SF IS NULL!!!");
+ return 0;
+ }
+
+ LOG(("who: %s, msg: %s, # files: %d", sf->who, sf->msg, i));
+ //mir_forkthread(yahoo_send_filethread, sf);
+
+ sf->ftoken=yahoo_ft7dc_send(m_id, sf->who, fs);
+
+ LOG(("Exiting SendRequest..."));
+
+ return sf;
+ }
+
+ LOG(("[/YahooSendFile]"));
+
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+// FileAllow - starts a file transfer
+
+HANDLE __cdecl CYahooProto::FileAllow( HANDLE /*hContact*/, HANDLE hTransfer, const PROTOCHAR* szPath )
+{
+ y_filetransfer *ft = (y_filetransfer *)hTransfer;
+ size_t len;
+
+ DebugLog("[YahooFileAllow]");
+
+ //LOG(LOG_INFO, "[%s] Requesting file from %s", ft->cookie, ft->user);
+ ft->pfts.tszWorkingDir = _tcsdup( szPath );
+
+ len = _tcslen(ft->pfts.tszWorkingDir) - 1;
+ if (ft->pfts.tszWorkingDir[len] == '\\')
+ ft->pfts.tszWorkingDir[len] = 0;
+
+ if (ft->y7) {
+ DebugLog("[YahooFileAllow] Trying to relay Y7 transfer.");
+ //void yahoo_ft7dc_accept(int id, const char *buddy, const char *ft_token);
+ yahoo_ft7dc_accept(ft->id, ft->who, ft->ftoken);
+
+ return hTransfer;
+ }
+
+ YForkThread(&CYahooProto::recv_filethread, ft);
+ return hTransfer;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+// FileCancel - cancels a file transfer
+
+int __cdecl CYahooProto::FileCancel( HANDLE /*hContact*/, HANDLE hTransfer )
+{
+ DebugLog("[YahooFileCancel]");
+
+ y_filetransfer* ft = (y_filetransfer*)hTransfer;
+
+ if (! (ft->pfts.flags & PFTS_SENDING) && ! ft->cancel) {
+ /* abort FT transfer */
+ yahoo_ft7dc_abort(ft->id, ft->who, ft->ftoken);
+ }
+
+ if ( ft->hWaitEvent != INVALID_HANDLE_VALUE )
+ SetEvent( ft->hWaitEvent );
+
+ ft->action = FILERESUME_CANCEL;
+ ft->cancel = 1;
+
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+// FileDeny - denies a file transfer
+
+int __cdecl CYahooProto::FileDeny( HANDLE /*hContact*/, HANDLE hTransfer, const PROTOCHAR* )
+{
+ /* deny file receive request.. just ignore it! */
+ y_filetransfer *ft = (y_filetransfer *)hTransfer;
+
+ DebugLog("[YahooFileDeny]");
+
+ if ( !m_bLoggedIn || ft == NULL ) {
+ DebugLog("[YahooFileDeny] Not logged-in or some other error!");
+ return 1;
+ }
+
+ if (ft->y7) {
+ DebugLog("[YahooFileDeny] Y7 Transfer detected.");
+ //void yahoo_ft7dc_accept(int id, const char *buddy, const char *ft_token);
+ yahoo_ft7dc_deny(ft->id, ft->who, ft->ftoken);
+ return 0;
+ }
+
+ if (ft->ftoken != NULL) {
+ struct yahoo_file_info *fi = (struct yahoo_file_info *)ft->files->data;
+
+ DebugLog("[YahooFileDeny] DC Detected: Denying File Transfer!");
+ yahoo_ftdc_deny(m_id, ft->who, fi->filename, ft->ftoken, 2);
+ }
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+// FileResume - processes file renaming etc
+
+int __cdecl CYahooProto::FileResume( HANDLE hTransfer, int* action, const PROTOCHAR** szFilename )
+{
+ y_filetransfer *ft = (y_filetransfer *)hTransfer;
+
+ DebugLog("[YahooFileResume] Action: %d", *action);
+
+ if ( !m_bLoggedIn || ft == NULL ) {
+ DebugLog("[YahooFileResume] Not loggedin or some other error!");
+ return 1;
+ }
+
+ ft->action = *action;
+
+ DebugLog("[YahooFileResume] Action: %d", *action);
+
+ if ( *action == FILERESUME_RENAME ) {
+ DebugLog("[YahooFileResume] Renamed file!");
+
+ FREE(ft->pfts.tszCurrentFile);
+ ft->pfts.tszCurrentFile = _tcsdup( *szFilename );
+ }
+
+ SetEvent( ft->hWaitEvent );
+ return 0;
+}
+