From e179ffc995c96568bfdce46ac73f58d569166f05 Mon Sep 17 00:00:00 2001 From: Kirill Volinsky Date: Sun, 14 Oct 2012 08:19:21 +0000 Subject: Yahoo: folders restructurization git-svn-id: http://svn.miranda-ng.org/main/trunk@1918 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/Yahoo/src/file_transfer.cpp | 901 ++++++++++++++++++++++++++++++++++ 1 file changed, 901 insertions(+) create mode 100644 protocols/Yahoo/src/file_transfer.cpp (limited to 'protocols/Yahoo/src/file_transfer.cpp') diff --git a/protocols/Yahoo/src/file_transfer.cpp b/protocols/Yahoo/src/file_transfer.cpp new file mode 100644 index 0000000000..be896a4363 --- /dev/null +++ b/protocols/Yahoo/src/file_transfer.cpp @@ -0,0 +1,901 @@ +/* + * $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 +#include + +#include "yahoo.h" +#include +#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) +{ + 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)); + + HANDLE hContact = getbuddyH(who); + if (hContact == NULL) + hContact = add_buddy(who, who, 0 /* NO FT for other IMs */, PALF_TEMPORARY); + + char fn[1024]; + 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"); + } + + yahoo_file_info *fi = y_new(struct yahoo_file_info,1); + fi->filename = strdup(fn); + fi->filesize = fesize; + + YList *files = NULL; + y_list_append(files, fi); + + y_filetransfer *ft = new_ft(this, m_id, hContact, who, msg, url, ft_token, y7, files, 0 /* downloading */); + if (ft == NULL) { + DebugLog("SF IS NULL!!!"); + return; + } + + TCHAR* ptszFileName = mir_a2t(fn); + + PROTORECVFILET pre = {0}; + pre.flags = PREF_TCHAR; + pre.fileCount = 1; + pre.timestamp = time(NULL); + pre.tszDescription = mir_a2t(msg); + pre.ptszFiles = &ptszFileName; + 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); + + mir_free(pre.tszDescription); + mir_free(ptszFileName); +} + +void CYahooProto::ext_got_files(const char *me, const char *who, const char *ft_token, int y7, YList* files) +{ + HANDLE hContact; + 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 */ + + } + + TCHAR* ptszFileName = mir_a2t(fn); + + PROTORECVFILET pre = {0}; + pre.flags = PREF_TCHAR; + pre.fileCount = 1; + pre.timestamp = time(NULL); + pre.tszDescription = _T(""); + pre.ptszFiles = &ptszFileName; + pre.lParam = (LPARAM)ft; + + CCSDATA ccs; + ccs.szProtoService = PSR_FILE; + ccs.hContact = ft->hContact; + ccs.wParam = 0; + ccs.lParam = (LPARAM)⪯ + CallService(MS_PROTO_CHAINRECV, 0, (LPARAM) & ccs); + + mir_free(ptszFileName); +} + +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 (!GetString(hContact, 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; +} + -- cgit v1.2.3