/* IRC plugin for Miranda IM Copyright (C) 2003-05 Jurgen Persson Copyright (C) 2007-09 George Hazan 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" #include "version.h" #define NICKSUBSTITUTE _T("!_nick_!") void CIrcProto::FormatMsg(CMString& text) { TCHAR temp[30]; mir_tstrncpy(temp, GetWord(text.c_str(), 0).c_str(), 29); CharLower(temp); CMString command = temp; CMString S = _T(""); if (command == _T("/quit") || command == _T("/away")) S = GetWord(text.c_str(), 0) + _T(" :") + GetWordAddress(text.c_str(), 1); else if (command == _T("/privmsg") || command == _T("/part") || command == _T("/topic") || command == _T("/notice")) { S = GetWord(text.c_str(), 0) + _T(" ") + GetWord(text.c_str(), 1) + _T(" :"); if (!GetWord(text.c_str(), 2).IsEmpty()) S += CMString(GetWordAddress(text.c_str(), 2)); } else if (command == _T("/kick")) { S = GetWord(text.c_str(), 0) + _T(" ") + GetWord(text.c_str(), 1) + _T(" ") + GetWord(text.c_str(), 2) + _T(" :") + GetWordAddress(text.c_str(), 3); } else if (command == _T("/nick")) { if (!_tcsstr(GetWord(text.c_str(), 1).c_str(), NICKSUBSTITUTE)) { sNick4Perform = GetWord(text.c_str(), 1); S = GetWordAddress(text.c_str(), 0); } else { CMString sNewNick = GetWord(text.c_str(), 1); if (sNick4Perform == _T("")) { DBVARIANT dbv; if (!getTString("PNick", &dbv)) { sNick4Perform = dbv.ptszVal; db_free(&dbv); } } sNewNick.Replace(NICKSUBSTITUTE, sNick4Perform.c_str()); S = GetWord(text.c_str(), 0) + _T(" ") + sNewNick; } } else S = GetWordAddress(text.c_str(), 0); S.Delete(0, 1); text = S; } static void AddCR(CMString& text) { text.Replace(_T("\n"), _T("\r\n")); text.Replace(_T("\r\r"), _T("\r")); } CMString CIrcProto::DoAlias(const TCHAR *text, TCHAR *window) { CMString Messageout = _T(""); const TCHAR* p1 = text; const TCHAR* p2 = text; bool LinebreakFlag = false, hasAlias = false; p2 = _tcsstr(p1, _T("\r\n")); if (!p2) p2 = _tcschr(p1, '\0'); if (p1 == p2) return (CMString)text; do { if (LinebreakFlag) Messageout += _T("\r\n"); TCHAR* line = new TCHAR[p2 - p1 + 1]; mir_tstrncpy(line, p1, p2 - p1 + 1); TCHAR* test = line; while (*test == ' ') test++; if (*test == '/') { mir_tstrncpy(line, GetWordAddress(line, 0), p2 - p1 + 1); CMString S = line; delete[] line; line = new TCHAR[S.GetLength() + 2]; mir_tstrncpy(line, S.c_str(), S.GetLength() + 1); CMString alias(m_alias); const TCHAR* p3 = _tcsstr(alias.c_str(), (GetWord(line, 0) + _T(" ")).c_str()); if (p3 != alias.c_str()) { CMString S = _T("\r\n"); S += GetWord(line, 0) + _T(" "); p3 = _tcsstr(alias.c_str(), S.c_str()); if (p3) p3 += 2; } if (p3 != NULL) { hasAlias = true; const TCHAR* p4 = _tcsstr(p3, _T("\r\n")); if (!p4) p4 = _tcschr(p3, '\0'); *(TCHAR*)p4 = 0; CMString S = p3; S.Replace(_T("##"), window); S.Replace(_T("$?"), _T("%question")); for (int index = 1; index < 8; index++) { TCHAR str[5]; mir_sntprintf(str, SIZEOF(str), _T("#$%u"), index); if (!GetWord(line, index).IsEmpty() && IsChannel(GetWord(line, index))) S.Replace(str, GetWord(line, index).c_str()); else { CMString S1 = _T("#"); S1 += GetWord(line, index); S.Replace(str, S1.c_str()); } } for (int index2 = 1; index2 < 8; index2++) { TCHAR str[5]; mir_sntprintf(str, SIZEOF(str), _T("$%u-"), index2); S.Replace(str, GetWordAddress(line, index2)); } for (int index3 = 1; index3 < 8; index3++) { TCHAR str[5]; mir_sntprintf(str, SIZEOF(str), _T("$%u"), index3); S.Replace(str, GetWord(line, index3).c_str()); } Messageout += GetWordAddress(S.c_str(), 1); } else Messageout += line; } else Messageout += line; p1 = p2; if (*p1 == '\r') p1 += 2; p2 = _tcsstr(p1, _T("\r\n")); if (!p2) p2 = _tcschr(p1, '\0'); delete[] line; LinebreakFlag = true; } while (*p1 != '\0'); return hasAlias ? DoIdentifiers(Messageout, window) : Messageout; } CMString CIrcProto::DoIdentifiers(CMString text, const TCHAR*) { SYSTEMTIME time; TCHAR str[2]; GetLocalTime(&time); text.Replace(_T("%mnick"), m_nick); text.Replace(_T("%anick"), m_alternativeNick); text.Replace(_T("%awaymsg"), m_statusMessage.c_str()); text.Replace(_T("%module"), _A2T(m_szModuleName)); text.Replace(_T("%name"), m_name); text.Replace(_T("%newl"), _T("\r\n")); text.Replace(_T("%network"), m_info.sNetwork.c_str()); text.Replace(_T("%me"), m_info.sNick.c_str()); char mirver[100]; CallService(MS_SYSTEM_GETVERSIONTEXT, SIZEOF(mirver), LPARAM(mirver)); text.Replace(_T("%mirver"), _A2T(mirver)); text.Replace(_T("%version"), _T(__VERSION_STRING_DOTS)); str[0] = 3; str[1] = '\0'; text.Replace(_T("%color"), str); str[0] = 2; text.Replace(_T("%bold"), str); str[0] = 31; text.Replace(_T("%underline"), str); str[0] = 22; text.Replace(_T("%italics"), str); return text; } static void __stdcall sttSetTimerOn(void* _pro) { CIrcProto *ppro = (CIrcProto*)_pro; ppro->DoEvent(GC_EVENT_INFORMATION, NULL, ppro->m_info.sNick.c_str(), TranslateT("The buddy check function is enabled"), NULL, NULL, NULL, true, false); ppro->SetChatTimer(ppro->OnlineNotifTimer, 500, OnlineNotifTimerProc); if (ppro->m_channelAwayNotification) ppro->SetChatTimer(ppro->OnlineNotifTimer3, 1500, OnlineNotifTimerProc3); } static void __stdcall sttSetTimerOff(void* _pro) { CIrcProto *ppro = (CIrcProto*)_pro; ppro->DoEvent(GC_EVENT_INFORMATION, NULL, ppro->m_info.sNick.c_str(), TranslateT("The buddy check function is disabled"), NULL, NULL, NULL, true, false); ppro->KillChatTimer(ppro->OnlineNotifTimer); ppro->KillChatTimer(ppro->OnlineNotifTimer3); } BOOL CIrcProto::DoHardcodedCommand(CMString text, TCHAR* window, MCONTACT hContact) { TCHAR temp[30]; mir_tstrncpy(temp, GetWord(text.c_str(), 0).c_str(), 29); CharLower(temp); CMString command = temp; CMString one = GetWord(text.c_str(), 1); CMString two = GetWord(text.c_str(), 2); CMString three = GetWord(text.c_str(), 3); CMString therest = GetWordAddress(text.c_str(), 4); if (command == _T("/servershow") || command == _T("/serverhide")) { if (m_useServer) { GCDEST gcd = { m_szModuleName, SERVERWINDOW, GC_EVENT_CONTROL }; GCEVENT gce = { sizeof(gce), &gcd }; CallChatEvent(command == _T("/servershow") ? WINDOW_VISIBLE : WINDOW_HIDDEN, (LPARAM)&gce); } return true; } else if (command == _T("/sleep") || command == _T("/wait")) { if (!one.IsEmpty()) { int ms; if (_stscanf(one.c_str(), _T("%d"), &ms) == 1 && ms > 0 && ms <= 4000) Sleep(ms); else DoEvent(GC_EVENT_INFORMATION, NULL, m_info.sNick.c_str(), TranslateT("Incorrect parameters. Usage: /sleep [ms], ms should be greater than 0 and less than 4000."), NULL, NULL, NULL, true, false); } return true; } if (command == _T("/clear")) { CMString S; if (!one.IsEmpty()) { if (one == _T("server")) S = SERVERWINDOW; else S = MakeWndID(one.c_str()); } else if (mir_tstrcmpi(window, SERVERWINDOW) == 0) S = window; else S = MakeWndID(window); GCDEST gcd = { m_szModuleName, S.c_str(), GC_EVENT_CONTROL }; GCEVENT gce = { sizeof(gce), &gcd }; CallChatEvent(WINDOW_CLEARLOG, (LPARAM)&gce); return true; } if (command == _T("/ignore")) { if (IsConnected()) { CMString IgnoreFlags; TCHAR temp[500]; if (one.IsEmpty()) { if (m_ignore) DoEvent(GC_EVENT_INFORMATION, NULL, m_info.sNick.c_str(), TranslateT("Ignore system is enabled"), NULL, NULL, NULL, true, false); else DoEvent(GC_EVENT_INFORMATION, NULL, m_info.sNick.c_str(), TranslateT("Ignore system is disabled"), NULL, NULL, NULL, true, false); return true; } if (!mir_tstrcmpi(one.c_str(), _T("on"))) { m_ignore = 1; DoEvent(GC_EVENT_INFORMATION, NULL, m_info.sNick.c_str(), TranslateT("Ignore system is enabled"), NULL, NULL, NULL, true, false); return true; } if (!mir_tstrcmpi(one.c_str(), _T("off"))) { m_ignore = 0; DoEvent(GC_EVENT_INFORMATION, NULL, m_info.sNick.c_str(), TranslateT("Ignore system is disabled"), NULL, NULL, NULL, true, false); return true; } if (!_tcschr(one.c_str(), '!') && !_tcschr(one.c_str(), '@')) one += _T("!*@*"); if (!two.IsEmpty() && two[0] == '+') { if (_tcschr(two.c_str(), 'q')) IgnoreFlags += 'q'; if (_tcschr(two.c_str(), 'n')) IgnoreFlags += 'n'; if (_tcschr(two.c_str(), 'i')) IgnoreFlags += 'i'; if (_tcschr(two.c_str(), 'd')) IgnoreFlags += 'd'; if (_tcschr(two.c_str(), 'c')) IgnoreFlags += 'c'; if (_tcschr(two.c_str(), 'm')) IgnoreFlags += 'm'; } else IgnoreFlags = _T("qnidc"); CMString m_network; if (three.IsEmpty()) m_network = m_info.sNetwork; else m_network = three; AddIgnore(one.c_str(), IgnoreFlags.c_str(), m_network.c_str()); mir_sntprintf(temp, SIZEOF(temp), TranslateT("%s on %s is now ignored (+%s)"), one.c_str(), m_network.c_str(), IgnoreFlags.c_str()); DoEvent(GC_EVENT_INFORMATION, NULL, m_info.sNick.c_str(), temp, NULL, NULL, NULL, true, false); } return true; } if (command == _T("/unignore")) { if (!_tcschr(one.c_str(), '!') && !_tcschr(one.c_str(), '@')) one += _T("!*@*"); TCHAR temp[500]; if (RemoveIgnore(one.c_str())) mir_sntprintf(temp, SIZEOF(temp), TranslateT("%s is not ignored now"), one.c_str()); else mir_sntprintf(temp, SIZEOF(temp), TranslateT("%s was not ignored"), one.c_str()); DoEvent(GC_EVENT_INFORMATION, NULL, m_info.sNick.c_str(), temp, NULL, NULL, NULL, true, false); return true; } if (command == _T("/userhost")) { if (one.IsEmpty()) return true; DoUserhostWithReason(1, _T("U"), false, temp); return false; } if (command == _T("/joinx")) { if (!one.IsEmpty()) { for (int i = 1;; i++) { CMString tmp = GetWord(text.c_str(), i); if (tmp.IsEmpty()) break; AddToJTemp('X', tmp); } PostIrcMessage(_T("/JOIN %s"), GetWordAddress(text.c_str(), 1)); } return true; } if (command == _T("/joinm")) { if (!one.IsEmpty()) { for (int i = 1;; i++) { CMString tmp = GetWord(text.c_str(), i); if (tmp.IsEmpty()) break; AddToJTemp('M', tmp); } PostIrcMessage(_T("/JOIN %s"), GetWordAddress(text.c_str(), 1)); } return true; } if (command == _T("/nusers")) { TCHAR szTemp[40]; CMString S = MakeWndID(window); GC_INFO gci = { 0 }; gci.Flags = GCF_BYID | GCF_NAME | GCF_COUNT; gci.pszModule = m_szModuleName; gci.pszID = S.c_str(); if (!CallServiceSync(MS_GC_GETINFO, 0, (LPARAM)&gci)) mir_sntprintf(szTemp, SIZEOF(szTemp), _T("users: %u"), gci.iCount); DoEvent(GC_EVENT_INFORMATION, NULL, m_info.sNick.c_str(), szTemp, NULL, NULL, NULL, true, false); return true; } if (command == _T("/echo")) { if (one.IsEmpty()) return true; if (!mir_tstrcmpi(one.c_str(), _T("on"))) { bEcho = TRUE; DoEvent(GC_EVENT_INFORMATION, NULL, m_info.sNick.c_str(), TranslateT("Outgoing commands are shown"), NULL, NULL, NULL, true, false); } if (!mir_tstrcmpi(one.c_str(), _T("off"))) { DoEvent(GC_EVENT_INFORMATION, NULL, m_info.sNick.c_str(), TranslateT("Outgoing commands are not shown"), NULL, NULL, NULL, true, false); bEcho = FALSE; } return true; } if (command == _T("/buddycheck")) { if (one.IsEmpty()) { if ((m_autoOnlineNotification && !bTempDisableCheck) || bTempForceCheck) DoEvent(GC_EVENT_INFORMATION, NULL, m_info.sNick.c_str(), TranslateT("The buddy check function is enabled"), NULL, NULL, NULL, true, false); else DoEvent(GC_EVENT_INFORMATION, NULL, m_info.sNick.c_str(), TranslateT("The buddy check function is disabled"), NULL, NULL, NULL, true, false); return true; } if (!mir_tstrcmpi(one.c_str(), _T("on"))) { bTempForceCheck = true; bTempDisableCheck = false; CallFunctionAsync(sttSetTimerOn, this); } if (!mir_tstrcmpi(one.c_str(), _T("off"))) { bTempForceCheck = false; bTempDisableCheck = true; CallFunctionAsync(sttSetTimerOff, this); } if (!mir_tstrcmpi(one.c_str(), _T("time")) && !two.IsEmpty()) { m_iTempCheckTime = StrToInt(two.c_str()); if (m_iTempCheckTime < 10 && m_iTempCheckTime != 0) m_iTempCheckTime = 10; if (m_iTempCheckTime == 0) DoEvent(GC_EVENT_INFORMATION, NULL, m_info.sNick.c_str(), TranslateT("The time interval for the buddy check function is now at default setting"), NULL, NULL, NULL, true, false); else { TCHAR temp[200]; mir_sntprintf(temp, SIZEOF(temp), TranslateT("The time interval for the buddy check function is now %u seconds"), m_iTempCheckTime); DoEvent(GC_EVENT_INFORMATION, NULL, m_info.sNick.c_str(), temp, NULL, NULL, NULL, true, false); } } return true; } if (command == _T("/whois")) { if (one.IsEmpty()) return false; m_manualWhoisCount++; return false; } if (command == _T("/channelmanager")) { if (window && !hContact && IsChannel(window)) { if (IsConnected()) { if (m_managerDlg != NULL) { SetActiveWindow(m_managerDlg->GetHwnd()); m_managerDlg->Close(); } else { m_managerDlg = new CManagerDlg(this); m_managerDlg->Show(); m_managerDlg->InitManager(1, window); } } } return true; } if (command == _T("/who")) { if (one.IsEmpty()) return true; DoUserhostWithReason(2, _T("U"), false, _T("%s"), one.c_str()); return false; } if (command == _T("/hop")) { if (!IsChannel(window)) return true; PostIrcMessage(_T("/PART %s"), window); if ((one.IsEmpty() || !IsChannel(one))) { CHANNELINFO *wi = (CHANNELINFO *)DoEvent(GC_EVENT_GETITEMDATA, window, NULL, NULL, NULL, NULL, NULL, FALSE, FALSE, 0); if (wi && wi->pszPassword) PostIrcMessage(_T("/JOIN %s %s"), window, wi->pszPassword); else PostIrcMessage(_T("/JOIN %s"), window); return true; } CMString S = MakeWndID(window); GCDEST gcd = { m_szModuleName, S.c_str(), GC_EVENT_CONTROL }; GCEVENT gce = { sizeof(gce), &gcd }; CallChatEvent(SESSION_TERMINATE, (LPARAM)&gce); PostIrcMessage(_T("/JOIN %s"), GetWordAddress(text.c_str(), 1)); return true; } if (command == _T("/list")) { if (m_listDlg == NULL) { m_listDlg = new CListDlg(this); m_listDlg->Show(); } SetActiveWindow(m_listDlg->GetHwnd()); int minutes = (int)m_noOfChannels / 4000; int minutes2 = (int)m_noOfChannels / 9000; TCHAR text[256]; mir_sntprintf(text, SIZEOF(text), TranslateT("This command is not recommended on a network of this size!\r\nIt will probably cause high CPU usage and/or high bandwidth\r\nusage for around %u to %u minute(s).\r\n\r\nDo you want to continue?"), minutes2, minutes); if (m_noOfChannels < 4000 || (m_noOfChannels >= 4000 && MessageBox(NULL, text, TranslateT("IRC warning"), MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON2) == IDYES)) { ListView_DeleteAllItems(GetDlgItem(m_listDlg->GetHwnd(), IDC_INFO_LISTVIEW)); PostIrcMessage(_T("/lusers")); return false; } m_listDlg->m_status.SetText(TranslateT("Aborted")); return true; } if (command == _T("/me")) { if (one.IsEmpty()) return true; TCHAR szTemp[4000]; mir_sntprintf(szTemp, SIZEOF(szTemp), _T("\001ACTION %s\001"), GetWordAddress(text.c_str(), 1)); PostIrcMessageWnd(window, hContact, szTemp); return true; } if (command == _T("/ame")) { if (one.IsEmpty()) return true; CMString S = _T("/ME ") + DoIdentifiers(GetWordAddress(text.c_str(), 1), window); S.Replace(_T("%"), _T("%%")); DoEvent(GC_EVENT_SENDMESSAGE, NULL, NULL, S.c_str(), NULL, NULL, NULL, FALSE, FALSE); return true; } if (command == _T("/amsg")) { if (one.IsEmpty()) return true; CMString S = DoIdentifiers(GetWordAddress(text.c_str(), 1), window); S.Replace(_T("%"), _T("%%")); DoEvent(GC_EVENT_SENDMESSAGE, NULL, NULL, S.c_str(), NULL, NULL, NULL, FALSE, FALSE); return true; } if (command == _T("/msg")) { if (one.IsEmpty() || two.IsEmpty()) return true; TCHAR szTemp[4000]; mir_sntprintf(szTemp, SIZEOF(szTemp), _T("/PRIVMSG %s"), GetWordAddress(text.c_str(), 1)); PostIrcMessageWnd(window, hContact, szTemp); return true; } if (command == _T("/query")) { if (one.IsEmpty() || IsChannel(one.c_str())) return true; CONTACT user = { (TCHAR*)one.c_str(), NULL, NULL, false, false, false }; MCONTACT hContact2 = CList_AddContact(&user, false, false); if (hContact2) { if (getByte(hContact, "AdvancedMode", 0) == 0) DoUserhostWithReason(1, (_T("S") + one).c_str(), true, one.c_str()); else { DBVARIANT dbv1; if (!getTString(hContact, "UWildcard", &dbv1)) { CMString S = _T("S"); S += dbv1.ptszVal; DoUserhostWithReason(2, S.c_str(), true, dbv1.ptszVal); db_free(&dbv1); } else { CMString S = _T("S"); S += one; DoUserhostWithReason(2, S.c_str(), true, one.c_str()); } } CallService(MS_MSG_SENDMESSAGE, (WPARAM)hContact2, 0); } if (!two.IsEmpty()) { TCHAR szTemp[4000]; mir_sntprintf(szTemp, SIZEOF(szTemp), _T("/PRIVMSG %s"), GetWordAddress(text.c_str(), 1)); PostIrcMessageWnd(window, hContact, szTemp); } return true; } if (command == _T("/ctcp")) { if (one.IsEmpty() || two.IsEmpty()) return true; TCHAR szTemp[1000]; unsigned long ulAdr = 0; if (m_manualHost) ulAdr = ConvertIPToInteger(m_mySpecifiedHostIP); else ulAdr = ConvertIPToInteger(m_IPFromServer ? m_myHost : m_myLocalHost); // if it is not dcc or if it is dcc and a local ip exist if (mir_tstrcmpi(two.c_str(), _T("dcc")) != 0 || ulAdr) { if (mir_tstrcmpi(two.c_str(), _T("ping")) == 0) mir_sntprintf(szTemp, SIZEOF(szTemp), _T("/PRIVMSG %s \001%s %u\001"), one.c_str(), two.c_str(), time(0)); else mir_sntprintf(szTemp, SIZEOF(szTemp), _T("/PRIVMSG %s \001%s\001"), one.c_str(), GetWordAddress(text.c_str(), 2)); PostIrcMessageWnd(window, hContact, szTemp); } if (mir_tstrcmpi(two.c_str(), _T("dcc")) != 0) { mir_sntprintf(szTemp, SIZEOF(szTemp), TranslateT("CTCP %s request sent to %s"), two.c_str(), one.c_str()); DoEvent(GC_EVENT_INFORMATION, SERVERWINDOW, m_info.sNick.c_str(), szTemp, NULL, NULL, NULL, true, false); } return true; } if (command == _T("/dcc")) { if (one.IsEmpty() || two.IsEmpty()) return true; if (mir_tstrcmpi(one.c_str(), _T("send")) == 0) { TCHAR szTemp[1000]; unsigned long ulAdr = 0; if (m_manualHost) ulAdr = ConvertIPToInteger(m_mySpecifiedHostIP); else ulAdr = ConvertIPToInteger(m_IPFromServer ? m_myHost : m_myLocalHost); if (ulAdr) { CONTACT user = { (TCHAR*)two.c_str(), NULL, NULL, false, false, true }; MCONTACT hContact = CList_AddContact(&user, false, false); if (hContact) { CMString s; if (getByte(hContact, "AdvancedMode", 0) == 0) DoUserhostWithReason(1, (_T("S") + two).c_str(), true, two.c_str()); else { DBVARIANT dbv1; CMString S = _T("S"); if (!getTString(hContact, "UWildcard", &dbv1)) { S += dbv1.ptszVal; DoUserhostWithReason(2, S.c_str(), true, dbv1.ptszVal); db_free(&dbv1); } else { S += two; DoUserhostWithReason(2, S.c_str(), true, two.c_str()); } } if (three.IsEmpty()) CallService(MS_FILE_SENDFILE, hContact, 0); else { CMString temp = GetWordAddress(text.c_str(), 3); TCHAR* pp[2]; TCHAR* p = (TCHAR*)temp.c_str(); pp[0] = p; pp[1] = NULL; CallService(MS_FILE_SENDSPECIFICFILEST, hContact, (LPARAM)pp); } } } else { mir_sntprintf(szTemp, SIZEOF(szTemp), TranslateT("DCC ERROR: Unable to automatically resolve external IP")); DoEvent(GC_EVENT_INFORMATION, 0, m_info.sNick.c_str(), szTemp, NULL, NULL, NULL, true, false); } return true; } if (mir_tstrcmpi(one.c_str(), _T("chat")) == 0) { TCHAR szTemp[1000]; unsigned long ulAdr = 0; if (m_manualHost) ulAdr = ConvertIPToInteger(m_mySpecifiedHostIP); else ulAdr = ConvertIPToInteger(m_IPFromServer ? m_myHost : m_myLocalHost); if (ulAdr) { CMString contact = two; contact += DCCSTRING; CONTACT user = { (TCHAR*)contact.c_str(), NULL, NULL, false, false, true }; MCONTACT hContact = CList_AddContact(&user, false, false); setByte(hContact, "DCC", 1); int iPort = 0; if (hContact) { DCCINFO* dci = new DCCINFO; dci->hContact = hContact; dci->sContactName = two; dci->iType = DCC_CHAT; dci->bSender = true; CDccSession* dcc = new CDccSession(this, dci); CDccSession* olddcc = FindDCCSession(hContact); if (olddcc) olddcc->Disconnect(); AddDCCSession(hContact, dcc); iPort = dcc->Connect(); } if (iPort != 0) { PostIrcMessage(_T("/CTCP %s DCC CHAT chat %u %u"), two.c_str(), ulAdr, iPort); mir_sntprintf(szTemp, SIZEOF(szTemp), TranslateT("DCC CHAT request sent to %s"), two.c_str(), one.c_str()); DoEvent(GC_EVENT_INFORMATION, 0, m_info.sNick.c_str(), szTemp, NULL, NULL, NULL, true, false); } else { mir_sntprintf(szTemp, SIZEOF(szTemp), TranslateT("DCC ERROR: Unable to bind port")); DoEvent(GC_EVENT_INFORMATION, 0, m_info.sNick.c_str(), szTemp, NULL, NULL, NULL, true, false); } } else { mir_sntprintf(szTemp, SIZEOF(szTemp), TranslateT("DCC ERROR: Unable to automatically resolve external IP")); DoEvent(GC_EVENT_INFORMATION, 0, m_info.sNick.c_str(), szTemp, NULL, NULL, NULL, true, false); } } return true; } return false; } ///////////////////////////////////////////////////////////////////////////////////////// struct DoInputRequestParam { DoInputRequestParam(CIrcProto* _pro, const TCHAR* _str) : ppro(_pro), str(mir_tstrdup(_str)) {} CIrcProto *ppro; TCHAR* str; }; static void __stdcall DoInputRequestAliasApcStub(void* _par) { DoInputRequestParam* param = (DoInputRequestParam*)_par; CIrcProto *ppro = param->ppro; TCHAR* str = param->str; TCHAR* infotext = NULL; TCHAR* title = NULL; TCHAR* defaulttext = NULL; CMString command = (TCHAR*)str; TCHAR* p = _tcsstr((TCHAR*)str, _T("%question")); if (p[9] == '=' && p[10] == '\"') { infotext = &p[11]; p = _tcschr(infotext, '\"'); if (p) { *p = '\0'; p++; if (*p == ',' && p[1] == '\"') { p++; p++; title = p; p = _tcschr(title, '\"'); if (p) { *p = '\0'; p++; if (*p == ',' && p[1] == '\"') { p++; p++; defaulttext = p; p = _tcschr(defaulttext, '\"'); if (p) *p = '\0'; } } } } } CQuestionDlg* dlg = new CQuestionDlg(ppro); dlg->Show(); HWND question_hWnd = dlg->GetHwnd(); if (title) SetDlgItemText(question_hWnd, IDC_CAPTION, title); else SetDlgItemText(question_hWnd, IDC_CAPTION, TranslateT("Input command")); if (infotext) SetDlgItemText(question_hWnd, IDC_TEXT, infotext); else SetDlgItemText(question_hWnd, IDC_TEXT, TranslateT("Please enter the reply")); if (defaulttext) SetDlgItemText(question_hWnd, IDC_EDIT, defaulttext); SetDlgItemText(question_hWnd, IDC_HIDDENEDIT, command.c_str()); dlg->Activate(); mir_free(str); delete param; } bool CIrcProto::PostIrcMessage(const TCHAR* fmt, ...) { if (!fmt || mir_tstrlen(fmt) < 1 || mir_tstrlen(fmt) > 4000) return 0; va_list marker; va_start(marker, fmt); static TCHAR szBuf[4 * 1024]; mir_vsntprintf(szBuf, SIZEOF(szBuf), fmt, marker); va_end(marker); return PostIrcMessageWnd(NULL, NULL, szBuf); } bool CIrcProto::PostIrcMessageWnd(TCHAR *window, MCONTACT hContact, const TCHAR *szBuf) { DBVARIANT dbv; TCHAR windowname[256]; BYTE bDCC = 0; if (hContact) bDCC = getByte(hContact, "DCC", 0); if (!IsConnected() && !bDCC || !szBuf || mir_tstrlen(szBuf) < 1) return 0; if (hContact && !getTString(hContact, "Nick", &dbv)) { mir_tstrncpy(windowname, dbv.ptszVal, 255); db_free(&dbv); } else if (window) mir_tstrncpy(windowname, window, 255); else mir_tstrncpy(windowname, SERVERWINDOW, 255); if (mir_tstrcmpi(window, SERVERWINDOW) != 0) { TCHAR* p1 = _tcschr(windowname, ' '); if (p1) *p1 = '\0'; } // remove unecessary linebreaks, and do the aliases CMString Message = szBuf; AddCR(Message); RemoveLinebreaks(Message); if (!hContact && IsConnected()) { Message = DoAlias(Message.c_str(), windowname); if (Message.Find(_T("%question")) != -1) { CallFunctionAsync(DoInputRequestAliasApcStub, new DoInputRequestParam(this, Message)); return 1; } Message.Replace(_T("%newl"), _T("\r\n")); RemoveLinebreaks(Message); } if (Message.IsEmpty()) return 0; CHANNELINFO *wi = (CHANNELINFO *)DoEvent(GC_EVENT_GETITEMDATA, windowname, NULL, NULL, NULL, NULL, NULL, FALSE, FALSE, 0); int codepage = (wi) ? wi->codepage : getCodepage(); // process the message while (!Message.IsEmpty()) { // split the text into lines, and do an automatic textsplit on long lies as well bool flag = false; CMString DoThis = _T(""); int index = Message.Find(_T("\r\n"), 0); if (index == -1) index = Message.GetLength(); if (index > 464) index = 432; DoThis = Message.Mid(0, index); Message.Delete(0, index); if (Message.Find(_T("\r\n"), 0) == 0) Message.Delete(0, 2); //do this if it's a /raw if (IsConnected() && (GetWord(DoThis.c_str(), 0) == _T("/raw") || GetWord(DoThis.c_str(), 0) == _T("/quote"))) { if (GetWord(DoThis.c_str(), 1).IsEmpty()) continue; CMString S = GetWordAddress(DoThis.c_str(), 1); SendIrcMessage(S.c_str(), true, codepage); continue; } // Do this if the message is not a command if ((GetWord(DoThis.c_str(), 0)[0] != '/') || // not a command ((GetWord(DoThis.c_str(), 0)[0] == '/') && (GetWord(DoThis.c_str(), 0)[1] == '/')) || // or double backslash at the beginning hContact) { CMString S = _T("/PRIVMSG "); if (mir_tstrcmpi(window, SERVERWINDOW) == 0 && !m_info.sServerName.IsEmpty()) S += m_info.sServerName + _T(" ") + DoThis; else S += CMString(windowname) + _T(" ") + DoThis; DoThis = S; flag = true; } // and here we send it unless the command was a hardcoded one that should not be sent if (DoHardcodedCommand(DoThis, windowname, hContact)) continue; if (!IsConnected() && !bDCC) continue; if (!flag && IsConnected()) DoThis = DoIdentifiers(DoThis, windowname); if (hContact) { if (flag && bDCC) { CDccSession* dcc = FindDCCSession(hContact); if (dcc) { FormatMsg(DoThis); CMString mess = GetWordAddress(DoThis.c_str(), 2); if (mess[0] == ':') mess.Delete(0, 1); mess += '\n'; dcc->SendStuff(mess.c_str()); } } else if (IsConnected()) { FormatMsg(DoThis); SendIrcMessage(DoThis.c_str(), false, codepage); } } else { FormatMsg(DoThis); SendIrcMessage(DoThis.c_str(), true, codepage); } } return 1; }