Example #1
0
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;
}
Example #2
0
File: log.cpp Project: Adam-/znc
bool CLogMod::OnLoad(const CString& sArgs, CString& sMessage) {
    VCString vsArgs;
    sArgs.QuoteSplit(vsArgs);

    bool bReadingTimestamp = false;
    bool bHaveLogPath = false;

    for (CString& sArg : vsArgs) {
        if (bReadingTimestamp) {
            m_sTimestamp = sArg;
            bReadingTimestamp = false;
        } else if (sArg.Equals("-sanitize")) {
            m_bSanitize = true;
        } else if (sArg.Equals("-timestamp")) {
            bReadingTimestamp = true;
        } else {
            // Only one arg may be LogPath
            if (bHaveLogPath) {
                sMessage = "Invalid args [" + sArgs +
                           "]. Only one log path allowed.  Check that there "
                           "are no spaces in the path.";
                return false;
            }
            m_sLogPath = sArg;
            bHaveLogPath = true;
        }
    }

    if (m_sTimestamp.empty()) {
        m_sTimestamp = "[%H:%M:%S]";
    }

    // Add default filename to path if it's a folder
    if (GetType() == CModInfo::UserModule) {
        if (m_sLogPath.Right(1) == "/" ||
            m_sLogPath.find("$WINDOW") == CString::npos ||
            m_sLogPath.find("$NETWORK") == CString::npos) {
            if (!m_sLogPath.empty()) {
                m_sLogPath += "/";
            }
            m_sLogPath += "$NETWORK/$WINDOW/%Y-%m-%d.log";
        }
    } else if (GetType() == CModInfo::NetworkModule) {
        if (m_sLogPath.Right(1) == "/" ||
            m_sLogPath.find("$WINDOW") == CString::npos) {
            if (!m_sLogPath.empty()) {
                m_sLogPath += "/";
            }
            m_sLogPath += "$WINDOW/%Y-%m-%d.log";
        }
    } else {
        if (m_sLogPath.Right(1) == "/" ||
            m_sLogPath.find("$USER") == CString::npos ||
            m_sLogPath.find("$WINDOW") == CString::npos ||
            m_sLogPath.find("$NETWORK") == CString::npos) {
            if (!m_sLogPath.empty()) {
                m_sLogPath += "/";
            }
            m_sLogPath += "$USER/$NETWORK/$WINDOW/%Y-%m-%d.log";
        }
    }

    CString sRules = GetNV("rules");
    VCString vsRules = SplitRules(sRules);
    SetRules(vsRules);

    // Check if it's allowed to write in this path in general
    m_sLogPath = CDir::CheckPathPrefix(GetSavePath(), m_sLogPath);
    if (m_sLogPath.empty()) {
        sMessage = "Invalid log path [" + m_sLogPath + "].";
        return false;
    } else {
        sMessage = "Logging to [" + m_sLogPath + "]. Using timestamp format '" +
                   m_sTimestamp + "'";
        return true;
    }
}
Example #3
0
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;
}