void HandleNeed(const CChan& Channel, const CString& sPerms) { MCString::iterator it = m_msChanModes.find(Channel.GetName()); if (it == m_msChanModes.end()) return; CString sModes = it->second; bool bMaster = (sModes.find("m") != CString::npos) || (sModes.find("n") != CString::npos); if (sPerms.find("o") != CString::npos) { bool bOp = (sModes.find("o") != CString::npos); bool bAutoOp = (sModes.find("a") != CString::npos); if (bMaster || bOp) { if (!bAutoOp) { PutModule("RequestPerms: Requesting op on " + Channel.GetName()); PutQ("OP " + Channel.GetName()); } return; } } if (sPerms.find("v") != CString::npos) { bool bVoice = (sModes.find("v") != CString::npos); bool bAutoVoice = (sModes.find("g") != CString::npos); if (bMaster || bVoice) { if (!bAutoVoice) { PutModule("RequestPerms: Requesting voice on " + Channel.GetName()); PutQ("VOICE " + Channel.GetName()); } return; } } }
bool SendIRCMsgToSkype(const CString& a_nick, const CString& a_channel, const CString& a_message) { if(m_chanNameMap.find(a_channel.AsLower()) != m_chanNameMap.end() && !a_message.empty()) { CString l_message = stripIRCColorCodes(a_message); if(!IsStrValidUTF8(l_message)) { l_message = AnsiToUtf8(l_message); } if(!a_nick.empty()) { l_message = "<" + a_nick + "> " + l_message; } return SendSkypeCommand("CHATMESSAGE " + m_chanNameMap[a_channel.AsLower()] + " " + l_message); } return false; }
void SendSkypeMsgToIRC(const CReceivedSkypeMsg *a_msg) { CString l_msgBuffer; if(a_msg->timestamp < time(0) - 120 && !a_msg->edited) { char l_timeBuf[100]; strftime(l_timeBuf, 100, "[%a %H:%M:%S] ", localtime(&a_msg->timestamp)); l_msgBuffer = l_timeBuf; } if(!a_msg->edited) { if(a_msg->type == "EMOTED") { l_msgBuffer += a_msg->fromDispname + " "; } else { l_msgBuffer += "<" + a_msg->fromDispname + "> "; } l_msgBuffer += a_msg->body; } else { char l_timeBuf[100]; strftime(l_timeBuf, 100, "%H:%M:%S", localtime(&a_msg->timestamp)); if(a_msg->body == "[deleted]") { l_msgBuffer += "(" + a_msg->fromDispname + " deleted their message from " + CString(l_timeBuf) + ")"; } else { l_msgBuffer += a_msg->fromDispname + " edited their message from " + CString(l_timeBuf) + ": " + a_msg->body; } } l_msgBuffer.Replace("\r", ""); l_msgBuffer.Replace("\n", " "); for(MCString::iterator it = m_chanNameMap.begin(); it != m_chanNameMap.end(); it++) { if(it->second.Equals(a_msg->chatName)) { std::wstring l_buffer = Utf8ToWide(l_msgBuffer); std::wstring l_line; CString l_utfLine; do { l_line = l_buffer.substr(0, 400); l_buffer.erase(0, 400); if(!l_buffer.empty()) { l_line += L"..."; l_buffer = L"..." + l_buffer; } l_utfLine = WideToUtf8(l_line); PutIRC("PRIVMSG " + it->first + " :" + l_utfLine); PutUser(":" + m_pUser->GetIRCNick().GetNick() + "!x@y PRIVMSG " + it->first + " :" + l_utfLine); } while(!l_buffer.empty()); return; } } PutModule("WARNING: Group chat " + a_msg->chatName + " not mapped to any channel. A message has been lost."); }
CString CTemplate::GetValue(const CString& sArgs, bool bFromIf) { CTemplateLoopContext* pContext = GetCurLoopContext(); CString sName = sArgs.Token(0); CString sRest = sArgs.Token(1, true); CString sRet; while (sRest.Replace(" =", "=", "\"", "\"")) {} while (sRest.Replace("= ", "=", "\"", "\"")) {} VCString vArgs; MCString msArgs; //sRest.Split(" ", vArgs, false, "\"", "\""); sRest.QuoteSplit(vArgs); for (unsigned int a = 0; a < vArgs.size(); a++) { const CString& sArg = vArgs[a]; msArgs[sArg.Token(0, false, "=").AsUpper()] = sArg.Token(1, true, "="); } /* We have no CConfig in ZNC land * Hmm... Actually, we do have it now. if (msArgs.find("CONFIG") != msArgs.end()) { sRet = CConfig::GetValue(sName); } else*/ if (msArgs.find("ROWS") != msArgs.end()) { vector<CTemplate*>* pLoop = GetLoop(sName); sRet = CString((pLoop) ? pLoop->size() : 0); } else if (msArgs.find("TOP") == msArgs.end() && pContext) { sRet = pContext->GetValue(sArgs, bFromIf); if (!sRet.empty()) { return sRet; } } else { if (sName.Left(1) == "*") { sName.LeftChomp(1); MCString::iterator it = find(sName); sName = (it != end()) ? it->second : ""; } MCString::iterator it = find(sName); sRet = (it != end()) ? it->second : ""; } vector<CSmartPtr<CTemplateTagHandler> >& vspTagHandlers = GetTagHandlers(); if (!vspTagHandlers.empty()) { // @todo this should go up to the top to grab handlers CTemplate* pTmpl = GetCurTemplate(); if (sRet.empty()) { for (unsigned int j = 0; j < vspTagHandlers.size(); j++) { CSmartPtr<CTemplateTagHandler> spTagHandler = vspTagHandlers[j]; CString sCustomOutput; if (!bFromIf && spTagHandler->HandleVar(*pTmpl, sArgs.Token(0), sArgs.Token(1, true), sCustomOutput)) { sRet = sCustomOutput; break; } else if (bFromIf && spTagHandler->HandleIf(*pTmpl, sArgs.Token(0), sArgs.Token(1, true), sCustomOutput)) { sRet = sCustomOutput; break; } } } for (unsigned int j = 0; j < vspTagHandlers.size(); j++) { CSmartPtr<CTemplateTagHandler> spTagHandler = vspTagHandlers[j]; if (spTagHandler->HandleValue(*pTmpl, sRet, msArgs)) { break; } } } if (!bFromIf) { if (sRet.empty()) { sRet = ResolveLiteral(msArgs["DEFAULT"]); } MCString::iterator it = msArgs.find("ESC"); if (it != msArgs.end()) { VCString vsEscs; it->second.Split(",", vsEscs, false); for (unsigned int a = 0; a < vsEscs.size(); a++) { sRet.Escape(CString::ToEscape(vsEscs[a])); } } else { sRet.Escape(m_spOptions->GetEscapeFrom(), m_spOptions->GetEscapeTo()); } } return sRet; }
bool CTemplate::Print(const CString& sFileName, ostream& oOut) { if (sFileName.empty()) { DEBUG("Empty filename in CTemplate::Print()"); return false; } CFile File(sFileName); if (!File.Open()) { DEBUG("Unable to open file [" + sFileName + "] in CTemplate::Print()"); return false; } CString sLine; CString sSetBlockVar; bool bValidLastIf = false; bool bInSetBlock = false; unsigned long uFilePos = 0; unsigned long uCurPos = 0; unsigned int uLineNum = 0; unsigned int uNestedIfs = 0; unsigned int uSkip = 0; bool bLoopCont = false; bool bLoopBreak = false; bool bExit = false; while (File.ReadLine(sLine)) { CString sOutput; bool bFoundATag = false; bool bTmplLoopHasData = false; uLineNum++; CString::size_type iPos = 0; uCurPos = uFilePos; unsigned int uLineSize = sLine.size(); bool bBroke = false; while (1) { iPos = sLine.find("<?"); if (iPos == CString::npos) { break; } uCurPos += iPos; bFoundATag = true; if (!uSkip) { sOutput += sLine.substr(0, iPos); } sLine = sLine.substr(iPos +2); CString::size_type iPos2 = sLine.find("?>"); // Make sure our tmpl tag is ended properly if (iPos2 == CString::npos) { DEBUG("Template tag not ended properly in file [" + sFileName + "] [<?" + sLine + "]"); return false; } uCurPos += iPos2 +4; CString sMid = CString(sLine.substr(0, iPos2)).Trim_n(); // Make sure we don't have a nested tag if (sMid.find("<?") == CString::npos) { sLine = sLine.substr(iPos2 +2); CString sAction = sMid.Token(0); CString sArgs = sMid.Token(1, true); bool bNotFound = false; // If we're breaking or continuing from within a loop, skip all tags that aren't ENDLOOP if ((bLoopCont || bLoopBreak) && !sAction.Equals("ENDLOOP")) { continue; } if (!uSkip) { if (sAction.Equals("INC")) { if (!Print(ExpandFile(sArgs, true), oOut)) { DEBUG("Unable to print INC'd file [" + sArgs + "]"); return false; } } else if (sAction.Equals("SETOPTION")) { m_spOptions->Parse(sArgs); } else if (sAction.Equals("ADDROW")) { CString sLoopName = sArgs.Token(0); MCString msRow; if (sArgs.Token(1, true, " ").OptionSplit(msRow)) { CTemplate& NewRow = AddRow(sLoopName); for (MCString::iterator it = msRow.begin(); it != msRow.end(); ++it) { NewRow[it->first] = it->second; } } } else if (sAction.Equals("SET")) { CString sName = sArgs.Token(0); CString sValue = sArgs.Token(1, true); (*this)[sName] = sValue; } else if (sAction.Equals("JOIN")) { VCString vsArgs; //sArgs.Split(" ", vsArgs, false, "\"", "\""); sArgs.QuoteSplit(vsArgs); if (vsArgs.size() > 1) { CString sDelim = vsArgs[0]; bool bFoundOne = false; CString::EEscape eEscape = CString::EASCII; for (unsigned int a = 1; a < vsArgs.size(); a++) { const CString& sArg = vsArgs[a]; if (sArg.Equals("ESC=", false, 4)) { eEscape = CString::ToEscape(sArg.LeftChomp_n(4)); } else { CString sValue = GetValue(sArg); if (!sValue.empty()) { if (bFoundOne) { sOutput += sDelim; } sOutput += sValue.Escape_n(eEscape); bFoundOne = true; } } } } } else if (sAction.Equals("SETBLOCK")) { sSetBlockVar = sArgs; bInSetBlock = true; } else if (sAction.Equals("EXPAND")) { sOutput += ExpandFile(sArgs, true); } else if (sAction.Equals("VAR")) { sOutput += GetValue(sArgs); } else if (sAction.Equals("LT")) { sOutput += "<?"; } else if (sAction.Equals("GT")) { sOutput += "?>"; } else if (sAction.Equals("CONTINUE")) { CTemplateLoopContext* pContext = GetCurLoopContext(); if (pContext) { uSkip++; bLoopCont = true; break; } else { DEBUG("[" + sFileName + ":" + CString(uCurPos - iPos2 -4) + "] <? CONTINUE ?> must be used inside of a loop!"); } } else if (sAction.Equals("BREAK")) { // break from loop CTemplateLoopContext* pContext = GetCurLoopContext(); if (pContext) { uSkip++; bLoopBreak = true; break; } else { DEBUG("[" + sFileName + ":" + CString(uCurPos - iPos2 -4) + "] <? BREAK ?> must be used inside of a loop!"); } } else if (sAction.Equals("EXIT")) { bExit = true; } else if (sAction.Equals("DEBUG")) { DEBUG("CTemplate DEBUG [" + sFileName + "@" + CString(uCurPos - iPos2 -4) + "b] -> [" + sArgs + "]"); } else if (sAction.Equals("LOOP")) { CTemplateLoopContext* pContext = GetCurLoopContext(); if (!pContext || pContext->GetFilePosition() != uCurPos) { // we are at a brand new loop (be it new or a first pass at an inner loop) CString sLoopName = sArgs.Token(0); bool bReverse = (sArgs.Token(1).Equals("REVERSE")); bool bSort = (sArgs.Token(1).Left(4).Equals("SORT")); vector<CTemplate*>* pvLoop = GetLoop(sLoopName); if (bSort && pvLoop != NULL && pvLoop->size() > 1) { CString sKey; if(sArgs.Token(1).TrimPrefix_n("SORT").Left(4).Equals("ASC=")) { sKey = sArgs.Token(1).TrimPrefix_n("SORTASC="); } else if(sArgs.Token(1).TrimPrefix_n("SORT").Left(5).Equals("DESC=")) { sKey = sArgs.Token(1).TrimPrefix_n("SORTDESC="); bReverse = true; } if (!sKey.empty()) { std::sort(pvLoop->begin(), pvLoop->end(), CLoopSorter(sKey)); } } if (pvLoop) { // If we found data for this loop, add it to our context vector //unsigned long uBeforeLoopTag = uCurPos - iPos2 - 4; unsigned long uAfterLoopTag = uCurPos; for (CString::size_type t = 0; t < sLine.size(); t++) { char c = sLine[t]; if (c == '\r' || c == '\n') { uAfterLoopTag++; } else { break; } } m_vLoopContexts.push_back(new CTemplateLoopContext(uAfterLoopTag, sLoopName, bReverse, pvLoop)); } else { // If we don't have data, just skip this loop and everything inside uSkip++; } } } else if (sAction.Equals("IF")) { if (ValidIf(sArgs)) { uNestedIfs++; bValidLastIf = true; } else { uSkip++; bValidLastIf = false; } } else if (sAction.Equals("REM")) { uSkip++; } else { bNotFound = true; } } else if (sAction.Equals("REM")) { uSkip++; } else if (sAction.Equals("IF")) { uSkip++; } else if (sAction.Equals("LOOP")) { uSkip++; } if (sAction.Equals("ENDIF")) { if (uSkip) { uSkip--; } else { uNestedIfs--; } } else if (sAction.Equals("ENDREM")) { if (uSkip) { uSkip--; } } else if (sAction.Equals("ENDSETBLOCK")) { bInSetBlock = false; sSetBlockVar = ""; } else if (sAction.Equals("ENDLOOP")) { if (bLoopCont && uSkip == 1) { uSkip--; bLoopCont = false; } if (bLoopBreak && uSkip == 1) { uSkip--; } if (uSkip) { uSkip--; } else { // We are at the end of the loop so we need to inc the index CTemplateLoopContext* pContext = GetCurLoopContext(); if (pContext) { pContext->IncRowIndex(); // If we didn't go out of bounds we need to seek back to the top of our loop if (!bLoopBreak && pContext->GetCurRow()) { uCurPos = pContext->GetFilePosition(); uFilePos = uCurPos; uLineSize = 0; File.Seek(uCurPos); bBroke = true; if (!sOutput.Trim_n().empty()) { pContext->SetHasData(); } break; } else { if (sOutput.Trim_n().empty()) { sOutput.clear(); } bTmplLoopHasData = pContext->HasData(); DelCurLoopContext(); bLoopBreak = false; } } } } else if (sAction.Equals("ELSE")) { if (!bValidLastIf && uSkip == 1) { CString sArg = sArgs.Token(0); if (sArg.empty() || (sArg.Equals("IF") && ValidIf(sArgs.Token(1, true)))) { uSkip = 0; bValidLastIf = true; } } else if (!uSkip) { uSkip = 1; } } else if (bNotFound) { // Unknown tag that isn't being skipped... vector<CSmartPtr<CTemplateTagHandler> >& vspTagHandlers = GetTagHandlers(); if (!vspTagHandlers.empty()) { // @todo this should go up to the top to grab handlers CTemplate* pTmpl = GetCurTemplate(); CString sCustomOutput; for (unsigned int j = 0; j < vspTagHandlers.size(); j++) { CSmartPtr<CTemplateTagHandler> spTagHandler = vspTagHandlers[j]; if (spTagHandler->HandleTag(*pTmpl, sAction, sArgs, sCustomOutput)) { sOutput += sCustomOutput; bNotFound = false; break; } } if (bNotFound) { DEBUG("Unknown/Unhandled tag [" + sAction + "]"); } } } continue; } DEBUG("Malformed tag on line " + CString(uLineNum) + " of [" << File.GetLongName() + "]"); DEBUG("--------------- [" + sLine + "]"); } if (!bBroke) { uFilePos += uLineSize; if (!uSkip) { sOutput += sLine; } } if (!bFoundATag || bTmplLoopHasData || sOutput.find_first_not_of(" \t\r\n") != CString::npos) { if (bInSetBlock) { CString sName = sSetBlockVar.Token(0); //CString sValue = sSetBlockVar.Token(1, true); (*this)[sName] += sOutput; } else { oOut << sOutput; } } if (bExit) { break; } } oOut.flush(); return true; }