From 960bb20ccd3c375bcfc8b642fcbe89feaf143b22 Mon Sep 17 00:00:00 2001 From: Kirill Volinsky Date: Mon, 2 Jul 2012 08:36:04 +0000 Subject: only add PasteIt, not adapted git-svn-id: http://svn.miranda-ng.org/main/trunk@712 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/PasteIt/PasteIt.cpp | 596 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 596 insertions(+) create mode 100644 plugins/PasteIt/PasteIt.cpp (limited to 'plugins/PasteIt/PasteIt.cpp') diff --git a/plugins/PasteIt/PasteIt.cpp b/plugins/PasteIt/PasteIt.cpp new file mode 100644 index 0000000000..1ae7e1d7e9 --- /dev/null +++ b/plugins/PasteIt/PasteIt.cpp @@ -0,0 +1,596 @@ +/* +Paste It plugin +Copyright (C) 2011 Krzysztof Kral + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation version 2 +of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#include "stdafx.h" +#include "PasteToWeb1.h" +#include "PasteToWeb2.h" +#include "version.h" +#include "resource.h" +#include "Options.h" + +// {1AAC15E8-DCEC-4050-B66F-2AA0E6120C22} +#define MIID_PASTEIT { 0x1aac15e8, 0xdcec, 0x4050, { 0xb6, 0x6f, 0x2a, 0xa0, 0xe6, 0x12, 0xc, 0x22 } } + +PLUGINLINK *pluginLink; +PasteToWeb* pasteToWebs[PasteToWeb::pages]; +std::map* contactWindows; +DWORD gMirandaVersion; + +extern HINSTANCE hInst; +HANDLE hModulesLoaded, hTabsrmmButtonPressed; +HANDLE g_hNetlibUser; +HANDLE hPrebuildContactMenu; +HANDLE hServiceContactMenu; +HGENMENU hContactMenu; +HGENMENU hWebPageMenus[PasteToWeb::pages]; +HANDLE hMainIcon; +HANDLE hOptionsInit; +HANDLE hWindowEvent = NULL; + +#define MODULE "PasteIt" +#define FROM_CLIPBOARD 10 +#define FROM_FILE 11 +#define DEF_PAGES_START 20 +#define MS_PASTEIT_CONTACTMENU "PasteIt/ContactMenu" + +PLUGININFOEX pluginInfo={ + sizeof(PLUGININFOEX), + __PLUGIN_NAME, + PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM), + __DESCRIPTION, + __AUTHOR, + __AUTHOREMAIL, + __COPYRIGHT, + __AUTHORWEB, + UNICODE_AWARE, + 0, + MIID_PASTEIT +}; + +MM_INTERFACE mmi = {0}; +XML_API xi = {0}; +int hLangpack = 0; + +extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion) +{ + gMirandaVersion = mirandaVersion; + if (mirandaVersion < PLUGIN_MAKE_VERSION(0, 8, 0, 0)) + return NULL; + + return &pluginInfo; +} + +static const MUUID interfaces[] = {MIID_PASTEIT, MIID_LAST}; +extern "C" __declspec(dllexport) const MUUID* MirandaPluginInterfaces(void) +{ + return interfaces; +} + +std::wstring GetFile() +{ + TCHAR filter[512]; + _tcscpy_s(filter, 512, TranslateT("All Files (*.*)")); + memcpy(filter + _tcslen(filter), _T("\0*.*\0"), 6 * sizeof(TCHAR)); + TCHAR stzFilePath[1024]; + stzFilePath[0] = 0; + stzFilePath[1] = 0; + OPENFILENAME ofn = {0}; + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = 0; + ofn.lpstrFilter = filter; + ofn.nFilterIndex = 1; + ofn.lpstrFile = stzFilePath; + ofn.lpstrTitle = TranslateT("Paste It - Select file"); + ofn.nMaxFile = 1024; + ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_EXPLORER | OFN_NOCHANGEDIR; + if(GetOpenFileName(&ofn)) + { + return stzFilePath; + } + + return L""; +} + +void PasteIt(HANDLE hContact, int mode) +{ + PasteToWeb* pasteToWeb = pasteToWebs[Options::instance->defWeb]; + if(mode == FROM_CLIPBOARD) + { + pasteToWeb->FromClipboard(); + } + else if(mode == FROM_FILE) + { + std::wstring file = GetFile(); + if(file.length() > 0) + { + pasteToWeb->FromFile(file); + } + else return; + } + else return; + + if(pasteToWeb->szFileLink[0] == 0 && pasteToWeb->error != NULL) + { + MessageBox(NULL, pasteToWeb->error, TranslateT("Error"), MB_OK | MB_ICONERROR); + } + else if(hContact != NULL && pasteToWeb->szFileLink[0] != 0) + { + char *szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + if (szProto && (INT_PTR)szProto != CALLSERVICE_NOTFOUND) + { + BOOL isChat = DBGetContactSettingByte(hContact, szProto, "ChatRoom", 0); + if(Options::instance->autoSend) + { + if(!isChat) + { + DBEVENTINFO dbei = {0}; + dbei.cbSize = sizeof(dbei); + dbei.eventType = EVENTTYPE_MESSAGE; + dbei.flags = DBEF_SENT; + dbei.szModule = szProto; + dbei.timestamp = (DWORD)time(NULL); + dbei.cbBlob = (DWORD)strlen(pasteToWeb->szFileLink) + 1; + dbei.pBlob = (PBYTE)pasteToWeb->szFileLink; + CallService(MS_DB_EVENT_ADD, (WPARAM)hContact, (LPARAM)&dbei); + CallContactService(hContact, PSS_MESSAGE, 0, (LPARAM)pasteToWeb->szFileLink); + } + else + { + // PSS_MESSAGE is not compatible with chat rooms + // there are no simple method to send text to all users + // in chat room. + // First I check if protocol is unicode or ascii. + BOOL isUnicodePlugin = TRUE; + PROTOACCOUNT* protoAc = ProtoGetAccount(szProto); + if(protoAc != NULL) + { + // protoAc->ppro is abstract class, that contains + // methods implemented in protocol ddl`s segment. + // Method address in vptr table must be converted + // to hInstance of protocol dll. + PROTO_INTERFACE* protoInt = protoAc->ppro; + MEMORY_BASIC_INFORMATION mb; + INT_PTR *vptr = *(INT_PTR**)&protoAc->ppro; + INT_PTR *vtable = (INT_PTR *)*vptr; + if(VirtualQuery((void*)vtable[0], &mb, sizeof(MEMORY_BASIC_INFORMATION))) + { + typedef PLUGININFO * (__cdecl * Miranda_Plugin_Info) ( DWORD mirandaVersion ); + typedef PLUGININFOEX * (__cdecl * Miranda_Plugin_InfoEx) ( DWORD mirandaVersion ); + HINSTANCE hInst = (HINSTANCE)mb.AllocationBase; + // Now I can get PLUGININFOEX from protocol + Miranda_Plugin_Info info = (Miranda_Plugin_Info) GetProcAddress(hInst, "MirandaPluginInfo"); + Miranda_Plugin_InfoEx infoEx = (Miranda_Plugin_InfoEx) GetProcAddress(hInst, "MirandaPluginInfoEx"); + PLUGININFOEX* pi = NULL; + if(infoEx != NULL) + { + pi = infoEx(gMirandaVersion); + } + else if(info != NULL) + { + pi = (PLUGININFOEX*)info(gMirandaVersion); + } + + // If PLUGININFOEX flags contains UNICODE_AWARE, + // this mean that protocol is unicode. + if(pi != NULL && pi->cbSize >= sizeof(PLUGININFO)) + { + isUnicodePlugin = pi->flags & UNICODE_AWARE; + } + } + } + + // Next step is to get all protocol sessions and find + // one with correct hContact + GC_INFO gci = {0}; + GCDEST gcd = {0}; + GCEVENT gce = {0}; + int cnt = (int)CallService(MS_GC_GETSESSIONCOUNT, 0, (LPARAM)szProto); + for (int i = 0; i < cnt ; i++ ) + { + gci.iItem = i; + gci.pszModule = szProto; + gci.Flags = BYINDEX | HCONTACT | ID; + CallService(MS_GC_GETINFO, 0, (LPARAM)(GC_INFO *) &gci); + if (gci.hContact == hContact) + { + // In this place session was finded, gci.pszID contains + // session ID, but it is in unicode or ascii format, + // depends on protocol wersion + gcd.pszModule = szProto; + gcd.iType = GC_EVENT_SENDMESSAGE; + gcd.ptszID = gci.pszID; + gce.cbSize = sizeof(GCEVENT); + gce.pDest = &gcd; + gce.bIsMe = TRUE; + gce.dwFlags = isUnicodePlugin ? (GCEF_ADDTOLOG | GC_UNICODE) : GCEF_ADDTOLOG; + wchar_t* s = NULL; + if(isUnicodePlugin) + { + // If session ID is in unicode, text must be too in unicode + s = mir_a2u_cp(pasteToWeb->szFileLink, CP_ACP); + gce.ptszText = s; + } + else + { + // If session ID is in ascii, text must be too in ascii + gce.pszText = pasteToWeb->szFileLink; + } + gce.time = time(NULL); + CallService(MS_GC_EVENT, 0, (LPARAM)(GCEVENT *) &gce); + if(s != NULL) + mir_free(s); + break; + } + } + } + + // Send message to focus window + CallServiceSync(MS_MSG_SENDMESSAGE, (WPARAM)hContact, 0); + } + else + { + if(isChat) + { + // MS_MSG_SENDMESSAGE in incompatible with chat rooms, + // because it sends text to IDC_MESSAGE window, + // but in chat rooms is only IDC_CHAT_MESSAGE window. + // contactWindows map contains all opened hContact + // with assaigned to them chat windows. + // This map is prepared in ME_MSG_WINDOWEVENT event. + std::map::iterator it = contactWindows->find(hContact); + if(it != contactWindows->end()) + { + // it->second is imput window, so now I can send to them + // new text. Afterr all is sended MS_MSG_SENDMESSAGE + // to focus window. + SendMessage(it->second, EM_SETSEL, -1, SendMessage(it->second, WM_GETTEXTLENGTH, 0, 0)); + SendMessageA(it->second, EM_REPLACESEL, FALSE, (LPARAM)pasteToWeb->szFileLink); + CallServiceSync(MS_MSG_SENDMESSAGE, (WPARAM)hContact, NULL); + } + else + { + // If window do not exist, maybe it is not chat + CallServiceSync(MS_MSG_SENDMESSAGE, (WPARAM)hContact, (LPARAM)pasteToWeb->szFileLink); + } + } + else + { + CallServiceSync(MS_MSG_SENDMESSAGE, (WPARAM)hContact, (LPARAM)pasteToWeb->szFileLink); + } + } + } + } +} + +int TabsrmmButtonPressed(WPARAM wParam, LPARAM lParam) +{ + CustomButtonClickData *cbc = (CustomButtonClickData *)lParam; + HANDLE hContact = (HANDLE)wParam; + + if (!strcmp(cbc->pszModule, MODULE) && cbc->dwButtonId == 1 && hContact) + { + if (cbc->flags == BBCF_ARROWCLICKED) + { + HMENU hMenu = CreatePopupMenu(); + if (hMenu) + { + AppendMenu(hMenu, MF_STRING, FROM_CLIPBOARD, TranslateT("Paste from clipboard")); + AppendMenu(hMenu, MF_STRING, FROM_FILE, TranslateT("Paste from file")); + HMENU hDefMenu = CreatePopupMenu(); + for(int i = 0 ; i < PasteToWeb::pages; ++i) + { + UINT flags = MF_STRING; + if(Options::instance->defWeb == i) + flags |= MF_CHECKED; + + AppendMenu(hDefMenu, flags, DEF_PAGES_START + i, pasteToWebs[i]->GetName()); + } + + AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT_PTR)hDefMenu, TranslateT("Default web page")); + + POINT pt; + GetCursorPos(&pt); + HWND hwndBtn = WindowFromPoint(pt); + if (hwndBtn) + { + RECT rc; + GetWindowRect(hwndBtn, &rc); + SetForegroundWindow(cbc->hwndFrom); + int selected = TrackPopupMenu(hMenu, TPM_RETURNCMD, rc.left, rc.bottom, 0, cbc->hwndFrom, 0); + if (selected != 0) + { + if(selected >= DEF_PAGES_START) + { + Options::instance->SetDefWeb(selected - DEF_PAGES_START); + } + else + { + PasteIt(hContact, selected); + } + } + } + + DestroyMenu(hDefMenu); + DestroyMenu(hMenu); + } + } + else + { + PasteIt(hContact, FROM_CLIPBOARD); + } + } + + return 0; +} + +int PrebuildContactMenu(WPARAM wParam, LPARAM lParam) +{ + bool bIsContact = false; + + char *szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, wParam, 0); + if (szProto && (INT_PTR)szProto != CALLSERVICE_NOTFOUND) bIsContact = (CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_IM) ? true : false; + + CLISTMENUITEM mi = {0}; + mi.cbSize = sizeof(mi); + mi.flags = CMIM_FLAGS; + + if (!bIsContact) mi.flags |= CMIF_HIDDEN; + else mi.flags &= ~CMIF_HIDDEN; + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hContactMenu, (LPARAM)&mi); + + return 0; +} + +INT_PTR ContactMenuService(WPARAM wParam, LPARAM lParam) +{ + if(lParam >= DEF_PAGES_START) + { + Options::instance->SetDefWeb(lParam - DEF_PAGES_START); + } + else + { + HANDLE hContact = (HANDLE)wParam; + PasteIt(hContact, lParam); + } + return 0; +} + +void InitIcolib() +{ + TCHAR stzFile[MAX_PATH]; + + SKINICONDESC sid = {0}; + sid.cbSize = sizeof(sid); + sid.cx = sid.cy = 16; + sid.ptszDefaultFile = stzFile; + sid.ptszSection = LPGENT("Paste It"); + sid.flags = SIDF_ALL_TCHAR; + + GetModuleFileName(hInst, stzFile, MAX_PATH); + + sid.pszName = "PasteIt_main"; + sid.ptszDescription = LPGENT("Paste It"); + sid.iDefaultIndex = -IDI_MENU; + hMainIcon = (HANDLE)CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid); +} + +void InitMenuItems() +{ + CLISTMENUITEM mi = {0}; + CLISTMENUITEM mi2 = {0}; + + mi.cbSize = sizeof(mi); + mi.flags = CMIF_ROOTPOPUP | CMIF_ICONFROMICOLIB | CMIF_TCHAR; + mi.icolibItem = hMainIcon; + mi.position = 3000090005; + mi.ptszName = _T("Paste It"); + + hContactMenu = (HGENMENU)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&mi); + + memset(&mi, 0, sizeof(mi)); + mi.cbSize = sizeof(mi); + mi.flags = CMIF_CHILDPOPUP | CMIF_ROOTHANDLE | CMIF_TCHAR; + mi.pszService = MS_PASTEIT_CONTACTMENU; + mi.hParentMenu = hContactMenu; + mi.popupPosition = FROM_CLIPBOARD; + mi.ptszName = _T("Paste from clipboard"); + CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&mi); + + mi.popupPosition = FROM_FILE; + mi.ptszName = _T("Paste from file"); + CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&mi); + + mi.popupPosition = DEF_PAGES_START - 1; + mi.ptszName = _T("Default web page"); + HGENMENU hDefWebMenu = (HGENMENU)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&mi); + + mi2.cbSize = sizeof(mi2); + mi2.pszService = MS_PASTEIT_CONTACTMENU; + mi2.hParentMenu = hDefWebMenu; + for(int i = 0 ; i < PasteToWeb::pages; ++i) + { + mi2.flags = CMIF_CHILDPOPUP | CMIF_ROOTHANDLE | CMIF_TCHAR; + if(Options::instance->defWeb == i) + mi2.flags |= CMIF_CHECKED; + mi2.ptszName = pasteToWebs[i]->GetName(); + mi2.popupPosition = mi2.position = DEF_PAGES_START + i; + hWebPageMenus[i] = (HGENMENU)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&mi2); + } + + hPrebuildContactMenu = HookEvent(ME_CLIST_PREBUILDCONTACTMENU, PrebuildContactMenu); +} + +void DefWebPageChanged() +{ + CLISTMENUITEM mi = {0}; + mi.cbSize = sizeof(mi); + + for (int i = 0; i < PasteToWeb::pages; i++) + { + mi.flags = CMIM_FLAGS; + if (Options::instance->defWeb == i) + { + mi.flags |= CMIF_CHECKED; + } + + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hWebPageMenus[i], (LPARAM)&mi); + } +} + +void InitTabsrmmButton() +{ + if (ServiceExists(MS_BB_ADDBUTTON)) + { + BBButton btn = {0}; + btn.cbSize = sizeof(btn); + btn.dwButtonID = 1; + btn.pszModuleName = MODULE; + btn.dwDefPos = 110; + btn.hIcon = hMainIcon; + btn.bbbFlags = BBBF_ISARROWBUTTON | BBBF_ISIMBUTTON | BBBF_ISLSIDEBUTTON | BBBF_CANBEHIDDEN | BBBF_ISCHATBUTTON; + btn.ptszTooltip = TranslateT("Paste It"); + CallService(MS_BB_ADDBUTTON, 0, (LPARAM)&btn); + if(hTabsrmmButtonPressed != NULL) + { + UnhookEvent(hTabsrmmButtonPressed); + } + + hTabsrmmButtonPressed = HookEvent(ME_MSG_BUTTONPRESSED, TabsrmmButtonPressed); + } +} + +void InitUpdater() +{ + if (ServiceExists(MS_UPDATE_REGISTER)) + { + Update update = {0}; + char szVersion[16]; + update.cbSize = sizeof(Update); + update.szComponentName = pluginInfo.shortName; + update.pbVersion = (BYTE *)CreateVersionStringPluginEx(&pluginInfo, szVersion); + update.cpbVersion = (int)strlen((char *)update.pbVersion); + +#ifdef _WIN64 + update.szUpdateURL = "http://programista.free.of.pl/miranda/PasteIt64.zip"; +#else + update.szUpdateURL = "http://programista.free.of.pl/miranda/PasteIt.zip"; +#endif + update.szVersionURL = "http://programista.free.of.pl/miranda/PasteItVersion.txt"; + update.pbVersionPrefix = (BYTE *)"Paste It "; + update.cpbVersionPrefix = (int)strlen((char *)update.pbVersionPrefix); + CallService(MS_UPDATE_REGISTER, 0, (WPARAM)&update); + } +} + +int WindowEvent(WPARAM wParam, MessageWindowEventData* lParam) +{ + if(lParam->uType == MSG_WINDOW_EVT_OPEN) + { + char *szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)lParam->hContact, 0); + if (szProto && (INT_PTR)szProto != CALLSERVICE_NOTFOUND) + { + if(DBGetContactSettingByte(lParam->hContact, szProto, "ChatRoom", 0)) + { + (*contactWindows)[lParam->hContact] = lParam->hwndInput; + } + } + } + else if(lParam->uType == MSG_WINDOW_EVT_CLOSE) + { + std::map::iterator it = contactWindows->find(lParam->hContact); + if(it != contactWindows->end()) + { + contactWindows->erase(it); + } + } + + return 0; +} + +int ModulesLoaded(WPARAM wParam, LPARAM lParam) +{ + InitIcolib(); + InitMenuItems(); + InitTabsrmmButton(); + InitUpdater(); + hWindowEvent = HookEvent(ME_MSG_WINDOWEVENT, (MIRANDAHOOK)WindowEvent); + + return 0; +} + +extern "C" int __declspec(dllexport) Load(PLUGINLINK *link) +{ + pluginLink = link; + mir_getMMI(&mmi); + mir_getXI(&xi); + mir_getLP(&pluginInfo); + NETLIBUSER nlu = {0}; + nlu.cbSize = sizeof(nlu); + nlu.flags = NUF_TCHAR | NUF_OUTGOING | NUF_HTTPCONNS; + nlu.szSettingsModule = MODULE; + nlu.ptszDescriptiveName = TranslateT("Paste It HTTP connections"); + g_hNetlibUser = ( HANDLE )CallService( MS_NETLIB_REGISTERUSER, 0, ( LPARAM )&nlu ); + + pasteToWebs[0] = new PasteToWeb1(); + pasteToWebs[0]->pageIndex = 0; + pasteToWebs[1] = new PasteToWeb2(); + pasteToWebs[1]->pageIndex = 1; + Options::instance = new Options(); + pasteToWebs[0]->ConfigureSettings(); + pasteToWebs[1]->ConfigureSettings(); + Options::instance->Load(); + hModulesLoaded = HookEvent(ME_SYSTEM_MODULESLOADED, ModulesLoaded); + hOptionsInit = HookEvent(ME_OPT_INITIALISE, Options::InitOptions); + hTabsrmmButtonPressed = NULL; + hServiceContactMenu = CreateServiceFunction(MS_PASTEIT_CONTACTMENU, ContactMenuService); + contactWindows = new std::map(); + return 0; +} + +extern "C" int __declspec(dllexport) Unload(void) +{ + UnhookEvent(hModulesLoaded); + UnhookEvent(hPrebuildContactMenu); + UnhookEvent(hOptionsInit); + if(hWindowEvent != NULL) + { + UnhookEvent(hWindowEvent); + } + DestroyServiceFunction(hServiceContactMenu); + Netlib_CloseHandle(g_hNetlibUser); + if(hTabsrmmButtonPressed != NULL) + { + UnhookEvent(hTabsrmmButtonPressed); + } + for(int i=0; i < PasteToWeb::pages; ++i) + { + if(pasteToWebs[i] != NULL) + { + delete pasteToWebs[i]; + pasteToWebs[i] = NULL; + } + } + if(Options::instance != NULL) + { + delete Options::instance; + Options::instance = NULL; + } + + delete contactWindows; + return 0; +} -- cgit v1.2.3