1 /* 2 * Copyright (C) 2004-2020 ZNC, see the NOTICE file for details. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ZNC_TEMPLATE_H 18 #define ZNC_TEMPLATE_H 19 20 #include <znc/zncconfig.h> 21 #include <znc/ZNCString.h> 22 #include <iostream> 23 #include <list> 24 #include <memory> 25 26 class CTemplate; 27 28 class CTemplateTagHandler { 29 public: CTemplateTagHandler()30 CTemplateTagHandler() {} ~CTemplateTagHandler()31 virtual ~CTemplateTagHandler() {} 32 HandleVar(CTemplate & Tmpl,const CString & sName,const CString & sArgs,CString & sOutput)33 virtual bool HandleVar(CTemplate& Tmpl, const CString& sName, 34 const CString& sArgs, CString& sOutput) { 35 return false; 36 } 37 HandleTag(CTemplate & Tmpl,const CString & sName,const CString & sArgs,CString & sOutput)38 virtual bool HandleTag(CTemplate& Tmpl, const CString& sName, 39 const CString& sArgs, CString& sOutput) { 40 return false; 41 } 42 HandleIf(CTemplate & Tmpl,const CString & sName,const CString & sArgs,CString & sOutput)43 virtual bool HandleIf(CTemplate& Tmpl, const CString& sName, 44 const CString& sArgs, CString& sOutput) { 45 return HandleVar(Tmpl, sName, sArgs, sOutput); 46 } 47 HandleValue(CTemplate & Tmpl,CString & sValue,const MCString & msOptions)48 virtual bool HandleValue(CTemplate& Tmpl, CString& sValue, 49 const MCString& msOptions) { 50 return false; 51 } 52 53 private: 54 }; 55 class CTemplate; 56 57 class CTemplateOptions { 58 public: CTemplateOptions()59 CTemplateOptions() 60 : m_eEscapeFrom(CString::EASCII), m_eEscapeTo(CString::EASCII) {} 61 ~CTemplateOptions()62 virtual ~CTemplateOptions() {} 63 64 void Parse(const CString& sLine); 65 66 // Getters GetEscapeFrom()67 CString::EEscape GetEscapeFrom() const { return m_eEscapeFrom; } GetEscapeTo()68 CString::EEscape GetEscapeTo() const { return m_eEscapeTo; } 69 // !Getters 70 private: 71 CString::EEscape m_eEscapeFrom; 72 CString::EEscape m_eEscapeTo; 73 }; 74 75 class CTemplateLoopContext { 76 public: CTemplateLoopContext(unsigned long uFilePos,const CString & sLoopName,bool bReverse,std::vector<CTemplate * > * pRows)77 CTemplateLoopContext(unsigned long uFilePos, const CString& sLoopName, 78 bool bReverse, std::vector<CTemplate*>* pRows) 79 : m_bReverse(bReverse), 80 m_bHasData(false), 81 m_sName(sLoopName), 82 m_uRowIndex(0), 83 m_uFilePosition(uFilePos), 84 m_pvRows(pRows) {} 85 ~CTemplateLoopContext()86 virtual ~CTemplateLoopContext() {} 87 88 CTemplateLoopContext(const CTemplateLoopContext&) = default; 89 CTemplateLoopContext& operator=(const CTemplateLoopContext&) = default; 90 91 // Setters 92 void SetHasData(bool b = true) { m_bHasData = b; } SetName(const CString & s)93 void SetName(const CString& s) { m_sName = s; } SetRowIndex(unsigned int u)94 void SetRowIndex(unsigned int u) { m_uRowIndex = u; } IncRowIndex()95 unsigned int IncRowIndex() { return ++m_uRowIndex; } DecRowIndex()96 unsigned int DecRowIndex() { 97 if (m_uRowIndex == 0) { 98 return 0; 99 } 100 return --m_uRowIndex; 101 } SetFilePosition(unsigned int u)102 void SetFilePosition(unsigned int u) { m_uFilePosition = u; } 103 // !Setters 104 105 // Getters HasData()106 bool HasData() const { return m_bHasData; } GetName()107 const CString& GetName() const { return m_sName; } GetFilePosition()108 unsigned long GetFilePosition() const { return m_uFilePosition; } GetRowIndex()109 unsigned int GetRowIndex() const { return m_uRowIndex; } GetRowCount()110 size_t GetRowCount() { return m_pvRows->size(); } GetRows()111 std::vector<CTemplate*>* GetRows() { return m_pvRows; } GetNextRow()112 CTemplate* GetNextRow() { return GetRow(IncRowIndex()); } GetCurRow()113 CTemplate* GetCurRow() { return GetRow(m_uRowIndex); } 114 115 CTemplate* GetRow(unsigned int uIndex); 116 CString GetValue(const CString& sName, bool bFromIf = false); 117 // !Getters 118 private: 119 bool m_bReverse; //!< Iterate through this loop in reverse order 120 bool m_bHasData; //!< Tells whether this loop has real data or not 121 CString m_sName; //!< The name portion of the <?LOOP name?> tag 122 unsigned int m_uRowIndex; //!< The index of the current row we're on 123 unsigned long 124 m_uFilePosition; //!< The file position of the opening <?LOOP?> tag 125 std::vector<CTemplate*>* 126 m_pvRows; //!< This holds pointers to the templates associated with this loop 127 }; 128 129 class CTemplate : public MCString { 130 public: CTemplate()131 CTemplate() : CTemplate("") {} 132 CTemplate(const CString & sFileName)133 CTemplate(const CString& sFileName) 134 : MCString(), 135 m_pParent(nullptr), 136 m_sFileName(sFileName), 137 m_lsbPaths(), 138 m_mvLoops(), 139 m_vLoopContexts(), 140 m_spOptions(new CTemplateOptions), 141 m_vspTagHandlers() {} 142 143 CTemplate(const std::shared_ptr<CTemplateOptions>& Options, 144 CTemplate* pParent = nullptr) MCString()145 : MCString(), 146 m_pParent(pParent), 147 m_sFileName(""), 148 m_lsbPaths(), 149 m_mvLoops(), 150 m_vLoopContexts(), 151 m_spOptions(Options), 152 m_vspTagHandlers() {} 153 154 virtual ~CTemplate(); 155 156 CTemplate(const CTemplate& other) = default; 157 CTemplate& operator=(const CTemplate& other) = default; 158 159 //! Class for implementing custom tags in subclasses AddTagHandler(std::shared_ptr<CTemplateTagHandler> spTagHandler)160 void AddTagHandler(std::shared_ptr<CTemplateTagHandler> spTagHandler) { 161 m_vspTagHandlers.push_back(spTagHandler); 162 } 163 GetTagHandlers()164 std::vector<std::shared_ptr<CTemplateTagHandler>>& GetTagHandlers() { 165 if (m_pParent) { 166 return m_pParent->GetTagHandlers(); 167 } 168 169 return m_vspTagHandlers; 170 } 171 172 CString ResolveLiteral(const CString& sString); 173 174 void Init(); 175 176 CTemplate* GetParent(bool bRoot); 177 CString ExpandFile(const CString& sFilename, bool bFromInc = false); 178 bool SetFile(const CString& sFileName); 179 180 void SetPath(const CString& sPath); // Sets the dir:dir:dir type path to 181 // look at for templates, as of right 182 // now no ../../.. protection 183 CString MakePath(const CString& sPath) const; 184 void PrependPath(const CString& sPath, bool bIncludesOnly = false); 185 void AppendPath(const CString& sPath, bool bIncludesOnly = false); 186 void RemovePath(const CString& sPath); 187 void ClearPaths(); 188 bool PrintString(CString& sRet); 189 bool Print(std::ostream& oOut); 190 bool Print(const CString& sFileName, std::ostream& oOut); 191 bool ValidIf(const CString& sArgs); 192 bool ValidExpr(const CString& sExpr); 193 bool IsTrue(const CString& sName); 194 bool HasLoop(const CString& sName); 195 CString GetValue(const CString& sName, bool bFromIf = false); 196 CTemplate& AddRow(const CString& sName); 197 CTemplate* GetRow(const CString& sName, unsigned int uIndex); 198 std::vector<CTemplate*>* GetLoop(const CString& sName); 199 void DelCurLoopContext(); 200 CTemplateLoopContext* GetCurLoopContext(); 201 CTemplate* GetCurTemplate(); 202 203 // Getters GetFileName()204 const CString& GetFileName() const { return m_sFileName; } 205 // !Getters 206 private: 207 CTemplate* m_pParent; 208 CString m_sFileName; 209 std::list<std::pair<CString, bool>> m_lsbPaths; 210 std::map<CString, std::vector<CTemplate*>> m_mvLoops; 211 std::vector<CTemplateLoopContext*> m_vLoopContexts; 212 std::shared_ptr<CTemplateOptions> m_spOptions; 213 std::vector<std::shared_ptr<CTemplateTagHandler>> m_vspTagHandlers; 214 }; 215 216 #endif // !ZNC_TEMPLATE_H 217