From 3634576b3903f8316b1dcdc396a70f40fa43f5f5 Mon Sep 17 00:00:00 2001 From: Vadim Dashevskiy Date: Wed, 18 Jul 2012 06:59:36 +0000 Subject: ExtraIcon, Favcontacts, FileAsMessage, FingerPrintModPlus: changed folder structure git-svn-id: http://svn.miranda-ng.org/main/trunk@1006 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/FileAsMessage/crc32.cpp | 31 - plugins/FileAsMessage/dialog.cpp | 1358 ------------------------ plugins/FileAsMessage/dialog.h | 120 --- plugins/FileAsMessage/fileecho.vcxproj | 23 +- plugins/FileAsMessage/fileecho.vcxproj.filters | 15 +- plugins/FileAsMessage/main.cpp | 326 ------ plugins/FileAsMessage/main.h | 57 - plugins/FileAsMessage/main.rc | 30 - plugins/FileAsMessage/optionsdlg.cpp | 112 -- plugins/FileAsMessage/res/resources.rc | 156 +++ plugins/FileAsMessage/resource.h | 45 - plugins/FileAsMessage/resources.rc | 156 --- plugins/FileAsMessage/src/crc32.cpp | 31 + plugins/FileAsMessage/src/dialog.cpp | 1358 ++++++++++++++++++++++++ plugins/FileAsMessage/src/dialog.h | 120 +++ plugins/FileAsMessage/src/main.cpp | 326 ++++++ plugins/FileAsMessage/src/main.h | 57 + plugins/FileAsMessage/src/optionsdlg.cpp | 112 ++ plugins/FileAsMessage/src/resource.h | 45 + 19 files changed, 2222 insertions(+), 2256 deletions(-) delete mode 100644 plugins/FileAsMessage/crc32.cpp delete mode 100644 plugins/FileAsMessage/dialog.cpp delete mode 100644 plugins/FileAsMessage/dialog.h delete mode 100644 plugins/FileAsMessage/main.cpp delete mode 100644 plugins/FileAsMessage/main.h delete mode 100644 plugins/FileAsMessage/main.rc delete mode 100644 plugins/FileAsMessage/optionsdlg.cpp create mode 100644 plugins/FileAsMessage/res/resources.rc delete mode 100644 plugins/FileAsMessage/resource.h delete mode 100644 plugins/FileAsMessage/resources.rc create mode 100644 plugins/FileAsMessage/src/crc32.cpp create mode 100644 plugins/FileAsMessage/src/dialog.cpp create mode 100644 plugins/FileAsMessage/src/dialog.h create mode 100644 plugins/FileAsMessage/src/main.cpp create mode 100644 plugins/FileAsMessage/src/main.h create mode 100644 plugins/FileAsMessage/src/optionsdlg.cpp create mode 100644 plugins/FileAsMessage/src/resource.h (limited to 'plugins/FileAsMessage') diff --git a/plugins/FileAsMessage/crc32.cpp b/plugins/FileAsMessage/crc32.cpp deleted file mode 100644 index ab34393f8d..0000000000 --- a/plugins/FileAsMessage/crc32.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#include "main.h" - -const ulong CRCPoly = 0xEDB88320; -ulong CRC32Table[256]; - -void InitCRC32() -{ - for (UINT32 i = 0; i < 256; i++) - { - UINT32 r = i; - for (int j = 0; j < 8; j++) - if (r & 1) - r = (r >> 1) ^ CRCPoly; - else - r >>= 1; - CRC32Table[i] = r; - } -} - -const ulong INITCRC = -1L; - -inline ulong UpdateCRC32(uchar val, ulong crc) -{ - return CRC32Table[(uchar)crc^val] ^ (crc>>8); -} - -ulong memcrc32(uchar *ptr, int size, ulong crc ) -{ - while(size--) crc = UpdateCRC32(*ptr++, crc); - return crc; -} diff --git a/plugins/FileAsMessage/dialog.cpp b/plugins/FileAsMessage/dialog.cpp deleted file mode 100644 index f038b87a33..0000000000 --- a/plugins/FileAsMessage/dialog.cpp +++ /dev/null @@ -1,1358 +0,0 @@ -#include"main.h" - -char *szFEMode[] = -{ - "Recv file", - "Send file" -}; - -#define USE_BUILDIN_BASE64 -// -// BASE64 encoding/decoding -// -#define Base64_GetDecodedBufferSize(cchEncoded) (((cchEncoded)>>2)*3) -#define Base64_GetEncodedBufferSize(cbDecoded) (((cbDecoded)*4+11)/12*4+1) -#ifdef USE_BUILDIN_BASE64 -#define Base64_Encode(nlb64) CallService(MS_NETLIB_BASE64ENCODE, 0, (LPARAM)nlb64) -#define Base64_Decode(nlb64) CallService(MS_NETLIB_BASE64DECODE, 0, (LPARAM)nlb64) -#else - -static char base64chars[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -#define Base64_Encode(nlb64) NetlibBase64Encode(0, (LPARAM)nlb64) -#define Base64_Decode(nlb64) NetlibBase64Decode(0, (LPARAM)nlb64) - -int NetlibBase64Encode(WPARAM wParam,LPARAM lParam) -{ - NETLIBBASE64 *nlb64=(NETLIBBASE64*)lParam; - int iIn; - char *pszOut; - PBYTE pbIn; - - if(nlb64==NULL || nlb64->pszEncoded==NULL || nlb64->pbDecoded==NULL) { - SetLastError(ERROR_INVALID_PARAMETER); - return 0; - } - if(nlb64->cchEncodedcbDecoded)) { - SetLastError(ERROR_BUFFER_OVERFLOW); - return 0; - } - nlb64->cchEncoded=Netlib_GetBase64EncodedBufferSize(nlb64->cbDecoded); - for(iIn=0,pbIn=nlb64->pbDecoded,pszOut=nlb64->pszEncoded;iIncbDecoded;iIn+=3,pbIn+=3,pszOut+=4) { - pszOut[0]=base64chars[pbIn[0]>>2]; - if(nlb64->cbDecoded-iIn==1) { - pszOut[1]=base64chars[(pbIn[0]&3)<<4]; - pszOut[2]='='; - pszOut[3]='='; - pszOut+=4; - break; - } - pszOut[1]=base64chars[((pbIn[0]&3)<<4)|(pbIn[1]>>4)]; - if(nlb64->cbDecoded-iIn==2) { - pszOut[2]=base64chars[(pbIn[1]&0xF)<<2]; - pszOut[3]='='; - pszOut+=4; - break; - } - pszOut[2]=base64chars[((pbIn[1]&0xF)<<2)|(pbIn[2]>>6)]; - pszOut[3]=base64chars[pbIn[2]&0x3F]; - } - pszOut[0]='\0'; - return 1; -} - -static BYTE Base64CharToInt(char c) -{ - if(c>='A' && c<='Z') return c-'A'; - if(c>='a' && c<='z') return c-'a'+26; - if(c>='0' && c<='9') return c-'0'+52; - if(c=='+') return 62; - if(c=='/') return 63; - if(c=='=') return 64; - return 255; -} - -int NetlibBase64Decode(WPARAM wParam,LPARAM lParam) -{ - NETLIBBASE64 *nlb64=(NETLIBBASE64*)lParam; - char *pszIn; - PBYTE pbOut; - BYTE b1,b2,b3,b4; - int iIn; - - if(nlb64==NULL || nlb64->pszEncoded==NULL || nlb64->pbDecoded==NULL) { - SetLastError(ERROR_INVALID_PARAMETER); - return 0; - } - if(nlb64->cchEncoded&3) { - SetLastError(ERROR_INVALID_DATA); - return 0; - } - if(nlb64->cbDecodedcchEncoded)) { - SetLastError(ERROR_BUFFER_OVERFLOW); - return 0; - } - nlb64->cbDecoded=Netlib_GetBase64DecodedBufferSize(nlb64->cchEncoded); - for(iIn=0,pszIn=nlb64->pszEncoded,pbOut=nlb64->pbDecoded;iIncchEncoded;iIn+=4,pszIn+=4,pbOut+=3) { - b1=Base64CharToInt(pszIn[0]); - b2=Base64CharToInt(pszIn[1]); - b3=Base64CharToInt(pszIn[2]); - b4=Base64CharToInt(pszIn[3]); - if(b1==255 || b1==64 || b2==255 || b2==64 || b3==255 || b4==255) { - SetLastError(ERROR_INVALID_DATA); - return 0; - } - pbOut[0]=(b1<<2)|(b2>>4); - if(b3==64) {nlb64->cbDecoded-=2; break;} - pbOut[1]=(b2<<4)|(b3>>2); - if(b4==64) {nlb64->cbDecoded--; break;} - pbOut[2]=b4|(b3<<6); - } - return 1; -} -#endif - -char* ltoax(char* s, DWORD value) -{ - if(value == 0) - { - *s++ = '0'; - } - uchar data; - int indx = 8; - while(indx && !(data = (uchar)(value >> 28) & 0x0F)) - { - value <<= 4; - indx--; - } - while(indx) - { - data = (uchar)(value >> 28) & 0x0F; - if(data > 9) data += 'A' - 10; - else data += '0'; - *s++ = data; - value <<= 4; - indx--; - } - return s; -} -uint atolx(char* &value) -{ - uint result = 0; - uchar ch; - - while( *value && (ch = *value - '0') >= 0 ) - { - if(ch > 9) - { - ch -= 'A' - '0'; - if(ch > 5) break; - ch += 10; - } - result = result * 16 + ch; - value++; - } - return result; -} - -char cCmdList[CMD_COUNT] = -{ - '?', - '+', - '-', - - '*', - - '>', - '!', - '.' -}; - -static int CALLBACK PopupDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - HANDLE hContact = PUGetContact(hWnd); - HWND hDlg = (HWND)PUGetPluginData(hWnd); -/* - if(hContact) - { - CLISTEVENT *lpcle; - int indx = 0; - for(;;) - { - if((lpcle = (CLISTEVENT*)CallService(MS_CLIST_GETEVENT, (WPARAM)hContact, indx)) == NULL) - break; - if(lstrcmp(lpcle->pszService, SERVICE_NAME "/FERecvFile") == 0) - { - lpcle->lParam = (LPARAM)hWnd; - break; - } - indx++; - } - } -*/ - switch(message) { - case WM_COMMAND: - { - PUDeletePopUp(hWnd); - CallService(MS_CLIST_REMOVEEVENT, (WPARAM)hContact, (LPARAM)0); - - if(IsWindow(hDlg)) - { - ShowWindow(hDlg, SW_SHOWNORMAL); - SetForegroundWindow(hDlg); - SetFocus(hDlg); - } - - break; - } - case WM_CONTEXTMENU: - PUDeletePopUp(hWnd); - break; - case UM_FREEPLUGINDATA: - return TRUE; //TRUE or FALSE is the same, it gets ignored. - default: - break; - } - return DefWindowProc(hWnd, message, wParam, lParam); -} -// -// Just create simple Popup for specified contact -// -void MakePopupMsg(HWND hDlg, HANDLE hContact, char *msg) -{ - HWND hFocused = GetForegroundWindow(); - if(hDlg == hFocused || hDlg == GetParent(hFocused)) return; - - POPUPDATAEX ppd; - // - //The text for the second line. You could even make something like: char lpzText[128]; lstrcpy(lpzText, "Hello world!"); It's your choice. - // - ZeroMemory(&ppd, sizeof(ppd)); //This is always a good thing to do. - ppd.lchContact = (HANDLE)hContact; //Be sure to use a GOOD handle, since this will not be checked. - ppd.lchIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_SMALLICON)); - lstrcpy(ppd.lpzContactName, (char *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, 0)); - lstrcpy(ppd.lpzText, msg); - ppd.colorBack = GetSysColor(COLOR_INFOBK); - ppd.colorText = GetSysColor(COLOR_INFOTEXT); - ppd.PluginWindowProc = (WNDPROC)PopupDlgProc; - ppd.PluginData = (void*)hDlg; - ppd.iSeconds = -1; - - CallService(MS_POPUP_ADDPOPUPEX, (WPARAM)&ppd, 0); -} -// -// Get ID of string message -// -int getMsgId(char *msg) -{ - for(int indx = 0; indx < CMD_COUNT; indx++) - { - if(*msg == cCmdList[indx]) return indx; - } - return -1; -}; - -int RetrieveFileSize(char *filename) -{ - int handle = open(filename, O_RDONLY|O_BINARY,0); - if(handle != -1) - { - int size = filelength(handle); - close(handle); - return size; - } - return handle; -} - -FILEECHO::FILEECHO(HANDLE Contact) -{ - hContact = Contact; - dwSendInterval = DBGetContactSettingDword(NULL, SERVICE_NAME, "SendDelay", 6000); - //dwChunkSize = DBGetContactSettingDword(NULL, SERVICE_NAME, "ChunkSize", 5000); - - chunkMaxLen = DBGetContactSettingDword(NULL, SERVICE_NAME, "ChunkSize", 5000); - chunkCount = 0; - filename = NULL; - - rgbRecv = DBGetContactSettingDword(NULL, SERVICE_NAME, "colorRecv", RGB(64,255,64)); - rgbSent = DBGetContactSettingDword(NULL, SERVICE_NAME, "colorSent", RGB(255,255,64)); - rgbUnSent = DBGetContactSettingDword(NULL, SERVICE_NAME, "colorUnsent", RGB(128,128,128)); - rgbToSend = DBGetContactSettingDword(NULL, SERVICE_NAME, "colorTosend", RGB(192,192,192)); - asBinary = DBGetContactSettingDword(NULL, SERVICE_NAME, "base64", 1) == 0; -} - -uint controlEnabled[][2] = -{ - IDC_PLAY, - STATE_OPERATE|STATE_PAUSED|STATE_PRERECV|STATE_ACKREQ|STATE_IDLE, - IDC_STOP, - STATE_OPERATE|STATE_PAUSED|STATE_PRERECV|STATE_REQSENT|STATE_ACKREQ, -// IDC_FILENAME, -// STATE_IDLE|STATE_PRERECV|STATE_FINISHED|STATE_CANCELLED, -// IDC_BROWSE, -// STATE_IDLE|STATE_PRERECV|STATE_FINISHED|STATE_CANCELLED, -}; -/* -char *stateMsg[][2] = -{ - (char*)STATE_IDLE,"Idle", - (char*)STATE_REQSENT,"ReqSent", - (char*)STATE_PRERECV,"PreRecv", - (char*)STATE_OPERATE,"Operate", - (char*)STATE_ACKREQ,"AckReq", - (char*)STATE_CANCELLED,"Cancelled", - (char*)STATE_FINISHED,"Finished", - (char*)STATE_PAUSED,"Paused" -}; -*/ - -char *hint_controls[4] = { - "Perform", - "Pause", - "Revive a transfer", - "Stop" -}; - -void FILEECHO::setState(DWORD state) -{ - iState = state; - int indx; - - for(indx = 0; indx < SIZEOF(controlEnabled); indx++) - { - EnableWindow(GetDlgItem(hDlg, controlEnabled[indx][0]), (iState & controlEnabled[indx][1]) != 0); - } - - if(!inSend) // recv - { - int kind; - SendDlgItemMessage(hDlg, IDC_FILENAME, EM_SETREADONLY, (state != STATE_PRERECV), 0); - EnableWindow(GetDlgItem(hDlg, IDC_BROWSE), (iState & (STATE_PRERECV|STATE_FINISHED))); - //SendDlgItemMessage(hDlg, IDC_FILENAME, EM_SETREADONLY, (iState & STATE_PRERECV) == 0, 0); - //EnableWindow(GetDlgItem(hDlg, IDC_FILENAME), (iState == STATE_PRERECV)); - //EnableWindow(GetDlgItem(hDlg, IDC_FILENAME), (iState & STATE_IDLE|STATE_PRERECV|STATE_FINISHED|STATE_CANCELLED) != 0); - if(state & (STATE_IDLE|STATE_FINISHED|STATE_CANCELLED|STATE_PRERECV)) - kind = ICON_PLAY; - else - kind = ICON_REFRESH; - SendDlgItemMessage(hDlg, IDC_PLAY,BM_SETIMAGE,IMAGE_ICON,(LPARAM)hIcons[kind]); - SendDlgItemMessage(hDlg, IDC_PLAY, BUTTONADDTOOLTIP,(WPARAM)Translate(hint_controls[kind]),0); - } - else - { - SendDlgItemMessage(hDlg, IDC_FILENAME, EM_SETREADONLY, (iState & (STATE_IDLE|STATE_FINISHED|STATE_CANCELLED)) == 0, 0); - EnableWindow(GetDlgItem(hDlg, IDC_BROWSE), (iState & (STATE_IDLE|STATE_FINISHED|STATE_CANCELLED)) != 0); - //EnableWindow(GetDlgItem(hDlg, IDC_FILENAME), (iState & STATE_IDLE|STATE_PRERECV|STATE_FINISHED|STATE_CANCELLED) != 0); - switch(state) - { - case STATE_FINISHED: - case STATE_CANCELLED: - case STATE_IDLE: - case STATE_PAUSED: - EnableWindow(GetDlgItem(hDlg, IDC_PLAY), TRUE); - SendDlgItemMessage(hDlg, IDC_PLAY, BM_SETIMAGE,IMAGE_ICON,(LPARAM)hIcons[ICON_PLAY]); - SendDlgItemMessage(hDlg, IDC_PLAY, BUTTONADDTOOLTIP,(WPARAM)Translate(hint_controls[ICON_PLAY]),0); - break; - case STATE_OPERATE: - SendDlgItemMessage(hDlg, IDC_PLAY, BM_SETIMAGE,IMAGE_ICON,(LPARAM)hIcons[ICON_PAUSE]); - SendDlgItemMessage(hDlg, IDC_PLAY, BUTTONADDTOOLTIP,(WPARAM)Translate(hint_controls[ICON_PAUSE]),0); - break; - } - } - updateProgress(); -} - -void FILEECHO::updateTitle() -{ - char newtitle[256], *contactName; - - contactName=(char*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME,(WPARAM)hContact,0); - if(iState == STATE_OPERATE && chunkCount != 0) - _snprintf(newtitle,sizeof(newtitle),"%d%% - %s: %s",chunkSent * 100 / chunkCount, Translate(szFEMode[inSend]), contactName); - else - _snprintf(newtitle,sizeof(newtitle),"%s: %s",Translate(szFEMode[inSend]), contactName); - SetWindowText(hDlg, newtitle); -} - -void BuildFreqTable(uchar *data, uint len, uint *freqTable) -{ - ZeroMemory(freqTable, 256*sizeof(uint)); - for(uint indx = 0; indx < len; indx++) - freqTable[data[indx]]++; -} - -int FILEECHO::createTransfer() -{ - uint LastError; - hFile = INVALID_HANDLE_VALUE; - hMapping = NULL; - lpData = NULL; -#ifdef DEBUG - overhead = 0; -#endif - hFile = CreateFile(filename, inSend?GENERIC_READ:(GENERIC_READ|GENERIC_WRITE), inSend?FILE_SHARE_READ:0, - NULL, inSend?OPEN_EXISTING:(DBGetContactSettingByte(NULL,"SRFile","AutoAccept",0)?CREATE_ALWAYS:CREATE_NEW), FILE_ATTRIBUTE_NORMAL, NULL); - if(hFile == INVALID_HANDLE_VALUE && !inSend && GetLastError() == ERROR_FILE_EXISTS) - { - if(MessageBox(hDlg, Translate("File already exists. Overwrite?"), - Translate(SERVICE_TITLE), - MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON2) != IDYES) return 0; - hFile = CreateFile(filename, GENERIC_READ|GENERIC_WRITE, 0, - NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - - } - if(hFile == INVALID_HANDLE_VALUE) goto createTransfer_FAILED; - if(!inSend) - { - SetFilePointer(hFile, fileSize, NULL, FILE_CURRENT); - SetEndOfFile(hFile); - } - else - fileSize = GetFileSize(hFile, NULL); - hMapping = CreateFileMapping(hFile, NULL, inSend?PAGE_READONLY:PAGE_READWRITE, - 0, fileSize, NULL); - LastError = GetLastError(); - if(hMapping == NULL) goto createTransfer_FAILED; - lpData = (uchar*)MapViewOfFile(hMapping, inSend?FILE_MAP_READ:FILE_MAP_WRITE, 0,0,0); - LastError = GetLastError(); - if(lpData == NULL) goto createTransfer_FAILED; - - if(inSend) - // - // frequency analysis of source file - // and building the table of offsets - // - { - if(asBinary) - { - uint freq_table[256]; - uchar *data; - uint len, chunk_offset, chunk_size, out_size, indx; - int chunk_count_limit; - - codeSymb = 1; - // - // searching for symbol with lowest frequency: "codeSymb" - // - BuildFreqTable(lpData, fileSize, freq_table); - for(int indx = codeSymb+1; indx < 256; indx++) - { - if(freq_table[codeSymb] > freq_table[indx]) codeSymb = indx; - } - //DEBUG - //codeSymb = ':'; - - // - // calculating chunks sizes - // build table of chunks offsets: chunkPos - // - chunk_count_limit = 2*fileSize/chunkMaxLen+2; - chunkPos = (uint*)malloc(sizeof(uint)*chunk_count_limit); - data = lpData; - chunk_size = 0; out_size = 0; indx = 0; chunk_offset = 0; - for(len = fileSize; len; len--) - { - if(*data == 0 || *data == codeSymb) - out_size += 2; - else - out_size++; - - data++; chunk_size++; - if(out_size >= chunkMaxLen-1) - { - chunkPos[indx] = chunk_offset; chunk_offset += chunk_size; - chunk_size = 0; out_size = 0; - indx++; - } - } - chunkPos[indx++] = chunk_offset; chunkCount = indx; - chunkPos = (uint*)realloc(chunkPos, sizeof(uint)*(chunkCount+1)); - chunkPos[indx] = chunk_offset + chunk_size; - } - else - { - int EncodedMaxLen = Base64_GetEncodedBufferSize(Base64_GetDecodedBufferSize(chunkMaxLen)); - int DecodedMaxLen = Base64_GetDecodedBufferSize(EncodedMaxLen); - int indx = 0; - - codeSymb = '-'; - chunkCount = (fileSize + DecodedMaxLen - 1) / DecodedMaxLen; - chunkPos = (uint*)malloc(sizeof(uint)*(chunkCount+1)); - for(uint chunk_offset = 0, indx = 0; indx < chunkCount; indx++, chunk_offset += DecodedMaxLen) - chunkPos[indx] = chunk_offset; - chunkPos[indx] = chunkPos[indx-1] + fileSize%DecodedMaxLen; - } - } - else - chunkCount = chunkCountx; - chunkAck = (uchar*)malloc(sizeof(uchar)*chunkCount); - memset(chunkAck, 0, sizeof(uchar)*chunkCount); - - chunkIndx = 0; chunkSent = 0; - - return 1; -createTransfer_FAILED: - if(lpData != NULL) UnmapViewOfFile(lpData); - if(hMapping != NULL) CloseHandle(hMapping); - if(hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile); - return 0; -} - -void FILEECHO::destroyTransfer() -{ - if(chunkCount) - { - chunkCount = 0; - if(inSend) - free(chunkPos); - free(chunkAck); - if(lpData != NULL) UnmapViewOfFile(lpData); - if(hMapping != NULL) CloseHandle(hMapping); - if(hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile); - } - //setState(STATE_IDLE); - return; -} - -void FILEECHO::sendReq() -{ - - char sendbuf[MAX_PATH]; - - if(!createTransfer()) - { - SetDlgItemText(hDlg, IDC_FILESIZE, Translate("Couldn't open a file")); - return; - } - ///!!!!!!! - char *p = filename + strlen(filename); - while(p != filename && *p != '\\') - p--; - if(*p == '\\') - strcpy(filename,p+1); - - _snprintf(sendbuf, sizeof(sendbuf), Translate("Size: %d bytes"), fileSize); - SetDlgItemText(hDlg, IDC_FILESIZE, sendbuf); - _snprintf(sendbuf, sizeof(sendbuf), "?%c%c%d:%d " NOPLUGIN_MESSAGE, asBinary+'0', codeSymb, chunkCount, fileSize); - sendCmd(0, CMD_REQ, sendbuf, filename); - - SetDlgItemText(hDlg, IDC_STATUS, Translate("Request sent. Awaiting of acceptance..")); - setState(STATE_REQSENT); -} -void FILEECHO::incomeRequest(char *param) -{ - // param: filename?cCOUNT:SIZE - char buf[MAX_PATH]; - // param == &filename - char *p = strchr(param, '?'); - if(p == NULL) return; *p++ = 0; - CallService(MS_FILE_GETRECEIVEDFILESFOLDER, (WPARAM)hContact, (LPARAM)buf); - strncat(buf, param, sizeof(buf)); - if(filename) free(filename); - filename = strdup(buf); - // p == &c - if(*p == 0) return; asBinary = (*p++) != '0'; - if(*p == 0) return; codeSymb = *p++; - // p == &COUNT - if(*p == 0) return; param = strchr(p, ':'); - // param == &SIZE - if(param == NULL) return; *param++ = 0; - if(*param == 0) return; - chunkCountx = atoi(p); - fileSize = atoi(param); - - _snprintf(buf, sizeof(buf), Translate("Size: %d bytes"), fileSize); - SetDlgItemText(hDlg, IDC_FILENAME, filename); - SetDlgItemText(hDlg, IDC_FILESIZE, buf); - - setState(STATE_PRERECV); - inSend = FALSE; - - SkinPlaySound("RecvFile"); - int AutoMin = DBGetContactSettingByte(NULL,"SRFile","AutoMin",0); - if(DBGetContactSettingByte(NULL,"SRFile","AutoAccept",0) && !DBGetContactSettingByte((HANDLE)hContact,"CList","NotOnList",0)) - { - PostMessage(hDlg, WM_COMMAND, IDC_PLAY, 0); - if(AutoMin) - ShowWindow(hDlg, SW_SHOWMINIMIZED); -// ShowWindow(hDlg, SW_MINIMIZE); -// UpdateWindow(hDlg); - } -// else - if(!IsWindowVisible(hDlg) && !AutoMin) - { - CLISTEVENT cle; - ZeroMemory(&cle, sizeof(cle)); - cle.cbSize = sizeof(cle); - cle.hContact = hContact; - cle.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_SMALLICON)); - cle.flags = CLEF_URGENT; - cle.hDbEvent = 0; - cle.pszService = SERVICE_NAME "/FERecvFile"; - CallService(MS_CLIST_ADDEVENT, 0, (LPARAM)&cle); - - MakePopupMsg(hDlg, hContact, "Incoming file..."); - } -} - -void FILEECHO::cmdACCEPT() -{ - if(chunkCount == 0) return; - setState(STATE_OPERATE); - SetDlgItemText(hDlg, IDC_STATUS, Translate("Sending...")); - lastTimestamp = GetTickCount(); - //PostMessage(hDlg, WM_TIMER, 0,0); - //onSendTimer(); - SetTimer(hDlg, TIMER_SEND, dwSendInterval, 0); -} - -void FILEECHO::updateProgress() -{ - InvalidateRect(GetDlgItem(hDlg, IDC_PROGRESS), NULL, TRUE); - updateTitle(); -} -// -// called in receive mode -// used to transfer acknowledge -// -void FILEECHO::onRecvTimer() -{ - if(chunkCount == 0) return; - char *buffer = (char*)malloc(1024); - char *p = buffer; - uchar prev_value; - uint indx, jndx; - - KillTimer(hDlg, TIMER_SEND); - // - // Build response about successfully received chunks - // - indx = jndx = 0; prev_value = chunkAck[jndx]; - while(jndx < chunkCount) - { - if(chunkAck[jndx] != prev_value) - { - if(prev_value != CHUNK_ACK) - { - p = ltoax(p, indx); - if(indx != jndx-1) - { - *p++ = '-'; - p = ltoax(p, jndx-1); - } - *p++ = ','; - } - indx = jndx; - prev_value = chunkAck[jndx]; - } - jndx++; - } - if(prev_value != CHUNK_ACK) - { - p = ltoax(p, indx); - if(indx != jndx-1) - { - *p++ = '-'; - p = ltoax(p, jndx-1); - } - } - *p = 0; - if(*buffer == 0) - { - char *msg = Translate("Received successfully"); - SetDlgItemText(hDlg, IDC_STATUS, msg); - MakePopupMsg(hDlg, hContact, msg); - setState(STATE_FINISHED); - if(DBGetContactSettingByte(NULL,"SRFile","AutoClose",0)) - { - PostMessage(hDlg, WM_CLOSE, 0,0); - CallService(MS_CLIST_REMOVEEVENT, (WPARAM)hContact, (LPARAM)0); - } - SkinPlaySound("FileDone"); - destroyTransfer(); - buffer[0] = 'x'; buffer[1] = 0; - } - sendCmd(0, CMD_DACK, buffer); - free(buffer); - //if(iState != STATE_FINISHED) SetTimer(hDlg, TIMER_SEND, lastDelay*2, 0); -} -// -// called in sending mode -// used to data transfer and -// sending of scheduled commands -// -void FILEECHO::onSendTimer() -{ - if(chunkCount == 0) return; - // - // perform request of acknowledge, if scheduled - // - KillTimer(hDlg, TIMER_SEND); - // - // Search for next unsent chunk - // - while(chunkIndx < chunkCount && chunkAck[chunkIndx] != CHUNK_UNSENT) chunkIndx++; - if(iState == STATE_ACKREQ || chunkIndx == chunkCount) - { - SetDlgItemText(hDlg, IDC_STATUS, Translate("Requesting of missing chunks")); - setState(STATE_OPERATE); - sendCmd(0, CMD_END, "", NULL); - chunkIndx = chunkCount+1; - return; - } - if(chunkIndx > chunkCount) return; - - uchar *buffer = (uchar*)malloc(chunkMaxLen*2); - uchar *p = buffer; - uchar *data = lpData + chunkPos[chunkIndx]; - uchar *data_end = lpData + chunkPos[chunkIndx+1]; - ulong chksum = memcrc32(data, data_end - data, INITCRC); - - if(asBinary) - { - // - // Encoding data to transfer with symb. filtering - // - while(data < data_end) - { - uchar ch = *data++; - if(ch == 0) - { - *p++ = codeSymb; *p++ = '0'; - } - else if (ch == codeSymb) - { - *p++ = codeSymb; *p++ = '+'; - } - else - *p++ = ch; - } - *p = 0; - } - else - { - NETLIBBASE64 nlb; - - nlb.pbDecoded = data; - nlb.cbDecoded = data_end - data; - nlb.pszEncoded = (char*)buffer; - nlb.cchEncoded = chunkMaxLen*2; - - Base64_Encode(&nlb); - } - - char prefix[128]; - _snprintf(prefix, sizeof(prefix), "%X,%X,%X>", chunkIndx+1, chunkPos[chunkIndx], chksum); -#ifdef DEBUG - overhead += lstrlen((char*)buffer); -#endif - sendCmd(0, CMD_DATA, (char*)buffer, (char*)prefix); - chunkAck[chunkIndx] = CHUNK_SENT; - - free(buffer); - - chunkIndx++; chunkSent++; - - if(chunkIndx == chunkCount) - setState(STATE_ACKREQ); - else - { - SetDlgItemText(hDlg, IDC_STATUS, Translate("Sending...")); - updateProgress(); - } - SetTimer(hDlg, TIMER_SEND, dwSendInterval, 0); -} -void FILEECHO::cmdDATA(char *param) -{ - if(chunkCount == 0) return; - chunkIndx = atolx(param); param++; - if(chunkIndx-- == 0) return; - uint filepos = atolx(param); param++; - if(filepos >= fileSize) return; - - ulong chksum_local; - ulong chksum_remote = atolx(param); param++; - - KillTimer(hDlg, TIMER_SEND); - - // - // Decoding of incoming data - // - uchar *data = lpData + filepos; - uchar *data_end = lpData + fileSize; - if(asBinary) - { - uchar ch; - while(ch = *param++) - { - if(ch == codeSymb) - { - if((ch = *param++) == 0) goto cmdDATA_corrupted; - switch(ch) - { - case '+': - ch = codeSymb; - break; - case '0': - ch = 0; - break; - default: - goto cmdDATA_corrupted; - } - } - if(data > data_end) goto cmdDATA_corrupted; - *data++ = ch; - } - } - else - { - NETLIBBASE64 nlb; - uchar *temp_buffer; - - nlb.pszEncoded = param; - nlb.cchEncoded = (int)_tcslen(param); - temp_buffer = (uchar*)malloc(nlb.cchEncoded); - nlb.pbDecoded = temp_buffer; - nlb.cbDecoded = nlb.cchEncoded; - - Base64_Decode(&nlb); - memcpy(data, temp_buffer, min(nlb.cbDecoded, data_end - data)); - data += nlb.cbDecoded; - } - // - // let's check it up - // - chksum_local = memcrc32(lpData + filepos, data - (lpData + filepos), INITCRC); - if(chksum_local == chksum_remote) - { - if(chunkAck[chunkIndx] != CHUNK_ACK) chunkSent++; - chunkAck[chunkIndx] = CHUNK_ACK; - //chunkPos[chunkIndx++] = filepos; - } - SetDlgItemText(hDlg, IDC_STATUS, Translate("Receiving...")); - updateProgress(); -cmdDATA_corrupted: - //SetTimer(hDlg, TIMER_SEND, lastDelay*2, 0); - ; -} -void FILEECHO::cmdEND() -{ - SetTimer(hDlg, TIMER_SEND, dwSendInterval, 0); -} -void FILEECHO::cmdDACK(char *param) -{ - uint indx, jndx; - - if(chunkCount == 0) return; - memset(chunkAck, CHUNK_ACK, sizeof(uchar)*chunkCount); - if(*param == 'x') - // - // All chunks has been received successfully - // - { -#ifdef DEBUG - char msg[100]; - - _snprintf(msg, sizeof(msg), "overhead: %d", overhead); - SetDlgItemText(hDlg, IDC_STATUS, msg); -#else - char *msg = Translate("Sent successfully"); - SetDlgItemText(hDlg, IDC_STATUS, msg); -#endif - SkinPlaySound("FileDone"); - destroyTransfer(); - MakePopupMsg(hDlg, hContact, msg); - setState(STATE_FINISHED); - return; - } - chunkSent = chunkCount; - // - // Mark chunks to re-transfer, - // according received info - // - // format: chunk1, chunk3-chunk10, etc.. - // - while(*param) - { - indx = atolx(param); - if(*param == '-') - { - param++; jndx = atolx(param); - } - else - jndx = indx; - if(*param == 0 || *param == ',') - { - for(uint p = indx; p <= jndx; p++) - { - if(p < chunkCount) - { - chunkAck[p] = CHUNK_UNSENT; - chunkSent--; - } - } - if(*param == ',') - param++; - } - } - updateProgress(); - - // - // retransfer some parts - // - chunkIndx = 0; - SetTimer(hDlg, TIMER_SEND, dwSendInterval, 0); -} - -void FILEECHO::perform(char *str) -{ - int msgId = getMsgId(str); - if(msgId == -1) - { - MakePopupMsg(hDlg, hContact, Translate("Unknown command for \"" SERVICE_TITLE "\" was received")); - return; - } - if(inSend) - switch(msgId) - { - case CMD_REQ: - if(MessageBox(hDlg, Translate("Incoming file request. Do you want proceed?"), - Translate(SERVICE_TITLE), MB_YESNO | MB_ICONWARNING) == IDYES) - { - SetDlgItemText(hDlg, IDC_STATUS, ""); - SendMessage(hDlg, WM_COMMAND, IDC_STOP, 0); - - incomeRequest(str+1); - updateTitle(); - break; - } - break; - case CMD_ACCEPT: - cmdACCEPT(); - break; - case CMD_CANCEL: - { - if(iState & (STATE_PRERECV|STATE_REQSENT|STATE_OPERATE|STATE_ACKREQ|STATE_PAUSED)) - { - char *msg = Translate("Cancelled by remote user"); - SetDlgItemText(hDlg, IDC_STATUS, msg); - MakePopupMsg(hDlg, hContact, msg); - destroyTransfer(); - setState(STATE_CANCELLED); - } - break; - } - case CMD_DACK: - cmdDACK(str+1); - break; - } - else - switch(msgId) - { - case CMD_CANCEL: - { - if(iState & (STATE_PRERECV|STATE_REQSENT|STATE_OPERATE|STATE_ACKREQ|STATE_PAUSED)) - { - char *msg = Translate("Cancelled by remote user"); - SetDlgItemText(hDlg, IDC_STATUS, msg); - MakePopupMsg(hDlg, hContact, msg); - destroyTransfer(); - setState(STATE_CANCELLED); - } - break; - } - case CMD_REQ: - if(chunkCount) - { - if(MessageBox(hDlg, Translate("New incoming file request. Do you want proceed?"), - Translate(SERVICE_TITLE), MB_YESNO | MB_ICONWARNING) != IDYES) - break; - //sendCmd(0, CMD_CANCEL, "", NULL); - destroyTransfer(); - } - SetDlgItemText(hDlg, IDC_STATUS, ""); - incomeRequest(str+1); - break; - case CMD_DATA: - cmdDATA(str+1); - break; - case CMD_END: - cmdEND(); - break; - }; -}; - -int FILEECHO::sendCmd(int id, int cmd, char *szParam, char *szPrefix) -{ - char *buf; - int retval; - int buflen = (int)_tcslen(szServicePrefix) + (int)_tcslen(szParam) + 2; - if(szPrefix != NULL) - buflen += (int)_tcslen(szPrefix); - - buf = (char*)malloc(buflen); - if(szPrefix == NULL) - _snprintf(buf,buflen,"%s%c%s", szServicePrefix, cCmdList[cmd], szParam); - else - _snprintf(buf,buflen,"%s%c%s%s", szServicePrefix, cCmdList[cmd], szPrefix, szParam); - retval = CallContactService(hContact, PSS_MESSAGE, 0, (LPARAM)buf); - free(buf); - updateProgress(); - return retval; -} - - -void CreateDirectoryTree(char *szDir) -{ - DWORD dwAttributes; - char *pszLastBackslash,szTestDir[MAX_PATH]; - - lstrcpyn(szTestDir,szDir,sizeof(szTestDir)); - if((dwAttributes=GetFileAttributes(szTestDir))!=0xffffffff - && dwAttributes&FILE_ATTRIBUTE_DIRECTORY) return; - pszLastBackslash=strrchr(szTestDir,'\\'); - if(pszLastBackslash==NULL) {GetCurrentDirectory(MAX_PATH,szDir); return;} - *pszLastBackslash='\0'; - CreateDirectoryTree(szTestDir); - CreateDirectory(szTestDir,NULL); -} - -void SubclassWnd(HWND hwnd, WNDPROC lpfnWndProc) -{ - SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG)GetWindowLongPtr(hwnd, GWLP_WNDPROC)); - SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG)lpfnWndProc); -} -#define CallSubclassed(hwnd, uMsg, wParam, lParam)\ - CallWindowProc((WNDPROC)GetWindowLongPtr(hwnd, GWLP_USERDATA), hwnd, uMsg, wParam, lParam) - -LRESULT CALLBACK ProgressWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch(uMsg) - { - case WM_NCPAINT: - return 0; - case WM_PAINT: - { - HDC hdc; - PAINTSTRUCT ps; - RECT rc; - HRGN hrgn; - HBRUSH frameBrush = (HBRUSH)GetStockObject(BLACK_BRUSH); - struct FILEECHO *dat; - - dat = (struct FILEECHO*)GetWindowLongPtr(GetParent(hwnd), GWLP_USERDATA); - //if(dat == NULL) - // return CallSubclassed(hwnd, uMsg, wParam, lParam); - GetClientRect(hwnd, &rc); - if(dat == NULL || dat->chunkCount == 0) - { - COLORREF colour; - HBRUSH hbr; - - if(dat == NULL || dat->iState != STATE_FINISHED) - { - hbr = (HBRUSH)(COLOR_3DFACE+1); - } - else - { - colour = dat->rgbRecv; - hbr = CreateSolidBrush(colour); - } - hdc=BeginPaint(hwnd,&ps); - FillRect(hdc, &rc, hbr); - FrameRect(hdc, &rc, frameBrush); - if(hbr != (HBRUSH)(COLOR_3DFACE+1)) - DeleteObject(hbr); - EndPaint(hwnd,&ps); - return 0; - } - - hrgn = CreateRectRgn(rc.left, rc.top, rc.right, rc.bottom); - - hdc=BeginPaint(hwnd,&ps); - SelectClipRgn(hdc, hrgn); - - RECT rc2 = rc; - //uint sliceWidth = (rc.right - rc.left) / dat->chunkCount; - float sliceWidth = (float)((float)(rc.right - rc.left) / (float)dat->chunkCount); - float dx = (float)rc2.left; - for(uint indx = 0; indx < dat->chunkCount; indx++) - { - HBRUSH hbr; - COLORREF colour; - if(dat->inSend && indx == dat->chunkIndx) - colour = dat->rgbToSend; - else - switch(dat->chunkAck[indx]) - { - case CHUNK_UNSENT: - colour = dat->rgbUnSent; - break; - case CHUNK_SENT: - colour = dat->rgbSent; - break; - case CHUNK_ACK: - colour = dat->rgbRecv; - break; - } - /* - if(indx == 5) colour = RGB(255,64,64); - else if(indx < 2) colour = RGB(64,255,64); - else if(indx < 4) colour = RGB(255,255,64); - else colour = RGB(128,128,128); - //*/ - if(indx == dat->chunkCount-1) - rc2.right = rc.right; - hbr = CreateSolidBrush(colour); - rc2.left = (int)dx; - rc2.right = (int)(dx + sliceWidth); - FillRect(hdc, &rc2, hbr); - FrameRect(hdc, &rc2, frameBrush); - DeleteObject(hbr); - dx += sliceWidth-1; - } - if(rc2.right < rc.right) - { - rc2.left = rc2.right; - rc2.right = rc.right; - FillRect(hdc, &rc2, (HBRUSH)(COLOR_3DFACE+1)); - } - //FrameRect(hdc, &rc, (HBRUSH)(COLOR_3DLIGHT+1)); - //OffsetRect(&rc, 1,1); - //FrameRect(hdc, &rc, (HBRUSH)(COLOR_BTNTEXT+1)); - //FrameRect(hdc, &rc, (HBRUSH)(COLOR_BTNTEXT+1)); - EndPaint(hwnd,&ps); - - DeleteObject(hrgn); - - return 0; - } - } - return CallSubclassed(hwnd, uMsg, wParam, lParam); -} - -INT_PTR CALLBACK DialogProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) -{ - struct FILEECHO *dat = (struct FILEECHO*)GetWindowLongPtr(hDlg, GWLP_USERDATA); - switch( uMsg ) - { - case WM_INITDIALOG: - { - dat = (FILEECHO*)lParam; - dat->hDlg = hDlg; - - dat->updateTitle(); - - CreateStatusWindow(WS_CHILD|WS_VISIBLE, "", hDlg, IDC_STATUS); - SetWindowLongPtr(hDlg, GWLP_USERDATA, (LONG)dat); - WindowList_Add(hFileList, hDlg, dat->hContact); - SendMessage(hDlg, WM_SETICON, ICON_SMALL, (LPARAM)hIcons[ICON_MAIN]); - SendMessage(hDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcons[ICON_MAIN]); - SendDlgItemMessage(hDlg, IDC_STOP, BUTTONADDTOOLTIP,(WPARAM)Translate(hint_controls[ICON_STOP]),0); - - //SetDlgItemText(hDlg, IDC_FILENAME, "C:\\!Developer\\!Miranda\\miranda\\bin\\release\\emo\\biggrin.gif"); - - SubclassWnd(GetDlgItem(hDlg, IDC_PROGRESS), ProgressWndProc); - - SendDlgItemMessage(hDlg, IDC_PLAY, BUTTONSETASFLATBTN,0,0); - SendDlgItemMessage(hDlg, IDC_PLAY, BM_SETIMAGE,IMAGE_ICON,(LPARAM)hIcons[ICON_PLAY]); - SendDlgItemMessage(hDlg, IDC_STOP, BUTTONSETASFLATBTN,0,0); - SendDlgItemMessage(hDlg, IDC_STOP, BM_SETIMAGE,IMAGE_ICON,(LPARAM)hIcons[ICON_STOP]); - dat->setState(STATE_IDLE); - - //ShowWindow(hDlg, SW_HIDE); - //UpdateWindow(hDlg); - - if(dat->inSend) - PostMessage(hDlg, WM_COMMAND, IDC_BROWSE, NULL); - - return FALSE; - } - case WM_FE_MESSAGE: - { - dat->perform((char *)lParam); - delete (char *)lParam; - - return TRUE; - } - case WM_FE_SKINCHANGE: - SendMessage(hDlg, WM_SETICON, ICON_SMALL, (LPARAM)hIcons[ICON_MAIN]); - SendMessage(hDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcons[ICON_MAIN]); - dat->setState(dat->iState); - SendDlgItemMessage(hDlg, IDC_STOP, BM_SETIMAGE,IMAGE_ICON,(LPARAM)hIcons[ICON_STOP]); - - break; - case WM_FE_STATUSCHANGE: - { - char *szProto; - szProto=(char*)CallService(MS_PROTO_GETCONTACTBASEPROTO,(WPARAM)dat->hContact,0); - if (szProto) - { - int dwStatus; - dwStatus = DBGetContactSettingWord(dat->hContact,szProto,"Status",ID_STATUS_OFFLINE); - if(dat->inSend && dwStatus != dat->contactStatus) - { - if(dat->contactStatus == ID_STATUS_OFFLINE) - { - dat->chunkIndx = dat->chunkCount; - } - else - if(dwStatus == ID_STATUS_OFFLINE) - { - if(dat->iState & (STATE_OPERATE|STATE_ACKREQ)) - { - char *msg = Translate("Paused, 'coz connection dropped"); - SetDlgItemText(hDlg, IDC_STATUS, msg); - MakePopupMsg(dat->hDlg, dat->hContact, msg); - dat->setState(STATE_PAUSED); - KillTimer(hDlg, TIMER_SEND); - } - } - } - dat->contactStatus = dwStatus; - } - return TRUE; - } - case WM_DESTROY: - WindowList_Remove(hFileList, hDlg); - delete dat; - - return TRUE; - - case WM_TIMER: - if(dat->inSend) - dat->onSendTimer(); - else - dat->onRecvTimer(); - break; - case WM_COMMAND: - switch(wParam) - { - case IDC_PLAY: - { - if(dat->iState & (STATE_IDLE|STATE_FINISHED|STATE_CANCELLED|STATE_PRERECV)) - { - int len = GetWindowTextLength(GetDlgItem(hDlg, IDC_FILENAME))+1; - if(dat->filename) free(dat->filename); - dat->filename = (char*)malloc(len); - GetDlgItemText(hDlg, IDC_FILENAME, dat->filename, len); - if(dat->inSend) - // Send offer to remote side - { - dat->sendReq(); - } - else - // Send the accept and starting to receive - { - char buff[MAX_PATH]; - char *bufname; - - GetFullPathName(dat->filename, sizeof(buff), buff, &bufname); - *bufname = 0; - CreateDirectoryTree(buff); - if(!dat->createTransfer()) - { - SetDlgItemText(hDlg, IDC_STATUS, Translate("Failed on file initialization")); - break; - } - dat->sendCmd(0, CMD_ACCEPT, ""); - dat->lastTimestamp = GetTickCount(); - SetDlgItemText(hDlg, IDC_STATUS, Translate("Receiving...")); - dat->setState(STATE_OPERATE); - } - } - else - { - if(dat->inSend) - { - if(dat->iState == STATE_OPERATE) - { - SetDlgItemText(hDlg, IDC_STATUS, Translate("Paused...")); - dat->setState(STATE_PAUSED); - KillTimer(hDlg, TIMER_SEND); - } - else - { - SetDlgItemText(hDlg, IDC_STATUS, Translate("Sending...")); - if(dat->chunkIndx < dat->chunkCount) - dat->setState(STATE_OPERATE); - else - dat->setState(STATE_ACKREQ); - PostMessage(hDlg, WM_TIMER, 0,0); - //dat->onRecvTimer(); - //SetTimer(hDlg, TIMER_SEND, dwSendInterval, NULL); - } - } - else - { - SetDlgItemText(hDlg, IDC_STATUS, Translate("Synchronizing...")); - dat->setState(STATE_ACKREQ); - PostMessage(hDlg, WM_TIMER, 0,0); - //dat->onRecvTimer(); - //SetTimer(hDlg, TIMER_SEND, dwSendInterval, 0); - } - break; - } - break; - } - case IDC_BROWSE: - { - char str[MAX_PATH]; - OPENFILENAME ofn; - - ZeroMemory(&ofn, sizeof(ofn)); - *str = 0; - GetDlgItemText(hDlg, IDC_FILENAME, str, sizeof(str)); - //ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400; - ofn.lStructSize = sizeof(ofn); - ofn.hwndOwner = hDlg; - //ofn.lpstrFilter = "*.*"; - ofn.lpstrFile = str; - ofn.Flags = dat->inSend?OFN_FILEMUSTEXIST:0; - ofn.lpstrTitle = dat->inSend?Translate("Select a file"):Translate("Save as"); - ofn.nMaxFile = sizeof(str); - ofn.nMaxFileTitle = MAX_PATH; - if(!GetOpenFileName(&ofn)) break; - if(!dat->inSend && dat->iState == STATE_FINISHED) break; - SetDlgItemText(hDlg, IDC_FILENAME, str); - - int size = RetrieveFileSize(str); - if(size != -1) - _snprintf(str, sizeof(str), Translate("Size: %d bytes"), size); - else - _snprintf(str, sizeof(str), Translate("Can't get a file size"), size); - SetDlgItemText(hDlg, IDC_FILESIZE, str); - - break; - } - - case IDC_STOP: - case IDCANCEL: - if(dat->iState == STATE_PRERECV) - { - SetDlgItemText(hDlg, IDC_STATUS, Translate("Cancelled by user")); - dat->sendCmd(0, CMD_CANCEL, "", NULL); - dat->setState(STATE_CANCELLED); - } - if(dat->chunkCount) - { - if(MessageBox(hDlg, Translate("Transfer is in progress. Do you really want to close?"), - Translate(SERVICE_TITLE), MB_ICONWARNING|MB_YESNO|MB_DEFBUTTON2) == IDYES) - { - SetDlgItemText(hDlg, IDC_STATUS, Translate("Cancelled by user")); - dat->setState(STATE_CANCELLED); - dat->sendCmd(0, CMD_CANCEL, "", NULL); - dat->destroyTransfer(); - if(wParam == IDCANCEL) - DestroyWindow(hDlg); - } - } - else - if(wParam == IDCANCEL) - DestroyWindow(hDlg); - break;//return TRUE; - } - break; - } - - return FALSE; -} diff --git a/plugins/FileAsMessage/dialog.h b/plugins/FileAsMessage/dialog.h deleted file mode 100644 index 679742c2f6..0000000000 --- a/plugins/FileAsMessage/dialog.h +++ /dev/null @@ -1,120 +0,0 @@ -#include -#include -#include -extern HINSTANCE hInst; - -int getMsgId(char *msg); - -INT_PTR CALLBACK DialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ); - -#ifdef _DEBUG - #define CHECKPOINT -#else - #define CHECKPOINT error -#endif - -#define TIMER_SEND 100 - -typedef unsigned int uint; -typedef unsigned char uchar; -typedef unsigned long ulong; -enum -{ - CMD_REQ, - CMD_ACCEPT, - CMD_CANCEL, - - CMD_NEXT, - - CMD_DATA, - CMD_DACK, - CMD_END, - - CMD_COUNT -}; - -extern char cFECmd[CMD_COUNT]; - -#define STATE_IDLE 0x100 // idle, no operation -#define STATE_REQSENT 0x02 // request sent, awaiting of response -#define STATE_PRERECV 0x04 // incoming request, awaiting of user -#define STATE_OPERATE 0x08 // operating mode -#define STATE_ACKREQ 0x10 // ACK-request scheduled -#define STATE_CANCELLED 0x20 // operation aborted -#define STATE_FINISHED 0x40 // ... finished successfully -#define STATE_PAUSED 0x80 // ... paused - -#define CHUNK_UNSENT 0x00 -#define CHUNK_SENT 0x01 -#define CHUNK_ACK 0x02 - -#define ICON_PLAY 0 -#define ICON_PAUSE 1 -#define ICON_REFRESH 2 -#define ICON_STOP 3 -#define ICON_MAIN 4 - -struct FILEECHO -{ -public: - HANDLE hContact; - HWND hDlg; - - bool inSend; - int iState; - int contactStatus; - - HANDLE hFile, hMapping; - uchar *lpData; - - char *filename; - uint chunkIndx; // next chunk to send - uint chunkCount; // count of chunks - uint chunkSent; - uint chunkCountx; - uint *chunkPos; // offsets of chunks in file - uchar *chunkAck; // acknowledge of incoming chunks - - uchar codeSymb; // symb for replace NUL-symb. - - uint fileSize; - uint chunkMaxLen; // limit for outgoing chunk - - DWORD lastTimestamp; - DWORD lastDelay; - bool asBinary; - - // settings - uint dwSendInterval; - //uint dwChunkSize; - - COLORREF rgbSent, rgbRecv, rgbUnSent, rgbToSend; -#ifdef DEBUG - uint overhead; -#endif - - FILEECHO(HANDLE Contact); - - void setState(DWORD state); - void updateProgress(); - void updateTitle(); - - void perform(char *str); - void cmdACCEPT(); - void cmdDACK(char *data); - void sendReq(); - int sendCmd(int id, int cmd, char *szParam, char *szPrefix = NULL); - - void cmdDATA(char *data); - void cmdEND(); - - int createTransfer(); - void destroyTransfer(); - - void onSendTimer(); - void onRecvTimer(); - void incomeRequest(char *data); - -}; - -void InitCRC32(); diff --git a/plugins/FileAsMessage/fileecho.vcxproj b/plugins/FileAsMessage/fileecho.vcxproj index f56a0cb4d5..f85432de07 100644 --- a/plugins/FileAsMessage/fileecho.vcxproj +++ b/plugins/FileAsMessage/fileecho.vcxproj @@ -149,7 +149,6 @@ Disabled WIN64;_DEBUG;_WINDOWS;_USRDLL;FILEECHO_EXPORTS;%(PreprocessorDefinitions) EnableFastChecks - MultiThreadedDebugDLL Level3 ..\..\include;..\ExternalAPI;%(AdditionalIncludeDirectories) @@ -167,24 +166,18 @@ - - - - - - - - + + + + - - - - - + + + - + diff --git a/plugins/FileAsMessage/fileecho.vcxproj.filters b/plugins/FileAsMessage/fileecho.vcxproj.filters index 68d28e0f7e..2668a9153b 100644 --- a/plugins/FileAsMessage/fileecho.vcxproj.filters +++ b/plugins/FileAsMessage/fileecho.vcxproj.filters @@ -15,24 +15,27 @@ - + Source Files - + Source Files - + Source Files - + Source Files - + Header Files - + + Header Files + + Header Files diff --git a/plugins/FileAsMessage/main.cpp b/plugins/FileAsMessage/main.cpp deleted file mode 100644 index 61dfdb512b..0000000000 --- a/plugins/FileAsMessage/main.cpp +++ /dev/null @@ -1,326 +0,0 @@ -#include "main.h" - -PLUGININFOEX pluginInfo = -{ - sizeof(PLUGININFOEX), - SERVICE_TITLE, - PLUGIN_MAKE_VERSION( 0,0,2,4 ), - "File tranfer by using the messaging services - as plain text", - "Denis Stanishevskiy // StDenis", - "stdenformiranda(at)fromru(dot)com", - "Copyright (c) 2004, Denis Stanishevskiy", - PLUGIN_URL, - UNICODE_AWARE, - // {34B5A402-1B79-4246-B041-43D0B590AE2C} - { 0x34b5a402, 0x1b79, 0x4246, { 0xb0, 0x41, 0x43, 0xd0, 0xb5, 0x90, 0xae, 0x2c } } -}; - -HANDLE hFileList; -HINSTANCE hInst; -int hLangpack; - -char *szServiceTitle = SERVICE_TITLE; -char *szServicePrefix = SERVICE_PREFIX; -HANDLE hHookDbSettingChange, hHookContactAdded, hHookSkinIconsChanged; - -extern INT_PTR CALLBACK OptionsDlgProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ); - -int idIcons[5] = {IDI_PLAY, IDI_PAUSE, IDI_REFRESH, IDI_STOP, IDI_SMALLICON}; -HICON hIcons[5]; - -char *szIconId[5] = -{ - "FePlay", - "FePause", - "FeRefresh", - "FeStop", - "FeMain" -}; -char *szIconName[5] = -{ - "Play", - "Pause", - "Revive", - "Stop", - "Main" -}; -/* -char *szIconGroup[5] = -{ - "gr1", - "gr3", - "gr2", - "gr3", - "gr1" -}; -*/ -int iIconId[5] = {3,2,4,1,0}; - -// -// wParam - Section name -// lParam - Icon ID -// -int OnSkinIconsChanged(WPARAM wParam,LPARAM lParam) -{ - int indx; -/* - if(lParam == NULL) - return 0; - for(indx = 0; indx < ARRAY_SIZE(hIcons); indx++) - { - if(strcmp((char*)lParam, szIconId[indx]) == 0) - { - hIcons[indx] = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)szIconId[indx]); - break; - } - } -*/ - for(indx = 0; indx < SIZEOF(hIcons); indx++) - hIcons[indx] = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)szIconId[indx]); - - WindowList_Broadcast(hFileList, WM_FE_SKINCHANGE, 0,0); - - return 0; -} - -int OnSettingChanged(WPARAM wParam,LPARAM lParam) -{ - DBCONTACTWRITESETTING *cws=(DBCONTACTWRITESETTING*)lParam; - - HWND hwnd = WindowList_Find(hFileList,(HANDLE)wParam); - PostMessage(hwnd, WM_FE_STATUSCHANGE, 0,0); - //OnSkinIconsChanged(0,0); - //PostMessage(hwnd, WM_FE_SKINCHANGE, 0,0); - - return 0; -} - -int OnContactAdded(WPARAM wParam,LPARAM lParam) -{ - CallService(MS_PROTO_ADDTOCONTACT, wParam, (LPARAM)SERVICE_NAME); - return 0; -} - -INT_PTR OnRecvFile(WPARAM wParam, LPARAM lParam) -{ - CLISTEVENT *clev = (CLISTEVENT*)lParam; - - HWND hwnd = WindowList_Find(hFileList,(HANDLE)clev->hContact); - if(IsWindow(hwnd)) - { - ShowWindow(hwnd, SW_SHOWNORMAL); - SetForegroundWindow(hwnd); - SetFocus(hwnd); - } - /* - else - { - if(hwnd != 0) WindowList_Remove(hFileList, hwnd); - FILEECHO *fe = new FILEECHO((HANDLE)clev->hContact); - fe->inSend = FALSE; - hwnd = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_MAIN), NULL, (DLGPROC)DialogProc, (LPARAM)fe); - if(hwnd == NULL) - { - delete fe; - return 0; - } - //SendMessage(hwnd, WM_FE_SERVICE, 0, TRUE); - ShowWindow(hwnd, SW_SHOWNORMAL); - } - */ - return 1; -} - -INT_PTR OnSendFile(WPARAM wParam, LPARAM lParam) -{ - HWND hwnd = WindowList_Find(hFileList,(HANDLE)wParam); - if(IsWindow(hwnd)) - { - SetForegroundWindow(hwnd); - SetFocus(hwnd); - } - else - { - if(hwnd != 0) WindowList_Remove(hFileList, hwnd); - FILEECHO *fe = new FILEECHO((HANDLE)wParam); - fe->inSend = TRUE; - hwnd = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_MAIN), NULL, DialogProc, (LPARAM)fe); - if(hwnd == NULL) - { - delete fe; - return 0; - } - //SendMessage(hwnd, WM_FE_SERVICE, 0, TRUE); - ShowWindow(hwnd, SW_SHOWNORMAL); - } - return 1; -} - -INT_PTR OnRecvMessage( WPARAM wParam, LPARAM lParam ) -{ - CCSDATA *pccsd = (CCSDATA *)lParam; - PROTORECVEVENT *ppre = ( PROTORECVEVENT * )pccsd->lParam; - - if(strncmp(ppre->szMessage, szServicePrefix, strlen(szServicePrefix))) - return CallService( MS_PROTO_CHAINRECV, wParam, lParam ); - - HWND hwnd = WindowList_Find(hFileList, (HANDLE)pccsd->hContact); - if(!IsWindow(hwnd)) - { - if(hwnd != 0) WindowList_Remove(hFileList, hwnd); - FILEECHO *fe = new FILEECHO((HANDLE)pccsd->hContact); - fe->inSend = FALSE; - hwnd = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_MAIN), NULL, DialogProc, (LPARAM)fe); - if(hwnd == NULL) - { - delete fe; - return 0; - } - } - char *msg = strdup(ppre->szMessage + strlen(szServicePrefix)); - PostMessage(hwnd, WM_FE_MESSAGE, (WPARAM)pccsd->hContact, (LPARAM)msg); - - return 0; -} - -int OnOptInitialise(WPARAM wParam, LPARAM lParam) -{ - OPTIONSDIALOGPAGE odp; - - ZeroMemory(&odp, sizeof(odp)); - - odp.cbSize = sizeof(odp); - odp.hInstance = hInst; - odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONS); - odp.ptszTitle = _T(SERVICE_TITLE); - odp.ptszGroup = _T("Plugins"); - odp.flags = ODPF_BOLDGROUPS|ODPF_TCHAR; - odp.pfnDlgProc = OptionsDlgProc; - Options_AddPage(wParam, &odp); - - return 0; -} - -// -// MirandaPluginInfo() -// Called by Miranda to get Version -// -extern "C" __declspec(dllexport) PLUGININFOEX *MirandaPluginInfoEx(DWORD dwVersion) -{ - return &pluginInfo; -} -/* -DWORD CreateSetting(char *name, DWORD defvalue) -{ - if(DBGetContactSettingDword(NULL, SERVICE_NAME, name, -1) == -1) - DBWriteContactSettingDword(NULL, SERVICE_NAME, name, defvalue); - else - defvalue = DBGetContactSettingDword(NULL, SERVICE_NAME, name, defvalue); - return defvalue; -} -*/ - -int OnModulesLoaded(WPARAM wparam,LPARAM lparam) -{ - int indx; - SKINICONDESC sid; - char ModuleName[MAX_PATH]; - - ZeroMemory(&sid, sizeof(sid)); - sid.cbSize = sizeof(sid); - sid.pszSection = Translate("fileAsMessage"); - GetModuleFileName(hInst, ModuleName, sizeof(ModuleName)); - for(indx = 0; indx < SIZEOF(hIcons); indx++) - { - //sid.pszSection = szIconGroup[indx]; - sid.pszName = szIconId[indx]; - sid.pszDescription = szIconName[indx]; - sid.pszDefaultFile = ModuleName; - sid.iDefaultIndex = iIconId[indx]; - Skin_AddIcon(&sid); - } - for(indx = 0; indx < SIZEOF(hIcons); indx++) - hIcons[indx] = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)szIconId[indx]); - - hHookSkinIconsChanged = HookEvent(ME_SKIN2_ICONSCHANGED, OnSkinIconsChanged); - HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); - while(hContact) - { - if(!CallService(MS_PROTO_ISPROTOONCONTACT, (WPARAM)hContact, (LPARAM)SERVICE_NAME)) - CallService(MS_PROTO_ADDTOCONTACT, (WPARAM)hContact, (LPARAM)SERVICE_NAME); - hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0); - } - - CLISTMENUITEM mi; - ZeroMemory(&mi, sizeof(mi)); - mi.cbSize = sizeof(CLISTMENUITEM); - mi.position = 200011; - mi.hIcon = hIcons[ICON_MAIN]; - mi.pszName = Translate("File As Message..."); - mi.pszService = SERVICE_NAME "/FESendFile"; - mi.pszContactOwner = NULL; - mi.flags = CMIF_NOTOFFLINE; - Menu_AddContactMenuItem(&mi); - - return 0; -} - -// -// Startup initializing -// -extern "C" __declspec(dllexport) int Load(void) -{ - mir_getLP(&pluginInfo); - - InitCRC32(); - -// for(int indx = 0; indx < ARRAY_SIZE(hIcons); indx++) -// hIcons[indx] = (HICON)LoadImage(hInst,MAKEINTRESOURCE(idIcons[indx]),IMAGE_ICON,GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),0); - - hFileList = (HANDLE)CallService(MS_UTILS_ALLOCWINDOWLIST, 0, 0); - - //CreateServiceFunction( SERVICE_NAME PS_GETCAPS, FEGetCaps ); - CreateServiceFunction(SERVICE_NAME PSR_MESSAGE, OnRecvMessage); - CreateServiceFunction(SERVICE_NAME "/FESendFile", OnSendFile); - CreateServiceFunction(SERVICE_NAME "/FERecvFile", OnRecvFile); - - PROTOCOLDESCRIPTOR pd; - memset(&pd, 0, sizeof( PROTOCOLDESCRIPTOR)); - pd.cbSize = sizeof(PROTOCOLDESCRIPTOR); - pd.szName = SERVICE_NAME; - pd.type = PROTOTYPE_FILTER; - CallService(MS_PROTO_REGISTERMODULE, 0, ( LPARAM ) &pd); - - HookEvent(ME_OPT_INITIALISE, OnOptInitialise); - HookEvent(ME_SYSTEM_MODULESLOADED, OnModulesLoaded); - hHookDbSettingChange = HookEvent(ME_DB_CONTACT_SETTINGCHANGED, OnSettingChanged); - hHookContactAdded = HookEvent(ME_DB_CONTACT_ADDED, OnContactAdded); - hHookSkinIconsChanged = NULL; - - return 0; -} - -// -// Unload() -// Called by Miranda when Plugin is unloaded. -// -extern "C" __declspec(dllexport) int Unload(void) -{ -// if(hFileList) -// WindowList_Broadcast(hFileList, WM_CLOSE, 0,0); - if(hHookSkinIconsChanged != NULL) - UnhookEvent(hHookSkinIconsChanged); - UnhookEvent(hHookDbSettingChange); - UnhookEvent(hHookContactAdded); - - return 0; -} - -// -// DllMain() -// -int WINAPI DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID pReserved ) -{ - hInst = hInstance; - return 1; -} diff --git a/plugins/FileAsMessage/main.h b/plugins/FileAsMessage/main.h deleted file mode 100644 index e21472e5a1..0000000000 --- a/plugins/FileAsMessage/main.h +++ /dev/null @@ -1,57 +0,0 @@ -#define _CRT_SECURE_NO_WARNINGS -#define _CRT_NONSTDC_NO_DEPRECATE -#define _WIN32_WINNT 0x0501 - -#include -#include -#include -#include - -#include "newpluginapi.h" -#include "m_system.h" -#include "m_database.h" -#include "m_protomod.h" -#include "m_protosvc.h" -#include "m_langpack.h" -#include "m_clist.h" -#include "m_options.h" -#include "m_clui.h" -#include "m_clc.h" -#include "m_utils.h" -#include "m_skin.h" -#include "m_popup.h" -#include "m_icolib.h" -#include "m_message.h" -#include "m_button.h" -#include "m_netlib.h" -#include "m_file.h" -#include "win2k.h" - -#include "dialog.h" -#include "resource.h" - -#define MAXBUFSIZE 4096 -#define SERVICE_TITLE "File As Message" -#define SERVICE_NAME "FileAsMessage" - -#define SERVICE_PREFIX "<%fAM-0023%>" - -#define PLUGIN_URL "http://miranda-im.org/download/details.php?action=viewfile&id=1811" -#define NOPLUGIN_MESSAGE "\nIf you see this \"garbage\", probably you "\ - "have no \"fileAsMessage\" plugin installed, see "\ - PLUGIN_URL " for more information and download." -extern char *szServiceTitle; -extern char *szServicePrefix; -extern const ulong INITCRC; - -#define WM_FE_MESSAGE WM_USER+100 -#define WM_FE_STATUSCHANGE WM_USER+101 -#define WM_FE_SKINCHANGE WM_USER+102 - -extern HINSTANCE hInst; -extern HANDLE hFileList; -extern HANDLE hEventNewFile; - -extern HICON hIcons[5]; - -ulong memcrc32(uchar *ptr, int size, ulong crc ); \ No newline at end of file diff --git a/plugins/FileAsMessage/main.rc b/plugins/FileAsMessage/main.rc deleted file mode 100644 index 73be51abff..0000000000 --- a/plugins/FileAsMessage/main.rc +++ /dev/null @@ -1,30 +0,0 @@ -#include "windows.h" -#include "resource.h" -IDD_OPTIONS DIALOGEX 0,0,210,164 -FONT 8,"MS Shell Dlg" -STYLE 0x50000008 -EXSTYLE 0x00010000 -BEGIN - CONTROL "Hide delay",IDC_STATIC,"Static",0x50020002,15,135,88,8,0x00000000 - CONTROL "",IDC_HIDEDELAY,"Edit",0x50010080,108,132,45,14,0x00000200 - CONTROL "ms",IDC_STATIC,"Static",0x50020000,155,117,33,8,0x00000000 - CONTROL "Show delay",IDC_STATIC,"Static",0x50020002,15,117,88,8,0x00000000 - CONTROL "",IDC_SHOWDELAY,"Edit",0x50010080,108,114,45,14,0x00000200 - CONTROL "ms",IDC_STATIC,"Static",0x50020000,155,135,40,8,0x00000000 - CONTROL "Screen position",IDC_STATIC,"Button",0x50000007,7,6,198,90,0x00000000 - CONTROL "",IDC_DISABLED,"MButtonClass",0x10010000,100,46,16,14,0x00000000 - CONTROL "",IDC_LEFT,"MButtonClass",0x10010000,14,46,16,14,0x00000000 - CONTROL "",IDC_UPLEFT,"MButtonClass",0x10010000,14,17,16,14,0x00000000 - CONTROL "",IDC_DOWNLEFT,"MButtonClass",0x10010000,14,76,16,14,0x00000000 - CONTROL "",IDC_RIGHT,"MButtonClass",0x10010000,182,46,16,14,0x00000000 - CONTROL "",IDC_UPRIGHT,"MButtonClass",0x10010000,182,17,16,14,0x00000000 - CONTROL "",IDC_DOWNRIGHT,"MButtonClass",0x10010000,182,76,16,14,0x00000000 - CONTROL "Delays",IDC_STATIC,"Button",0x50000007,8,99,198,59,0x00000000 -END -IDI_DISABLED ICON DISCARDABLE "res/Disabled.ico" -IDI_LEFT ICON DISCARDABLE "res/Left.ico" -IDI_RIGHT ICON DISCARDABLE "res/Right.ico" -IDI_UPLEFT ICON DISCARDABLE "res/LeftUp.ico" -IDI_UPRIGHT ICON DISCARDABLE "res/RightUp.ico" -IDI_DOWNLEFT ICON DISCARDABLE "res/LeftDown.ico" -IDI_DOWNRIGHT ICON DISCARDABLE "res/RightDown.ico" diff --git a/plugins/FileAsMessage/optionsdlg.cpp b/plugins/FileAsMessage/optionsdlg.cpp deleted file mode 100644 index 748a118db5..0000000000 --- a/plugins/FileAsMessage/optionsdlg.cpp +++ /dev/null @@ -1,112 +0,0 @@ -#include "main.h" - -DWORD settingDefault[] = -{ - RGB(64,255,64), - RGB(255,255,64), - RGB(128,128,128), - RGB(192,192,192), - - 6000, - 5000 -}; -char *settingName[] = -{ - "colorRecv", - "colorSent", - "colorUnsent", - "colorTosend", - - "SendDelay", - "ChunkSize" -}; -int settingId[] = -{ - IDC_RECV, - IDC_SENT, - IDC_UNSENT, - IDC_TOSEND, - - -IDC_SENDDELAY, - -IDC_CHUNKSIZE -}; -// -// OptionsDlgProc() -// this handles the options page -// verwaltet die Optionsseite -// -INT_PTR CALLBACK OptionsDlgProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) -{ - switch( uMsg ) - { - case WM_INITDIALOG: - { - TranslateDialogDefault(hwndDlg); - - for(int indx = 0; indx < SIZEOF(settingId); indx++) - if(settingId[indx] > 0) - SendDlgItemMessage(hwndDlg, settingId[indx], CPM_SETCOLOUR, 0, DBGetContactSettingDword(NULL, SERVICE_NAME, settingName[indx], settingDefault[indx])); - else - SetDlgItemInt(hwndDlg, -settingId[indx], DBGetContactSettingDword(NULL, SERVICE_NAME, settingName[indx], settingDefault[indx]), FALSE); - - CheckDlgButton(hwndDlg, IDC_ALPHANUM, DBGetContactSettingDword(NULL, SERVICE_NAME, "base64", 1)?BST_CHECKED:BST_UNCHECKED); - - return TRUE; - - } - case WM_COMMAND: - { - if(//MAKEWPARAM(IDC_AUTO, BN_CLICKED) != wParam || - MAKEWPARAM(IDC_ALPHANUM, BN_CLICKED) != wParam) - { - for(int indx = 0; indx < SIZEOF(settingId); indx++) - { - if(LOWORD(wParam) == abs(settingId[indx])) - { - if(settingId[indx] > 0) - { - if(HIWORD(wParam) != CPN_COLOURCHANGED) return FALSE; - } - else - { - if(HIWORD(wParam) != EN_CHANGE) return FALSE; - if((HWND)lParam != GetFocus()) return FALSE; - } - } - } - } - SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0,0); - break; - } - case WM_DESTROY: - return FALSE; - - case WM_NOTIFY: - { - if((((NMHDR*)lParam)->idFrom == 0) && (((LPNMHDR)lParam)->code == PSN_APPLY)) - { - int value; - BOOL succ; - - for(int indx = 0; indx < SIZEOF(settingId); indx++) - { - if(settingId[indx] > 0) - value = SendDlgItemMessage(hwndDlg, settingId[indx], CPM_GETCOLOUR, 0, 0); - else - { - value = GetDlgItemInt(hwndDlg, -settingId[indx], &succ, FALSE); - if(!succ) value = settingDefault[indx]; - } - DBWriteContactSettingDword(NULL,SERVICE_NAME,settingName[indx], value); - } - DBWriteContactSettingDword(NULL,SERVICE_NAME, "base64", (IsDlgButtonChecked(hwndDlg, IDC_ALPHANUM) == BST_CHECKED)?1:0); - - return TRUE; - } - break; - } - - } - - return FALSE; -} diff --git a/plugins/FileAsMessage/res/resources.rc b/plugins/FileAsMessage/res/resources.rc new file mode 100644 index 0000000000..e9a89d8c8f --- /dev/null +++ b/plugins/FileAsMessage/res/resources.rc @@ -0,0 +1,156 @@ +//Microsoft Developer Studio generated resource script. +// +#include "..\src\resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Russian resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS) +#ifdef _WIN32 +LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT +#pragma code_page(1251) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_MAIN DIALOGEX 0, 0, 252, 75 +STYLE DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | + WS_SYSMENU +CAPTION "fileAsMessage" +FONT 8, "MS Sans Serif" +BEGIN + LTEXT "Filename:",IDC_STATIC,7,7,31,8 + EDITTEXT IDC_FILENAME,7,16,221,14,ES_AUTOHSCROLL + LTEXT "Size:",IDC_FILESIZE,7,32,238,8 + PUSHBUTTON "...",IDC_BROWSE,232,16,13,14 + LTEXT "",IDC_PROGRESS,43,44,202,14,0,WS_EX_STATICEDGE + CONTROL "",IDC_PLAY,"MButtonClass",WS_TABSTOP,7,44,16,14 + CONTROL "",IDC_STOP,"MButtonClass",WS_TABSTOP,25,44,16,14 +END + +IDD_OPTIONS DIALOGEX 0, 0, 241, 181 +STYLE DS_FIXEDSYS | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL "",IDC_UNSENT,"ColourPicker",WS_GROUP | WS_TABSTOP,124, + 106,39,12,WS_EX_NOPARENTNOTIFY + RTEXT "Chunk size",IDC_STATIC,9,41,92,8 + EDITTEXT IDC_CHUNKSIZE,123,39,41,14,ES_AUTOHSCROLL | NOT + WS_BORDER,WS_EX_CLIENTEDGE + LTEXT "ms",IDC_STATIC,170,23,28,8 + RTEXT "Delays between sends",IDC_STATIC,9,23,93,8 + EDITTEXT IDC_SENDDELAY,123,20,41,14,ES_AUTOHSCROLL | NOT + WS_BORDER,WS_EX_CLIENTEDGE + LTEXT "bytes",IDC_STATIC,170,41,28,8 + GROUPBOX "Transfer settings",IDC_STATIC,5,5,230,67 + GROUPBOX "Appearance",IDC_STATIC,5,75,230,100 + CONTROL "",IDC_SENT,"ColourPicker",WS_GROUP | WS_TABSTOP,124,124, + 39,12,WS_EX_NOPARENTNOTIFY + CONTROL "",IDC_TOSEND,"ColourPicker",WS_GROUP | WS_TABSTOP,124, + 141,39,12,WS_EX_NOPARENTNOTIFY + CONTROL "",IDC_RECV,"ColourPicker",WS_GROUP | WS_TABSTOP,124,89, + 39,12,WS_EX_NOPARENTNOTIFY + RTEXT "Unsent",IDC_STATIC,15,108,86,8 + RTEXT "Sent",IDC_STATIC,15,126,86,8 + RTEXT "To send",IDC_STATIC,15,143,86,8 + RTEXT "Received",IDC_STATIC,15,91,86,8 + CONTROL "Use only alphanumeric encoding on transfer", + IDC_ALPHANUM,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,57, + 217,10 + LTEXT "Extra options: Events » File Transfers, ""Receiving files"" group", + IDC_STATIC,10,160,220,8 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_MAIN, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 245 + TOPMARGIN, 7 + BOTTOMMARGIN, 58 + END + + IDD_OPTIONS, DIALOG + BEGIN + RIGHTMARGIN, 221 + BOTTOMMARGIN, 163 + END +END +#endif // APSTUDIO_INVOKED + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_SMALLICON ICON "file.ico" +IDI_STOP ICON "abort.ico" +IDI_PAUSE ICON "pause.ico" +IDI_PLAY ICON "play.ico" +IDI_REFRESH ICON "refresh.ico" +#endif // Russian resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/plugins/FileAsMessage/resource.h b/plugins/FileAsMessage/resource.h deleted file mode 100644 index b6a254dcf7..0000000000 --- a/plugins/FileAsMessage/resource.h +++ /dev/null @@ -1,45 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Developer Studio generated include file. -// Used by resources.rc -// -#define IDC_PLAY 1 -#define IDD_DIALOG1 101 -#define IDD_MAIN 101 -#define IDI_SMALLICON 102 -#define IDD_OPTIONS 103 -#define IDI_STOP 104 -#define IDI_PAUSE 105 -#define IDI_PLAY 106 -#define IDI_REFRESH 107 -#define IDC_FILENAME 1001 -#define IDC_BROWSE 1002 -#define IDC_STOP 1003 -#define IDC_REFRESH 1004 -#define IDC_PROGRESS 1005 -#define IDC_STATUS 1006 -#define IDC_FILESIZE 1008 -#define IDC_LIST1 1020 -#define IDC_ALPHANUM 1022 -#define IDC_HIDEDELAY 1051 -#define IDC_CHUNKSIZE 1051 -#define IDC_SHOWDELAY 1052 -#define IDC_SENDDELAY 1052 -#define IDC_SENTCOLOR 1053 -#define IDC_UNSENT 1053 -#define IDC_SENTCOLOR2 1054 -#define IDC_SENT 1054 -#define IDC_SENTCOLOR3 1055 -#define IDC_TOSEND 1055 -#define IDC_SENTCOLOR4 1056 -#define IDC_RECV 1056 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 108 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1022 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/plugins/FileAsMessage/resources.rc b/plugins/FileAsMessage/resources.rc deleted file mode 100644 index cbca7fcacc..0000000000 --- a/plugins/FileAsMessage/resources.rc +++ /dev/null @@ -1,156 +0,0 @@ -//Microsoft Developer Studio generated resource script. -// -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "afxres.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// Russian resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS) -#ifdef _WIN32 -LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT -#pragma code_page(1251) -#endif //_WIN32 - -///////////////////////////////////////////////////////////////////////////// -// -// Dialog -// - -IDD_MAIN DIALOGEX 0, 0, 252, 75 -STYLE DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | - WS_SYSMENU -CAPTION "fileAsMessage" -FONT 8, "MS Sans Serif" -BEGIN - LTEXT "Filename:",IDC_STATIC,7,7,31,8 - EDITTEXT IDC_FILENAME,7,16,221,14,ES_AUTOHSCROLL - LTEXT "Size:",IDC_FILESIZE,7,32,238,8 - PUSHBUTTON "...",IDC_BROWSE,232,16,13,14 - LTEXT "",IDC_PROGRESS,43,44,202,14,0,WS_EX_STATICEDGE - CONTROL "",IDC_PLAY,"MButtonClass",WS_TABSTOP,7,44,16,14 - CONTROL "",IDC_STOP,"MButtonClass",WS_TABSTOP,25,44,16,14 -END - -IDD_OPTIONS DIALOGEX 0, 0, 241, 181 -STYLE DS_FIXEDSYS | WS_CHILD | WS_VISIBLE -EXSTYLE WS_EX_CONTROLPARENT -FONT 8, "MS Shell Dlg" -BEGIN - CONTROL "",IDC_UNSENT,"ColourPicker",WS_GROUP | WS_TABSTOP,124, - 106,39,12,WS_EX_NOPARENTNOTIFY - RTEXT "Chunk size",IDC_STATIC,9,41,92,8 - EDITTEXT IDC_CHUNKSIZE,123,39,41,14,ES_AUTOHSCROLL | NOT - WS_BORDER,WS_EX_CLIENTEDGE - LTEXT "ms",IDC_STATIC,170,23,28,8 - RTEXT "Delays between sends",IDC_STATIC,9,23,93,8 - EDITTEXT IDC_SENDDELAY,123,20,41,14,ES_AUTOHSCROLL | NOT - WS_BORDER,WS_EX_CLIENTEDGE - LTEXT "bytes",IDC_STATIC,170,41,28,8 - GROUPBOX "Transfer settings",IDC_STATIC,5,5,230,67 - GROUPBOX "Appearance",IDC_STATIC,5,75,230,100 - CONTROL "",IDC_SENT,"ColourPicker",WS_GROUP | WS_TABSTOP,124,124, - 39,12,WS_EX_NOPARENTNOTIFY - CONTROL "",IDC_TOSEND,"ColourPicker",WS_GROUP | WS_TABSTOP,124, - 141,39,12,WS_EX_NOPARENTNOTIFY - CONTROL "",IDC_RECV,"ColourPicker",WS_GROUP | WS_TABSTOP,124,89, - 39,12,WS_EX_NOPARENTNOTIFY - RTEXT "Unsent",IDC_STATIC,15,108,86,8 - RTEXT "Sent",IDC_STATIC,15,126,86,8 - RTEXT "To send",IDC_STATIC,15,143,86,8 - RTEXT "Received",IDC_STATIC,15,91,86,8 - CONTROL "Use only alphanumeric encoding on transfer", - IDC_ALPHANUM,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,57, - 217,10 - LTEXT "Extra options: Events » File Transfers, ""Receiving files"" group", - IDC_STATIC,10,160,220,8 -END - - -///////////////////////////////////////////////////////////////////////////// -// -// DESIGNINFO -// - -#ifdef APSTUDIO_INVOKED -GUIDELINES DESIGNINFO DISCARDABLE -BEGIN - IDD_MAIN, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 245 - TOPMARGIN, 7 - BOTTOMMARGIN, 58 - END - - IDD_OPTIONS, DIALOG - BEGIN - RIGHTMARGIN, 221 - BOTTOMMARGIN, 163 - END -END -#endif // APSTUDIO_INVOKED - - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE DISCARDABLE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE DISCARDABLE -BEGIN - "#include ""afxres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE DISCARDABLE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Icon -// - -// Icon with lowest ID value placed first to ensure application icon -// remains consistent on all systems. -IDI_SMALLICON ICON DISCARDABLE "res\\file.ico" -IDI_STOP ICON DISCARDABLE "res\\abort.ico" -IDI_PAUSE ICON DISCARDABLE "res\\pause.ico" -IDI_PLAY ICON DISCARDABLE "res\\play.ico" -IDI_REFRESH ICON DISCARDABLE "res\\refresh.ico" -#endif // Russian resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - diff --git a/plugins/FileAsMessage/src/crc32.cpp b/plugins/FileAsMessage/src/crc32.cpp new file mode 100644 index 0000000000..ab34393f8d --- /dev/null +++ b/plugins/FileAsMessage/src/crc32.cpp @@ -0,0 +1,31 @@ +#include "main.h" + +const ulong CRCPoly = 0xEDB88320; +ulong CRC32Table[256]; + +void InitCRC32() +{ + for (UINT32 i = 0; i < 256; i++) + { + UINT32 r = i; + for (int j = 0; j < 8; j++) + if (r & 1) + r = (r >> 1) ^ CRCPoly; + else + r >>= 1; + CRC32Table[i] = r; + } +} + +const ulong INITCRC = -1L; + +inline ulong UpdateCRC32(uchar val, ulong crc) +{ + return CRC32Table[(uchar)crc^val] ^ (crc>>8); +} + +ulong memcrc32(uchar *ptr, int size, ulong crc ) +{ + while(size--) crc = UpdateCRC32(*ptr++, crc); + return crc; +} diff --git a/plugins/FileAsMessage/src/dialog.cpp b/plugins/FileAsMessage/src/dialog.cpp new file mode 100644 index 0000000000..f038b87a33 --- /dev/null +++ b/plugins/FileAsMessage/src/dialog.cpp @@ -0,0 +1,1358 @@ +#include"main.h" + +char *szFEMode[] = +{ + "Recv file", + "Send file" +}; + +#define USE_BUILDIN_BASE64 +// +// BASE64 encoding/decoding +// +#define Base64_GetDecodedBufferSize(cchEncoded) (((cchEncoded)>>2)*3) +#define Base64_GetEncodedBufferSize(cbDecoded) (((cbDecoded)*4+11)/12*4+1) +#ifdef USE_BUILDIN_BASE64 +#define Base64_Encode(nlb64) CallService(MS_NETLIB_BASE64ENCODE, 0, (LPARAM)nlb64) +#define Base64_Decode(nlb64) CallService(MS_NETLIB_BASE64DECODE, 0, (LPARAM)nlb64) +#else + +static char base64chars[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +#define Base64_Encode(nlb64) NetlibBase64Encode(0, (LPARAM)nlb64) +#define Base64_Decode(nlb64) NetlibBase64Decode(0, (LPARAM)nlb64) + +int NetlibBase64Encode(WPARAM wParam,LPARAM lParam) +{ + NETLIBBASE64 *nlb64=(NETLIBBASE64*)lParam; + int iIn; + char *pszOut; + PBYTE pbIn; + + if(nlb64==NULL || nlb64->pszEncoded==NULL || nlb64->pbDecoded==NULL) { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + if(nlb64->cchEncodedcbDecoded)) { + SetLastError(ERROR_BUFFER_OVERFLOW); + return 0; + } + nlb64->cchEncoded=Netlib_GetBase64EncodedBufferSize(nlb64->cbDecoded); + for(iIn=0,pbIn=nlb64->pbDecoded,pszOut=nlb64->pszEncoded;iIncbDecoded;iIn+=3,pbIn+=3,pszOut+=4) { + pszOut[0]=base64chars[pbIn[0]>>2]; + if(nlb64->cbDecoded-iIn==1) { + pszOut[1]=base64chars[(pbIn[0]&3)<<4]; + pszOut[2]='='; + pszOut[3]='='; + pszOut+=4; + break; + } + pszOut[1]=base64chars[((pbIn[0]&3)<<4)|(pbIn[1]>>4)]; + if(nlb64->cbDecoded-iIn==2) { + pszOut[2]=base64chars[(pbIn[1]&0xF)<<2]; + pszOut[3]='='; + pszOut+=4; + break; + } + pszOut[2]=base64chars[((pbIn[1]&0xF)<<2)|(pbIn[2]>>6)]; + pszOut[3]=base64chars[pbIn[2]&0x3F]; + } + pszOut[0]='\0'; + return 1; +} + +static BYTE Base64CharToInt(char c) +{ + if(c>='A' && c<='Z') return c-'A'; + if(c>='a' && c<='z') return c-'a'+26; + if(c>='0' && c<='9') return c-'0'+52; + if(c=='+') return 62; + if(c=='/') return 63; + if(c=='=') return 64; + return 255; +} + +int NetlibBase64Decode(WPARAM wParam,LPARAM lParam) +{ + NETLIBBASE64 *nlb64=(NETLIBBASE64*)lParam; + char *pszIn; + PBYTE pbOut; + BYTE b1,b2,b3,b4; + int iIn; + + if(nlb64==NULL || nlb64->pszEncoded==NULL || nlb64->pbDecoded==NULL) { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + if(nlb64->cchEncoded&3) { + SetLastError(ERROR_INVALID_DATA); + return 0; + } + if(nlb64->cbDecodedcchEncoded)) { + SetLastError(ERROR_BUFFER_OVERFLOW); + return 0; + } + nlb64->cbDecoded=Netlib_GetBase64DecodedBufferSize(nlb64->cchEncoded); + for(iIn=0,pszIn=nlb64->pszEncoded,pbOut=nlb64->pbDecoded;iIncchEncoded;iIn+=4,pszIn+=4,pbOut+=3) { + b1=Base64CharToInt(pszIn[0]); + b2=Base64CharToInt(pszIn[1]); + b3=Base64CharToInt(pszIn[2]); + b4=Base64CharToInt(pszIn[3]); + if(b1==255 || b1==64 || b2==255 || b2==64 || b3==255 || b4==255) { + SetLastError(ERROR_INVALID_DATA); + return 0; + } + pbOut[0]=(b1<<2)|(b2>>4); + if(b3==64) {nlb64->cbDecoded-=2; break;} + pbOut[1]=(b2<<4)|(b3>>2); + if(b4==64) {nlb64->cbDecoded--; break;} + pbOut[2]=b4|(b3<<6); + } + return 1; +} +#endif + +char* ltoax(char* s, DWORD value) +{ + if(value == 0) + { + *s++ = '0'; + } + uchar data; + int indx = 8; + while(indx && !(data = (uchar)(value >> 28) & 0x0F)) + { + value <<= 4; + indx--; + } + while(indx) + { + data = (uchar)(value >> 28) & 0x0F; + if(data > 9) data += 'A' - 10; + else data += '0'; + *s++ = data; + value <<= 4; + indx--; + } + return s; +} +uint atolx(char* &value) +{ + uint result = 0; + uchar ch; + + while( *value && (ch = *value - '0') >= 0 ) + { + if(ch > 9) + { + ch -= 'A' - '0'; + if(ch > 5) break; + ch += 10; + } + result = result * 16 + ch; + value++; + } + return result; +} + +char cCmdList[CMD_COUNT] = +{ + '?', + '+', + '-', + + '*', + + '>', + '!', + '.' +}; + +static int CALLBACK PopupDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + HANDLE hContact = PUGetContact(hWnd); + HWND hDlg = (HWND)PUGetPluginData(hWnd); +/* + if(hContact) + { + CLISTEVENT *lpcle; + int indx = 0; + for(;;) + { + if((lpcle = (CLISTEVENT*)CallService(MS_CLIST_GETEVENT, (WPARAM)hContact, indx)) == NULL) + break; + if(lstrcmp(lpcle->pszService, SERVICE_NAME "/FERecvFile") == 0) + { + lpcle->lParam = (LPARAM)hWnd; + break; + } + indx++; + } + } +*/ + switch(message) { + case WM_COMMAND: + { + PUDeletePopUp(hWnd); + CallService(MS_CLIST_REMOVEEVENT, (WPARAM)hContact, (LPARAM)0); + + if(IsWindow(hDlg)) + { + ShowWindow(hDlg, SW_SHOWNORMAL); + SetForegroundWindow(hDlg); + SetFocus(hDlg); + } + + break; + } + case WM_CONTEXTMENU: + PUDeletePopUp(hWnd); + break; + case UM_FREEPLUGINDATA: + return TRUE; //TRUE or FALSE is the same, it gets ignored. + default: + break; + } + return DefWindowProc(hWnd, message, wParam, lParam); +} +// +// Just create simple Popup for specified contact +// +void MakePopupMsg(HWND hDlg, HANDLE hContact, char *msg) +{ + HWND hFocused = GetForegroundWindow(); + if(hDlg == hFocused || hDlg == GetParent(hFocused)) return; + + POPUPDATAEX ppd; + // + //The text for the second line. You could even make something like: char lpzText[128]; lstrcpy(lpzText, "Hello world!"); It's your choice. + // + ZeroMemory(&ppd, sizeof(ppd)); //This is always a good thing to do. + ppd.lchContact = (HANDLE)hContact; //Be sure to use a GOOD handle, since this will not be checked. + ppd.lchIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_SMALLICON)); + lstrcpy(ppd.lpzContactName, (char *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, 0)); + lstrcpy(ppd.lpzText, msg); + ppd.colorBack = GetSysColor(COLOR_INFOBK); + ppd.colorText = GetSysColor(COLOR_INFOTEXT); + ppd.PluginWindowProc = (WNDPROC)PopupDlgProc; + ppd.PluginData = (void*)hDlg; + ppd.iSeconds = -1; + + CallService(MS_POPUP_ADDPOPUPEX, (WPARAM)&ppd, 0); +} +// +// Get ID of string message +// +int getMsgId(char *msg) +{ + for(int indx = 0; indx < CMD_COUNT; indx++) + { + if(*msg == cCmdList[indx]) return indx; + } + return -1; +}; + +int RetrieveFileSize(char *filename) +{ + int handle = open(filename, O_RDONLY|O_BINARY,0); + if(handle != -1) + { + int size = filelength(handle); + close(handle); + return size; + } + return handle; +} + +FILEECHO::FILEECHO(HANDLE Contact) +{ + hContact = Contact; + dwSendInterval = DBGetContactSettingDword(NULL, SERVICE_NAME, "SendDelay", 6000); + //dwChunkSize = DBGetContactSettingDword(NULL, SERVICE_NAME, "ChunkSize", 5000); + + chunkMaxLen = DBGetContactSettingDword(NULL, SERVICE_NAME, "ChunkSize", 5000); + chunkCount = 0; + filename = NULL; + + rgbRecv = DBGetContactSettingDword(NULL, SERVICE_NAME, "colorRecv", RGB(64,255,64)); + rgbSent = DBGetContactSettingDword(NULL, SERVICE_NAME, "colorSent", RGB(255,255,64)); + rgbUnSent = DBGetContactSettingDword(NULL, SERVICE_NAME, "colorUnsent", RGB(128,128,128)); + rgbToSend = DBGetContactSettingDword(NULL, SERVICE_NAME, "colorTosend", RGB(192,192,192)); + asBinary = DBGetContactSettingDword(NULL, SERVICE_NAME, "base64", 1) == 0; +} + +uint controlEnabled[][2] = +{ + IDC_PLAY, + STATE_OPERATE|STATE_PAUSED|STATE_PRERECV|STATE_ACKREQ|STATE_IDLE, + IDC_STOP, + STATE_OPERATE|STATE_PAUSED|STATE_PRERECV|STATE_REQSENT|STATE_ACKREQ, +// IDC_FILENAME, +// STATE_IDLE|STATE_PRERECV|STATE_FINISHED|STATE_CANCELLED, +// IDC_BROWSE, +// STATE_IDLE|STATE_PRERECV|STATE_FINISHED|STATE_CANCELLED, +}; +/* +char *stateMsg[][2] = +{ + (char*)STATE_IDLE,"Idle", + (char*)STATE_REQSENT,"ReqSent", + (char*)STATE_PRERECV,"PreRecv", + (char*)STATE_OPERATE,"Operate", + (char*)STATE_ACKREQ,"AckReq", + (char*)STATE_CANCELLED,"Cancelled", + (char*)STATE_FINISHED,"Finished", + (char*)STATE_PAUSED,"Paused" +}; +*/ + +char *hint_controls[4] = { + "Perform", + "Pause", + "Revive a transfer", + "Stop" +}; + +void FILEECHO::setState(DWORD state) +{ + iState = state; + int indx; + + for(indx = 0; indx < SIZEOF(controlEnabled); indx++) + { + EnableWindow(GetDlgItem(hDlg, controlEnabled[indx][0]), (iState & controlEnabled[indx][1]) != 0); + } + + if(!inSend) // recv + { + int kind; + SendDlgItemMessage(hDlg, IDC_FILENAME, EM_SETREADONLY, (state != STATE_PRERECV), 0); + EnableWindow(GetDlgItem(hDlg, IDC_BROWSE), (iState & (STATE_PRERECV|STATE_FINISHED))); + //SendDlgItemMessage(hDlg, IDC_FILENAME, EM_SETREADONLY, (iState & STATE_PRERECV) == 0, 0); + //EnableWindow(GetDlgItem(hDlg, IDC_FILENAME), (iState == STATE_PRERECV)); + //EnableWindow(GetDlgItem(hDlg, IDC_FILENAME), (iState & STATE_IDLE|STATE_PRERECV|STATE_FINISHED|STATE_CANCELLED) != 0); + if(state & (STATE_IDLE|STATE_FINISHED|STATE_CANCELLED|STATE_PRERECV)) + kind = ICON_PLAY; + else + kind = ICON_REFRESH; + SendDlgItemMessage(hDlg, IDC_PLAY,BM_SETIMAGE,IMAGE_ICON,(LPARAM)hIcons[kind]); + SendDlgItemMessage(hDlg, IDC_PLAY, BUTTONADDTOOLTIP,(WPARAM)Translate(hint_controls[kind]),0); + } + else + { + SendDlgItemMessage(hDlg, IDC_FILENAME, EM_SETREADONLY, (iState & (STATE_IDLE|STATE_FINISHED|STATE_CANCELLED)) == 0, 0); + EnableWindow(GetDlgItem(hDlg, IDC_BROWSE), (iState & (STATE_IDLE|STATE_FINISHED|STATE_CANCELLED)) != 0); + //EnableWindow(GetDlgItem(hDlg, IDC_FILENAME), (iState & STATE_IDLE|STATE_PRERECV|STATE_FINISHED|STATE_CANCELLED) != 0); + switch(state) + { + case STATE_FINISHED: + case STATE_CANCELLED: + case STATE_IDLE: + case STATE_PAUSED: + EnableWindow(GetDlgItem(hDlg, IDC_PLAY), TRUE); + SendDlgItemMessage(hDlg, IDC_PLAY, BM_SETIMAGE,IMAGE_ICON,(LPARAM)hIcons[ICON_PLAY]); + SendDlgItemMessage(hDlg, IDC_PLAY, BUTTONADDTOOLTIP,(WPARAM)Translate(hint_controls[ICON_PLAY]),0); + break; + case STATE_OPERATE: + SendDlgItemMessage(hDlg, IDC_PLAY, BM_SETIMAGE,IMAGE_ICON,(LPARAM)hIcons[ICON_PAUSE]); + SendDlgItemMessage(hDlg, IDC_PLAY, BUTTONADDTOOLTIP,(WPARAM)Translate(hint_controls[ICON_PAUSE]),0); + break; + } + } + updateProgress(); +} + +void FILEECHO::updateTitle() +{ + char newtitle[256], *contactName; + + contactName=(char*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME,(WPARAM)hContact,0); + if(iState == STATE_OPERATE && chunkCount != 0) + _snprintf(newtitle,sizeof(newtitle),"%d%% - %s: %s",chunkSent * 100 / chunkCount, Translate(szFEMode[inSend]), contactName); + else + _snprintf(newtitle,sizeof(newtitle),"%s: %s",Translate(szFEMode[inSend]), contactName); + SetWindowText(hDlg, newtitle); +} + +void BuildFreqTable(uchar *data, uint len, uint *freqTable) +{ + ZeroMemory(freqTable, 256*sizeof(uint)); + for(uint indx = 0; indx < len; indx++) + freqTable[data[indx]]++; +} + +int FILEECHO::createTransfer() +{ + uint LastError; + hFile = INVALID_HANDLE_VALUE; + hMapping = NULL; + lpData = NULL; +#ifdef DEBUG + overhead = 0; +#endif + hFile = CreateFile(filename, inSend?GENERIC_READ:(GENERIC_READ|GENERIC_WRITE), inSend?FILE_SHARE_READ:0, + NULL, inSend?OPEN_EXISTING:(DBGetContactSettingByte(NULL,"SRFile","AutoAccept",0)?CREATE_ALWAYS:CREATE_NEW), FILE_ATTRIBUTE_NORMAL, NULL); + if(hFile == INVALID_HANDLE_VALUE && !inSend && GetLastError() == ERROR_FILE_EXISTS) + { + if(MessageBox(hDlg, Translate("File already exists. Overwrite?"), + Translate(SERVICE_TITLE), + MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON2) != IDYES) return 0; + hFile = CreateFile(filename, GENERIC_READ|GENERIC_WRITE, 0, + NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + + } + if(hFile == INVALID_HANDLE_VALUE) goto createTransfer_FAILED; + if(!inSend) + { + SetFilePointer(hFile, fileSize, NULL, FILE_CURRENT); + SetEndOfFile(hFile); + } + else + fileSize = GetFileSize(hFile, NULL); + hMapping = CreateFileMapping(hFile, NULL, inSend?PAGE_READONLY:PAGE_READWRITE, + 0, fileSize, NULL); + LastError = GetLastError(); + if(hMapping == NULL) goto createTransfer_FAILED; + lpData = (uchar*)MapViewOfFile(hMapping, inSend?FILE_MAP_READ:FILE_MAP_WRITE, 0,0,0); + LastError = GetLastError(); + if(lpData == NULL) goto createTransfer_FAILED; + + if(inSend) + // + // frequency analysis of source file + // and building the table of offsets + // + { + if(asBinary) + { + uint freq_table[256]; + uchar *data; + uint len, chunk_offset, chunk_size, out_size, indx; + int chunk_count_limit; + + codeSymb = 1; + // + // searching for symbol with lowest frequency: "codeSymb" + // + BuildFreqTable(lpData, fileSize, freq_table); + for(int indx = codeSymb+1; indx < 256; indx++) + { + if(freq_table[codeSymb] > freq_table[indx]) codeSymb = indx; + } + //DEBUG + //codeSymb = ':'; + + // + // calculating chunks sizes + // build table of chunks offsets: chunkPos + // + chunk_count_limit = 2*fileSize/chunkMaxLen+2; + chunkPos = (uint*)malloc(sizeof(uint)*chunk_count_limit); + data = lpData; + chunk_size = 0; out_size = 0; indx = 0; chunk_offset = 0; + for(len = fileSize; len; len--) + { + if(*data == 0 || *data == codeSymb) + out_size += 2; + else + out_size++; + + data++; chunk_size++; + if(out_size >= chunkMaxLen-1) + { + chunkPos[indx] = chunk_offset; chunk_offset += chunk_size; + chunk_size = 0; out_size = 0; + indx++; + } + } + chunkPos[indx++] = chunk_offset; chunkCount = indx; + chunkPos = (uint*)realloc(chunkPos, sizeof(uint)*(chunkCount+1)); + chunkPos[indx] = chunk_offset + chunk_size; + } + else + { + int EncodedMaxLen = Base64_GetEncodedBufferSize(Base64_GetDecodedBufferSize(chunkMaxLen)); + int DecodedMaxLen = Base64_GetDecodedBufferSize(EncodedMaxLen); + int indx = 0; + + codeSymb = '-'; + chunkCount = (fileSize + DecodedMaxLen - 1) / DecodedMaxLen; + chunkPos = (uint*)malloc(sizeof(uint)*(chunkCount+1)); + for(uint chunk_offset = 0, indx = 0; indx < chunkCount; indx++, chunk_offset += DecodedMaxLen) + chunkPos[indx] = chunk_offset; + chunkPos[indx] = chunkPos[indx-1] + fileSize%DecodedMaxLen; + } + } + else + chunkCount = chunkCountx; + chunkAck = (uchar*)malloc(sizeof(uchar)*chunkCount); + memset(chunkAck, 0, sizeof(uchar)*chunkCount); + + chunkIndx = 0; chunkSent = 0; + + return 1; +createTransfer_FAILED: + if(lpData != NULL) UnmapViewOfFile(lpData); + if(hMapping != NULL) CloseHandle(hMapping); + if(hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile); + return 0; +} + +void FILEECHO::destroyTransfer() +{ + if(chunkCount) + { + chunkCount = 0; + if(inSend) + free(chunkPos); + free(chunkAck); + if(lpData != NULL) UnmapViewOfFile(lpData); + if(hMapping != NULL) CloseHandle(hMapping); + if(hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile); + } + //setState(STATE_IDLE); + return; +} + +void FILEECHO::sendReq() +{ + + char sendbuf[MAX_PATH]; + + if(!createTransfer()) + { + SetDlgItemText(hDlg, IDC_FILESIZE, Translate("Couldn't open a file")); + return; + } + ///!!!!!!! + char *p = filename + strlen(filename); + while(p != filename && *p != '\\') + p--; + if(*p == '\\') + strcpy(filename,p+1); + + _snprintf(sendbuf, sizeof(sendbuf), Translate("Size: %d bytes"), fileSize); + SetDlgItemText(hDlg, IDC_FILESIZE, sendbuf); + _snprintf(sendbuf, sizeof(sendbuf), "?%c%c%d:%d " NOPLUGIN_MESSAGE, asBinary+'0', codeSymb, chunkCount, fileSize); + sendCmd(0, CMD_REQ, sendbuf, filename); + + SetDlgItemText(hDlg, IDC_STATUS, Translate("Request sent. Awaiting of acceptance..")); + setState(STATE_REQSENT); +} +void FILEECHO::incomeRequest(char *param) +{ + // param: filename?cCOUNT:SIZE + char buf[MAX_PATH]; + // param == &filename + char *p = strchr(param, '?'); + if(p == NULL) return; *p++ = 0; + CallService(MS_FILE_GETRECEIVEDFILESFOLDER, (WPARAM)hContact, (LPARAM)buf); + strncat(buf, param, sizeof(buf)); + if(filename) free(filename); + filename = strdup(buf); + // p == &c + if(*p == 0) return; asBinary = (*p++) != '0'; + if(*p == 0) return; codeSymb = *p++; + // p == &COUNT + if(*p == 0) return; param = strchr(p, ':'); + // param == &SIZE + if(param == NULL) return; *param++ = 0; + if(*param == 0) return; + chunkCountx = atoi(p); + fileSize = atoi(param); + + _snprintf(buf, sizeof(buf), Translate("Size: %d bytes"), fileSize); + SetDlgItemText(hDlg, IDC_FILENAME, filename); + SetDlgItemText(hDlg, IDC_FILESIZE, buf); + + setState(STATE_PRERECV); + inSend = FALSE; + + SkinPlaySound("RecvFile"); + int AutoMin = DBGetContactSettingByte(NULL,"SRFile","AutoMin",0); + if(DBGetContactSettingByte(NULL,"SRFile","AutoAccept",0) && !DBGetContactSettingByte((HANDLE)hContact,"CList","NotOnList",0)) + { + PostMessage(hDlg, WM_COMMAND, IDC_PLAY, 0); + if(AutoMin) + ShowWindow(hDlg, SW_SHOWMINIMIZED); +// ShowWindow(hDlg, SW_MINIMIZE); +// UpdateWindow(hDlg); + } +// else + if(!IsWindowVisible(hDlg) && !AutoMin) + { + CLISTEVENT cle; + ZeroMemory(&cle, sizeof(cle)); + cle.cbSize = sizeof(cle); + cle.hContact = hContact; + cle.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_SMALLICON)); + cle.flags = CLEF_URGENT; + cle.hDbEvent = 0; + cle.pszService = SERVICE_NAME "/FERecvFile"; + CallService(MS_CLIST_ADDEVENT, 0, (LPARAM)&cle); + + MakePopupMsg(hDlg, hContact, "Incoming file..."); + } +} + +void FILEECHO::cmdACCEPT() +{ + if(chunkCount == 0) return; + setState(STATE_OPERATE); + SetDlgItemText(hDlg, IDC_STATUS, Translate("Sending...")); + lastTimestamp = GetTickCount(); + //PostMessage(hDlg, WM_TIMER, 0,0); + //onSendTimer(); + SetTimer(hDlg, TIMER_SEND, dwSendInterval, 0); +} + +void FILEECHO::updateProgress() +{ + InvalidateRect(GetDlgItem(hDlg, IDC_PROGRESS), NULL, TRUE); + updateTitle(); +} +// +// called in receive mode +// used to transfer acknowledge +// +void FILEECHO::onRecvTimer() +{ + if(chunkCount == 0) return; + char *buffer = (char*)malloc(1024); + char *p = buffer; + uchar prev_value; + uint indx, jndx; + + KillTimer(hDlg, TIMER_SEND); + // + // Build response about successfully received chunks + // + indx = jndx = 0; prev_value = chunkAck[jndx]; + while(jndx < chunkCount) + { + if(chunkAck[jndx] != prev_value) + { + if(prev_value != CHUNK_ACK) + { + p = ltoax(p, indx); + if(indx != jndx-1) + { + *p++ = '-'; + p = ltoax(p, jndx-1); + } + *p++ = ','; + } + indx = jndx; + prev_value = chunkAck[jndx]; + } + jndx++; + } + if(prev_value != CHUNK_ACK) + { + p = ltoax(p, indx); + if(indx != jndx-1) + { + *p++ = '-'; + p = ltoax(p, jndx-1); + } + } + *p = 0; + if(*buffer == 0) + { + char *msg = Translate("Received successfully"); + SetDlgItemText(hDlg, IDC_STATUS, msg); + MakePopupMsg(hDlg, hContact, msg); + setState(STATE_FINISHED); + if(DBGetContactSettingByte(NULL,"SRFile","AutoClose",0)) + { + PostMessage(hDlg, WM_CLOSE, 0,0); + CallService(MS_CLIST_REMOVEEVENT, (WPARAM)hContact, (LPARAM)0); + } + SkinPlaySound("FileDone"); + destroyTransfer(); + buffer[0] = 'x'; buffer[1] = 0; + } + sendCmd(0, CMD_DACK, buffer); + free(buffer); + //if(iState != STATE_FINISHED) SetTimer(hDlg, TIMER_SEND, lastDelay*2, 0); +} +// +// called in sending mode +// used to data transfer and +// sending of scheduled commands +// +void FILEECHO::onSendTimer() +{ + if(chunkCount == 0) return; + // + // perform request of acknowledge, if scheduled + // + KillTimer(hDlg, TIMER_SEND); + // + // Search for next unsent chunk + // + while(chunkIndx < chunkCount && chunkAck[chunkIndx] != CHUNK_UNSENT) chunkIndx++; + if(iState == STATE_ACKREQ || chunkIndx == chunkCount) + { + SetDlgItemText(hDlg, IDC_STATUS, Translate("Requesting of missing chunks")); + setState(STATE_OPERATE); + sendCmd(0, CMD_END, "", NULL); + chunkIndx = chunkCount+1; + return; + } + if(chunkIndx > chunkCount) return; + + uchar *buffer = (uchar*)malloc(chunkMaxLen*2); + uchar *p = buffer; + uchar *data = lpData + chunkPos[chunkIndx]; + uchar *data_end = lpData + chunkPos[chunkIndx+1]; + ulong chksum = memcrc32(data, data_end - data, INITCRC); + + if(asBinary) + { + // + // Encoding data to transfer with symb. filtering + // + while(data < data_end) + { + uchar ch = *data++; + if(ch == 0) + { + *p++ = codeSymb; *p++ = '0'; + } + else if (ch == codeSymb) + { + *p++ = codeSymb; *p++ = '+'; + } + else + *p++ = ch; + } + *p = 0; + } + else + { + NETLIBBASE64 nlb; + + nlb.pbDecoded = data; + nlb.cbDecoded = data_end - data; + nlb.pszEncoded = (char*)buffer; + nlb.cchEncoded = chunkMaxLen*2; + + Base64_Encode(&nlb); + } + + char prefix[128]; + _snprintf(prefix, sizeof(prefix), "%X,%X,%X>", chunkIndx+1, chunkPos[chunkIndx], chksum); +#ifdef DEBUG + overhead += lstrlen((char*)buffer); +#endif + sendCmd(0, CMD_DATA, (char*)buffer, (char*)prefix); + chunkAck[chunkIndx] = CHUNK_SENT; + + free(buffer); + + chunkIndx++; chunkSent++; + + if(chunkIndx == chunkCount) + setState(STATE_ACKREQ); + else + { + SetDlgItemText(hDlg, IDC_STATUS, Translate("Sending...")); + updateProgress(); + } + SetTimer(hDlg, TIMER_SEND, dwSendInterval, 0); +} +void FILEECHO::cmdDATA(char *param) +{ + if(chunkCount == 0) return; + chunkIndx = atolx(param); param++; + if(chunkIndx-- == 0) return; + uint filepos = atolx(param); param++; + if(filepos >= fileSize) return; + + ulong chksum_local; + ulong chksum_remote = atolx(param); param++; + + KillTimer(hDlg, TIMER_SEND); + + // + // Decoding of incoming data + // + uchar *data = lpData + filepos; + uchar *data_end = lpData + fileSize; + if(asBinary) + { + uchar ch; + while(ch = *param++) + { + if(ch == codeSymb) + { + if((ch = *param++) == 0) goto cmdDATA_corrupted; + switch(ch) + { + case '+': + ch = codeSymb; + break; + case '0': + ch = 0; + break; + default: + goto cmdDATA_corrupted; + } + } + if(data > data_end) goto cmdDATA_corrupted; + *data++ = ch; + } + } + else + { + NETLIBBASE64 nlb; + uchar *temp_buffer; + + nlb.pszEncoded = param; + nlb.cchEncoded = (int)_tcslen(param); + temp_buffer = (uchar*)malloc(nlb.cchEncoded); + nlb.pbDecoded = temp_buffer; + nlb.cbDecoded = nlb.cchEncoded; + + Base64_Decode(&nlb); + memcpy(data, temp_buffer, min(nlb.cbDecoded, data_end - data)); + data += nlb.cbDecoded; + } + // + // let's check it up + // + chksum_local = memcrc32(lpData + filepos, data - (lpData + filepos), INITCRC); + if(chksum_local == chksum_remote) + { + if(chunkAck[chunkIndx] != CHUNK_ACK) chunkSent++; + chunkAck[chunkIndx] = CHUNK_ACK; + //chunkPos[chunkIndx++] = filepos; + } + SetDlgItemText(hDlg, IDC_STATUS, Translate("Receiving...")); + updateProgress(); +cmdDATA_corrupted: + //SetTimer(hDlg, TIMER_SEND, lastDelay*2, 0); + ; +} +void FILEECHO::cmdEND() +{ + SetTimer(hDlg, TIMER_SEND, dwSendInterval, 0); +} +void FILEECHO::cmdDACK(char *param) +{ + uint indx, jndx; + + if(chunkCount == 0) return; + memset(chunkAck, CHUNK_ACK, sizeof(uchar)*chunkCount); + if(*param == 'x') + // + // All chunks has been received successfully + // + { +#ifdef DEBUG + char msg[100]; + + _snprintf(msg, sizeof(msg), "overhead: %d", overhead); + SetDlgItemText(hDlg, IDC_STATUS, msg); +#else + char *msg = Translate("Sent successfully"); + SetDlgItemText(hDlg, IDC_STATUS, msg); +#endif + SkinPlaySound("FileDone"); + destroyTransfer(); + MakePopupMsg(hDlg, hContact, msg); + setState(STATE_FINISHED); + return; + } + chunkSent = chunkCount; + // + // Mark chunks to re-transfer, + // according received info + // + // format: chunk1, chunk3-chunk10, etc.. + // + while(*param) + { + indx = atolx(param); + if(*param == '-') + { + param++; jndx = atolx(param); + } + else + jndx = indx; + if(*param == 0 || *param == ',') + { + for(uint p = indx; p <= jndx; p++) + { + if(p < chunkCount) + { + chunkAck[p] = CHUNK_UNSENT; + chunkSent--; + } + } + if(*param == ',') + param++; + } + } + updateProgress(); + + // + // retransfer some parts + // + chunkIndx = 0; + SetTimer(hDlg, TIMER_SEND, dwSendInterval, 0); +} + +void FILEECHO::perform(char *str) +{ + int msgId = getMsgId(str); + if(msgId == -1) + { + MakePopupMsg(hDlg, hContact, Translate("Unknown command for \"" SERVICE_TITLE "\" was received")); + return; + } + if(inSend) + switch(msgId) + { + case CMD_REQ: + if(MessageBox(hDlg, Translate("Incoming file request. Do you want proceed?"), + Translate(SERVICE_TITLE), MB_YESNO | MB_ICONWARNING) == IDYES) + { + SetDlgItemText(hDlg, IDC_STATUS, ""); + SendMessage(hDlg, WM_COMMAND, IDC_STOP, 0); + + incomeRequest(str+1); + updateTitle(); + break; + } + break; + case CMD_ACCEPT: + cmdACCEPT(); + break; + case CMD_CANCEL: + { + if(iState & (STATE_PRERECV|STATE_REQSENT|STATE_OPERATE|STATE_ACKREQ|STATE_PAUSED)) + { + char *msg = Translate("Cancelled by remote user"); + SetDlgItemText(hDlg, IDC_STATUS, msg); + MakePopupMsg(hDlg, hContact, msg); + destroyTransfer(); + setState(STATE_CANCELLED); + } + break; + } + case CMD_DACK: + cmdDACK(str+1); + break; + } + else + switch(msgId) + { + case CMD_CANCEL: + { + if(iState & (STATE_PRERECV|STATE_REQSENT|STATE_OPERATE|STATE_ACKREQ|STATE_PAUSED)) + { + char *msg = Translate("Cancelled by remote user"); + SetDlgItemText(hDlg, IDC_STATUS, msg); + MakePopupMsg(hDlg, hContact, msg); + destroyTransfer(); + setState(STATE_CANCELLED); + } + break; + } + case CMD_REQ: + if(chunkCount) + { + if(MessageBox(hDlg, Translate("New incoming file request. Do you want proceed?"), + Translate(SERVICE_TITLE), MB_YESNO | MB_ICONWARNING) != IDYES) + break; + //sendCmd(0, CMD_CANCEL, "", NULL); + destroyTransfer(); + } + SetDlgItemText(hDlg, IDC_STATUS, ""); + incomeRequest(str+1); + break; + case CMD_DATA: + cmdDATA(str+1); + break; + case CMD_END: + cmdEND(); + break; + }; +}; + +int FILEECHO::sendCmd(int id, int cmd, char *szParam, char *szPrefix) +{ + char *buf; + int retval; + int buflen = (int)_tcslen(szServicePrefix) + (int)_tcslen(szParam) + 2; + if(szPrefix != NULL) + buflen += (int)_tcslen(szPrefix); + + buf = (char*)malloc(buflen); + if(szPrefix == NULL) + _snprintf(buf,buflen,"%s%c%s", szServicePrefix, cCmdList[cmd], szParam); + else + _snprintf(buf,buflen,"%s%c%s%s", szServicePrefix, cCmdList[cmd], szPrefix, szParam); + retval = CallContactService(hContact, PSS_MESSAGE, 0, (LPARAM)buf); + free(buf); + updateProgress(); + return retval; +} + + +void CreateDirectoryTree(char *szDir) +{ + DWORD dwAttributes; + char *pszLastBackslash,szTestDir[MAX_PATH]; + + lstrcpyn(szTestDir,szDir,sizeof(szTestDir)); + if((dwAttributes=GetFileAttributes(szTestDir))!=0xffffffff + && dwAttributes&FILE_ATTRIBUTE_DIRECTORY) return; + pszLastBackslash=strrchr(szTestDir,'\\'); + if(pszLastBackslash==NULL) {GetCurrentDirectory(MAX_PATH,szDir); return;} + *pszLastBackslash='\0'; + CreateDirectoryTree(szTestDir); + CreateDirectory(szTestDir,NULL); +} + +void SubclassWnd(HWND hwnd, WNDPROC lpfnWndProc) +{ + SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG)GetWindowLongPtr(hwnd, GWLP_WNDPROC)); + SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG)lpfnWndProc); +} +#define CallSubclassed(hwnd, uMsg, wParam, lParam)\ + CallWindowProc((WNDPROC)GetWindowLongPtr(hwnd, GWLP_USERDATA), hwnd, uMsg, wParam, lParam) + +LRESULT CALLBACK ProgressWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch(uMsg) + { + case WM_NCPAINT: + return 0; + case WM_PAINT: + { + HDC hdc; + PAINTSTRUCT ps; + RECT rc; + HRGN hrgn; + HBRUSH frameBrush = (HBRUSH)GetStockObject(BLACK_BRUSH); + struct FILEECHO *dat; + + dat = (struct FILEECHO*)GetWindowLongPtr(GetParent(hwnd), GWLP_USERDATA); + //if(dat == NULL) + // return CallSubclassed(hwnd, uMsg, wParam, lParam); + GetClientRect(hwnd, &rc); + if(dat == NULL || dat->chunkCount == 0) + { + COLORREF colour; + HBRUSH hbr; + + if(dat == NULL || dat->iState != STATE_FINISHED) + { + hbr = (HBRUSH)(COLOR_3DFACE+1); + } + else + { + colour = dat->rgbRecv; + hbr = CreateSolidBrush(colour); + } + hdc=BeginPaint(hwnd,&ps); + FillRect(hdc, &rc, hbr); + FrameRect(hdc, &rc, frameBrush); + if(hbr != (HBRUSH)(COLOR_3DFACE+1)) + DeleteObject(hbr); + EndPaint(hwnd,&ps); + return 0; + } + + hrgn = CreateRectRgn(rc.left, rc.top, rc.right, rc.bottom); + + hdc=BeginPaint(hwnd,&ps); + SelectClipRgn(hdc, hrgn); + + RECT rc2 = rc; + //uint sliceWidth = (rc.right - rc.left) / dat->chunkCount; + float sliceWidth = (float)((float)(rc.right - rc.left) / (float)dat->chunkCount); + float dx = (float)rc2.left; + for(uint indx = 0; indx < dat->chunkCount; indx++) + { + HBRUSH hbr; + COLORREF colour; + if(dat->inSend && indx == dat->chunkIndx) + colour = dat->rgbToSend; + else + switch(dat->chunkAck[indx]) + { + case CHUNK_UNSENT: + colour = dat->rgbUnSent; + break; + case CHUNK_SENT: + colour = dat->rgbSent; + break; + case CHUNK_ACK: + colour = dat->rgbRecv; + break; + } + /* + if(indx == 5) colour = RGB(255,64,64); + else if(indx < 2) colour = RGB(64,255,64); + else if(indx < 4) colour = RGB(255,255,64); + else colour = RGB(128,128,128); + //*/ + if(indx == dat->chunkCount-1) + rc2.right = rc.right; + hbr = CreateSolidBrush(colour); + rc2.left = (int)dx; + rc2.right = (int)(dx + sliceWidth); + FillRect(hdc, &rc2, hbr); + FrameRect(hdc, &rc2, frameBrush); + DeleteObject(hbr); + dx += sliceWidth-1; + } + if(rc2.right < rc.right) + { + rc2.left = rc2.right; + rc2.right = rc.right; + FillRect(hdc, &rc2, (HBRUSH)(COLOR_3DFACE+1)); + } + //FrameRect(hdc, &rc, (HBRUSH)(COLOR_3DLIGHT+1)); + //OffsetRect(&rc, 1,1); + //FrameRect(hdc, &rc, (HBRUSH)(COLOR_BTNTEXT+1)); + //FrameRect(hdc, &rc, (HBRUSH)(COLOR_BTNTEXT+1)); + EndPaint(hwnd,&ps); + + DeleteObject(hrgn); + + return 0; + } + } + return CallSubclassed(hwnd, uMsg, wParam, lParam); +} + +INT_PTR CALLBACK DialogProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + struct FILEECHO *dat = (struct FILEECHO*)GetWindowLongPtr(hDlg, GWLP_USERDATA); + switch( uMsg ) + { + case WM_INITDIALOG: + { + dat = (FILEECHO*)lParam; + dat->hDlg = hDlg; + + dat->updateTitle(); + + CreateStatusWindow(WS_CHILD|WS_VISIBLE, "", hDlg, IDC_STATUS); + SetWindowLongPtr(hDlg, GWLP_USERDATA, (LONG)dat); + WindowList_Add(hFileList, hDlg, dat->hContact); + SendMessage(hDlg, WM_SETICON, ICON_SMALL, (LPARAM)hIcons[ICON_MAIN]); + SendMessage(hDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcons[ICON_MAIN]); + SendDlgItemMessage(hDlg, IDC_STOP, BUTTONADDTOOLTIP,(WPARAM)Translate(hint_controls[ICON_STOP]),0); + + //SetDlgItemText(hDlg, IDC_FILENAME, "C:\\!Developer\\!Miranda\\miranda\\bin\\release\\emo\\biggrin.gif"); + + SubclassWnd(GetDlgItem(hDlg, IDC_PROGRESS), ProgressWndProc); + + SendDlgItemMessage(hDlg, IDC_PLAY, BUTTONSETASFLATBTN,0,0); + SendDlgItemMessage(hDlg, IDC_PLAY, BM_SETIMAGE,IMAGE_ICON,(LPARAM)hIcons[ICON_PLAY]); + SendDlgItemMessage(hDlg, IDC_STOP, BUTTONSETASFLATBTN,0,0); + SendDlgItemMessage(hDlg, IDC_STOP, BM_SETIMAGE,IMAGE_ICON,(LPARAM)hIcons[ICON_STOP]); + dat->setState(STATE_IDLE); + + //ShowWindow(hDlg, SW_HIDE); + //UpdateWindow(hDlg); + + if(dat->inSend) + PostMessage(hDlg, WM_COMMAND, IDC_BROWSE, NULL); + + return FALSE; + } + case WM_FE_MESSAGE: + { + dat->perform((char *)lParam); + delete (char *)lParam; + + return TRUE; + } + case WM_FE_SKINCHANGE: + SendMessage(hDlg, WM_SETICON, ICON_SMALL, (LPARAM)hIcons[ICON_MAIN]); + SendMessage(hDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcons[ICON_MAIN]); + dat->setState(dat->iState); + SendDlgItemMessage(hDlg, IDC_STOP, BM_SETIMAGE,IMAGE_ICON,(LPARAM)hIcons[ICON_STOP]); + + break; + case WM_FE_STATUSCHANGE: + { + char *szProto; + szProto=(char*)CallService(MS_PROTO_GETCONTACTBASEPROTO,(WPARAM)dat->hContact,0); + if (szProto) + { + int dwStatus; + dwStatus = DBGetContactSettingWord(dat->hContact,szProto,"Status",ID_STATUS_OFFLINE); + if(dat->inSend && dwStatus != dat->contactStatus) + { + if(dat->contactStatus == ID_STATUS_OFFLINE) + { + dat->chunkIndx = dat->chunkCount; + } + else + if(dwStatus == ID_STATUS_OFFLINE) + { + if(dat->iState & (STATE_OPERATE|STATE_ACKREQ)) + { + char *msg = Translate("Paused, 'coz connection dropped"); + SetDlgItemText(hDlg, IDC_STATUS, msg); + MakePopupMsg(dat->hDlg, dat->hContact, msg); + dat->setState(STATE_PAUSED); + KillTimer(hDlg, TIMER_SEND); + } + } + } + dat->contactStatus = dwStatus; + } + return TRUE; + } + case WM_DESTROY: + WindowList_Remove(hFileList, hDlg); + delete dat; + + return TRUE; + + case WM_TIMER: + if(dat->inSend) + dat->onSendTimer(); + else + dat->onRecvTimer(); + break; + case WM_COMMAND: + switch(wParam) + { + case IDC_PLAY: + { + if(dat->iState & (STATE_IDLE|STATE_FINISHED|STATE_CANCELLED|STATE_PRERECV)) + { + int len = GetWindowTextLength(GetDlgItem(hDlg, IDC_FILENAME))+1; + if(dat->filename) free(dat->filename); + dat->filename = (char*)malloc(len); + GetDlgItemText(hDlg, IDC_FILENAME, dat->filename, len); + if(dat->inSend) + // Send offer to remote side + { + dat->sendReq(); + } + else + // Send the accept and starting to receive + { + char buff[MAX_PATH]; + char *bufname; + + GetFullPathName(dat->filename, sizeof(buff), buff, &bufname); + *bufname = 0; + CreateDirectoryTree(buff); + if(!dat->createTransfer()) + { + SetDlgItemText(hDlg, IDC_STATUS, Translate("Failed on file initialization")); + break; + } + dat->sendCmd(0, CMD_ACCEPT, ""); + dat->lastTimestamp = GetTickCount(); + SetDlgItemText(hDlg, IDC_STATUS, Translate("Receiving...")); + dat->setState(STATE_OPERATE); + } + } + else + { + if(dat->inSend) + { + if(dat->iState == STATE_OPERATE) + { + SetDlgItemText(hDlg, IDC_STATUS, Translate("Paused...")); + dat->setState(STATE_PAUSED); + KillTimer(hDlg, TIMER_SEND); + } + else + { + SetDlgItemText(hDlg, IDC_STATUS, Translate("Sending...")); + if(dat->chunkIndx < dat->chunkCount) + dat->setState(STATE_OPERATE); + else + dat->setState(STATE_ACKREQ); + PostMessage(hDlg, WM_TIMER, 0,0); + //dat->onRecvTimer(); + //SetTimer(hDlg, TIMER_SEND, dwSendInterval, NULL); + } + } + else + { + SetDlgItemText(hDlg, IDC_STATUS, Translate("Synchronizing...")); + dat->setState(STATE_ACKREQ); + PostMessage(hDlg, WM_TIMER, 0,0); + //dat->onRecvTimer(); + //SetTimer(hDlg, TIMER_SEND, dwSendInterval, 0); + } + break; + } + break; + } + case IDC_BROWSE: + { + char str[MAX_PATH]; + OPENFILENAME ofn; + + ZeroMemory(&ofn, sizeof(ofn)); + *str = 0; + GetDlgItemText(hDlg, IDC_FILENAME, str, sizeof(str)); + //ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400; + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = hDlg; + //ofn.lpstrFilter = "*.*"; + ofn.lpstrFile = str; + ofn.Flags = dat->inSend?OFN_FILEMUSTEXIST:0; + ofn.lpstrTitle = dat->inSend?Translate("Select a file"):Translate("Save as"); + ofn.nMaxFile = sizeof(str); + ofn.nMaxFileTitle = MAX_PATH; + if(!GetOpenFileName(&ofn)) break; + if(!dat->inSend && dat->iState == STATE_FINISHED) break; + SetDlgItemText(hDlg, IDC_FILENAME, str); + + int size = RetrieveFileSize(str); + if(size != -1) + _snprintf(str, sizeof(str), Translate("Size: %d bytes"), size); + else + _snprintf(str, sizeof(str), Translate("Can't get a file size"), size); + SetDlgItemText(hDlg, IDC_FILESIZE, str); + + break; + } + + case IDC_STOP: + case IDCANCEL: + if(dat->iState == STATE_PRERECV) + { + SetDlgItemText(hDlg, IDC_STATUS, Translate("Cancelled by user")); + dat->sendCmd(0, CMD_CANCEL, "", NULL); + dat->setState(STATE_CANCELLED); + } + if(dat->chunkCount) + { + if(MessageBox(hDlg, Translate("Transfer is in progress. Do you really want to close?"), + Translate(SERVICE_TITLE), MB_ICONWARNING|MB_YESNO|MB_DEFBUTTON2) == IDYES) + { + SetDlgItemText(hDlg, IDC_STATUS, Translate("Cancelled by user")); + dat->setState(STATE_CANCELLED); + dat->sendCmd(0, CMD_CANCEL, "", NULL); + dat->destroyTransfer(); + if(wParam == IDCANCEL) + DestroyWindow(hDlg); + } + } + else + if(wParam == IDCANCEL) + DestroyWindow(hDlg); + break;//return TRUE; + } + break; + } + + return FALSE; +} diff --git a/plugins/FileAsMessage/src/dialog.h b/plugins/FileAsMessage/src/dialog.h new file mode 100644 index 0000000000..679742c2f6 --- /dev/null +++ b/plugins/FileAsMessage/src/dialog.h @@ -0,0 +1,120 @@ +#include +#include +#include +extern HINSTANCE hInst; + +int getMsgId(char *msg); + +INT_PTR CALLBACK DialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ); + +#ifdef _DEBUG + #define CHECKPOINT +#else + #define CHECKPOINT error +#endif + +#define TIMER_SEND 100 + +typedef unsigned int uint; +typedef unsigned char uchar; +typedef unsigned long ulong; +enum +{ + CMD_REQ, + CMD_ACCEPT, + CMD_CANCEL, + + CMD_NEXT, + + CMD_DATA, + CMD_DACK, + CMD_END, + + CMD_COUNT +}; + +extern char cFECmd[CMD_COUNT]; + +#define STATE_IDLE 0x100 // idle, no operation +#define STATE_REQSENT 0x02 // request sent, awaiting of response +#define STATE_PRERECV 0x04 // incoming request, awaiting of user +#define STATE_OPERATE 0x08 // operating mode +#define STATE_ACKREQ 0x10 // ACK-request scheduled +#define STATE_CANCELLED 0x20 // operation aborted +#define STATE_FINISHED 0x40 // ... finished successfully +#define STATE_PAUSED 0x80 // ... paused + +#define CHUNK_UNSENT 0x00 +#define CHUNK_SENT 0x01 +#define CHUNK_ACK 0x02 + +#define ICON_PLAY 0 +#define ICON_PAUSE 1 +#define ICON_REFRESH 2 +#define ICON_STOP 3 +#define ICON_MAIN 4 + +struct FILEECHO +{ +public: + HANDLE hContact; + HWND hDlg; + + bool inSend; + int iState; + int contactStatus; + + HANDLE hFile, hMapping; + uchar *lpData; + + char *filename; + uint chunkIndx; // next chunk to send + uint chunkCount; // count of chunks + uint chunkSent; + uint chunkCountx; + uint *chunkPos; // offsets of chunks in file + uchar *chunkAck; // acknowledge of incoming chunks + + uchar codeSymb; // symb for replace NUL-symb. + + uint fileSize; + uint chunkMaxLen; // limit for outgoing chunk + + DWORD lastTimestamp; + DWORD lastDelay; + bool asBinary; + + // settings + uint dwSendInterval; + //uint dwChunkSize; + + COLORREF rgbSent, rgbRecv, rgbUnSent, rgbToSend; +#ifdef DEBUG + uint overhead; +#endif + + FILEECHO(HANDLE Contact); + + void setState(DWORD state); + void updateProgress(); + void updateTitle(); + + void perform(char *str); + void cmdACCEPT(); + void cmdDACK(char *data); + void sendReq(); + int sendCmd(int id, int cmd, char *szParam, char *szPrefix = NULL); + + void cmdDATA(char *data); + void cmdEND(); + + int createTransfer(); + void destroyTransfer(); + + void onSendTimer(); + void onRecvTimer(); + void incomeRequest(char *data); + +}; + +void InitCRC32(); diff --git a/plugins/FileAsMessage/src/main.cpp b/plugins/FileAsMessage/src/main.cpp new file mode 100644 index 0000000000..61dfdb512b --- /dev/null +++ b/plugins/FileAsMessage/src/main.cpp @@ -0,0 +1,326 @@ +#include "main.h" + +PLUGININFOEX pluginInfo = +{ + sizeof(PLUGININFOEX), + SERVICE_TITLE, + PLUGIN_MAKE_VERSION( 0,0,2,4 ), + "File tranfer by using the messaging services - as plain text", + "Denis Stanishevskiy // StDenis", + "stdenformiranda(at)fromru(dot)com", + "Copyright (c) 2004, Denis Stanishevskiy", + PLUGIN_URL, + UNICODE_AWARE, + // {34B5A402-1B79-4246-B041-43D0B590AE2C} + { 0x34b5a402, 0x1b79, 0x4246, { 0xb0, 0x41, 0x43, 0xd0, 0xb5, 0x90, 0xae, 0x2c } } +}; + +HANDLE hFileList; +HINSTANCE hInst; +int hLangpack; + +char *szServiceTitle = SERVICE_TITLE; +char *szServicePrefix = SERVICE_PREFIX; +HANDLE hHookDbSettingChange, hHookContactAdded, hHookSkinIconsChanged; + +extern INT_PTR CALLBACK OptionsDlgProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ); + +int idIcons[5] = {IDI_PLAY, IDI_PAUSE, IDI_REFRESH, IDI_STOP, IDI_SMALLICON}; +HICON hIcons[5]; + +char *szIconId[5] = +{ + "FePlay", + "FePause", + "FeRefresh", + "FeStop", + "FeMain" +}; +char *szIconName[5] = +{ + "Play", + "Pause", + "Revive", + "Stop", + "Main" +}; +/* +char *szIconGroup[5] = +{ + "gr1", + "gr3", + "gr2", + "gr3", + "gr1" +}; +*/ +int iIconId[5] = {3,2,4,1,0}; + +// +// wParam - Section name +// lParam - Icon ID +// +int OnSkinIconsChanged(WPARAM wParam,LPARAM lParam) +{ + int indx; +/* + if(lParam == NULL) + return 0; + for(indx = 0; indx < ARRAY_SIZE(hIcons); indx++) + { + if(strcmp((char*)lParam, szIconId[indx]) == 0) + { + hIcons[indx] = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)szIconId[indx]); + break; + } + } +*/ + for(indx = 0; indx < SIZEOF(hIcons); indx++) + hIcons[indx] = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)szIconId[indx]); + + WindowList_Broadcast(hFileList, WM_FE_SKINCHANGE, 0,0); + + return 0; +} + +int OnSettingChanged(WPARAM wParam,LPARAM lParam) +{ + DBCONTACTWRITESETTING *cws=(DBCONTACTWRITESETTING*)lParam; + + HWND hwnd = WindowList_Find(hFileList,(HANDLE)wParam); + PostMessage(hwnd, WM_FE_STATUSCHANGE, 0,0); + //OnSkinIconsChanged(0,0); + //PostMessage(hwnd, WM_FE_SKINCHANGE, 0,0); + + return 0; +} + +int OnContactAdded(WPARAM wParam,LPARAM lParam) +{ + CallService(MS_PROTO_ADDTOCONTACT, wParam, (LPARAM)SERVICE_NAME); + return 0; +} + +INT_PTR OnRecvFile(WPARAM wParam, LPARAM lParam) +{ + CLISTEVENT *clev = (CLISTEVENT*)lParam; + + HWND hwnd = WindowList_Find(hFileList,(HANDLE)clev->hContact); + if(IsWindow(hwnd)) + { + ShowWindow(hwnd, SW_SHOWNORMAL); + SetForegroundWindow(hwnd); + SetFocus(hwnd); + } + /* + else + { + if(hwnd != 0) WindowList_Remove(hFileList, hwnd); + FILEECHO *fe = new FILEECHO((HANDLE)clev->hContact); + fe->inSend = FALSE; + hwnd = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_MAIN), NULL, (DLGPROC)DialogProc, (LPARAM)fe); + if(hwnd == NULL) + { + delete fe; + return 0; + } + //SendMessage(hwnd, WM_FE_SERVICE, 0, TRUE); + ShowWindow(hwnd, SW_SHOWNORMAL); + } + */ + return 1; +} + +INT_PTR OnSendFile(WPARAM wParam, LPARAM lParam) +{ + HWND hwnd = WindowList_Find(hFileList,(HANDLE)wParam); + if(IsWindow(hwnd)) + { + SetForegroundWindow(hwnd); + SetFocus(hwnd); + } + else + { + if(hwnd != 0) WindowList_Remove(hFileList, hwnd); + FILEECHO *fe = new FILEECHO((HANDLE)wParam); + fe->inSend = TRUE; + hwnd = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_MAIN), NULL, DialogProc, (LPARAM)fe); + if(hwnd == NULL) + { + delete fe; + return 0; + } + //SendMessage(hwnd, WM_FE_SERVICE, 0, TRUE); + ShowWindow(hwnd, SW_SHOWNORMAL); + } + return 1; +} + +INT_PTR OnRecvMessage( WPARAM wParam, LPARAM lParam ) +{ + CCSDATA *pccsd = (CCSDATA *)lParam; + PROTORECVEVENT *ppre = ( PROTORECVEVENT * )pccsd->lParam; + + if(strncmp(ppre->szMessage, szServicePrefix, strlen(szServicePrefix))) + return CallService( MS_PROTO_CHAINRECV, wParam, lParam ); + + HWND hwnd = WindowList_Find(hFileList, (HANDLE)pccsd->hContact); + if(!IsWindow(hwnd)) + { + if(hwnd != 0) WindowList_Remove(hFileList, hwnd); + FILEECHO *fe = new FILEECHO((HANDLE)pccsd->hContact); + fe->inSend = FALSE; + hwnd = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_MAIN), NULL, DialogProc, (LPARAM)fe); + if(hwnd == NULL) + { + delete fe; + return 0; + } + } + char *msg = strdup(ppre->szMessage + strlen(szServicePrefix)); + PostMessage(hwnd, WM_FE_MESSAGE, (WPARAM)pccsd->hContact, (LPARAM)msg); + + return 0; +} + +int OnOptInitialise(WPARAM wParam, LPARAM lParam) +{ + OPTIONSDIALOGPAGE odp; + + ZeroMemory(&odp, sizeof(odp)); + + odp.cbSize = sizeof(odp); + odp.hInstance = hInst; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONS); + odp.ptszTitle = _T(SERVICE_TITLE); + odp.ptszGroup = _T("Plugins"); + odp.flags = ODPF_BOLDGROUPS|ODPF_TCHAR; + odp.pfnDlgProc = OptionsDlgProc; + Options_AddPage(wParam, &odp); + + return 0; +} + +// +// MirandaPluginInfo() +// Called by Miranda to get Version +// +extern "C" __declspec(dllexport) PLUGININFOEX *MirandaPluginInfoEx(DWORD dwVersion) +{ + return &pluginInfo; +} +/* +DWORD CreateSetting(char *name, DWORD defvalue) +{ + if(DBGetContactSettingDword(NULL, SERVICE_NAME, name, -1) == -1) + DBWriteContactSettingDword(NULL, SERVICE_NAME, name, defvalue); + else + defvalue = DBGetContactSettingDword(NULL, SERVICE_NAME, name, defvalue); + return defvalue; +} +*/ + +int OnModulesLoaded(WPARAM wparam,LPARAM lparam) +{ + int indx; + SKINICONDESC sid; + char ModuleName[MAX_PATH]; + + ZeroMemory(&sid, sizeof(sid)); + sid.cbSize = sizeof(sid); + sid.pszSection = Translate("fileAsMessage"); + GetModuleFileName(hInst, ModuleName, sizeof(ModuleName)); + for(indx = 0; indx < SIZEOF(hIcons); indx++) + { + //sid.pszSection = szIconGroup[indx]; + sid.pszName = szIconId[indx]; + sid.pszDescription = szIconName[indx]; + sid.pszDefaultFile = ModuleName; + sid.iDefaultIndex = iIconId[indx]; + Skin_AddIcon(&sid); + } + for(indx = 0; indx < SIZEOF(hIcons); indx++) + hIcons[indx] = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)szIconId[indx]); + + hHookSkinIconsChanged = HookEvent(ME_SKIN2_ICONSCHANGED, OnSkinIconsChanged); + HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + while(hContact) + { + if(!CallService(MS_PROTO_ISPROTOONCONTACT, (WPARAM)hContact, (LPARAM)SERVICE_NAME)) + CallService(MS_PROTO_ADDTOCONTACT, (WPARAM)hContact, (LPARAM)SERVICE_NAME); + hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0); + } + + CLISTMENUITEM mi; + ZeroMemory(&mi, sizeof(mi)); + mi.cbSize = sizeof(CLISTMENUITEM); + mi.position = 200011; + mi.hIcon = hIcons[ICON_MAIN]; + mi.pszName = Translate("File As Message..."); + mi.pszService = SERVICE_NAME "/FESendFile"; + mi.pszContactOwner = NULL; + mi.flags = CMIF_NOTOFFLINE; + Menu_AddContactMenuItem(&mi); + + return 0; +} + +// +// Startup initializing +// +extern "C" __declspec(dllexport) int Load(void) +{ + mir_getLP(&pluginInfo); + + InitCRC32(); + +// for(int indx = 0; indx < ARRAY_SIZE(hIcons); indx++) +// hIcons[indx] = (HICON)LoadImage(hInst,MAKEINTRESOURCE(idIcons[indx]),IMAGE_ICON,GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),0); + + hFileList = (HANDLE)CallService(MS_UTILS_ALLOCWINDOWLIST, 0, 0); + + //CreateServiceFunction( SERVICE_NAME PS_GETCAPS, FEGetCaps ); + CreateServiceFunction(SERVICE_NAME PSR_MESSAGE, OnRecvMessage); + CreateServiceFunction(SERVICE_NAME "/FESendFile", OnSendFile); + CreateServiceFunction(SERVICE_NAME "/FERecvFile", OnRecvFile); + + PROTOCOLDESCRIPTOR pd; + memset(&pd, 0, sizeof( PROTOCOLDESCRIPTOR)); + pd.cbSize = sizeof(PROTOCOLDESCRIPTOR); + pd.szName = SERVICE_NAME; + pd.type = PROTOTYPE_FILTER; + CallService(MS_PROTO_REGISTERMODULE, 0, ( LPARAM ) &pd); + + HookEvent(ME_OPT_INITIALISE, OnOptInitialise); + HookEvent(ME_SYSTEM_MODULESLOADED, OnModulesLoaded); + hHookDbSettingChange = HookEvent(ME_DB_CONTACT_SETTINGCHANGED, OnSettingChanged); + hHookContactAdded = HookEvent(ME_DB_CONTACT_ADDED, OnContactAdded); + hHookSkinIconsChanged = NULL; + + return 0; +} + +// +// Unload() +// Called by Miranda when Plugin is unloaded. +// +extern "C" __declspec(dllexport) int Unload(void) +{ +// if(hFileList) +// WindowList_Broadcast(hFileList, WM_CLOSE, 0,0); + if(hHookSkinIconsChanged != NULL) + UnhookEvent(hHookSkinIconsChanged); + UnhookEvent(hHookDbSettingChange); + UnhookEvent(hHookContactAdded); + + return 0; +} + +// +// DllMain() +// +int WINAPI DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID pReserved ) +{ + hInst = hInstance; + return 1; +} diff --git a/plugins/FileAsMessage/src/main.h b/plugins/FileAsMessage/src/main.h new file mode 100644 index 0000000000..e21472e5a1 --- /dev/null +++ b/plugins/FileAsMessage/src/main.h @@ -0,0 +1,57 @@ +#define _CRT_SECURE_NO_WARNINGS +#define _CRT_NONSTDC_NO_DEPRECATE +#define _WIN32_WINNT 0x0501 + +#include +#include +#include +#include + +#include "newpluginapi.h" +#include "m_system.h" +#include "m_database.h" +#include "m_protomod.h" +#include "m_protosvc.h" +#include "m_langpack.h" +#include "m_clist.h" +#include "m_options.h" +#include "m_clui.h" +#include "m_clc.h" +#include "m_utils.h" +#include "m_skin.h" +#include "m_popup.h" +#include "m_icolib.h" +#include "m_message.h" +#include "m_button.h" +#include "m_netlib.h" +#include "m_file.h" +#include "win2k.h" + +#include "dialog.h" +#include "resource.h" + +#define MAXBUFSIZE 4096 +#define SERVICE_TITLE "File As Message" +#define SERVICE_NAME "FileAsMessage" + +#define SERVICE_PREFIX "<%fAM-0023%>" + +#define PLUGIN_URL "http://miranda-im.org/download/details.php?action=viewfile&id=1811" +#define NOPLUGIN_MESSAGE "\nIf you see this \"garbage\", probably you "\ + "have no \"fileAsMessage\" plugin installed, see "\ + PLUGIN_URL " for more information and download." +extern char *szServiceTitle; +extern char *szServicePrefix; +extern const ulong INITCRC; + +#define WM_FE_MESSAGE WM_USER+100 +#define WM_FE_STATUSCHANGE WM_USER+101 +#define WM_FE_SKINCHANGE WM_USER+102 + +extern HINSTANCE hInst; +extern HANDLE hFileList; +extern HANDLE hEventNewFile; + +extern HICON hIcons[5]; + +ulong memcrc32(uchar *ptr, int size, ulong crc ); \ No newline at end of file diff --git a/plugins/FileAsMessage/src/optionsdlg.cpp b/plugins/FileAsMessage/src/optionsdlg.cpp new file mode 100644 index 0000000000..748a118db5 --- /dev/null +++ b/plugins/FileAsMessage/src/optionsdlg.cpp @@ -0,0 +1,112 @@ +#include "main.h" + +DWORD settingDefault[] = +{ + RGB(64,255,64), + RGB(255,255,64), + RGB(128,128,128), + RGB(192,192,192), + + 6000, + 5000 +}; +char *settingName[] = +{ + "colorRecv", + "colorSent", + "colorUnsent", + "colorTosend", + + "SendDelay", + "ChunkSize" +}; +int settingId[] = +{ + IDC_RECV, + IDC_SENT, + IDC_UNSENT, + IDC_TOSEND, + + -IDC_SENDDELAY, + -IDC_CHUNKSIZE +}; +// +// OptionsDlgProc() +// this handles the options page +// verwaltet die Optionsseite +// +INT_PTR CALLBACK OptionsDlgProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + switch( uMsg ) + { + case WM_INITDIALOG: + { + TranslateDialogDefault(hwndDlg); + + for(int indx = 0; indx < SIZEOF(settingId); indx++) + if(settingId[indx] > 0) + SendDlgItemMessage(hwndDlg, settingId[indx], CPM_SETCOLOUR, 0, DBGetContactSettingDword(NULL, SERVICE_NAME, settingName[indx], settingDefault[indx])); + else + SetDlgItemInt(hwndDlg, -settingId[indx], DBGetContactSettingDword(NULL, SERVICE_NAME, settingName[indx], settingDefault[indx]), FALSE); + + CheckDlgButton(hwndDlg, IDC_ALPHANUM, DBGetContactSettingDword(NULL, SERVICE_NAME, "base64", 1)?BST_CHECKED:BST_UNCHECKED); + + return TRUE; + + } + case WM_COMMAND: + { + if(//MAKEWPARAM(IDC_AUTO, BN_CLICKED) != wParam || + MAKEWPARAM(IDC_ALPHANUM, BN_CLICKED) != wParam) + { + for(int indx = 0; indx < SIZEOF(settingId); indx++) + { + if(LOWORD(wParam) == abs(settingId[indx])) + { + if(settingId[indx] > 0) + { + if(HIWORD(wParam) != CPN_COLOURCHANGED) return FALSE; + } + else + { + if(HIWORD(wParam) != EN_CHANGE) return FALSE; + if((HWND)lParam != GetFocus()) return FALSE; + } + } + } + } + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0,0); + break; + } + case WM_DESTROY: + return FALSE; + + case WM_NOTIFY: + { + if((((NMHDR*)lParam)->idFrom == 0) && (((LPNMHDR)lParam)->code == PSN_APPLY)) + { + int value; + BOOL succ; + + for(int indx = 0; indx < SIZEOF(settingId); indx++) + { + if(settingId[indx] > 0) + value = SendDlgItemMessage(hwndDlg, settingId[indx], CPM_GETCOLOUR, 0, 0); + else + { + value = GetDlgItemInt(hwndDlg, -settingId[indx], &succ, FALSE); + if(!succ) value = settingDefault[indx]; + } + DBWriteContactSettingDword(NULL,SERVICE_NAME,settingName[indx], value); + } + DBWriteContactSettingDword(NULL,SERVICE_NAME, "base64", (IsDlgButtonChecked(hwndDlg, IDC_ALPHANUM) == BST_CHECKED)?1:0); + + return TRUE; + } + break; + } + + } + + return FALSE; +} diff --git a/plugins/FileAsMessage/src/resource.h b/plugins/FileAsMessage/src/resource.h new file mode 100644 index 0000000000..b6a254dcf7 --- /dev/null +++ b/plugins/FileAsMessage/src/resource.h @@ -0,0 +1,45 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by resources.rc +// +#define IDC_PLAY 1 +#define IDD_DIALOG1 101 +#define IDD_MAIN 101 +#define IDI_SMALLICON 102 +#define IDD_OPTIONS 103 +#define IDI_STOP 104 +#define IDI_PAUSE 105 +#define IDI_PLAY 106 +#define IDI_REFRESH 107 +#define IDC_FILENAME 1001 +#define IDC_BROWSE 1002 +#define IDC_STOP 1003 +#define IDC_REFRESH 1004 +#define IDC_PROGRESS 1005 +#define IDC_STATUS 1006 +#define IDC_FILESIZE 1008 +#define IDC_LIST1 1020 +#define IDC_ALPHANUM 1022 +#define IDC_HIDEDELAY 1051 +#define IDC_CHUNKSIZE 1051 +#define IDC_SHOWDELAY 1052 +#define IDC_SENDDELAY 1052 +#define IDC_SENTCOLOR 1053 +#define IDC_UNSENT 1053 +#define IDC_SENTCOLOR2 1054 +#define IDC_SENT 1054 +#define IDC_SENTCOLOR3 1055 +#define IDC_TOSEND 1055 +#define IDC_SENTCOLOR4 1056 +#define IDC_RECV 1056 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 108 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1022 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif -- cgit v1.2.3