void CUrlBufferModule::CheckLineForLink(const CString& sMessage, const CString& sOrigin) { if(sOrigin != m_pUser->GetUserName() && GetNV("enable").ToBool() ) { VCString words; CString output; sMessage.Split(" ", words, false, "", "", true, true); for (size_t a = 0; a < words.size(); a++) { CString& word = words[a]; if(word.Left(4) == "http" || word.Left(4) == "www.") { //if you find an image download it, save it in the www directory and keep the new link in buffer VCString tokens; word.Split("/", tokens, false, "", "", true, true); CString name = tokens[tokens.size()-1]; word.Split(".", tokens, false, "", "", true, true); //if it's an image link download/upload it else just keep the link time_t curtime; time(&curtime); CString dir = GetNV("directory") + CUtils::FormatTime(curtime,"%Y-%m-%d", m_pUser->GetTimezone()) + "/"; CString nickname = (sOrigin.empty())? m_pUser->GetUserName() : sOrigin; if(!CFile::Exists(dir) && !CFile::IsDir(dir, false)) { CDir::MakeDir(dir, 0775); } if(isValidExtension( tokens[tokens.size()-1] )) { std::stringstream ss; if( GetNV("enablelocal").ToBool()) { ss << "wget -b -O " << dir.c_str() << name <<" -q " << word.c_str() << " 2>&1"; getStdoutFromCommand(ss.str()); } ss.str(""); if (!word.WildCmp("*imgur*") && GetNV("reupload").ToBool()) { ss << "curl -d \"image=" << word.c_str() << "\" -d \"key=5ce86e7f95d8e58b18931bf290f387be\" http://api.imgur.com/2/upload.xml | sed -n 's/.*<original>\\(.*\\)<\\/original>.*/\\1/p' 2>&1"; output = getStdoutFromCommand(ss.str()); lastUrls.push_back(output); } else { lastUrls.push_back(word); } } else if(GetNV("bufferalllinks").ToBool()){ lastUrls.push_back(word); //append nick:link to file CString filename = dir + "links.txt"; std::ofstream log(filename.c_str() , std::ios_base::app | std::ios_base::out); log << nickname << ": " << word << "\n"; } nicks.push_back( nickname ); } } } }
bool CClient::OnJoinMessage(CJoinMessage& Message) { CString sChans = Message.GetTarget(); CString sKeys = Message.GetKey(); VCString vsChans; sChans.Split(",", vsChans, false); sChans.clear(); VCString vsKeys; sKeys.Split(",", vsKeys, true); sKeys.clear(); for (unsigned int a = 0; a < vsChans.size(); a++) { Message.SetTarget(vsChans[a]); Message.SetKey((a < vsKeys.size()) ? vsKeys[a] : ""); if (m_pNetwork) { // May be nullptr. Message.SetChan(m_pNetwork->FindChan(vsChans[a])); } bool bContinue = false; NETWORKMODULECALL(OnUserJoinMessage(Message), m_pUser, m_pNetwork, this, &bContinue); if (bContinue) continue; CString sChannel = Message.GetTarget(); CString sKey = Message.GetKey(); if (m_pNetwork) { CChan* pChan = m_pNetwork->FindChan(sChannel); if (pChan) { if (pChan->IsDetached()) pChan->AttachUser(this); else pChan->JoinUser(sKey); continue; } else if (!sChannel.empty()) { pChan = new CChan(sChannel, m_pNetwork, false); if (m_pNetwork->AddChan(pChan)) { pChan->SetKey(sKey); } } } if (!sChannel.empty()) { sChans += (sChans.empty()) ? sChannel : CString("," + sChannel); if (!vsKeys.empty()) { sKeys += (sKeys.empty()) ? sKey : CString("," + sKey); } } } Message.SetTarget(sChans); Message.SetKey(sKeys); return sChans.empty(); }
virtual EModRet OnUserRaw(CString& sLine) { CAlias current_alias; try { if (sLine.Equals("ZNC-CLEAR-ALL-ALIASES!")) { ListCommand(""); PutModule("Clearing all of them!"); ClearNV(); return HALT; } else if (CAlias::AliasGet(current_alias, this, sLine)) { VCString rawLines; current_alias.Imprint(sLine).Split("\n", rawLines, false); for (size_t i = 0; i < rawLines.size(); ++i) PutIRC(rawLines[i]); return HALT; } } catch (std::exception &e) { CString my_nick = (GetNetwork() == NULL ? "" : GetNetwork()->GetCurNick()); if (my_nick.empty()) my_nick = "*"; PutUser(CString(":znc.in 461 " + my_nick + " " + current_alias.GetName() + " :ZNC alias error: ") + e.what()); return HALTCORE; } return CONTINUE; }
void AddChans(const CString& sChans) { VCString vsChans; sChans.Split(" ", vsChans); for (unsigned int a = 0; a < vsChans.size(); a++) { m_ssChans.insert(vsChans[a].AsLower()); } }
void CTemplate::SetPath(const CString& sPaths) { VCString vsDirs; sPaths.Split(":", vsDirs, false); for (size_t a = 0; a < vsDirs.size(); a++) { AppendPath(vsDirs[a], false); } }
void CHTTPSock::ReadLine(const CString& sData) { if (m_bGotHeader) { return; } CString sLine = sData; sLine.TrimRight("\r\n"); CString sName = sLine.Token(0); if (sName.Equals("GET")) { m_bPost = false; m_sURI = sLine.Token(1); m_bHTTP10Client = sLine.Token(2).Equals("HTTP/1.0"); ParseURI(); } else if (sName.Equals("POST")) { m_bPost = true; m_sURI = sLine.Token(1); ParseURI(); } else if (sName.Equals("Cookie:")) { VCString vsNV; sLine.Token(1, true).Split(";", vsNV, false, "", "", true, true); for (unsigned int a = 0; a < vsNV.size(); a++) { CString s(vsNV[a]); m_msRequestCookies[s.Token(0, false, "=").Escape_n(CString::EURL, CString::EASCII)] = s.Token(1, true, "=").Escape_n(CString::EURL, CString::EASCII); } } else if (sName.Equals("Authorization:")) { CString sUnhashed; sLine.Token(2).Base64Decode(sUnhashed); m_sUser = sUnhashed.Token(0, false, ":"); m_sPass = sUnhashed.Token(1, true, ":"); m_bLoggedIn = OnLogin(m_sUser, m_sPass); } else if (sName.Equals("Content-Length:")) { m_uPostLen = sLine.Token(1).ToULong(); if (m_uPostLen > MAX_POST_SIZE) PrintErrorPage(413, "Request Entity Too Large", "The request you sent was too large."); } else if (sName.Equals("If-None-Match:")) { // this is for proper client cache support (HTTP 304) on static files: m_sIfNoneMatch = sLine.Token(1, true); } else if (sLine.empty()) { m_bGotHeader = true; if (m_bPost) { m_sPostData = GetInternalReadBuffer(); CheckPost(); } else { GetPage(); } DisableReadLine(); } }
void CIRCSock::ParseISupport(const CMessage& Message) { const VCString vsParams = Message.GetParams(); for (size_t i = 1; i < vsParams.size() - 1; ++i) { const CString& sParam = vsParams[i]; CString sName = sParam.Token(0, false, "="); CString sValue = sParam.Token(1, true, "="); if (0 < sName.length() && ':' == sName[0]) { break; } m_mISupport[sName] = sValue; if (sName.Equals("PREFIX")) { CString sPrefixes = sValue.Token(1, false, ")"); CString sPermModes = sValue.Token(0, false, ")"); sPermModes.TrimLeft("("); if (!sPrefixes.empty() && sPermModes.size() == sPrefixes.size()) { m_sPerms = sPrefixes; m_sPermModes = sPermModes; } } else if (sName.Equals("CHANTYPES")) { m_pNetwork->SetChanPrefixes(sValue); } else if (sName.Equals("NICKLEN")) { unsigned int uMax = sValue.ToUInt(); if (uMax) { m_uMaxNickLen = uMax; } } else if (sName.Equals("CHANMODES")) { if (!sValue.empty()) { m_mueChanModes.clear(); for (unsigned int a = 0; a < 4; a++) { CString sModes = sValue.Token(a, false, ","); for (unsigned int b = 0; b < sModes.size(); b++) { m_mueChanModes[sModes[b]] = (EChanModeArgs) a; } } } } else if (sName.Equals("NAMESX")) { if (m_bNamesx) continue; m_bNamesx = true; PutIRC("PROTOCTL NAMESX"); } else if (sName.Equals("UHNAMES")) { if (m_bUHNames) continue; m_bUHNames = true; PutIRC("PROTOCTL UHNAMES"); } } }
void CWebSock::SetPaths(CModule* pModule, bool bIsTemplate) { m_Template.ClearPaths(); VCString vsDirs = GetDirs(pModule, bIsTemplate); for (size_t i = 0; i < vsDirs.size(); ++i) { m_Template.AppendPath(vsDirs[i]); } m_bPathsSet = true; }
CString CWebSock::FindTmpl(CModule* pModule, const CString& sName) { VCString vsDirs = GetDirs(pModule, true); CString sFile = pModule->GetModName() + "_" + sName; for (size_t i = 0; i < vsDirs.size(); ++i) { if (CFile::Exists(CDir::ChangeDir(vsDirs[i], sFile))) { m_Template.AppendPath(vsDirs[i]); return sFile; } } return sName; }
void CHTTPSock::ParseParams(const CString& sParams, map<CString, VCString> &msvsParams) { msvsParams.clear(); VCString vsPairs; sParams.Split("&", vsPairs, true); for (unsigned int a = 0; a < vsPairs.size(); a++) { const CString& sPair = vsPairs[a]; CString sName = sPair.Token(0, false, "=").Escape_n(CString::EURL, CString::EASCII); CString sValue = sPair.Token(1, true, "=").Escape_n(CString::EURL, CString::EASCII); msvsParams[sName].push_back(sValue); } }
void CUrlBufferModule::CheckLineForTrigger(const CString& sMessage, const CString& sTarget) { if(GetNV("enablepublic").ToBool()) { VCString words; sMessage.Split(" ", words, false, "", "", true, true); for (size_t a = 0; a < words.size(); a++) { CString& word = words[a]; if(word.AsLower() == "!showlinks") { if(lastUrls.empty()) PutIRC("PRIVMSG " + sTarget + " :No links were found..."); else { unsigned int maxLinks = GetNV("buffersize").ToUInt(); if (a+1 < words.size()) { unsigned int size = words[a+1].ToUInt(); if(size!=0 && size<UINT_MAX) //if it was a valid number maxLinks = size; } unsigned int maxSize = lastUrls.size()-1; for(unsigned int i=0; i<=maxSize && i<maxLinks; i++) { sleep(1); PutIRC("PRIVMSG " + sTarget + " :" + nicks[maxSize-i] + ": "+ lastUrls[maxSize-i]); } } } } } }
size_t CHTTPSock::GetParamValues(const CString& sName, VCString& vsRet, const map<CString, VCString>& msvsParams, const CString& sFilter) { vsRet.clear(); map<CString, VCString>::const_iterator it = msvsParams.find(sName); if (it != msvsParams.end()) { for (CString sParam : it->second) { sParam.Trim(); for (size_t i = 0; i < sFilter.length(); i++) { sParam.Replace(CString(sFilter.at(i)), ""); } vsRet.push_back(sParam); } } return vsRet.size(); }
void OnModCommand(const CString& sCommand) override { CString sResult; VCString vsResult; CString sCmd = sCommand; if (sCmd.Token(0).CaseCmp(".tcl") == 0) sCmd = sCmd.Token(1, true); if (sCmd.Left(1).CaseCmp(".") == 0) sCmd = "Binds::ProcessDcc - - {" + sCmd + "}"; Tcl_Eval(interp, sCmd.c_str()); sResult = CString(Tcl_GetStringResult(interp)); if (!sResult.empty()) { sResult.Split("\n", vsResult); unsigned int a = 0; for (a = 0; a < vsResult.size(); a++) PutModule(vsResult[a].TrimRight_n()); } }
CMessage CBufLine::ToMessage(const CClient& Client, const MCString& mssParams) const { CMessage Line = m_Message; CString sSender = Line.GetNick().GetNickMask(); Line.SetNick(CNick(CString::NamedFormat(sSender, mssParams))); MCString mssThisParams = mssParams; if (Client.HasServerTime()) { mssThisParams["text"] = m_sText; } else { mssThisParams["text"] = Client.GetUser()->AddTimestamp(Line.GetTime().tv_sec, m_sText); } // make a copy of params, because the following loop modifies the original VCString vsParams = Line.GetParams(); for (unsigned int uIdx = 0; uIdx < vsParams.size(); ++uIdx) { Line.SetParam(uIdx, CString::NamedFormat(vsParams[uIdx], mssThisParams)); } return Line; }
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; }
CUser* GetNewUser(CWebSock& WebSock, CUser* pUser) { CSmartPtr<CWebSession> spSession = WebSock.GetSession(); CString sUsername = WebSock.GetParam("newuser"); if (sUsername.empty()) { sUsername = WebSock.GetParam("user"); } if (sUsername.empty()) { WebSock.PrintErrorPage("Invalid Submission [Username is required]"); return NULL; } if (pUser) { /* If we are editing a user we must not change the user name */ sUsername = pUser->GetUserName(); } CString sArg = WebSock.GetParam("password"); if (sArg != WebSock.GetParam("password2")) { WebSock.PrintErrorPage("Invalid Submission [Passwords do not match]"); return NULL; } CUser* pNewUser = new CUser(sUsername); if (!sArg.empty()) { CString sSalt = CUtils::GetSalt(); CString sHash = CUser::SaltedHash(sArg, sSalt); pNewUser->SetPass(sHash, CUser::HASH_DEFAULT, sSalt); } VCString vsArgs; WebSock.GetRawParam("servers").Split("\n", vsArgs); unsigned int a = 0; for (a = 0; a < vsArgs.size(); a++) { pNewUser->AddServer(vsArgs[a].Trim_n()); } WebSock.GetRawParam("allowedips").Split("\n", vsArgs); if (vsArgs.size()) { for (a = 0; a < vsArgs.size(); a++) { pNewUser->AddAllowedHost(vsArgs[a].Trim_n()); } } else { pNewUser->AddAllowedHost("*"); } WebSock.GetRawParam("ctcpreplies").Split("\n", vsArgs); for (a = 0; a < vsArgs.size(); a++) { CString sReply = vsArgs[a].TrimRight_n("\r"); pNewUser->AddCTCPReply(sReply.Token(0).Trim_n(), sReply.Token(1, true).Trim_n()); } sArg = WebSock.GetParam("nick"); if (!sArg.empty()) { pNewUser->SetNick(sArg); } sArg = WebSock.GetParam("altnick"); if (!sArg.empty()) { pNewUser->SetAltNick(sArg); } sArg = WebSock.GetParam("statusprefix"); if (!sArg.empty()) { pNewUser->SetStatusPrefix(sArg); } sArg = WebSock.GetParam("ident"); if (!sArg.empty()) { pNewUser->SetIdent(sArg); } sArg = WebSock.GetParam("skin"); if (!sArg.empty()) { pNewUser->SetSkinName(sArg); } sArg = WebSock.GetParam("realname"); if (!sArg.empty()) { pNewUser->SetRealName(sArg); } sArg = WebSock.GetParam("quitmsg"); if (!sArg.empty()) { pNewUser->SetQuitMsg(sArg); } sArg = WebSock.GetParam("chanmodes"); if (!sArg.empty()) { pNewUser->SetDefaultChanModes(sArg); } sArg = WebSock.GetParam("timestampformat"); if (!sArg.empty()) { pNewUser->SetTimestampFormat(sArg); } sArg = WebSock.GetParam("bindhost"); // To change BindHosts be admin or don't have DenySetBindHost if (spSession->IsAdmin() || !spSession->GetUser()->DenySetBindHost()) { if (!sArg.empty()) { pNewUser->SetBindHost(sArg); } } else if (pUser){ pNewUser->SetBindHost(pUser->GetBindHost()); } // First apply the old limit in case the new one is too high if (pUser) pNewUser->SetBufferCount(pUser->GetBufferCount(), true); pNewUser->SetBufferCount(WebSock.GetParam("bufsize").ToUInt()); pNewUser->SetSkinName(WebSock.GetParam("skin")); pNewUser->SetKeepBuffer(WebSock.GetParam("keepbuffer").ToBool()); pNewUser->SetMultiClients(WebSock.GetParam("multiclients").ToBool()); pNewUser->SetBounceDCCs(WebSock.GetParam("bouncedccs").ToBool()); pNewUser->SetUseClientIP(WebSock.GetParam("useclientip").ToBool()); pNewUser->SetTimestampAppend(WebSock.GetParam("appendtimestamp").ToBool()); pNewUser->SetTimestampPrepend(WebSock.GetParam("prependtimestamp").ToBool()); pNewUser->SetTimezoneOffset(WebSock.GetParam("timezoneoffset").ToDouble()); pNewUser->SetJoinTries(WebSock.GetParam("jointries").ToUInt()); pNewUser->SetMaxJoins(WebSock.GetParam("maxjoins").ToUInt()); pNewUser->SetIRCConnectEnabled(WebSock.GetParam("doconnect").ToBool()); if (spSession->IsAdmin()) { pNewUser->SetDenyLoadMod(WebSock.GetParam("denyloadmod").ToBool()); pNewUser->SetDenySetBindHost(WebSock.GetParam("denysetbindhost").ToBool()); } else if (pUser) { pNewUser->SetDenyLoadMod(pUser->DenyLoadMod()); pNewUser->SetDenySetBindHost(pUser->DenySetBindHost()); } // If pUser is not NULL, we are editing an existing user. // Users must not be able to change their own admin flag. if (pUser != CZNC::Get().FindUser(WebSock.GetUser())) { pNewUser->SetAdmin(WebSock.GetParam("isadmin").ToBool()); } else if (pUser) { pNewUser->SetAdmin(pUser->IsAdmin()); } WebSock.GetParamValues("channel", vsArgs); for (a = 0; a < vsArgs.size(); a++) { const CString& sChan = vsArgs[a]; pNewUser->AddChan(sChan.TrimRight_n("\r"), WebSock.GetParam("save_" + sChan).ToBool()); } if (spSession->IsAdmin() || (pUser && !pUser->DenyLoadMod())) { WebSock.GetParamValues("loadmod", vsArgs); for (a = 0; a < vsArgs.size(); a++) { CString sModRet; CString sModName = vsArgs[a].TrimRight_n("\r"); CString sModLoadError; if (!sModName.empty()) { CString sArgs = WebSock.GetParam("modargs_" + sModName); try { if (!pNewUser->GetModules().LoadModule(sModName, sArgs, pNewUser, sModRet)) { sModLoadError = "Unable to load module [" + sModName + "] [" + sModRet + "]"; } } catch (...) { sModLoadError = "Unable to load module [" + sModName + "] [" + sArgs + "]"; } if (!sModLoadError.empty()) { DEBUG(sModLoadError); spSession->AddError(sModLoadError); } } } } else if (pUser) { CModules& Modules = pUser->GetModules(); for (a = 0; a < Modules.size(); a++) { CString sModName = Modules[a]->GetModName(); CString sArgs = Modules[a]->GetArgs(); CString sModRet; CString sModLoadError; try { if (!pNewUser->GetModules().LoadModule(sModName, sArgs, pNewUser, sModRet)) { sModLoadError = "Unable to load module [" + sModName + "] [" + sModRet + "]"; } } catch (...) { sModLoadError = "Unable to load module [" + sModName + "]"; } if (!sModLoadError.empty()) { DEBUG(sModLoadError); spSession->AddError(sModLoadError); } } } return pNewUser; }
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; }
void CUrlBufferModule::OnModCommand(const CString& sCommand) { CString command = sCommand.Token(0).AsLower().Trim_n(); if (command == "help") { CTable CmdTable; CmdTable.AddColumn("Command"); CmdTable.AddColumn("Description"); CmdTable.AddRow(); CmdTable.SetCell("Command", "ENABLE"); CmdTable.SetCell("Description", "Activates link buffering."); CmdTable.AddRow(); CmdTable.SetCell("Command", "DISABLE"); CmdTable.SetCell("Description", "Deactivates link buffering."); CmdTable.AddRow(); CmdTable.SetCell("Command", "ENABLELOCAL"); CmdTable.SetCell("Description", "Enables downloading of each link to local directory."); CmdTable.AddRow(); CmdTable.SetCell("Command", "DISABLELOCAL"); CmdTable.SetCell("Description", "Disables downloading of each link to local directory."); CmdTable.AddRow(); CmdTable.SetCell("Command","ENABLEPUBLIC"); CmdTable.SetCell("Description", "Enables the usage of !showlinks publicly, by other users."); CmdTable.AddRow(); CmdTable.SetCell("Command","DISABLEPUBLIC"); CmdTable.SetCell("Description", "Disables the usage of !showlinks publicly, by other users."); CmdTable.AddRow(); CmdTable.SetCell("Command", "DIRECTORY <#directory>"); CmdTable.SetCell("Description", "Sets the local directory where the links will be saved."); CmdTable.AddRow(); CmdTable.SetCell("Command", "CLEARBUFFER"); CmdTable.SetCell("Description", "Empties the link buffer."); CmdTable.AddRow(); CmdTable.SetCell("Command", "BUFFERSIZE <#size>"); CmdTable.SetCell("Description", "Sets the size of the link buffer. Only integers >=0."); CmdTable.AddRow(); CmdTable.SetCell("Command", "SHOWSETTINGS"); CmdTable.SetCell("Description", "Prints all the settings."); CmdTable.AddRow(); CmdTable.SetCell("Command", "BUFFERALLLINKS"); CmdTable.SetCell("Description", "Toggles the buffering of all links or only image links."); CmdTable.AddRow(); CmdTable.SetCell("Command", "REUPLOAD"); CmdTable.SetCell("Description", "Toggles the reuploading of image links to imgur."); CmdTable.AddRow(); CmdTable.SetCell("Command", "SHOWLINKS <#number>"); CmdTable.SetCell("Description", "Prints <#number> or <#buffersize> number of cached links."); CmdTable.AddRow(); CmdTable.SetCell("Command", "HELP"); CmdTable.SetCell("Description", "This help."); PutModule(CmdTable); return; } else if (command == "enable") { SetNV("enable","true",true); PutModule("Enabled buffering"); } else if (command == "disable") { SetNV("enable","false",true); PutModule("Disabled buffering"); } else if (command == "enablelocal") { if(GetNV("directory") == "") { PutModule("Directory is not set. First set a directory and then enable local caching"); return; } SetNV("enablelocal","true",true); PutModule("Enabled local caching"); } else if (command == "disablelocal") { SetNV("enablelocal", "false", true); PutModule("Disabled local caching"); } else if (command == "enablepublic") { SetNV("enablepublic", "true", true); PutModule("Enabled public usage of showlinks."); } else if (command == "disablepublic") { SetNV("enablepublic", "false", true); PutModule("Disabled public usage of showlinks."); } else if (command == "directory") { CString dir=sCommand.Token(1).Replace_n("//", "/").TrimRight_n("/") + "/"; if (!isValidDir(dir)) { PutModule("Error in directory name. Avoid using: | ; ! @ # ( ) < > \" ' ` ~ = & ^ <space> <tab>"); return; } // Check if file exists and is directory if (dir.empty() || !CFile::Exists(dir) || !CFile::IsDir(dir, false)) { PutModule("Invalid path or no write access to ["+ sCommand.Token(1) +"]."); return; } SetNV("directory", dir, true); PutModule("Directory for local caching set to " + GetNV("directory")); } else if (command == "clearbuffer") { lastUrls.clear(); nicks.clear(); } else if (command == "buffersize") { unsigned int bufSize = sCommand.Token(1).ToUInt(); if(bufSize==0 || bufSize==UINT_MAX) { PutModule("Error in buffer size. Use only integers >= 0."); return; } SetNV("buffersize", CString(bufSize), true); PutModule("Buffer size set to " + GetNV("buffersize")); } else if (command == "showsettings") { for(MCString::iterator it = BeginNV(); it != EndNV(); it++) { PutModule(it->first.AsUpper() + " : " + it->second); } } else if(command == "bufferalllinks"){ SetNV("bufferalllinks", CString(!GetNV("bufferalllinks").ToBool()), true); PutModule( CString(GetNV("bufferalllinks").ToBool()?"Enabled":"Disabled") + " buffering of all links."); } else if(command == "reupload"){ SetNV("reupload", CString(!GetNV("reupload").ToBool()), true); PutModule( CString(GetNV("reupload").ToBool()?"Enabled":"Disabled") + " reuploading of images."); } else if (command == "showlinks") { if(lastUrls.empty()) PutModule("No links were found..."); else { unsigned int maxLinks = GetNV("buffersize").ToUInt(); unsigned int size = sCommand.Token(1).ToUInt(); if(size!=0 && size<UINT_MAX) //if it was a valid number maxLinks = size; unsigned int maxSize = lastUrls.size()-1; for(unsigned int i=0; i<=maxSize && i< maxLinks; i++) { PutModule(nicks[maxSize-i] + ": " + lastUrls[maxSize-i]); } } } else { PutModule("Unknown command! Try HELP."); } }