/* IRC plugin for Miranda IM Copyright (C) 2003 Jörgen Persson This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "irc.h" CIrcSessionInfo si; HANDLE g_hModulesLoaded = NULL; HANDLE g_hSystemPreShutdown = NULL; HANDLE g_hContactDblClick = NULL; HANDLE g_hEventDblClick = NULL; HANDLE g_hContactDeleted = NULL; HANDLE g_hIconsChanged = NULL; HANDLE g_hUserInfoInit = NULL; HANDLE g_hMenuCreation = NULL; HANDLE g_hGCUserEvent = NULL; HANDLE g_hGCMenuBuild = NULL; HANDLE g_hOptionsInit = NULL; HANDLE hContactMenu1 = NULL; HANDLE hContactMenu2 = NULL; HANDLE hContactMenu3 = NULL; HANDLE hMenuQuick = NULL; HANDLE hMenuJoin = NULL; HANDLE hMenuNick = NULL; HANDLE hMenuList = NULL; HANDLE hMenuServer = NULL; HANDLE hMenuAvatar = NULL; HANDLE hMenuConsole = NULL; HANDLE hNetlib = NULL; HANDLE hNetlibDCC = NULL; HWND join_hWnd = NULL; HWND quickconn_hWnd = NULL; volatile bool bChatInstalled = FALSE; bool bMbotInstalled = FALSE; extern HWND nick_hWnd; extern HWND list_hWnd ; int RetryCount =0; int PortCount =0; DWORD bConnectRequested = 0; DWORD bConnectThreadRunning = 0; extern bool bTempDisableCheck ; extern bool bTempForceCheck ; extern bool bPerformDone; int iTempCheckTime = 0; int OldStatus= ID_STATUS_OFFLINE; int GlobalStatus = ID_STATUS_OFFLINE; UINT_PTR RetryTimer = 0; String StatusMessage =""; extern CIrcSession g_ircSession; extern char * IRCPROTONAME; extern char * ALTIRCPROTONAME; extern char * pszServerFile; extern char * pszPerformFile; extern char * pszIgnoreFile; extern PREFERENCES* prefs; extern CRITICAL_SECTION cs; extern CRITICAL_SECTION m_gchook; extern bool nickflag; extern String sUserModes; extern String sUserModePrefixes; extern String sChannelPrefixes; extern String sChannelModes; extern String WhoisAwayReply ; extern char mirandapath[MAX_PATH]; extern MM_INTERFACE mmi; GETEVENTFUNC pfnAddEvent = 0; // Nudge extern HANDLE hIRCNudge; // PopUp bool whois_popup=true; // Updater extern PLUGININFO pluginInfo; // xStatus HANDLE hHookUserMenu = NULL; HANDLE hUserMenuXStatus = NULL; // IcoLib HANDLE hHookIconsChanged = NULL; VOID CALLBACK RetryTimerProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime); int Service_SetMyAvatar(WPARAM wParam, LPARAM lParam); static void InitMenus(void) { CLISTMENUITEM mi = { 0 }; char temp[MAXMODULELABELLENGTH]; ZeroMemory(&mi, sizeof(mi)); mi.cbSize = sizeof(mi); if (bChatInstalled) { mi.pszName = Translate("&Quick connect"); mi.hIcon = LoadIconEx(IDI_QUICK,"quick",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON)); wsprintf(temp,"%s/QuickConnectMenu", IRCPROTONAME); mi.pszService = temp; mi.popupPosition = 500090000; mi.pszPopupName = ALTIRCPROTONAME; hMenuQuick= (void *)CallService(MS_CLIST_ADDMAINMENUITEM, (WPARAM)0, (LPARAM)&mi); mi.pszName = Translate("&Join a channel"); mi.hIcon = LoadIconEx(IDI_JOIN,"join",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON)); wsprintf(temp,"%s/JoinChannelMenu", IRCPROTONAME); mi.pszService = temp; mi.popupPosition = 500090001; mi.pszPopupName = ALTIRCPROTONAME; hMenuJoin = (void *)CallService(MS_CLIST_ADDMAINMENUITEM, (WPARAM)0, (LPARAM)&mi); mi.pszName = Translate("&Change your nickname"); mi.hIcon = LoadIconEx(IDI_WHOIS,"whois",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON)); wsprintf(temp,"%s/ChangeNickMenu", IRCPROTONAME); mi.pszService = temp; mi.popupPosition = 500090002; mi.pszPopupName = ALTIRCPROTONAME; hMenuNick = (void *)CallService(MS_CLIST_ADDMAINMENUITEM, (WPARAM)0, (LPARAM)&mi); mi.pszName = Translate("Show the &list of available channels"); mi.hIcon = LoadIconEx(IDI_LIST,"list",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON)); wsprintf(temp,"%s/ShowListMenu", IRCPROTONAME); mi.pszService = temp; mi.popupPosition = 500090003; mi.pszPopupName = ALTIRCPROTONAME; hMenuList = (void *)CallService(MS_CLIST_ADDMAINMENUITEM, (WPARAM)0, (LPARAM)&mi); mi.pszName = Translate("&Show the server window"); mi.hIcon = LoadIconEx(IDI_SERVER,"server",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON)); wsprintf(temp,"%s/ShowServerMenu", IRCPROTONAME); mi.pszService = temp; mi.popupPosition = 500090004; mi.pszPopupName = ALTIRCPROTONAME; hMenuServer = (void *)CallService(MS_CLIST_ADDMAINMENUITEM, (WPARAM)0, (LPARAM)&mi); if(prefs->AvatarsEnabled) { mi.pszName = Translate("Set proto picture"); mi.hIcon = LoadIconEx(IDI_AVATAR,"avatar",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON)); wsprintf(temp,"%s/SetAvatarMenu", IRCPROTONAME); mi.pszService = temp; mi.popupPosition = 500090005; mi.pszPopupName = ALTIRCPROTONAME; hMenuAvatar = (void *)CallService(MS_CLIST_ADDMAINMENUITEM, (WPARAM)0, (LPARAM)&mi); } } mi.pszName = Translate("&Leave the channel"); mi.hIcon = LoadIconEx(IDI_DELETE,"delete",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON)); wsprintf(temp,"%s/Menu1ChannelMenu", IRCPROTONAME); mi.pszService = temp; mi.pszContactOwner = IRCPROTONAME; mi.popupPosition = 500090000; hContactMenu1 = (void *)CallService(MS_CLIST_ADDCONTACTMENUITEM, (WPARAM)0, (LPARAM)&mi); mi.pszName = Translate("&User details"); mi.hIcon = LoadIconEx(IDI_WHOIS,"whois",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON)); wsprintf(temp,"%s/Menu2ChannelMenu", IRCPROTONAME); mi.pszService = temp; mi.pszContactOwner = IRCPROTONAME; mi.popupPosition = 500090001; hContactMenu2 = (void *)CallService(MS_CLIST_ADDCONTACTMENUITEM, (WPARAM)0, (LPARAM)&mi); mi.pszName = Translate("&Ignore"); mi.hIcon = LoadIconEx(IDI_BLOCK,"block",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON)); wsprintf(temp,"%s/Menu3ChannelMenu", IRCPROTONAME); mi.pszService = temp; mi.pszContactOwner = IRCPROTONAME; mi.popupPosition = 500090002; hContactMenu3 = (void *)CallService(MS_CLIST_ADDCONTACTMENUITEM, (WPARAM)0, (LPARAM)&mi); mi.pszName = IRCTranslate("Show custom status details"); mi.hIcon = NULL; // dynamically updated wsprintf(temp,"%s%s", IRCPROTONAME, MS_XSTATUS_SHOWDETAILS); mi.pszService = temp; mi.flags=CMIF_NOTOFFLINE; mi.popupPosition = 500090003; hUserMenuXStatus = (HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&mi); CLISTMENUITEM clmi; memset( &clmi, 0, sizeof( clmi )); clmi.cbSize = sizeof( clmi ); clmi.flags = CMIM_FLAGS|CMIF_GRAYED; CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hMenuJoin, ( LPARAM )&clmi ); CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hMenuList, ( LPARAM )&clmi ); CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hMenuNick, ( LPARAM )&clmi ); if(!prefs->UseServer) CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hMenuServer, ( LPARAM )&clmi ); return; } static int Service_FileAllow(WPARAM wParam,LPARAM lParam) { CCSDATA *ccs = (CCSDATA *) lParam; DCCINFO * di = (DCCINFO *) ccs->wParam;; if (g_ircSession) { String sFile = (String)(char *)ccs->lParam + di->sFile; di->sFileAndPath = sFile; di->sPath = (char *)ccs->lParam; CDccSession * dcc = new CDccSession(di); g_ircSession.AddDCCSession(di, dcc); dcc->Connect(); } else delete di; return ccs->wParam; } static int Service_FileDeny(WPARAM wParam,LPARAM lParam) { CCSDATA *ccs = (CCSDATA *) lParam; DCCINFO * di = (DCCINFO *) ccs->wParam; delete di; return 0; } static int Service_FileCancel(WPARAM wParam,LPARAM lParam) { CCSDATA *ccs = (CCSDATA *) lParam; DCCINFO *di = (DCCINFO *) ccs->wParam; CDccSession * dcc = g_ircSession.FindDCCSession(di); if (dcc) { InterlockedExchange(&dcc->dwWhatNeedsDoing, (long)FILERESUME_CANCEL); SetEvent(dcc->hEvent); dcc->Disconnect(); } return 0; } static int Service_FileSend(WPARAM wParam,LPARAM lParam) { CCSDATA *ccs = (CCSDATA *) lParam; char **files = (char **) ccs->lParam; DCCINFO * dci = NULL; int iPort = 0; int index= 0; DWORD size = 0; // do not send to channels :-P if(DBGetContactSettingByte(ccs->hContact, IRCPROTONAME, "ChatRoom", 0) != 0) return 0; // stop if it is an active type filetransfer and the user's IP is not known unsigned long ulAdr = 0; if (prefs->ManualHost) ulAdr = ConvertIPToInteger(prefs->MySpecifiedHostIP); else ulAdr = ConvertIPToInteger(prefs->IPFromServer?prefs->MyHost:prefs->MyLocalHost); if(!prefs->DCCPassive && !ulAdr) { DoEvent(GC_EVENT_INFORMATION, 0, g_ircSession.GetInfo().sNick.c_str(), Translate("DCC ERROR: Unable to automatically resolve external IP"), NULL, NULL, NULL, true, false); return 0; } if(files[index]) { //get file size FILE * hFile = NULL; while (files[index] && hFile == 0) { hFile = fopen ( files[index] , "rb" ); if(hFile) { fseek (hFile , 0 , SEEK_END); size = ftell (hFile); rewind (hFile); fclose(hFile); break; } index++; } if(size == 0) { DoEvent(GC_EVENT_INFORMATION, 0, g_ircSession.GetInfo().sNick.c_str(), Translate("DCC ERROR: No valid files specified"), NULL, NULL, NULL, true, false); return 0; } DBVARIANT dbv; if (!DBGetContactSetting(ccs->hContact, IRCPROTONAME, "Nick", &dbv) && dbv.type == DBVT_ASCIIZ) { // set up a basic DCCINFO struct and pass it to a DCC object dci = new DCCINFO; dci->sFileAndPath = files[index]; int i = dci->sFileAndPath.rfind("\\", dci->sFileAndPath.length()); if (i != string::npos) { dci->sPath = dci->sFileAndPath.substr(0, i+1); dci->sFile = dci->sFileAndPath.substr(i+1, dci->sFileAndPath.length()); } String sFileWithQuotes = dci->sFile; // if spaces in the filename surround witrh quotes if (sFileWithQuotes.find(' ', 0) != string::npos) { sFileWithQuotes.insert(0, "\""); sFileWithQuotes.insert(sFileWithQuotes.length(), "\""); } dci->hContact = ccs->hContact; dci->sContactName = dbv.pszVal; dci->iType = DCC_SEND; dci->bReverse = prefs->DCCPassive?true:false; dci->bSender = true; dci->dwSize = size; // create new dcc object CDccSession * dcc = new CDccSession(dci); // keep track of all objects created g_ircSession.AddDCCSession(dci, dcc); // need to make sure that %'s are doubled to avoid having chat interpret as color codes String sFileCorrect = ReplaceString(dci->sFile, "%", "%%"); // is it an reverse filetransfer (receiver acts as server) if(dci->bReverse) { char szTemp[256]; PostIrcMessage("/CTCP %s DCC SEND %s 200 0 %u %u", dci->sContactName.c_str(), sFileWithQuotes.c_str(), dci->dwSize, dcc->iToken); mir_snprintf(szTemp, sizeof(szTemp), Translate("DCC reversed file transfer request sent to %s [%s]"), dci->sContactName.c_str(), sFileCorrect.c_str()); DoEvent(GC_EVENT_INFORMATION, 0, g_ircSession.GetInfo().sNick.c_str(), szTemp, NULL, NULL, NULL, true, false); mir_snprintf(szTemp, sizeof(szTemp), "/NOTICE %s I am sending the file \'\002%s\002\' (%u kB) to you, please accept it. [Reverse transfer]", dci->sContactName.c_str(), sFileCorrect.c_str(), dci->dwSize/1024); if(prefs->SendNotice) PostIrcMessage(szTemp); } else // ... normal filetransfer. { iPort = dcc->Connect(); if(iPort) { char szTemp[256]; PostIrcMessage("/CTCP %s DCC SEND %s %u %u %u", dci->sContactName.c_str(), sFileWithQuotes.c_str(), ulAdr, iPort, dci->dwSize); mir_snprintf(szTemp, sizeof(szTemp), Translate("DCC file transfer request sent to %s [%s]"), dci->sContactName.c_str(), sFileCorrect.c_str()); DoEvent(GC_EVENT_INFORMATION, 0, g_ircSession.GetInfo().sNick.c_str(), szTemp, NULL, NULL, NULL, true, false); mir_snprintf(szTemp, sizeof(szTemp), "/NOTICE %s I am sending the file \'\002%s\002\' (%u kB) to you, please accept it. [IP: %s]", dci->sContactName.c_str(), sFileCorrect.c_str(), dci->dwSize/1024, ConvertIntegerToIP(ulAdr)); if(prefs->SendNotice) PostIrcMessage(szTemp); } else DoEvent(GC_EVENT_INFORMATION, 0, g_ircSession.GetInfo().sNick.c_str(), Translate("DCC ERROR: Unable to bind local port"), NULL, NULL, NULL, true, false); } // fix for sending multiple files index++; while(files[index]) { hFile = NULL; hFile = fopen ( files[index] , "rb" ); if(hFile) { fclose(hFile); PostIrcMessage("/DCC SEND %s %s", dci->sContactName.c_str(), files[index]); } index++; } DBFreeVariant(&dbv); } } if(dci) return (int)(HANDLE) dci; return NULL; } static int Service_FileReceive(WPARAM wParam,LPARAM lParam) { DBEVENTINFO dbei; CCSDATA *ccs = (CCSDATA *) lParam; PROTORECVEVENT *pre = (PROTORECVEVENT *) ccs->lParam; char *szDesc, *szFile; DBDeleteContactSetting(ccs->hContact, "CList", "Hidden"); szFile = pre->szMessage + sizeof(DWORD); szDesc = szFile + strlen(szFile) + 1; ZeroMemory(&dbei, sizeof(dbei)); dbei.cbSize = sizeof(dbei); dbei.szModule = IRCPROTONAME; dbei.timestamp = pre->timestamp; dbei.flags = pre->flags & (PREF_CREATEREAD ? DBEF_READ : 0); dbei.eventType = EVENTTYPE_FILE; dbei.cbBlob = sizeof(DWORD) + strlen(szFile) + strlen(szDesc) + 2; dbei.pBlob = (PBYTE) pre->szMessage; CallService(MS_DB_EVENT_ADD, (WPARAM) ccs->hContact, (LPARAM) &dbei); return 0; } static int Service_FileResume(WPARAM wParam,LPARAM lParam) { DCCINFO * di = (DCCINFO *) wParam; PROTOFILERESUME * pfr = (PROTOFILERESUME *) lParam; long i = (long)pfr->action; CDccSession * dcc = g_ircSession.FindDCCSession(di); if(dcc) { InterlockedExchange(&dcc->dwWhatNeedsDoing, i); if(pfr->action == FILERESUME_RENAME) { char * szTemp = strdup(pfr->szFilename); InterlockedExchange((volatile long*)&dcc->NewFileName, (long)szTemp); } if(pfr->action == FILERESUME_RESUME) { DWORD dwPos = 0; String sFile; char * pszTemp = NULL;; FILE * hFile = NULL; hFile = fopen(di->sFileAndPath.c_str(), "rb"); if(hFile) { fseek(hFile,0,SEEK_END); dwPos = ftell(hFile); rewind (hFile); fclose(hFile); hFile = NULL; } String sFileWithQuotes = di->sFile; // if spaces in the filename surround witrh quotes if (sFileWithQuotes.find(' ', 0) != string::npos) { sFileWithQuotes.insert(0, "\""); sFileWithQuotes.insert(sFileWithQuotes.length(), "\""); } if (di->bReverse) PostIrcMessage("/PRIVMSG %s \001DCC RESUME %s 0 %u %s\001", di->sContactName.c_str(), sFileWithQuotes.c_str(), dwPos, dcc->di->sToken.c_str()); else PostIrcMessage("/PRIVMSG %s \001DCC RESUME %s %u %u\001", di->sContactName.c_str(), sFileWithQuotes.c_str(), di->iPort, dwPos); return 0; } SetEvent(dcc->hEvent); } return 0; } static int Service_EventDoubleclicked(WPARAM wParam,LPARAM lParam) { if (!lParam) return 0; CLISTEVENT* pcle = (CLISTEVENT*)lParam; if(DBGetContactSettingByte((HANDLE) pcle->hContact, IRCPROTONAME, "DCC", 0) != 0) { char szTemp[500]; DCCINFO * pdci = (DCCINFO *) pcle->lParam; HWND hWnd = CreateDialogParam(g_hInstance,MAKEINTRESOURCE(IDD_MESSAGEBOX),NULL,MessageboxWndProc, (LPARAM)pdci); mir_snprintf(szTemp, sizeof(szTemp), Translate("%s (%s) is requesting a client-to-client chat connection."), pdci->sContactName.c_str(), pdci->sHostmask.c_str() ); SetDlgItemText(hWnd,IDC_TEXT, szTemp); ShowWindow(hWnd, SW_SHOW); return 1; } return 0; } int Service_UserDeletedContact(WPARAM wp, LPARAM lp) { DBVARIANT dbv; HANDLE hContact = (HANDLE) wp; if (!hContact) return 0; if (!DBGetContactSetting((HANDLE)wp, IRCPROTONAME, "Nick", &dbv) && dbv.type == DBVT_ASCIIZ ) { int type = DBGetContactSettingByte(hContact, IRCPROTONAME, "ChatRoom", 0); if ( type != 0) { GCEVENT gce = {0}; GCDEST gcd = {0}; String S = ""; if(type == GCW_CHATROOM) S = MakeWndID(dbv.pszVal); if(type == GCW_SERVER) S = "Network log"; gce.cbSize = sizeof(GCEVENT); gce.dwItemData = 0; gcd.iType = GC_EVENT_CONTROL; gcd.pszModule = IRCPROTONAME; gce.pDest = &gcd; gcd.pszID = (char *)S.c_str(); int i = CallChatEvent( SESSION_TERMINATE, (LPARAM)&gce); if (i && type == GCW_CHATROOM) PostIrcMessage( "/PART %s", dbv.pszVal); } else { BYTE bDCC = DBGetContactSettingByte((HANDLE)wp, IRCPROTONAME, "DCC", 0) ; if(bDCC) { CDccSession * dcc = g_ircSession.FindDCCSession((HANDLE)wp); if(dcc) dcc->Disconnect(); } } DBFreeVariant(&dbv); } return 0; } static int Service_Menu1Command(WPARAM wp, LPARAM lp) { DBVARIANT dbv; if (!wp ) return 0; if (!DBGetContactSetting((HANDLE)wp, IRCPROTONAME, "Nick", &dbv) && dbv.type == DBVT_ASCIIZ ) { int type = DBGetContactSettingByte((HANDLE)wp, IRCPROTONAME, "ChatRoom", 0); if ( type != 0) { GCEVENT gce = {0}; GCDEST gcd = {0}; String S = ""; if(type == GCW_CHATROOM) S = MakeWndID(dbv.pszVal); if(type == GCW_SERVER) S = "Network log"; gcd.iType = GC_EVENT_CONTROL; gcd.pszID = (char *)S.c_str(); gcd.pszModule = IRCPROTONAME; gce.cbSize = sizeof(GCEVENT); gce.pDest = &gcd; CallChatEvent( WINDOW_VISIBLE, (LPARAM)&gce); } else CallService(MS_MSG_SENDMESSAGE, (WPARAM)wp, 0); } return 0; } static int Service_Menu2Command(WPARAM wp, LPARAM lp) { DBVARIANT dbv; if (!wp ) return 0; if (!DBGetContactSetting((HANDLE)wp, IRCPROTONAME, "Nick", &dbv) && dbv.type == DBVT_ASCIIZ ) { int type = DBGetContactSettingByte((HANDLE)wp, IRCPROTONAME, "ChatRoom", 0); if ( type != 0) { if (type == GCW_CHATROOM) PostIrcMessage( "/PART %s", dbv.pszVal); GCEVENT gce = {0}; GCDEST gcd = {0}; String S = ""; if(type == GCW_CHATROOM) S = MakeWndID(dbv.pszVal); if(type == GCW_SERVER) S = "Network log"; gce.cbSize = sizeof(GCEVENT); gcd.iType = GC_EVENT_CONTROL; gcd.pszModule = IRCPROTONAME; gce.pDest = &gcd; gcd.pszID = (char *)S.c_str(); CallChatEvent( SESSION_TERMINATE, (LPARAM)&gce); } else { BYTE bDCC = DBGetContactSettingByte((HANDLE)wp, IRCPROTONAME, "DCC", 0) ; if(bDCC) { CDccSession * dcc = g_ircSession.FindDCCSession((HANDLE)wp); if(dcc) dcc->Disconnect(); } else { PostIrcMessage( "/WHOIS %s", dbv.pszVal); whois_popup = true; } } DBFreeVariant(&dbv); } return 0; } static int Service_Menu3Command(WPARAM wp, LPARAM lp) { if (!wp ) return 0; HANDLE hContact = (HANDLE) wp; DBVARIANT dbv; if (!DBGetContactSetting(hContact, IRCPROTONAME, "Nick", &dbv) && dbv.type == DBVT_ASCIIZ ) { if (DBGetContactSettingByte((HANDLE)wp, IRCPROTONAME, "ChatRoom", 0) ==0) { char * host = NULL; DBVARIANT dbv1; if (!DBGetContactSetting((HANDLE) wp, IRCPROTONAME, "Host", &dbv1) && dbv1.type == DBVT_ASCIIZ) host = dbv1.pszVal; if (host) { String S; if(prefs->IgnoreChannelDefault) S = "+qnidcm"; else S = "+qnidc"; PostIrcMessage( "/IGNORE %%question=\"%s\",\"%s\",\"*!*@%s\" %s",Translate("Please enter the hostmask (nick!user@host) \nNOTE! Contacts on your contact list are never ignored"), Translate("Ignore"), host, S.c_str()); } if (host) DBFreeVariant(&dbv1); } else { PostIrcMessageWnd(dbv.pszVal, NULL, "/CHANNELMANAGER"); } DBFreeVariant(&dbv); } return 0; } static int Service_JoinMenuCommand(WPARAM wp, LPARAM lp) { if (!join_hWnd) join_hWnd = CreateDialog(g_hInstance, MAKEINTRESOURCE(IDD_NICK), NULL, JoinWndProc); SetDlgItemText(join_hWnd, IDC_CAPTION, Translate("Join channel")); SetWindowText(GetDlgItem(join_hWnd, IDC_TEXT), Translate("Please enter a channel to join")); SendMessage(GetDlgItem(join_hWnd, IDC_ENICK), EM_SETSEL, 0,MAKELPARAM(0,-1)); ShowWindow(join_hWnd, SW_SHOW); SetActiveWindow(join_hWnd); return 0; } static int Service_QuickConnectMenuCommand(WPARAM wp, LPARAM lp) { if (!quickconn_hWnd) quickconn_hWnd = CreateDialog(g_hInstance, MAKEINTRESOURCE(IDD_QUICKCONN), NULL, QuickWndProc); SetWindowText(quickconn_hWnd, Translate("Quick connect")); SetWindowText(GetDlgItem(quickconn_hWnd, IDC_TEXT), Translate("Please select IRC network and enter the password if needed")); SetWindowText(GetDlgItem(quickconn_hWnd, IDC_CAPTION), Translate("Quick connect")); SendMessage(quickconn_hWnd, WM_SETICON, ICON_BIG,(LPARAM)LoadIconEx(IDI_QUICK,"quick",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON))); ShowWindow(quickconn_hWnd, SW_SHOW); SetActiveWindow(quickconn_hWnd); return 0; } static int Service_ShowListMenuCommand(WPARAM wp, LPARAM lp) { PostIrcMessage( "/LIST"); return 0; } static int Service_ShowServerMenuCommand(WPARAM wp, LPARAM lp) { GCEVENT gce = {0}; GCDEST gcd = {0}; gcd.iType = GC_EVENT_CONTROL; gcd.pszID = "Network log"; gcd.pszModule = IRCPROTONAME; gce.cbSize = sizeof(GCEVENT); gce.pDest = &gcd; CallChatEvent( WINDOW_VISIBLE, (LPARAM)&gce); return 0; } static int Service_ChangeNickMenuCommand(WPARAM wp, LPARAM lp) { if (!nick_hWnd) nick_hWnd = CreateDialog(g_hInstance,MAKEINTRESOURCE(IDD_NICK), NULL, NickWndProc); SetDlgItemText(nick_hWnd, IDC_CAPTION, Translate("Change nick name")); SetWindowText(GetDlgItem(nick_hWnd, IDC_TEXT), Translate("Please enter a unique nickname")); SetWindowText(GetDlgItem(nick_hWnd, IDC_ENICK), g_ircSession.GetInfo().sNick.c_str()); SendMessage(GetDlgItem(nick_hWnd, IDC_ENICK), CB_SETEDITSEL, 0,MAKELPARAM(0,-1)); ShowWindow(nick_hWnd, SW_SHOW); SetActiveWindow(nick_hWnd); return 0; } static int Service_SetAvatarMenuCommand(WPARAM wp, LPARAM lp) { char* szDest = (char*)SAFE_MALLOC(MAX_PATH+0x10); char str[MAX_PATH]; char szFilter[512]; OPENFILENAME ofn = {0}; str[0] = 0; CallService(MS_UTILS_GETBITMAPFILTERSTRINGS,sizeof(szFilter),(LPARAM)szFilter); ofn.lStructSize = sizeof(OPENFILENAME); ofn.lpstrFilter = szFilter; ofn.lpstrFile = szDest; ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; ofn.nMaxFile = MAX_PATH; ofn.nMaxFileTitle = MAX_PATH; ofn.lpstrDefExt = "jpg"; if(GetOpenFileName(&ofn)) Service_SetMyAvatar(NULL, (LPARAM)szDest); else Service_SetMyAvatar(NULL, NULL); return 0; } static void DoChatFormatting(char * pszText) { char * p1 = pszText; int iFG = -1; int iRemoveChars; char InsertThis[50]; while(*p1 != '\0') { iRemoveChars = 0; mir_snprintf(InsertThis, sizeof(InsertThis), ""); if (*p1 == '%') { switch (p1[1]) { case 'B': case 'b': mir_snprintf(InsertThis, sizeof(InsertThis), "\002"); iRemoveChars = 2; break; case 'I': case 'i': mir_snprintf(InsertThis, sizeof(InsertThis), "\026"); iRemoveChars = 2; break; case 'U': case 'u': mir_snprintf(InsertThis, sizeof(InsertThis), "\037"); iRemoveChars = 2; break; case 'c': { char szTemp[3]; mir_snprintf(InsertThis, sizeof(InsertThis), "\003"); iRemoveChars = 2; lstrcpyn(szTemp, p1 + 2, 3); iFG = atoi(szTemp); }break; case 'C': if(p1[2] =='%' && p1[3] == 'F') { mir_snprintf(InsertThis, sizeof(InsertThis), "\00399,99"); iRemoveChars = 4; } else { mir_snprintf(InsertThis, sizeof(InsertThis), "\00399"); iRemoveChars = 2; } iFG = -1; break; case 'f': { char szTemp[3]; if(p1 - 3 >= pszText && p1[-3] == '\003') mir_snprintf(InsertThis, sizeof(InsertThis), ","); else if( iFG >= 0 ) mir_snprintf(InsertThis, sizeof(InsertThis), "\003%u,", iFG); else mir_snprintf(InsertThis, sizeof(InsertThis), "\00399,"); iRemoveChars = 2; lstrcpyn(szTemp, p1 + 2, 3); }break; case 'F': if(iFG >= 0) mir_snprintf(InsertThis, sizeof(InsertThis), "\003%u,99", iFG); else mir_snprintf(InsertThis, sizeof(InsertThis), "\00399,99"); iRemoveChars = 2; break; case '%': mir_snprintf(InsertThis, sizeof(InsertThis), "%%"); iRemoveChars = 2; break; default: iRemoveChars = 2; break; } MoveMemory(p1 + lstrlen(InsertThis) , p1 + iRemoveChars, lstrlen(p1) - iRemoveChars +1); CopyMemory(p1, InsertThis, lstrlen(InsertThis)); if(iRemoveChars || lstrlen(InsertThis)) p1 += lstrlen(InsertThis); else p1++; } else p1++; } } int Service_SendUserIsTyping(WPARAM wParam, LPARAM lParam) { int nResult = 1; HANDLE hContact = (HANDLE)wParam; if (hContact && GlobalStatus != ID_STATUS_OFFLINE && DBGetContactSettingWord(hContact,IRCPROTONAME, "Status", ID_STATUS_OFFLINE) != ID_STATUS_OFFLINE && DBGetContactSettingByte(NULL,IRCPROTONAME, "TypingEnabled", 0)) { switch (lParam) { case PROTOTYPE_SELFTYPING_ON: sendTypingNotification(hContact, MTN_BEGUN); nResult = 0; break; case PROTOTYPE_SELFTYPING_OFF: sendTypingNotification(hContact, MTN_FINISHED); nResult = 0; break; default: break; } } return nResult; } static int Service_SendNudge( WPARAM wParam, LPARAM lParam ) { /* DBVARIANT dbv; DBCONTACTGETSETTING dcs; dcs.szModule=IRCPROTONAME; dcs.szSetting="Nick"; dcs.pValue=&dbv; dbv.type=DBVT_ASCIIZ; CallService(MS_DB_CONTACT_GETSETTING,(WPARAM)wParam,(LPARAM)&dcs); if(ServiceExists(MS_NUDGE_SEND)) PostIrcMessage( "/PRIVMSG %s \001NUDGE\001", dbv.pszVal); DBFreeVariant(&dbv); */ if(ServiceExists(MS_NUDGE_SEND)) PostIrcMessage( "/PRIVMSG %s \001NUDGE\001", IRCGetContactSettingString((HANDLE)wParam, "Nick", "")); return 0; } int Service_GCEventHook(WPARAM wParam,LPARAM lParam) { GCHOOK *gchook= (GCHOOK*) lParam; GCHOOK *gchtemp = NULL; GCHOOK *gch = NULL; String S = ""; EnterCriticalSection(&m_gchook); // handle the hook if(gchook) { if (!lstrcmpi(gchook->pDest->pszModule, IRCPROTONAME)) { // first see if the scripting module should modify or stop this event if(bMbotInstalled && prefs->ScriptingEnabled && wParam == NULL) { gchtemp = (GCHOOK *)mmi.mmi_malloc(sizeof(GCHOOK)); gchtemp->pDest = (GCDEST *)mmi.mmi_malloc(sizeof(GCDEST)); gchtemp->pDest->iType = gchook->pDest->iType; gchtemp->dwData = gchook->dwData; if(gchook->pDest->pszID) { char * pTemp = NULL; gchtemp->pDest->pszID = (char *)mmi.mmi_malloc(lstrlen(gchook->pDest->pszID) + 1); lstrcpyn(gchtemp->pDest->pszID, gchook->pDest->pszID, lstrlen(gchook->pDest->pszID) + 1); pTemp = strchr(gchtemp->pDest->pszID, ' '); if(pTemp) *pTemp = '\0'; }else gchtemp->pDest->pszID = NULL; if(gchook->pDest->pszModule) { gchtemp->pDest->pszModule = (char *)mmi.mmi_malloc(lstrlen(gchook->pDest->pszModule) + 1); lstrcpyn(gchtemp->pDest->pszModule, gchook->pDest->pszModule, lstrlen(gchook->pDest->pszModule) + 1); }else gchtemp->pDest->pszModule = NULL; if(gchook->pszText) { gchtemp->pszText = (char *)mmi.mmi_malloc(lstrlen(gchook->pszText) + 1); lstrcpyn(gchtemp->pszText, gchook->pszText, lstrlen(gchook->pszText) + 1); }else gchtemp->pszText = NULL; if(gchook->pszUID) { gchtemp->pszUID = (char *)mmi.mmi_malloc(lstrlen(gchook->pszUID) + 1); lstrcpyn(gchtemp->pszUID, gchook->pszUID, lstrlen(gchook->pszUID) + 1); }else gchtemp->pszUID = NULL; if( Scripting_TriggerMSPGuiOut(gchtemp) && gchtemp) gch = gchtemp; else gch = NULL; } else gch = gchook; if(gch) { char * p1 = new char[lstrlen(gch->pDest->pszID)+1]; lstrcpy(p1, gch->pDest->pszID); char * p2 = strstr(p1, " - "); if(p2) { *p2 = '\0'; } switch (gch->pDest->iType) { case GC_SESSION_TERMINATE: FreeWindowItemData(p1, (CHANNELINFO*)gch->dwData); break; case GC_USER_MESSAGE: if(gch && gch->pszText && lstrlen(gch->pszText)> 0) { char * pszText = new char[lstrlen(gch->pszText)+1000]; lstrcpy(pszText, gch->pszText); DoChatFormatting(pszText); PostIrcMessageWnd(p1, NULL, pszText); delete []pszText; } break; case GC_USER_CHANMGR: PostIrcMessageWnd(p1, NULL, "/CHANNELMANAGER"); break; case GC_USER_PRIVMESS: char szTemp[4000]; mir_snprintf(szTemp, sizeof(szTemp), "/QUERY %s", gch->pszUID); PostIrcMessageWnd(p1, NULL, szTemp); break; case GC_USER_LOGMENU: switch(gch->dwData) { case 1: PostIrcMessageWnd(p1, NULL, "/CHANNELMANAGER"); break; case 2: { PostIrcMessage( "/PART %s", p1); GCEVENT gce = {0}; GCDEST gcd = {0}; S = MakeWndID(p1); gce.cbSize = sizeof(GCEVENT); gcd.iType = GC_EVENT_CONTROL; gcd.pszModule = IRCPROTONAME; gce.pDest = &gcd; gcd.pszID = (char *)S.c_str(); CallChatEvent( SESSION_TERMINATE, (LPARAM)&gce); }break; case 3: PostIrcMessageWnd(p1, NULL, "/SERVERSHOW"); break; default:break; }break; case GC_USER_NICKLISTMENU: switch(gch->dwData) { case 1: PostIrcMessage( "/MODE %s +o %s", p1, gch->pszUID); break; case 2: PostIrcMessage( "/MODE %s -o %s", p1, gch->pszUID); break; case 3: PostIrcMessage( "/MODE %s +v %s", p1, gch->pszUID); break; case 4: PostIrcMessage( "/MODE %s -v %s", p1, gch->pszUID); break; case 5: PostIrcMessage( "/KICK %s %s", p1, gch->pszUID); break; case 6: PostIrcMessage( "/KICK %s %s %%question=\"%s\",\"%s\",\"%s\"", p1, gch->pszUID, Translate("Please enter the reason"), Translate("Kick"), Translate("Jerk") ); break; case 7: DoUserhostWithReason(1, "B" + (String)p1, true, "%s", gch->pszUID); break; case 8: DoUserhostWithReason(1, "K" + (String)p1, true, "%s", gch->pszUID); break; case 9: DoUserhostWithReason(1, "L" + (String)p1, true, "%s", gch->pszUID); break; case 10: PostIrcMessage( "/WHOIS %s", gch->pszUID); break; // case 11: // DoUserhostWithReason(1, "I", true, "%s", gch->pszUID); // break; // case 12: // DoUserhostWithReason(1, "J", true, "%s", gch->pszUID); // break; case 13: PostIrcMessage( "/DCC CHAT %s", gch->pszUID); break; case 14: PostIrcMessage( "/DCC SEND %s", gch->pszUID); break; case 15: DoUserhostWithReason(1, "I", true, "%s", gch->pszUID); break; case 16: PostIrcMessage( "/MODE %s +h %s", p1, gch->pszUID); break; case 17: PostIrcMessage( "/MODE %s -h %s", p1, gch->pszUID); break; case 30: { PROTOSEARCHRESULT psr; ZeroMemory(&psr, sizeof(psr)); psr.cbSize = sizeof(psr); psr.nick = (char *)gch->pszUID; ADDCONTACTSTRUCT acs; ZeroMemory(&acs, sizeof(acs)); acs.handleType =HANDLE_SEARCHRESULT; acs.szProto = IRCPROTONAME; acs.psr = &psr; CallService(MS_ADDCONTACT_SHOW, (WPARAM)NULL, (LPARAM)&acs); }break; break; default:break; }break; default:break; } delete[]p1; } } } if (gchtemp) { if(gchtemp->pszUID) mmi.mmi_free(gchtemp->pszUID); if(gchtemp->pszText) mmi.mmi_free(gchtemp->pszText); if(gchtemp->pDest->pszID) mmi.mmi_free(gchtemp->pDest->pszID); if(gchtemp->pDest->pszModule) mmi.mmi_free(gchtemp->pDest->pszModule); mmi.mmi_free(gchtemp->pDest); mmi.mmi_free(gchtemp); } LeaveCriticalSection(&m_gchook); return 0; } static int Service_GCMenuHook(WPARAM wParam,LPARAM lParam) { GCMENUITEMS *gcmi= (GCMENUITEMS*) lParam; if(gcmi) { if (!lstrcmpi(gcmi->pszModule, IRCPROTONAME)) { if(gcmi->Type == MENU_ON_LOG) { if(lstrcmpi(gcmi->pszID, "Network log")) { static struct gc_item Item[] = { {Translate("Channel &settings"), 1, MENU_ITEM, FALSE}, {Translate("&Leave the channel"), 2, MENU_ITEM, FALSE}, {Translate("Show the server &window"), 3, MENU_ITEM, FALSE}}; gcmi->nItems = sizeof(Item)/sizeof(Item[0]); gcmi->Item = &Item[0]; } else gcmi->nItems = 0; } if(gcmi->Type == MENU_ON_NICKLIST) { struct CONTACT_TYPE user ={(char *)gcmi->pszUID, NULL, NULL, false, false, false}; HANDLE hContact = CList_FindContact(&user); BOOL bFlag = FALSE; if (hContact && DBGetContactSettingByte(hContact,"CList", "NotOnList", 0) == 0) bFlag = TRUE; static struct gc_item Item[] = { {Translate("&WhoIs info"), 10, MENU_ITEM, FALSE}, {Translate("&Control"), 0, MENU_NEWPOPUP, FALSE}, {Translate("Give &Op"), 1, MENU_POPUPITEM, FALSE}, {Translate("Take O&p"), 2, MENU_POPUPITEM, FALSE}, {Translate("Give &Halfop"), 16, MENU_POPUPITEM, FALSE}, {Translate("Take H&alfop"), 17, MENU_POPUPITEM, FALSE}, {Translate("Give &Voice"), 3, MENU_POPUPITEM, FALSE}, {Translate("Take V&oice"), 4, MENU_POPUPITEM, FALSE}, {"", 0, MENU_POPUPSEPARATOR, FALSE}, {Translate("&Kick"), 5, MENU_POPUPITEM, FALSE}, {Translate("Ki&ck (reason)"), 6, MENU_POPUPITEM, FALSE}, {Translate("&Ban"), 7, MENU_POPUPITEM, FALSE}, {Translate("Ban'&n kick"), 8, MENU_POPUPITEM, FALSE}, {Translate("Ban'n kick (&reason)"), 9, MENU_POPUPITEM, FALSE}, {Translate("&Direct Connection"), 0, MENU_NEWPOPUP, FALSE}, {Translate("Request &Chat"), 13, MENU_POPUPITEM, FALSE}, {Translate("Send &File"), 14, MENU_POPUPITEM, FALSE}, {Translate("Add to &ignore list"), 15, MENU_ITEM, FALSE}, {"", 12, MENU_SEPARATOR, FALSE}, {Translate("&Add User"), 30, MENU_ITEM, bFlag} }; gcmi->nItems = sizeof(Item)/sizeof(Item[0]); gcmi->Item = &Item[0]; gcmi->Item[gcmi->nItems-1].bDisabled = bFlag; unsigned long ulAdr = 0; if (prefs->ManualHost) ulAdr = ConvertIPToInteger(prefs->MySpecifiedHostIP); else ulAdr = ConvertIPToInteger(prefs->IPFromServer?prefs->MyHost:prefs->MyLocalHost); bool bDcc = ulAdr == 0 ?false:true; gcmi->Item[14].bDisabled = !bDcc; gcmi->Item[15].bDisabled = !bDcc; gcmi->Item[16].bDisabled = !bDcc; bool bHalfop = strchr(sUserModes.c_str(), 'h') == NULL?false:true; gcmi->Item[5].bDisabled = !bHalfop; gcmi->Item[4].bDisabled = !bHalfop; } } } return 0; } static int Service_SystemPreShutdown(WPARAM wParam,LPARAM lParam) { EnterCriticalSection(&cs); if (prefs->Perform && g_ircSession) { if(DoPerform("Event: Disconnect")) Sleep(200); } g_ircSession.DisconnectAllDCCSessions(true); if (g_ircSession) g_ircSession.Disconnect(); if (list_hWnd) SendMessage(list_hWnd, WM_CLOSE, 0, 0); if (nick_hWnd) SendMessage(nick_hWnd, WM_CLOSE, 0, 0); if (join_hWnd) SendMessage(join_hWnd, WM_CLOSE, 0, 0); LeaveCriticalSection(&cs); return 0; } static int Service_MenuPreBuild(WPARAM wParam,LPARAM lParam) { DBVARIANT dbv; char *szProto; CLISTMENUITEM clmi; HANDLE hContact = (HANDLE) wParam; if (!hContact) return 0; memset( &clmi, 0, sizeof( clmi )); clmi.cbSize = sizeof( clmi ); clmi.flags = CMIM_FLAGS|CMIM_NAME|CMIM_ICON; szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) wParam, 0); if (szProto && !lstrcmpi(szProto, IRCPROTONAME)) { if(DBGetContactSettingByte(hContact, IRCPROTONAME, "ChatRoom", 0) == GCW_CHATROOM) { clmi.hIcon = LoadIconEx(IDI_PART,"part",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON)); clmi.pszName = Translate("&Leave channel"); CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hContactMenu2, ( LPARAM )&clmi ); clmi.hIcon = LoadIconEx(IDI_MANAGER,"manager",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON)); clmi.pszName = Translate("Channel &settings"); CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hContactMenu3, ( LPARAM )&clmi ); clmi.hIcon = LoadIconEx(IDI_SHOW,"show",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON)); clmi.pszName = Translate("&Show channel"); CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hContactMenu1, ( LPARAM )&clmi ); } else if(DBGetContactSettingByte(hContact, IRCPROTONAME, "ChatRoom", 0) == GCW_SERVER) { clmi.hIcon = LoadIconEx(IDI_SERVER,"server",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON)); clmi.pszName = Translate("&Show server"); CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hContactMenu1, ( LPARAM )&clmi ); clmi.flags = CMIM_FLAGS|CMIF_HIDDEN; CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hContactMenu2, ( LPARAM )&clmi ); CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hContactMenu3, ( LPARAM )&clmi ); } else if (!DBGetContactSetting((void *)wParam, IRCPROTONAME, "Default", &dbv)&& dbv.type == DBVT_ASCIIZ) { BYTE bDcc = DBGetContactSettingByte((HANDLE) wParam, IRCPROTONAME, "DCC", 0) ; clmi.flags = CMIM_FLAGS|CMIF_HIDDEN; CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hContactMenu1, ( LPARAM )&clmi ); clmi.flags = CMIM_NAME|CMIM_ICON | CMIM_FLAGS; if(bDcc) { if(DBGetContactSettingWord((void *)wParam, IRCPROTONAME, "Status", ID_STATUS_OFFLINE) == ID_STATUS_OFFLINE) clmi.flags = CMIM_NAME|CMIM_ICON | CMIM_FLAGS |CMIF_HIDDEN; clmi.hIcon = LoadIconEx(IDI_DELETE,"delete",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON)); clmi.pszName = Translate("Di&sconnect"); CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hContactMenu2, ( LPARAM )&clmi ); } else { if(!g_ircSession) clmi.flags = CMIM_NAME|CMIM_ICON | CMIM_FLAGS |CMIF_HIDDEN; clmi.hIcon = LoadIconEx(IDI_WHOIS,"whois",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON)); clmi.pszName = Translate("&WhoIs info"); CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hContactMenu2, ( LPARAM )&clmi ); } if(!g_ircSession || bDcc) clmi.flags = CMIM_NAME|CMIM_ICON | CMIM_FLAGS |CMIF_HIDDEN; else clmi.flags = CMIM_NAME|CMIM_ICON | CMIM_FLAGS; clmi.hIcon = LoadIconEx(IDI_BLOCK,"block",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON)); if (DBGetContactSettingWord((HANDLE)wParam, IRCPROTONAME, "Status", ID_STATUS_OFFLINE) !=ID_STATUS_OFFLINE) { char * host = NULL; DBVARIANT dbv3; if (!DBGetContactSetting((HANDLE) wParam, IRCPROTONAME, "Host", &dbv3) && dbv3.type == DBVT_ASCIIZ) host = dbv3.pszVal; if (host) { clmi.pszName = Translate("&Add to ignore list"); } else clmi.flags = CMIM_NAME|CMIM_ICON | CMIM_FLAGS |CMIF_HIDDEN; if (host) DBFreeVariant(&dbv3); } else clmi.flags = CMIM_NAME|CMIM_ICON | CMIM_FLAGS |CMIF_HIDDEN; CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hContactMenu3, ( LPARAM )&clmi ); DBFreeVariant(&dbv); } } return 0; } static int Service_GetCaps(WPARAM wParam,LPARAM lParam) { if(wParam==PFLAGNUM_1) return PF1_BASICSEARCH | PF1_MODEMSG | PF1_FILE |PF1_CANRENAMEFILE | PF1_PEER2PEER | PF1_IM; if(wParam==PFLAGNUM_2) return PF2_ONLINE|PF2_SHORTAWAY; if(wParam==PFLAGNUM_3) return PF2_SHORTAWAY; if(wParam==PFLAGNUM_4) return PF4_NOCUSTOMAUTH | PF4_SUPPORTTYPING; if(wParam==PFLAG_UNIQUEIDTEXT) return (int) Translate("Nickname"); if(wParam==PFLAG_MAXLENOFMESSAGE) return 400; if(wParam==PFLAG_UNIQUEIDSETTING) return (int) "Default"; return 0; } static int Service_GetName(WPARAM wParam,LPARAM lParam) { lstrcpyn((char *) lParam, ALTIRCPROTONAME, wParam); return 0; } static int Service_LoadIcon(WPARAM wParam,LPARAM lParam) { switch(wParam&0xFFFF) { case PLI_PROTOCOL: return (int)LoadImage(g_hInstance,MAKEINTRESOURCE(IDI_MAIN),IMAGE_ICON,16,16,LR_SHARED); default: return (int)(HICON)NULL; } return 0; } static void __cdecl AckBasicSearch(void * pszNick) { PROTOSEARCHRESULT psr; ZeroMemory(&psr, sizeof(psr)); psr.cbSize = sizeof(psr); psr.nick = (char *)pszNick; ProtoBroadcastAck(IRCPROTONAME, NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE) 1, (LPARAM) & psr); ProtoBroadcastAck(IRCPROTONAME, NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE) 1, 0); } static int Service_BasicSearch(WPARAM wParam,LPARAM lParam) { static char buf[50]; if (lParam) { lstrcpyn(buf, (const char *)lParam, 50); if (OldStatus != ID_STATUS_OFFLINE && OldStatus != ID_STATUS_CONNECTING && lstrlen(buf) >0 && !IsChannel(buf)) { forkthread(AckBasicSearch, 0, &buf ); return 1; } } return 0; } static int Service_AddToList(WPARAM wParam,LPARAM lParam) { HANDLE hContact; PROTOSEARCHRESULT *psr = (PROTOSEARCHRESULT *) lParam; CONTACT user ={(char *)psr->nick, NULL, NULL, true, false, false}; if (OldStatus == ID_STATUS_OFFLINE || OldStatus == ID_STATUS_CONNECTING) return 0; hContact = CList_AddContact(&user, true, false); if (hContact) { DBVARIANT dbv1; if(DBGetContactSettingByte(hContact, IRCPROTONAME, "AdvancedMode", 0) == 0) DoUserhostWithReason(1, ((String)"S" + psr->nick).c_str(), true, psr->nick); else { if (!DBGetContactSetting(hContact, IRCPROTONAME, "UWildcard", &dbv1) && dbv1.type == DBVT_ASCIIZ) { DoUserhostWithReason(2, ((String)"S" + dbv1.pszVal).c_str(), true, dbv1.pszVal); DBFreeVariant(&dbv1); } else { DoUserhostWithReason(2, ((String)"S" + psr->nick).c_str(), true, psr->nick); } } } return (int) hContact; } static void __cdecl ConnectServerThread(LPVOID di) { EnterCriticalSection(&cs); InterlockedIncrement((volatile long *) &bConnectThreadRunning); InterlockedIncrement((volatile long *) &bConnectRequested); while ( !Miranda_Terminated() && bConnectRequested > 0 ) { while(bConnectRequested > 0) InterlockedDecrement((volatile long *) &bConnectRequested); if (g_ircSession) { Sleep(200); g_ircSession.Disconnect(); } g_ircSession.GetInfo().bNickFlag = false; int Temp = OldStatus; OldStatus = ID_STATUS_CONNECTING; nickflag = false; ProtoBroadcastAck(IRCPROTONAME,NULL,ACKTYPE_STATUS,ACKRESULT_SUCCESS,(HANDLE)Temp,ID_STATUS_CONNECTING); Sleep(100); g_ircSession.Connect(si); if (g_ircSession) { KillChatTimer(RetryTimer); if(lstrlen(prefs->MySpecifiedHost)) { IPRESOLVE * ipr = new IPRESOLVE; ipr->iType = IP_MANUAL; ipr->pszAdr = prefs->MySpecifiedHost; forkthread(ResolveIPThread, NULL, ipr); } } else { Temp = OldStatus; OldStatus = ID_STATUS_OFFLINE; ProtoBroadcastAck(IRCPROTONAME,NULL,ACKTYPE_STATUS,ACKRESULT_SUCCESS,(HANDLE)Temp,ID_STATUS_OFFLINE); Sleep(100); } } InterlockedDecrement((volatile long *) &bConnectThreadRunning); LeaveCriticalSection(&cs); return; } static void __cdecl DisconnectServerThread(LPVOID di) { EnterCriticalSection(&cs); KillChatTimer(RetryTimer); if (g_ircSession) g_ircSession.Disconnect(); LeaveCriticalSection(&cs); return; } void ConnectToServer(void) { PortCount= StrToInt(prefs->PortStart); si.sServer = GetWord(prefs->ServerName, 0); si.iPort = PortCount; si.sNick = prefs->Nick; si.sUserID = prefs->UserID; si.sFullName = prefs->Name; si.sPassword = prefs->Password; si.bIdentServer = ((prefs->Ident) ? (true) : (false)); si.iIdentServerPort = StrToInt(prefs->IdentPort); si.sIdentServerType = prefs->IdentSystem; si.sNetwork = prefs->Network; si.iSSL = prefs->iSSL; RetryCount = 1; KillChatTimer(RetryTimer); if (prefs->Retry) { if (StrToInt(prefs->RetryWait)<10) lstrcpy(prefs->RetryWait, "10"); SetChatTimer(RetryTimer, StrToInt(prefs->RetryWait)*1000, RetryTimerProc); } bPerformDone = false; bTempDisableCheck = false; bTempForceCheck = false; iTempCheckTime = 0; sChannelPrefixes = "&#"; sUserModes = "ov"; sUserModePrefixes = "@+"; sChannelModes = "btnimklps"; if (!bConnectThreadRunning) { forkthread(ConnectServerThread, 0, NULL ); } else if (bConnectRequested < 1) InterlockedIncrement((volatile long *) &bConnectRequested); char szTemp[300]; mir_snprintf(szTemp, sizeof(szTemp), "\0033%s \002%s\002 (%s: %u)", Translate("Connecting to"), si.sNetwork.c_str(), si.sServer.c_str(), si.iPort); DoEvent(GC_EVENT_INFORMATION, "Network log", NULL, szTemp, NULL, NULL, NULL, true, false); return; } void DisconnectFromServer(void) { GCEVENT gce = {0}; GCDEST gcd = {0}; if (prefs->Perform && g_ircSession) { DoPerform("Event: Disconnect"); } gcd.iType = GC_EVENT_CONTROL; gcd.pszID = NULL; // all windows gcd.pszModule = IRCPROTONAME; gce.cbSize = sizeof(GCEVENT); gce.pDest = &gcd; CallChatEvent( SESSION_TERMINATE, (LPARAM)&gce); forkthread(DisconnectServerThread, 0, NULL ); return; } static int Service_SetStatus(WPARAM wParam,LPARAM lParam) { if (!bChatInstalled) { MIRANDASYSTRAYNOTIFY msn; msn.cbSize = sizeof(MIRANDASYSTRAYNOTIFY); msn.szProto = IRCPROTONAME; msn.szInfoTitle = Translate("Information"); msn.szInfo = Translate("This protocol is dependent on another plugin named \'Chat\'\nPlease download it from the Miranda IM website!"); msn.dwInfoFlags = NIIF_ERROR; msn.uTimeout = 15000; CallService(MS_CLIST_SYSTRAY_NOTIFY, (WPARAM)NULL,(LPARAM) &msn); return 0; } if (wParam != ID_STATUS_OFFLINE && lstrlen(prefs->Network) <1) { if (lstrlen(prefs->Nick) > 0 && !prefs->DisableDefaultServer) { HWND hwnd=CreateDialog(g_hInstance,MAKEINTRESOURCE(IDD_QUICKCONN),NULL,QuickWndProc); SetWindowText(hwnd, "Miranda IRC"); SetWindowText(GetDlgItem(hwnd, IDC_TEXT), Translate("Please choose an IRC-network to go online. This network will be the default.")); SetWindowText(GetDlgItem(hwnd, IDC_CAPTION), Translate("Default network")); HICON hIcon = LoadIconEx(IDI_MAIN,"main",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON)); SendMessage(hwnd, WM_SETICON, ICON_BIG,(LPARAM)hIcon); ShowWindow(hwnd, SW_SHOW); SetActiveWindow(hwnd); } return 0; } if (wParam != ID_STATUS_OFFLINE && (lstrlen(prefs->Nick) <1 || lstrlen(prefs->UserID) < 1 || lstrlen(prefs->Name) < 1)) { MIRANDASYSTRAYNOTIFY msn; msn.cbSize = sizeof(MIRANDASYSTRAYNOTIFY); msn.szProto = IRCPROTONAME; msn.szInfoTitle = Translate("IRC error"); msn.szInfo = Translate("Connection can not be established! You have not completed all necessary fields (Nickname, User ID and Name)." ); msn.dwInfoFlags = NIIF_ERROR; msn.uTimeout = 15000; CallService(MS_CLIST_SYSTRAY_NOTIFY, (WPARAM)NULL,(LPARAM) &msn); return 0; } if (wParam == ID_STATUS_FREECHAT && prefs->Perform && g_ircSession) DoPerform("Event: Free for chat" ); if (wParam == ID_STATUS_ONTHEPHONE && prefs->Perform && g_ircSession) DoPerform("Event: On the phone"); if (wParam == ID_STATUS_OUTTOLUNCH && prefs->Perform && g_ircSession) DoPerform("Event: Out for lunch"); if (wParam == ID_STATUS_ONLINE && prefs->Perform && g_ircSession && (GlobalStatus ==ID_STATUS_ONTHEPHONE ||GlobalStatus ==ID_STATUS_OUTTOLUNCH) && OldStatus !=ID_STATUS_AWAY) DoPerform("Event: Available" ); if (lParam != 1) GlobalStatus = wParam; // clear custom status on status change if (wParam != OldStatus) if (IRCGetContactSettingByte(NULL, "XStatusReset", DEFAULT_XSTATUS_RESET)) IRCSetXStatus(0, 0); if ((wParam == ID_STATUS_ONLINE || wParam == ID_STATUS_AWAY || wParam == ID_STATUS_FREECHAT) && !g_ircSession ) //go from offline to online ConnectToServer(); else if ((wParam == ID_STATUS_ONLINE || wParam == ID_STATUS_FREECHAT) && g_ircSession && OldStatus == ID_STATUS_AWAY) //go to online while connected { StatusMessage = ""; PostIrcMessage( "/AWAY"); return 0; } else if (wParam == ID_STATUS_OFFLINE && g_ircSession) //go from online/away to offline DisconnectFromServer(); else if (wParam == ID_STATUS_OFFLINE && !g_ircSession) //offline to offline { KillChatTimer( RetryTimer); return 0; } else if (wParam == ID_STATUS_AWAY && g_ircSession) //go to away while connected return 0; else if (wParam == ID_STATUS_ONLINE && g_ircSession) //already online return 0; else Service_SetStatus(ID_STATUS_AWAY, 1); return 0; } static int Service_GetStatus(WPARAM wParam,LPARAM lParam) { if (OldStatus == ID_STATUS_CONNECTING) return ID_STATUS_CONNECTING; else if (g_ircSession && OldStatus == ID_STATUS_ONLINE) return ID_STATUS_ONLINE; else if (g_ircSession && OldStatus == ID_STATUS_AWAY) return ID_STATUS_AWAY; else return ID_STATUS_OFFLINE; } static int Service_SetAwayMsg(WPARAM wParam, LPARAM lParam) { if (wParam != ID_STATUS_ONLINE && wParam != ID_STATUS_INVISIBLE && wParam != ID_STATUS_FREECHAT && wParam != ID_STATUS_CONNECTING && wParam != ID_STATUS_OFFLINE) { if (StatusMessage == "" || lParam == NULL || StatusMessage != ReplaceString((char *)lParam, "\r\n", " ") ) { if(lParam == NULL || *(char*)lParam == '\0') StatusMessage = STR_AWAYMESSAGE; else StatusMessage = ReplaceString((char *)lParam, "\r\n", " "); PostIrcMessage( "/AWAY %s", (StatusMessage.substr(0,450)).c_str()); } } return 0; } static int Service_AddIncMessToDB(WPARAM wParam, LPARAM lParam) { DBEVENTINFO dbei; CCSDATA *ccs = (CCSDATA *) lParam; PROTORECVEVENT *pre = (PROTORECVEVENT *) ccs->lParam; DBDeleteContactSetting(ccs->hContact, "CList", "Hidden"); ZeroMemory(&dbei, sizeof(dbei)); dbei.cbSize = sizeof(dbei); dbei.szModule = IRCPROTONAME; dbei.timestamp = pre->timestamp; dbei.flags = pre->flags & (PREF_CREATEREAD ? DBEF_READ : 0); dbei.eventType = EVENTTYPE_MESSAGE; dbei.cbBlob = strlen(pre->szMessage) + 1; dbei.pBlob = (PBYTE) pre->szMessage; CallService(MS_DB_EVENT_ADD, (WPARAM) ccs->hContact, (LPARAM) & dbei); return 0; } static void __cdecl AckMessageFail(void * lParam) { ProtoBroadcastAck(IRCPROTONAME, (void*)lParam, ACKTYPE_MESSAGE, ACKRESULT_FAILED, (HANDLE) 1, (LONG)Translate("The protocol is not online")); } static void __cdecl AckMessageFailDcc(void * lParam) { ProtoBroadcastAck(IRCPROTONAME, (void*)lParam, ACKTYPE_MESSAGE, ACKRESULT_FAILED, (HANDLE) 1, (LONG)Translate("The dcc chat connection is not active")); } static void __cdecl AckMessageSuccess(void * lParam) { ProtoBroadcastAck(IRCPROTONAME, (void*)lParam, ACKTYPE_MESSAGE, ACKRESULT_SUCCESS, (HANDLE) 1, 0); } static int Service_GetMessFromSRMM(WPARAM wParam, LPARAM lParam) { CCSDATA *ccs = (CCSDATA *) lParam; BYTE bDcc = DBGetContactSettingByte(ccs->hContact, IRCPROTONAME, "DCC", 0) ; WORD wStatus = DBGetContactSettingWord(ccs->hContact, IRCPROTONAME, "Status", ID_STATUS_OFFLINE) ; if (OldStatus !=ID_STATUS_OFFLINE && OldStatus !=ID_STATUS_CONNECTING && !bDcc || bDcc && wStatus == ID_STATUS_ONLINE) { PostIrcMessageWnd(NULL, ccs->hContact, (char *) ccs->lParam); forkthread(AckMessageSuccess, 0, ccs->hContact); } else { if(bDcc) forkthread(AckMessageFailDcc, 0, ccs->hContact); else forkthread(AckMessageFail, 0, ccs->hContact); } return 1; } static int Service_GetAwayMessage(WPARAM wParam, LPARAM lParam) { CCSDATA *ccs = (CCSDATA *) lParam; WhoisAwayReply = ""; DBVARIANT dbv; // bypass chat contacts. if(DBGetContactSettingByte(ccs->hContact, IRCPROTONAME, "ChatRoom", 0) == 0) if (ccs->hContact && !DBGetContactSetting(ccs->hContact, IRCPROTONAME, "Nick", &dbv) && dbv.type == DBVT_ASCIIZ ) { int i = DBGetContactSettingWord(ccs->hContact,IRCPROTONAME, "Status", ID_STATUS_OFFLINE); // if ( i != ID_STATUS_OFFLINE) // { // if(DBGetContactSettingByte(NULL,IRCPROTONAME, "XStatusEnabled", 0) && DBGetContactSettingByte(NULL,IRCPROTONAME, "XStatusAuto", 0)) // if(strcmp(UniGetContactSettingUtf(ccs->hContact,IRCPROTONAME, "MirVer", ""), "Miranda")) // { // #ifdef _DEBUG // DBGprintf("XSTATUS REQUESTED from %s\n", dbv.pszVal); // #endif // PostIrcMessage( "/PRIVMSG %s \001XSTATUS\001", dbv.pszVal); // } // } if ( i != ID_STATUS_AWAY) { DBFreeVariant( &dbv); return 0; } whois_popup = false; String S="WHOIS " + (String)dbv.pszVal ; if (g_ircSession) g_ircSession << CIrcMessage(S.c_str(), false, false); DBFreeVariant( &dbv); } return 1; } static int Service_InitUserInfo(WPARAM wParam, LPARAM lParam) { char *szProto; szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, lParam, 0); DBVARIANT dbv; HANDLE hContact = (HANDLE) lParam; if (!hContact || !szProto || lstrcmpi(szProto, IRCPROTONAME)) { return 0; } if(DBGetContactSettingByte(hContact, IRCPROTONAME, "ChatRoom", 0) != 0) return 0; if(DBGetContactSettingByte(hContact, IRCPROTONAME, "DCC", 0) != 0) return 0; if (!DBGetContactSetting(hContact, IRCPROTONAME, "Default", &dbv) && dbv.type == DBVT_ASCIIZ) { if (IsChannel(dbv.pszVal)) { DBFreeVariant(&dbv); return 0; } DBFreeVariant(&dbv); } OPTIONSDIALOGPAGE odp; odp.cbSize = sizeof(odp); odp.pszTitle = ALTIRCPROTONAME; odp.hIcon = NULL; odp.hInstance = g_hInstance; odp.position = -1900000000; odp.pfnDlgProc = UserDetailsDlgProc; odp.pszTemplate = MAKEINTRESOURCE(IDD_USERINFO); odp.pszTitle = ALTIRCPROTONAME; CallService(MS_USERINFO_ADDPAGE, wParam, (LPARAM) & odp); return 0; } static void CListShowMenuItem(HANDLE hMenuItem, BYTE bShow) { CLISTMENUITEM mi = {0}; mi.cbSize = sizeof(mi); // Menu modification if (bShow || !prefs->XStatusAuto) mi.flags = CMIM_FLAGS; else mi.flags = CMIM_FLAGS | CMIF_HIDDEN; CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuItem, (LPARAM)&mi); } static void CListSetMenuItemIcon(HANDLE hMenuItem, HICON hIcon) { CLISTMENUITEM mi = {0}; mi.cbSize = sizeof(mi); mi.flags = CMIM_FLAGS | CMIM_ICON; mi.hIcon = hIcon; CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuItem, (LPARAM)&mi); } static int PrebuildContactMenu(WPARAM wParam, LPARAM lParam) { BYTE bXStatus; // if(IRCGetContactSettingByte((HANDLE)wParam, "ChatRoom", 0) != 0) // { // CListShowMenuItem(hUserMenuXStatus, 0); // return 0; // } bXStatus = IRCGetContactSettingByte((HANDLE)wParam, DBSETTING_XSTATUSID, 0); CListShowMenuItem(hUserMenuXStatus, bXStatus); if (bXStatus) { HICON iXStatus = GetXStatusIcon(bXStatus); CListSetMenuItemIcon(hUserMenuXStatus, iXStatus); if (iXStatus && !IconLibInstalled()) DestroyIcon(iXStatus); // release icon } return 0; } static int IconLibIconsChanged(WPARAM wParam, LPARAM lParam) { CListSetMenuItemIcon(hMenuQuick, IconLibProcess(LoadIconEx(IDI_QUICK,"quick",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON)), "quick")); CListSetMenuItemIcon(hMenuJoin, IconLibProcess(LoadIconEx(IDI_JOIN,"join",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON)), "join")); CListSetMenuItemIcon(hMenuNick, IconLibProcess(LoadIconEx(IDI_WHOIS,"whois",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON)), "whois")); CListSetMenuItemIcon(hMenuList, IconLibProcess(LoadIconEx(IDI_LIST,"list",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON)), "list")); CListSetMenuItemIcon(hMenuServer, IconLibProcess(LoadIconEx(IDI_SERVER,"server",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON)), "server")); CListSetMenuItemIcon(hMenuAvatar, IconLibProcess(LoadIconEx(IDI_AVATAR,"avatar",GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON)), "avatar")); ChangedIconsXStatus(); return 0; } static int Service_ModulesLoaded(WPARAM wParam,LPARAM lParam) { char szTemp[MAX_PATH]; char szTemp3[256]; NETLIBUSER nlu = {0}; DBDeleteContactSetting(NULL, IRCPROTONAME, "JTemp"); InitIconLib(); hHookUserMenu = HookEvent(ME_CLIST_PREBUILDCONTACTMENU, PrebuildContactMenu); hHookIconsChanged = IconLibHookIconsChanged(IconLibIconsChanged); // Initialize IconLib icons InitIcons(); InitXStatusIcons(); InitXStatusEvents(); InitXStatusItems(FALSE); // Init extra optional modules InitPopUps(); nlu.cbSize = sizeof(nlu); nlu.flags = NUF_OUTGOING|NUF_INCOMING|NUF_HTTPCONNS; nlu.szSettingsModule = IRCPROTONAME; wsprintf(szTemp, Translate("%s server connection"), ALTIRCPROTONAME); nlu.szDescriptiveName = szTemp; hNetlib=(HANDLE)CallService(MS_NETLIB_REGISTERUSER, 0, (LPARAM)&nlu); char szTemp2[256]; nlu.flags = NUF_OUTGOING|NUF_INCOMING|NUF_HTTPCONNS; mir_snprintf(szTemp2, sizeof(szTemp2), "%s DCC", IRCPROTONAME); nlu.szSettingsModule = szTemp2; wsprintf(szTemp, Translate("%s client-to-client connections"), ALTIRCPROTONAME); nlu.szDescriptiveName = szTemp; hNetlibDCC=(HANDLE)CallService(MS_NETLIB_REGISTERUSER, 0, (LPARAM)&nlu); //add as a known module in DB Editor ++ CallService("DBEditorpp/RegisterSingleModule",(WPARAM)IRCPROTONAME,0); mir_snprintf(szTemp3, sizeof(szTemp3), "%s DCC", IRCPROTONAME); CallService("DBEditorpp/RegisterSingleModule",(WPARAM)szTemp3,0); // updater plugin support if(ServiceExists(MS_UPDATE_REGISTER)) { Update upd = {0}; char szCurrentVersion[30]; char *szVersionUrl = "http://dev.mirandaim.ru/iron/IRC/version.txt"; char *szUpdateUrl = "http://dev.mirandaim.ru/iron/files/IRC.zip"; // char *szFLVersionUrl = "http://addons.miranda-im.org/details.php?action=viewfile&id=2951"; // char *szFLUpdateurl = "http://addons.miranda-im.org/feed.php?dlfile=2951"; char *szPrefix = "IRC "; upd.cbSize = sizeof(upd); upd.szComponentName = pluginInfo.shortName; upd.pbVersion = (BYTE *)CreateVersionStringPlugin(&pluginInfo, szCurrentVersion); upd.cpbVersion = strlen((char *)upd.pbVersion); // upd.szVersionURL = szFLVersionUrl; // upd.szUpdateURL = szFLUpdateurl; // upd.pbVersionPrefix = (BYTE *)"Updater "; upd.szBetaUpdateURL = szUpdateUrl; upd.szBetaVersionURL = szVersionUrl; upd.pbBetaVersionPrefix = (BYTE *)szPrefix; upd.pbVersion = (PBYTE)szCurrentVersion; upd.cpbVersion = lstrlenA(szCurrentVersion); // upd.cpbVersionPrefix = strlen((char *)upd.pbVersionPrefix); upd.cpbBetaVersionPrefix = strlen((char *)upd.pbBetaVersionPrefix); CallService(MS_UPDATE_REGISTER, 0, (LPARAM)&upd); } if(ServiceExists("MBot/GetFcnTable")) { CallService(MS_MBOT_REGISTERIRC, 0, (LPARAM)IRCPROTONAME); bMbotInstalled = TRUE; } if(ServiceExists(MS_GC_REGISTER)) { GCREGISTER gcr = {0}; GCPTRS gp = {0}; CallService(MS_GC_GETEVENTPTR, 0, (LPARAM)&gp); pfnAddEvent = gp.pfnAddEvent; gcr.cbSize = sizeof(GCREGISTER); gcr.dwFlags = GC_CHANMGR|GC_BOLD|GC_ITALICS|GC_UNDERLINE|GC_COLOR|GC_BKGCOLOR; gcr.iMaxText = 0; gcr.nColors = 16; gcr.pColors = prefs->colors; gcr.pszModuleDispName = IRCPROTONAME; gcr.pszModule = IRCPROTONAME; CallService(MS_GC_REGISTER, NULL, (LPARAM)&gcr); g_hGCUserEvent = HookEvent(ME_GC_EVENT, Service_GCEventHook); g_hGCMenuBuild = HookEvent(ME_GC_BUILDMENU, Service_GCMenuHook ); GCSESSION gcw = {0}; GCDEST gcd = {0}; GCEVENT gce = {0}; gcw.cbSize = sizeof(GCSESSION); gcw.iType = GCW_SERVER; gcw.pszID = "Network log"; gcw.pszModule = IRCPROTONAME; gcw.pszName = Translate("Offline"); CallService(MS_GC_NEWSESSION, 0, (LPARAM)&gcw); gce.cbSize = sizeof(GCEVENT); gce.pDest = &gcd; gcd.pszID = "Network log"; gcd.pszModule = IRCPROTONAME; gcd.iType = GC_EVENT_CONTROL; gce.pDest = &gcd; if (prefs->UseServer && !prefs->HideServerWindow) CallChatEvent( WINDOW_VISIBLE, (LPARAM)&gce); else CallChatEvent( WINDOW_HIDDEN, (LPARAM)&gce); bChatInstalled = TRUE; } else { if(IDYES == MessageBoxA(0,Translate("The IRC protocol depends on another plugin called \'Chat\'\n\nDo you want to download it from the Miranda IM web site now?"),Translate("Information"),MB_YESNO|MB_ICONINFORMATION)) CallService(MS_UTILS_OPENURL, 1, (LPARAM) "http://www.miranda-im.org/download/details.php?action=viewfile&id=1309"); } mir_snprintf(szTemp, sizeof(szTemp), "%s\\%s_servers.ini", mirandapath, IRCPROTONAME); pszServerFile = IrcLoadFile(szTemp); mir_snprintf(szTemp, sizeof(szTemp), "%s\\%s_perform.ini", mirandapath, IRCPROTONAME); pszPerformFile = IrcLoadFile(szTemp); mir_snprintf(szTemp, sizeof(szTemp), "%s\\%s_ignore.ini", mirandapath, IRCPROTONAME); pszIgnoreFile = IrcLoadFile(szTemp); InitMenus(); g_hUserInfoInit = HookEvent(ME_USERINFO_INITIALISE, Service_InitUserInfo); g_hMenuCreation = HookEvent(ME_CLIST_PREBUILDCONTACTMENU, Service_MenuPreBuild ); g_hOptionsInit = HookEvent(ME_OPT_INITIALISE, InitOptionsPages); if (lstrlen(prefs->Nick) == 0) CreateDialog(g_hInstance,MAKEINTRESOURCE(IDD_INIT),NULL, InitWndProc); else { if (lstrlen(prefs->AlternativeNick) == 0) { mir_snprintf(szTemp, 30, "%s%u", prefs->Nick, rand()%9999); DBWriteContactSettingString(NULL, IRCPROTONAME, "AlernativeNick", szTemp); lstrcpyn(prefs->AlternativeNick, szTemp, 30); } if (lstrlen(prefs->Name) == 0) { mir_snprintf(szTemp, 30, "Miranda%u", rand()%9999); DBWriteContactSettingString(NULL, IRCPROTONAME, "Name", szTemp); lstrcpyn(prefs->Name, szTemp, 200); } } return 0; } void HookEvents(void) { g_hModulesLoaded = HookEvent(ME_SYSTEM_MODULESLOADED, Service_ModulesLoaded); // g_hContactDblClick= HookEvent(ME_CLIST_DOUBLECLICKED, Service_ContactDoubleclicked); g_hSystemPreShutdown = HookEvent(ME_SYSTEM_PRESHUTDOWN, Service_SystemPreShutdown); g_hContactDeleted = HookEvent(ME_DB_CONTACT_DELETED, Service_UserDeletedContact ); // g_hIconsChanged = HookEvent(ME_SKIN2_ICONSCHANGED, Service_IconsChanged ); return; } void UnhookEvents(void) { UnhookEvent(g_hModulesLoaded); UnhookEvent(g_hSystemPreShutdown); // UnhookEvent(g_hContactDblClick); UnhookEvent(g_hContactDeleted); UnhookEvent(g_hUserInfoInit); UnhookEvent(g_hMenuCreation); UnhookEvent(g_hGCUserEvent); UnhookEvent(g_hGCMenuBuild); UnhookEvent(g_hIconsChanged); Netlib_CloseHandle(hNetlib); Netlib_CloseHandle(hNetlibDCC); return; } int Service_GetAvatarInfo(WPARAM wParam, LPARAM lParam) { // #ifdef _DEBUG // DBGprintf( "Event: Service_GetAvatarInfo\n"); // #endif PROTO_AVATAR_INFORMATION* pai = (PROTO_AVATAR_INFORMATION*)lParam; // DWORD dwUIN; // uid_str szUID; DBVARIANT dbv; int dwPaFormat; if (!prefs->AvatarsEnabled) return GAIR_NOAVATAR; if (IRCGetContactSetting(pai->hContact, "AvatarHash", &dbv) || dbv.cpbVal != 0x14) return GAIR_NOAVATAR; // we did not found avatar hash or hash invalid - no avatar available // if (ICQGetContactSettingUID(pai->hContact, &dwUIN, &szUID)) // { // ICQFreeVariant(&dbv); // return GAIR_NOAVATAR; // we do not support avatars for invalid contacts // } dwPaFormat = IRCGetContactSettingByte(pai->hContact, "AvatarType", PA_FORMAT_UNKNOWN); if (dwPaFormat != PA_FORMAT_UNKNOWN) { // we know the format, test file // GetFullAvatarFileName(dwUIN, szUID, dwPaFormat, pai->filename, MAX_PATH); pai->format = dwPaFormat; if (!IsAvatarSaved(pai->hContact, (char *)dbv.pbVal)) { // hashes are the same if (access(pai->filename, 0) == 0) { IRCFreeVariant(&dbv); return GAIR_SUCCESS; // we have found the avatar file, whoala } } } if (IsAvatarSaved(pai->hContact, (char *)dbv.pbVal)) { // we didn't received the avatar before - this ensures we will not request avatar again and again if ((wParam & GAIF_FORCE) != 0 && pai->hContact != 0) { // request avatar data // GetAvatarFileName(dwUIN, szUID, pai->filename, MAX_PATH); // GetAvatarData(pai->hContact, dwUIN, szUID, dbv.pbVal, dbv.cpbVal, pai->filename); IRCFreeVariant(&dbv); return GAIR_WAITFOR; } } IRCFreeVariant(&dbv); return GAIR_NOAVATAR; } int Service_GetMaxAvatarSize(WPARAM wParam, LPARAM lParam) { // #ifdef _DEBUG // DBGprintf( "Event: Service_GetMaxAvatarSize\n"); // #endif if (wParam) *((int*)wParam) = 64; if (lParam) *((int*)lParam) = 64; return 0; } int Service_AvatarFormatSupported(WPARAM wParam, LPARAM lParam) { // #ifdef _DEBUG // DBGprintf( "Event: Service_AvatarFormatSupported\n"); // #endif if (lParam == PA_FORMAT_JPEG || lParam == PA_FORMAT_GIF) return -2; else return 0; } int Service_GetMyAvatar(WPARAM wParam, LPARAM lParam) { // #ifdef _DEBUG // DBGprintf( "Event: Service_GetMyAvatar\n"); // #endif if (!prefs->AvatarsEnabled) return -2; if (!wParam) return -3; if (!IRCGetContactStaticString(NULL, "AvatarFile", (char*)wParam, (int)lParam)) { if (!access((char*)wParam, 0)) return 0; } return -1; } int Service_SetMyAvatar(WPARAM wParam, LPARAM lParam) { // #ifdef _DEBUG // DBGprintf( "Event: Service_SetMyAvatar\n"); // #endif char* szFile = (char*)lParam; int iRet = -1; if (!prefs->AvatarsEnabled) return -2; if (szFile) { // set file for avatar char szMyFile[MAX_PATH+1]; int dwPaFormat = DetectAvatarFormat(szFile); char* hash; HBITMAP avt; avt = (HBITMAP)CallService(MS_UTILS_LOADBITMAP, 0, (WPARAM)szFile); if (!avt) return iRet; DeleteObject(avt); GetFullAvatarFileName(0, NULL, dwPaFormat, szMyFile, MAX_PATH); if (!CopyFile(szFile, szMyFile, FALSE)) return iRet; hash = calcMD5Hash(szMyFile); if (hash) { char* ihash = (char*)_alloca(0x14); // upload hash to server ihash[0] = 0; //unknown ihash[1] = 1; //hash type ihash[2] = 1; //hash status ihash[3] = 0x10; //hash len memcpy(ihash+4, hash, 0x10); IRCWriteContactSettingBlob(NULL, "AvatarHash", ihash, 0x14); IRCWriteContactSettingString(NULL, "AvatarFile", szMyFile); iRet = 0; SAFE_FREE((void **)&hash); } } else { // delete user avatar IRCDeleteContactSetting(NULL, "AvatarFile"); IRCDeleteContactSetting(NULL, "AvatarHash"); iRet = 0; } return iRet; } void CreateServiceFunctions(void) { char temp[MAXMODULELABELLENGTH]; wsprintf(temp, "%s%s", IRCPROTONAME, PS_GETCAPS); CreateServiceFunction(temp, Service_GetCaps); wsprintf(temp, "%s%s", IRCPROTONAME, PS_GETNAME); CreateServiceFunction(temp,Service_GetName); wsprintf(temp, "%s%s", IRCPROTONAME, PS_LOADICON); CreateServiceFunction(temp,Service_LoadIcon); wsprintf(temp, "%s%s", IRCPROTONAME, PS_SETSTATUS); CreateServiceFunction(temp,Service_SetStatus); wsprintf(temp, "%s%s", IRCPROTONAME, PS_GETSTATUS); CreateServiceFunction(temp,Service_GetStatus); wsprintf(temp, "%s%s", IRCPROTONAME, PS_SETAWAYMSG); CreateServiceFunction(temp, Service_SetAwayMsg); wsprintf(temp, "%s%s", IRCPROTONAME, PS_BASICSEARCH); CreateServiceFunction(temp, Service_BasicSearch); wsprintf(temp, "%s%s", IRCPROTONAME, PS_ADDTOLIST); CreateServiceFunction(temp, Service_AddToList); wsprintf(temp, "%s%s", IRCPROTONAME, PSR_MESSAGE); CreateServiceFunction(temp,Service_AddIncMessToDB); wsprintf(temp, "%s%s", IRCPROTONAME, PSS_MESSAGE); CreateServiceFunction(temp, Service_GetMessFromSRMM); wsprintf(temp, "%s%s", IRCPROTONAME, PSS_GETAWAYMSG); CreateServiceFunction(temp, Service_GetAwayMessage); wsprintf(temp,"%s/JoinChannelMenu", IRCPROTONAME); CreateServiceFunction(temp,Service_JoinMenuCommand); wsprintf(temp,"%s/QuickConnectMenu", IRCPROTONAME); CreateServiceFunction(temp,Service_QuickConnectMenuCommand); wsprintf(temp,"%s/ChangeNickMenu", IRCPROTONAME); CreateServiceFunction(temp,Service_ChangeNickMenuCommand); wsprintf(temp,"%s/ShowListMenu", IRCPROTONAME); CreateServiceFunction(temp,Service_ShowListMenuCommand); wsprintf(temp,"%s/ShowServerMenu", IRCPROTONAME); CreateServiceFunction(temp,Service_ShowServerMenuCommand); wsprintf(temp,"%s/SetAvatarMenu", IRCPROTONAME); CreateServiceFunction(temp, Service_SetAvatarMenuCommand); wsprintf(temp,"%s/Menu1ChannelMenu", IRCPROTONAME); CreateServiceFunction(temp,Service_Menu1Command); wsprintf(temp,"%s/Menu2ChannelMenu", IRCPROTONAME); CreateServiceFunction(temp,Service_Menu2Command); wsprintf(temp,"%s/Menu3ChannelMenu", IRCPROTONAME); CreateServiceFunction(temp,Service_Menu3Command); wsprintf(temp,"%s/DblClickEvent", IRCPROTONAME); CreateServiceFunction(temp, Service_EventDoubleclicked); wsprintf(temp,"%s/InsertRawIn", IRCPROTONAME); CreateServiceFunction(temp, Scripting_InsertRawIn); wsprintf(temp,"%s/InsertRawOut", IRCPROTONAME); CreateServiceFunction(temp, Scripting_InsertRawOut); wsprintf(temp,"%s/InsertGuiIn", IRCPROTONAME); CreateServiceFunction(temp, Scripting_InsertGuiIn); wsprintf(temp,"%s/InsertGuiOut", IRCPROTONAME); CreateServiceFunction(temp, Scripting_InsertGuiOut); wsprintf(temp,"%s/GetIrcData", IRCPROTONAME); CreateServiceFunction(temp, Scripting_GetIrcData); wsprintf(temp,"%s%s", IRCPROTONAME, PSS_FILEALLOW); CreateServiceFunction(temp, Service_FileAllow); wsprintf(temp,"%s%s", IRCPROTONAME, PSS_FILEDENY); CreateServiceFunction(temp, Service_FileDeny); wsprintf(temp,"%s%s", IRCPROTONAME, PSS_FILECANCEL); CreateServiceFunction(temp, Service_FileCancel); wsprintf(temp,"%s%s", IRCPROTONAME, PSS_FILE); CreateServiceFunction(temp, Service_FileSend); wsprintf(temp,"%s%s", IRCPROTONAME, PSR_FILE); CreateServiceFunction(temp, Service_FileReceive); wsprintf(temp,"%s%s", IRCPROTONAME, PS_FILERESUME); CreateServiceFunction(temp, Service_FileResume); // Typing Notify wsprintf(temp,"%s%s", IRCPROTONAME, PSS_USERISTYPING); CreateServiceFunction(temp, Service_SendUserIsTyping); // Nudge wsprintf(temp,"%s%s", IRCPROTONAME, PS_SEND_NUDGE); CreateServiceFunction(temp, Service_SendNudge); //Begin Custom Status API wsprintf(temp,"%s%s", IRCPROTONAME, PS_SETCUSTOMSTATUS); CreateServiceFunction(temp, IRCSetXStatus); wsprintf(temp,"%s%s", IRCPROTONAME, PS_GETCUSTOMSTATUSICON); CreateServiceFunction(temp, IRCGetXStatusIcon); wsprintf(temp,"%s%s", IRCPROTONAME, PS_GETCUSTOMSTATUS); CreateServiceFunction(temp, IRCGetXStatus); wsprintf(temp,"%s%s", IRCPROTONAME, PS_REQUESTCUSTOMSTATUS); CreateServiceFunction(temp, IRCRequestXStatusDetails); wsprintf(temp,"%s%s", IRCPROTONAME, MS_XSTATUS_SHOWDETAILS); CreateServiceFunction(temp, IRCShowXStatusDetails); //End Custom Status API // Begin Avatar API wsprintf(temp,"%s%s", IRCPROTONAME, PS_IRC_GETMYAVATARMAXSIZE); CreateServiceFunction(temp, Service_GetMaxAvatarSize); wsprintf(temp,"%s%s", IRCPROTONAME, PS_IRC_ISAVATARFORMATSUPPORTED); CreateServiceFunction(temp, Service_AvatarFormatSupported); wsprintf(temp,"%s%s", IRCPROTONAME, PS_IRC_GETMYAVATAR); CreateServiceFunction(temp, Service_GetMyAvatar); wsprintf(temp,"%s%s", IRCPROTONAME, PS_IRC_SETMYAVATAR); CreateServiceFunction(temp, Service_SetMyAvatar); wsprintf(temp,"%s%s", IRCPROTONAME, PS_GETAVATARINFO); CreateServiceFunction(temp, Service_GetAvatarInfo); // End Avatar API return; } void handleNudgeNotification(const char* NickName) { if(ServiceExists(MS_NUDGE_SEND)) { HANDLE hContact = GetContactByName(NickName); if(hContact) { #ifdef _DEBUG DBGprintf( "Event: NudgeNotification (TRUE)\n"); #endif DBVARIANT dbv1; if(DBGetContactSettingByte(hContact, IRCPROTONAME, "AdvancedMode", 0) == 0) DoUserhostWithReason(1, ((String)"S" + NickName).c_str(), true, NickName); else { if (!DBGetContactSetting(hContact, IRCPROTONAME, "UWildcard", &dbv1) && dbv1.type == DBVT_ASCIIZ) { DoUserhostWithReason(2, ((String)"S" + dbv1.pszVal).c_str(), true, dbv1.pszVal); DBFreeVariant(&dbv1); } else { DoUserhostWithReason(2, ((String)"S" + NickName).c_str(), true, NickName); } } NotifyEventHooks(hIRCNudge,WPARAM(hContact),0); } else { #ifdef _DEBUG DBGprintf( "Event: NudgeNotification (FALSE)\n"); #endif } } } void handleTypingNotification(const char* NickName, WORD wMTNCode) { LPARAM lParam; if(prefs->TypingEnabled) { switch (wMTNCode) { case MTN_TYPED: lParam = PROTOTYPE_CONTACTTYPING_OFF; break; case MTN_BEGUN: lParam = (LPARAM)60; break; default: break; } HANDLE hContact = GetContactByName(NickName); DBWriteContactSettingByte(hContact,"SRMsg", "SupportTyping", 1); if (hContact) { DBVARIANT dbv1; if(DBGetContactSettingByte(hContact, IRCPROTONAME, "AdvancedMode", 0) == 0) DoUserhostWithReason(1, ((String)"S" + NickName).c_str(), true, NickName); else { if (!DBGetContactSetting(hContact, IRCPROTONAME, "UWildcard", &dbv1) && dbv1.type == DBVT_ASCIIZ) { DoUserhostWithReason(2, ((String)"S" + dbv1.pszVal).c_str(), true, dbv1.pszVal); DBFreeVariant(&dbv1); } else { DoUserhostWithReason(2, ((String)"S" + NickName).c_str(), true, NickName); } } } CallService(MS_PROTO_CONTACTISTYPING, (WPARAM)hContact, lParam); } } void handleXStatus(const char* NickName) { BYTE bXStatus = NULL; char *szName; if(DBGetContactSettingByte(NULL,IRCPROTONAME, "XStatusEnabled", 0)) { bXStatus = IRCGetContactSettingByte(NULL, DBSETTING_XSTATUSID, 0); szName = UniGetContactSettingUtf(NULL, ALTIRCPROTONAME, DBSETTING_XSTATUSNAME, ""); String szText = UniGetContactSettingUtf(NULL, ALTIRCPROTONAME, DBSETTING_XSTATUSMSG, ""); szText = ReplaceString( (char *)szText.c_str(), "\r\n", "\005"); PostIrcMessage("/NOTICE %s \001XSTATUS %d %s\004%s\001", NickName, bXStatus, szName, szText.c_str()); } else PostIrcMessage("/NOTICE %s \001XSTATUS OFF\001", NickName); } void handleAvatarHash(const char* NickName) { DBVARIANT dbvHash; if(!IRCGetContactSetting(NULL, "AvatarHash", &dbvHash)) { char hash[50]="",h[9],path[255]; for(int i=0;i<20;i+=4) { sprintf(h,"%.8X",*((unsigned int*)(dbvHash.pbVal+i))); strcat(hash,h); } IRCFreeVariant(&dbvHash); IRCGetContactSettingString(NULL,"AvatarPath",path); // #ifdef _DEBUG // DBGprintf("AvatarHash = %s\n", hash); // #endif PostIrcMessage("/NOTICE %s \001AVATAR %s %s\001", NickName, hash, path); } } void sendTypingNotification(HANDLE hContact, WORD wMTNCode) { DBVARIANT dbv; DBCONTACTGETSETTING dcs; dcs.szModule=IRCPROTONAME; dcs.szSetting="Nick"; dcs.pValue=&dbv; dbv.type=DBVT_ASCIIZ; CallService(MS_DB_CONTACT_GETSETTING,(WPARAM)hContact,(LPARAM)&dcs); switch (wMTNCode) { case MTN_BEGUN: PostIrcMessage( "/PRIVMSG %s \001TYPINGSTART\001", dbv.pszVal); break; case MTN_FINISHED: PostIrcMessage( "/PRIVMSG %s \001TYPINGSTOP\001", dbv.pszVal); break; default: break; } DBFreeVariant(&dbv); return; } VOID CALLBACK RetryTimerProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime) { if (RetryCount <= StrToInt(prefs->RetryCount) && prefs->Retry) { char szTemp[300]; PortCount++; if (PortCount > StrToInt(prefs->PortEnd) || StrToInt(prefs->PortEnd) ==0) PortCount = StrToInt(prefs->PortStart); si.iPort = PortCount; mir_snprintf(szTemp, sizeof(szTemp), "\0033%s \002%s\002 (%s: %u, try %u)", Translate("Reconnecting to"), si.sNetwork.c_str(), si.sServer.c_str(), si.iPort, RetryCount); DoEvent(GC_EVENT_INFORMATION, "Network log", NULL, szTemp, NULL, NULL, NULL, true, false); if (!bConnectThreadRunning) { forkthread(ConnectServerThread, 0, NULL ); } else bConnectRequested = true; RetryCount++; } else KillChatTimer(RetryTimer); }