diff --git a/FileUtils.cpp b/FileUtils.cpp index f377b834..e8a24c77 100644 --- a/FileUtils.cpp +++ b/FileUtils.cpp @@ -1,4 +1,12 @@ #include "FileUtils.h" +#include + +using std::cout; +using std::cerr; +using std::endl; + +CFile::CFile() { +} CFile::CFile(const CString& sLongName) { SetFileName(sLongName); @@ -195,7 +203,17 @@ bool CFile::Chmod(const CString& sFile, mode_t mode) { } bool CFile::Seek(unsigned long uPos) { - return (m_iFD == -1) ? false : ((unsigned int) lseek(m_iFD, uPos, SEEK_SET) == uPos); + if (m_iFD != -1 && (unsigned int) lseek(m_iFD, uPos, SEEK_SET) == uPos) { + ClearBuffer(); + return true; + } + + return false; +} + +bool CFile::Open(const CString& sFileName, int iFlags, mode_t iMode) { + SetFileName(sFileName); + return Open(iFlags, iMode); } bool CFile::Open(int iFlags, mode_t iMode) { @@ -215,9 +233,10 @@ int CFile::Read(char *pszBuffer, int iBytes) { return read(m_iFD, pszBuffer, iBytes); } -bool CFile::ReadLine(CString & sData) { +bool CFile::ReadLine(CString& sData) { char buff[64]; sData.clear(); + if (m_iFD == -1) { return false; } @@ -234,6 +253,7 @@ bool CFile::ReadLine(CString & sData) { memset((char *)buff, '\0', 64); int iBytes = read(m_iFD, buff, 64); + switch(iBytes) { case -1: { bEOF = true; @@ -274,7 +294,19 @@ int CFile::Write(const CString & sData) { return Write(sData.data(), sData.size()); } void CFile::Close() { close(m_iFD); m_iFD = -1; } +void CFile::ClearBuffer() { m_sBuffer.clear(); } +bool CFile::IsOpen() const { return (m_iFD != -1); } CString CFile::GetLongName() const { return m_sLongName; } CString CFile::GetShortName() const { return m_sShortName; } +CString CFile::GetDir() const { + CString sDir(m_sLongName); + + while (!sDir.empty() && sDir.Right(1) != "/" && sDir.Right(1) != "\\") { + sDir.RightChomp(); + } + + return sDir; +} + void CFile::SetFD(int iFD) { m_iFD = iFD; } diff --git a/FileUtils.h b/FileUtils.h index 07500fe3..02054f19 100644 --- a/FileUtils.h +++ b/FileUtils.h @@ -10,8 +10,6 @@ #include #include -#include "Utils.h" - #include "String.h" #include #include @@ -20,9 +18,17 @@ using std::map; class CFile { public: + CFile(); CFile(const CString& sLongName); virtual ~CFile(); + enum EOptions { + F_Read = O_RDONLY, + F_Write = O_WRONLY, + F_Create = O_CREAT, + F_Truncate = O_TRUNC + }; + enum EFileTypes { FT_REGULAR, FT_DIRECTORY, @@ -97,15 +103,19 @@ public: bool Chmod(mode_t mode); static bool Chmod(const CString& sFile, mode_t mode); bool Seek(unsigned long uPos); + bool Open(const CString& sFileName, int iFlags, mode_t iMode = 0644); bool Open(int iFlags, mode_t iMode = 0644); int Read(char *pszBuffer, int iBytes); bool ReadLine(CString & sData); int Write(const char *pszBuffer, u_int iBytes); int Write(const CString & sData); void Close(); + void ClearBuffer(); + bool IsOpen() const; CString GetLongName() const; CString GetShortName() const; + CString GetDir() const; void SetFD(int iFD); private: diff --git a/HTTPSock.cpp b/HTTPSock.cpp index c1f14657..bdfac1ff 100644 --- a/HTTPSock.cpp +++ b/HTTPSock.cpp @@ -112,8 +112,8 @@ void CHTTPSock::ParseParams(const CString& sParams) { 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); + CString sName = sPair.Token(0, false, "=").Escape_n(CString::EURL, CString::EASCII); + CString sValue = sPair.Token(1, true, "=").Escape_n(CString::EURL, CString::EASCII); m_msvsParams[sName].push_back(sValue); } diff --git a/Makefile.in b/Makefile.in index cefce138..24d78553 100644 --- a/Makefile.in +++ b/Makefile.in @@ -4,8 +4,8 @@ INCLUDES=@INCLUDES@ LIBS=@LIBS@ prefix=@prefix@ -OBJS=String.o Csocket.o main.o znc.o User.o IRCSock.o Client.o DCCBounce.o DCCSock.o Chan.o Nick.o Server.o Modules.o MD5.o Buffer.o Utils.o FileUtils.o HTTPSock.o -SRCS=String.cpp Csocket.cpp main.cpp znc.cpp User.cpp IRCSock.cpp Client.cpp DCCBounce.cpp DCCSock.cpp Chan.cpp Nick.cpp Server.cpp Modules.cpp MD5.cpp Buffer.cpp Utils.cpp FileUtils.cpp HTTPSock.cpp +OBJS=String.o Csocket.o main.o znc.o User.o IRCSock.o Client.o DCCBounce.o DCCSock.o Chan.o Nick.o Server.o Modules.o MD5.o Buffer.o Utils.o FileUtils.o HTTPSock.o Template.o +SRCS=String.cpp Csocket.cpp main.cpp znc.cpp User.cpp IRCSock.cpp Client.cpp DCCBounce.cpp DCCSock.cpp Chan.cpp Nick.cpp Server.cpp Modules.cpp MD5.cpp Buffer.cpp Utils.cpp FileUtils.cpp HTTPSock.cpp Template.cpp all: znc @MODTARGET@ diff --git a/String.cpp b/String.cpp index 3914c277..92e5cf73 100644 --- a/String.cpp +++ b/String.cpp @@ -239,6 +239,20 @@ CString CString::AsLower() const { return sRet; } +CString::EEscape CString::ToEscape(const CString& sEsc) { + if (sEsc.CaseCmp("ASCII") == 0) { + return EASCII; + } else if (sEsc.CaseCmp("HTML") == 0) { + return EHTML; + } else if (sEsc.CaseCmp("URL") == 0) { + return EURL; + } else if (sEsc.CaseCmp("SQL") == 0) { + return ESQL; + } + + return EASCII; +} + CString CString::Escape_n(EEscape eFrom, EEscape eTo) const { CString sRet; const char szHex[] = "0123456789ABCDEF"; @@ -290,7 +304,7 @@ CString CString::Escape_n(EEscape eFrom, EEscape eTo) const { ch = *p; } break; - case EAscii: + case EASCII: ch = *p; break; case EURL: @@ -316,6 +330,29 @@ CString CString::Escape_n(EEscape eFrom, EEscape eTo) const { ch = *p; } + break; + case ESQL: + if (*p != '\\' || iLength < (a +1)) { + ch = *p; + } else { + a++; + p++; + + if (*p == 'n') { + ch = '\n'; + } else if (*p == 'r') { + ch = '\r'; + } else if (*p == '0') { + ch = '\0'; + } else if (*p == 't') { + ch = '\t'; + } else if (*p == 'b') { + ch = '\b'; + } else { + ch = *p; + } + } + break; } @@ -328,7 +365,7 @@ CString CString::Escape_n(EEscape eFrom, EEscape eTo) const { } break; - case EAscii: + case EASCII: sRet += ch; break; case EURL: @@ -342,6 +379,18 @@ CString CString::Escape_n(EEscape eFrom, EEscape eTo) const { sRet += szHex[ch & 0xf]; } + break; + case ESQL: + if (ch == '\0') { sRet += '\\'; sRet += '0'; + } else if (ch == '\n') { sRet += '\\'; sRet += 'n'; + } else if (ch == '\t') { sRet += '\\'; sRet += 't'; + } else if (ch == '\r') { sRet += '\\'; sRet += 'r'; + } else if (ch == '\b') { sRet += '\\'; sRet += 'b'; + } else if (ch == '\"') { sRet += '\\'; sRet += '\"'; + } else if (ch == '\'') { sRet += '\\'; sRet += '\''; + } else if (ch == '\\') { sRet += '\\'; sRet += '\\'; + } else { sRet += ch; } + break; } } @@ -351,7 +400,7 @@ CString CString::Escape_n(EEscape eFrom, EEscape eTo) const { } CString CString::Escape_n(EEscape eTo) const { - return Escape_n(EAscii, eTo); + return Escape_n(EASCII, eTo); } CString& CString::Escape(EEscape eFrom, EEscape eTo) { @@ -362,41 +411,61 @@ CString& CString::Escape(EEscape eTo) { return (*this = Escape_n(eTo)); } -unsigned int CString::Replace(const CString& sReplace, const CString& sWith) { - return CString::Replace(*this, sReplace, sWith); -} - -CString CString::Replace_n(const CString& sReplace, const CString& sWith) const { - CString sRet(*this); - sRet.Replace(sReplace, sWith); +CString CString::Replace_n(const CString& sReplace, const CString& sWith, const CString& sLeft, const CString& sRight, bool bRemoveDelims) const { + CString sRet = *this; + CString::Replace(sRet, sReplace, sWith, sLeft, sRight, bRemoveDelims); return sRet; } -unsigned int CString::Replace(CString& sStr, const CString& sReplace, const CString& sWith) { - unsigned int uRet = 0; - size_type uPos = sStr.find(sReplace); +unsigned int CString::Replace(const CString& sReplace, const CString& sWith, const CString& sLeft, const CString& sRight, bool bRemoveDelims) { + return CString::Replace(*this, sReplace, sWith, sLeft, sRight, bRemoveDelims); +} - while (uPos != npos) { - sStr.replace(uPos, sReplace.length(), sWith); - uPos = sStr.find(sReplace, uPos + sReplace.length() +1); - uRet++; +unsigned int CString::Replace(CString& sStr, const CString& sReplace, const CString& sWith, const CString& sLeft, const CString& sRight, bool bRemoveDelims) { + unsigned int uRet = 0; + CString sCopy = sStr; + sStr.clear(); + + unsigned int uReplaceWidth = sReplace.length(); + unsigned int uLeftWidth = sLeft.length(); + unsigned int uRightWidth = sRight.length(); + const char* p = sCopy.c_str(); + bool bInside = false; + + while (*p) { + if (!bInside && uLeftWidth && strncmp(p, sLeft.c_str(), uLeftWidth) == 0) { + if (!bRemoveDelims) { + sStr += sLeft; + } + + p += uLeftWidth -1; + bInside = true; + } else if (bInside && uRightWidth && strncmp(p, sRight.c_str(), uRightWidth) == 0) { + if (!bRemoveDelims) { + sStr += sRight; + } + + p += uRightWidth -1; + bInside = false; + } else if (!bInside && strncmp(p, sReplace.c_str(), uReplaceWidth) == 0) { + sStr += sWith; + p += uReplaceWidth -1; + uRet++; + } else { + sStr.append(p, 1); + } + + p++; } return uRet; } CString CString::Token(unsigned int uPos, bool bRest, const CString& sSep) const { - CString sRet; - Token(sRet, uPos, bRest, sSep); - return sRet; -} - -bool CString::Token(CString& sRet, unsigned int uPos, bool bRest, const CString& sSep) const { + string sRet; const char* p = c_str(); unsigned int uSepLen = sSep.length(); - sRet.clear(); - if (uSepLen) { uSepLen--; } @@ -410,7 +479,7 @@ bool CString::Token(CString& sRet, unsigned int uPos, bool bRest, const CString& } else { if (strncmp(p, sSep.c_str(), sSep.length()) == 0) { if (!bRest) { - return true; + return sRet; } } @@ -420,7 +489,7 @@ bool CString::Token(CString& sRet, unsigned int uPos, bool bRest, const CString& p++; } - return !sRet.empty(); + return sRet; } CString CString::Ellipsize(unsigned int uLen) const { @@ -454,25 +523,75 @@ CString CString::Right(unsigned int uCount) const { return substr(length() - uCount, uCount); } -void CString::Split(SCString& ssRet, const CString& sDelim) { - ssRet.clear(); +unsigned int CString::URLSplit(MCString& msRet) const { + msRet.clear(); - unsigned int a = 0; - CString sTok; + VCString vsPairs; + Split("&", vsPairs); - while (Token(sTok, a++, false, sDelim)) { - ssRet.insert(sTok); + for (size_t a = 0; a < vsPairs.size(); a++) { + const CString& sPair = vsPairs[a]; + + msRet[sPair.Token(0, false, "=").Escape(CString::EURL, CString::EASCII)] = sPair.Token(1, true, "=").Escape(CString::EURL, CString::EASCII); } + + return msRet.size(); } -VCString CString::Split(const CString& sDelim, bool bAllowEmpty) const { - VCString vsRet; - Split(sDelim, vsRet, bAllowEmpty); - return vsRet; -} - -unsigned int CString::Split(const CString& sDelim, VCString& vsRet, bool bAllowEmpty) const { +unsigned int CString::Split(const CString& sDelim, VCString& vsRet, bool bAllowEmpty, const CString& sLeft, const CString& sRight) const { vsRet.clear(); + + if (empty()) { + return 0; + } + + CString sTmp; + bool bInside = false; + unsigned int uDelimLen = sDelim.length(); + unsigned int uLeftLen = sLeft.length(); + unsigned int uRightLen = sRight.length(); + const char* p = c_str(); + + while (*p) { + if (uLeftLen && uRightLen && !bInside && strncasecmp(p, sLeft.c_str(), uLeftLen) == 0) { + p += uLeftLen; + bInside = true; + continue; + } + + if (uLeftLen && uRightLen && bInside && strncasecmp(p, sRight.c_str(), uRightLen) == 0) { + p += uRightLen; + bInside = false; + continue; + } + + if (uDelimLen && !bInside && strncasecmp(p, sDelim.c_str(), uDelimLen) == 0) { + vsRet.push_back(sTmp); + sTmp.clear(); + p += uDelimLen; + + if (!bAllowEmpty) { + while (strncasecmp(p, sDelim.c_str(), uDelimLen) == 0) { + p += uDelimLen; + } + } + + bInside = false; + continue; + } else { + sTmp += *p; + } + + p++; + } + + if (!sTmp.empty()) { + vsRet.push_back(sTmp); + } + + return vsRet.size(); + + /*vsRet.clear(); CString sTmp = *this; while (sTmp.size()) { @@ -490,7 +609,25 @@ unsigned int CString::Split(const CString& sDelim, VCString& vsRet, bool bAllowE sTmp = sRest; } - return vsRet.size(); + return vsRet.size();*/ +} + +unsigned int CString::Split(const CString& sDelim, SCString& ssRet, bool bAllowEmpty, const CString& sLeft, const CString& sRight) const { + VCString vsTokens; + + Split(sDelim, vsTokens, bAllowEmpty, sLeft, sRight); + + ssRet.clear(); + + for (size_t a = 0; a < vsTokens.size(); a++) { + ssRet.insert(vsTokens[a]); + } + + return ssRet.size(); +} + +CString CString::Format(const CString& sFormatStr, ...) { + return ""; } CString CString::RandomString(unsigned int uLength) { @@ -503,10 +640,6 @@ CString CString::RandomString(unsigned int uLength) { return sRet; } -CString CString::Format(const CString& sFormatStr, ...) { - return ""; -} - bool CString::Base64Encode(unsigned int uWrap) { CString sCopy(*this); return sCopy.Base64Encode(*this, uWrap); @@ -620,12 +753,12 @@ unsigned long CString::Base64Decode(CString& sRet) const { unsigned long i; unsigned long uLen = size(); char* out = (char*) malloc(size() +1); - + for (i = 0, p = out; i < uLen; i++) { c = (char)base64_table[(unsigned char)in[i++]]; c1 = (char)base64_table[(unsigned char)in[i++]]; *p++ = (c << 2) | ((c1 >> 4) & 0x3); - + if (i < uLen) { if (in[i] == '=') { break; @@ -633,7 +766,7 @@ unsigned long CString::Base64Decode(CString& sRet) const { c = (char)base64_table[(unsigned char)in[i]]; *p++ = ((c1 << 4) & 0xf0) | ((c >> 2) & 0xf); } - + if (++i < uLen) { if (in[i] == '=') { break; @@ -641,7 +774,7 @@ unsigned long CString::Base64Decode(CString& sRet) const { *p++ = ((c << 6) & 0xc0) | (char)base64_table[(unsigned char)in[i]]; } } - + *p = '\0'; unsigned long uRet = p - out; sRet.clear(); @@ -727,7 +860,7 @@ CString CString::ToKBytes(double d) { return szRet; } -bool CString::ToBool() const { return (!Trim_n().Trim_n("0").empty() && CaseCmp("false") != 0); } +bool CString::ToBool() const { return (!Trim_n().Trim_n("0").empty() && Trim_n().CaseCmp("false") != 0); } short CString::ToShort() const { return strtoul(this->c_str(), (char**) NULL, 10); } unsigned short CString::ToUShort() const { return strtoul(this->c_str(), (char**) NULL, 10); } unsigned int CString::ToUInt() const { return strtoul(this->c_str(), (char**) NULL, 10); } @@ -783,13 +916,13 @@ CString CString::TrimRight_n(const CString& s) const { return sRet; } -CString CString::LeftChomp_n(unsigned int uLen) { +CString CString::LeftChomp_n(unsigned int uLen) const { CString sRet = *this; sRet.LeftChomp(uLen); return sRet; } -CString CString::RightChomp_n(unsigned int uLen) { +CString CString::RightChomp_n(unsigned int uLen) const { CString sRet = *this; sRet.RightChomp(uLen); return sRet; diff --git a/String.h b/String.h index a8192a9f..f10e79a4 100644 --- a/String.h +++ b/String.h @@ -1,22 +1,38 @@ #ifndef X_STRING_H #define X_STRING_H +#ifdef USE_PCRE +#include +#endif + +#include +#include #include #include -#include -#include #include -using std::map; -using std::string; using std::set; +using std::map; +using std::multimap; +using std::string; +using std::pair; using std::vector; using std::stringstream; + +#define _SQL(s) CString("'" + CString(s).Escape_n(CString::ESQL) + "'") +#define _URL(s) CString("'" + CString(s).Escape_n(CString::EURL) + "'") +#define _HTML(s) CString("'" + CString(s).Escape_n(CString::EHTML) + "'") + + class CString; -typedef vector VCString; -typedef set SCString; -typedef map MVCString; +class MCString; + +typedef set SCString; +typedef vector VCString; +typedef map MVCString; +typedef vector VMCString; +typedef multimap MMCString; static const unsigned char XX = 0xff; static const unsigned char base64_table[256] = { @@ -43,9 +59,10 @@ extern const char* g_szHTMLescapes[256]; class CString : public string { public: typedef enum { - EAscii, + EASCII, EURL, EHTML, + ESQL, } EEscape; CString() : string() {} @@ -64,26 +81,26 @@ public: CString AsUpper() const; CString AsLower() const; + static EEscape ToEscape(const CString& sEsc); CString Escape_n(EEscape eFrom, EEscape eTo) const; CString Escape_n(EEscape eTo) const; CString& Escape(EEscape eFrom, EEscape eTo); CString& Escape(EEscape eTo); - static unsigned int Replace(CString& sStr, const CString& sReplace, const CString& sWith); - unsigned int Replace(const CString& sReplace, const CString& sWith); - CString Replace_n(const CString& sReplace, const CString& sWith) const; + static unsigned int Replace(CString& sStr, const CString& sReplace, const CString& sWith, const CString& sLeft = "", const CString& sRight = "", bool bRemoveDelims = false); + CString Replace_n(const CString& sReplace, const CString& sWith, const CString& sLeft = "", const CString& sRight = "", bool bRemoveDelims = false) const; + unsigned int Replace(const CString& sReplace, const CString& sWith, const CString& sLeft = "", const CString& sRight = "", bool bRemoveDelims = false); CString Ellipsize(unsigned int uLen) const; CString Left(unsigned int uCount) const; CString Right(unsigned int uCount) const; - static CString RandomString(unsigned int uLength); - CString Token(unsigned int uPos, bool bRest = false, const CString& sSep = " ") const; - bool Token(CString& sRet, unsigned int uPos, bool bRest = false, const CString& sSep = " ") const; - VCString Split(const CString& sDelim, bool bKeepEmpty = true) const; - unsigned int Split(const CString& sDelim, VCString& vsRet, bool bAllowEmpty = true) const; + unsigned int URLSplit(MCString& msRet) const; + unsigned int Split(const CString& sDelim, VCString& vsRet, bool bAllowEmpty = true, const CString& sLeft = "", const CString& sRight = "") const; + unsigned int Split(const CString& sDelim, SCString& ssRet, bool bAllowEmpty = true, const CString& sLeft = "", const CString& sRight = "") const; static CString Format(const CString& sFormatStr, ...); - void Split(SCString& ssRet, const CString& sDelim = " "); + + static CString RandomString(unsigned int uLength); CString MD5() const; unsigned long Base64Decode(CString& sRet) const; @@ -135,8 +152,8 @@ public: bool LeftChomp(unsigned int uLen = 1); bool RightChomp(unsigned int uLen = 1); - CString LeftChomp_n(unsigned int uLen = 1); - CString RightChomp_n(unsigned int uLen = 1); + CString LeftChomp_n(unsigned int uLen = 1) const; + CString RightChomp_n(unsigned int uLen = 1) const; private: protected: diff --git a/Template.cpp b/Template.cpp new file mode 100644 index 00000000..c6278f2a --- /dev/null +++ b/Template.cpp @@ -0,0 +1,446 @@ +#include "Template.h" +#include "Utils.h" + +using std::cerr; + +CTemplate* CTemplateLoopContext::GetRow(unsigned int uIndex) { + if (uIndex < m_pvRows->size()) { + return (*m_pvRows)[uIndex]; + } + + return NULL; +} + +CString CTemplateLoopContext::GetValue(const CString& sName) { + CTemplate* pTemplate = GetCurRow(); + + if (!pTemplate) { + return ""; + } + + if (sName.CaseCmp("__ID__") == 0) { + return CString::ToString(GetRowIndex() +1); + } else if (sName.CaseCmp("__COUNT__") == 0) { + return CString::ToString(GetRowCount()); + } else if (sName.CaseCmp("__ODD__") == 0) { + return ((GetRowIndex() %2) ? "" : "1"); + } else if (sName.CaseCmp("__EVEN__") == 0) { + return ((GetRowIndex() %2) ? "1" : ""); + } else if (sName.CaseCmp("__FIRST__") == 0) { + return ((GetRowIndex() == 0) ? "1" : ""); + } else if (sName.CaseCmp("__LAST__") == 0) { + return ((GetRowIndex() == m_pvRows->size() -1) ? "1" : ""); + } else if (sName.CaseCmp("__OUTER__") == 0) { + return ((GetRowIndex() == 0 || GetRowIndex() == m_pvRows->size() -1) ? "1" : ""); + } else if (sName.CaseCmp("__INNER__") == 0) { + return ((GetRowIndex() == 0 || GetRowIndex() == m_pvRows->size() -1) ? "" : "1"); + } + + return pTemplate->GetValue(sName); +} + +CTemplate::~CTemplate() { + for (map >::iterator it = m_mvLoops.begin(); it != m_mvLoops.end(); it++) { + vector& vLoop = it->second; + for (unsigned int a = 0; a < vLoop.size(); a++) { + delete vLoop[a]; + } + } + + for (unsigned int a = 0; a < m_vLoopContexts.size(); a++) { + delete m_vLoopContexts[a]; + } +} + +bool CTemplate::SetFile(const CString& sFileName) { + if (sFileName.empty()) { + return false; + } + + if (!CFile::Exists(sFileName)) { + return false; + } + + m_sFileName = sFileName; + return true; +} + +CTemplate& CTemplate::AddRow(const CString& sName) { + CTemplate* pTmpl = new CTemplate; + m_mvLoops[sName].push_back(pTmpl); + + return *pTmpl; +} + +CTemplate* CTemplate::GetRow(const CString& sName, unsigned int uIndex) { + vector* pvLoop = GetLoop(sName); + + if (pvLoop) { + if (pvLoop->size() > uIndex) { + return (*pvLoop)[uIndex]; + } + } + + return NULL; +} + +vector* CTemplate::GetLoop(const CString& sName) { + CTemplateLoopContext* pContext = GetCurLoopContext(); + + if (pContext) { + CTemplate* pTemplate = pContext->GetCurRow(); + + if (pTemplate) { + return pTemplate->GetLoop(sName); + } + } + + map >::iterator it = m_mvLoops.find(sName); + + if (it != m_mvLoops.end()) { + return &(it->second); + } + + return NULL; +} + +bool CTemplate::Print(ostream& oOut) { + return Print(m_sFileName, oOut); +} + +bool CTemplate::Print(const CString& sFileName, ostream& oOut) { + if (sFileName.empty()) { + DEBUG_ONLY(cerr << "Empty filename in CTemplate::Print()" << endl); + return false; + } + + CFile File(sFileName); + + if (!File.Open(O_RDONLY)) { + DEBUG_ONLY(cerr << "Unable to open file [" << sFileName << "] in CTemplate::Print()" << endl); + return false; + } + + CString sLine; + CString sOutput; + bool bValidLastIf = false; + unsigned long uFilePos = 0; + unsigned long uCurPos = 0; + unsigned int uLineNum = 0; + unsigned int uNestedIfs = 0; + unsigned int uSkip = 0; + + while (File.ReadLine(sLine)) { + bool bFoundOneTag = false; + uLineNum++; + CString::size_type iPos = 0; + uCurPos = uFilePos; + unsigned int uLineSize = sLine.size(); + + do { + iPos = sLine.find(""); + + // Make sure our tmpl tag is ended properly + if (iPos2 != CString::npos) { + CString sMid = CString(sLine.substr(0, iPos2)).Trim_n(); + + // Make sure we don't have a nested tag + if (sMid.find("first] = it->second; + } + } + } else if (sAction.CaseCmp("SET") == 0) { + CString sName = sArgs.Token(0); + CString sValue = sArgs.Token(1, true); + + (*this)[sName] = sValue; + } else if (sAction.CaseCmp("JOIN") == 0) { + VCString vsArgs; + sArgs.Split(" ", vsArgs, false, "\"", "\""); + + 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.Left(4).CaseCmp("ESC=") == 0) { + 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.CaseCmp("VAR") == 0) { + sOutput += GetValue(sArgs); + } else if (sAction.CaseCmp("LOOP") == 0) { + 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); + vector* pvLoop = GetLoop(sLoopName); + + if (pvLoop) { + // If we found data for this loop, add it to our context vector + m_vLoopContexts.push_back(new CTemplateLoopContext(uCurPos, sLoopName, pvLoop)); + } else { // If we don't have data, just skip this loop and everything inside + uSkip++; + } + } + } else if (sAction.CaseCmp("IF") == 0) { + if (ValidIf(sArgs)) { + uNestedIfs++; + bValidLastIf = true; + } else { + uSkip++; + bValidLastIf = false; + } + } + } else if (sAction.CaseCmp("IF") == 0) { + uSkip++; + } else if (sAction.CaseCmp("LOOP") == 0) { + uSkip++; + } + + if (sAction.CaseCmp("ENDIF") == 0) { + if (uSkip) { + uSkip--; + } else { + uNestedIfs--; + } + } else if (sAction.CaseCmp("ENDLOOP") == 0) { + 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 (pContext->GetCurRow()) { + uCurPos = pContext->GetFilePosition(); + uFilePos = uCurPos; + uLineSize = 0; + + File.Seek(uCurPos); + } else { + DelCurLoopContext(); + } + } + } + } else if (sAction.CaseCmp("ELSE") == 0) { + if (!bValidLastIf && uSkip == 1) { + CString sArg = sArgs.Token(0); + + if (sArg.empty() || (sArg.CaseCmp("IF") == 0 && ValidIf(sArgs.Token(1, true)))) { + uSkip = 0; + bValidLastIf = true; + } + } else if (!uSkip) { + uSkip = 1; + } + } + + continue; + } + } + + DEBUG_ONLY(cerr << "Malformed tag on line " << uLineNum << " of [" << File.GetLongName() << "]" << endl); + DEBUG_ONLY(cerr << "--------------- [" << sLine << "]" << endl); + } + } while (iPos != CString::npos); + + uFilePos += uLineSize; + + if (!uSkip) { + sOutput += sLine; + } + + if (!bFoundOneTag || sOutput.find_first_not_of(" \t\r\n") != CString::npos) { + oOut << sOutput; + } + + sOutput.clear(); + } + + oOut.flush(); + + return true; +} + +void CTemplate::DelCurLoopContext() { + if (m_vLoopContexts.empty()) { + return; + } + + delete m_vLoopContexts.back(); + m_vLoopContexts.pop_back(); +} + +CTemplateLoopContext* CTemplate::GetCurLoopContext() { + if (!m_vLoopContexts.empty()) { + return m_vLoopContexts.back(); + } + + return NULL; +} + +bool CTemplate::ValidIf(const CString& sArgs) { + CString sArgStr = sArgs; + sArgStr.Replace(" ", "", "\"", "\"", true); + + CString::size_type uOrPos = sArgStr.find("||"); + CString::size_type uAndPos = sArgStr.find("&&"); + + while (uOrPos != CString::npos || uAndPos != CString::npos || !sArgStr.empty()) { + bool bAnd = false; + + if (uAndPos < uOrPos) { + bAnd = true; + } + + CString sExpr = sArgStr.Token(0, false, ((bAnd) ? "&&" : "||")); + sArgStr = sArgStr.Token(1, true, ((bAnd) ? "&&" : "||")); + + if (ValidExpr(sExpr)) { + if (!bAnd) { + return true; + } + } else { + if (bAnd) { + return false; + } + } + + uOrPos = sArgStr.find("||"); + uAndPos = sArgStr.find("&&"); + } + + return false; +} + +bool CTemplate::ValidExpr(const CString& sExpr) { + bool bNegate = false; + CString sName; + CString sValue; + + if (sExpr.find("!=") != CString::npos) { + sName = sExpr.Token(0, false, "!=").Trim_n(); + sValue = sExpr.Token(1, true, "!=").Trim_n(); + bNegate = true; + } else if (sExpr.find("==") != CString::npos) { + sName = sExpr.Token(0, false, "==").Trim_n(); + sValue = sExpr.Token(1, true, "==").Trim_n(); + bNegate = false; + } else { + sName = sExpr.Trim_n(); + } + + if (sName.Left(1) == "!") { + bNegate = true; + sName.LeftChomp(); + } + + if (sValue.empty()) { + return (bNegate != IsTrue(sName)); + } + + return (bNegate != (GetValue(sName).CaseCmp(sValue) == 0)); +} + +bool CTemplate::IsTrue(const CString& sName) { + if (HasLoop(sName)) { + return true; + } + + return GetValue(sName).ToBool(); +} + +bool CTemplate::HasLoop(const CString& sName) { + return (GetLoop(sName) != NULL); +} + +CTemplate* CTemplate::GetCurTemplate() { + CTemplateLoopContext* pContext = GetCurLoopContext(); + + if (!pContext) { + return this; + } + + return pContext->GetCurRow(); +} + +CString CTemplate::GetValue(const CString& sArgs) { + CTemplateLoopContext* pContext = GetCurLoopContext(); + CString sName = sArgs.Token(0); + CString sRest = sArgs.Token(1, true); + CString sRet; + + if (pContext) { + sRet = pContext->GetValue(sName); + } else { + MCString::iterator it = find(sName); + sRet = (it != end()) ? it->second : ""; + } + + while (sRest.Replace(" =", "=", "\"", "\"")); + while (sRest.Replace("= ", "=", "\"", "\"")); + + VCString vArgs; + sRest.Split(" ", vArgs, false, "\"", "\""); + + for (unsigned int a = 0; a < vArgs.size(); a++) { + const CString& sArg = vArgs[a]; + + if (sArg.Left(4).CaseCmp("ESC=") == 0) { + sRet.Escape(CString::ToEscape(sArg.LeftChomp_n(4))); + } else if (sRet.empty() && sArg.Left(8).CaseCmp("DEFAULT=") == 0) { + sRet = sArg.LeftChomp_n(8); + } + + } + + return sRet; +} diff --git a/Template.h b/Template.h new file mode 100644 index 00000000..747990aa --- /dev/null +++ b/Template.h @@ -0,0 +1,85 @@ +#ifndef _TEMPLATE_H +#define _TEMPLATE_H + +#include "FileUtils.h" +#include + +using std::ostream; +using std::cout; +using std::endl; + +class CTemplate; + +class CTemplateLoopContext { +public: + CTemplateLoopContext(unsigned long uFilePos, const CString& sLoopName, vector* pRows) { + m_uFilePosition = uFilePos; + m_sName = sLoopName; + m_uRowIndex = 0; + m_pvRows = pRows; + } + + virtual ~CTemplateLoopContext() {} + + // Setters + void SetName(const CString& s) { m_sName = s; } + void SetRowIndex(unsigned int u) { m_uRowIndex = u; } + unsigned int IncRowIndex() { return ++m_uRowIndex; } + unsigned int DecRowIndex() { if (m_uRowIndex == 0) { return 0; } return --m_uRowIndex; } + void SetFilePosition(unsigned int u) { m_uFilePosition = u; } + // !Setters + + // Getters + const CString& GetName() const { return m_sName; } + unsigned long GetFilePosition() const { return m_uFilePosition; } + unsigned int GetRowIndex() const { return m_uRowIndex; } + const unsigned int GetRowCount() { return m_pvRows->size(); } + vector* GetRows() { return m_pvRows; } + CTemplate* GetNextRow() { return GetRow(IncRowIndex()); } + CTemplate* GetCurRow() { return GetRow(m_uRowIndex); } + + CTemplate* GetRow(unsigned int uIndex); + CString GetValue(const CString& sName); + // !Getters +private: +protected: + CString m_sName; //! The name portion of the tag + unsigned int m_uRowIndex; //! The index of the current row we're on + unsigned long m_uFilePosition; //! The file position of the opening tag + vector* m_pvRows; //! This holds pointers to the templates associated with this loop +}; + +class CTemplate : public MCString { +public: + CTemplate() {} + CTemplate(const CString& sFileName) : m_sFileName(sFileName) {} + virtual ~CTemplate(); + + bool SetFile(const CString& sFileName); + bool Print(ostream& oOut = cout); + bool Print(const CString& sFileName, ostream& oOut = cout); + bool ValidIf(const CString& sArgs); + bool ValidExpr(const CString& sExpr); + bool IsTrue(const CString& sName); + bool HasLoop(const CString& sName); + CString GetValue(const CString& sName); + CTemplate& AddRow(const CString& sName); + CTemplate* GetRow(const CString& sName, unsigned int uIndex); + vector* GetLoop(const CString& sName); + void DelCurLoopContext(); + CTemplateLoopContext* GetCurLoopContext(); + CTemplate* GetCurTemplate(); + + // Getters + const CString& GetFileName() const { return m_sFileName; } + // !Getters +private: +protected: + CString m_sFileName; + CFile m_File; + map > m_mvLoops; + vector m_vLoopContexts; +}; + +#endif // !_TEMPLATE_H + diff --git a/modules/autoop.cpp b/modules/autoop.cpp index d5b5d72c..c29c527f 100644 --- a/modules/autoop.cpp +++ b/modules/autoop.cpp @@ -108,7 +108,7 @@ public: m_sUsername = sLine.Token(0, false, "\t"); m_sHostmask = sLine.Token(1, false, "\t"); m_sUserKey = sLine.Token(2, false, "\t"); - sLine.Token(3, false, "\t").Split(m_ssChans); + sLine.Token(3, false, "\t").Split(" ", m_ssChans); return !m_sUserKey.empty(); } diff --git a/modules/webadmin.cpp b/modules/webadmin.cpp index 93abbb8f..17fc8060 100644 --- a/modules/webadmin.cpp +++ b/modules/webadmin.cpp @@ -6,6 +6,7 @@ #include "znc.h" #include "HTTPSock.h" #include "Server.h" +#include "Template.h" class CWebAdminMod; @@ -18,19 +19,13 @@ public: virtual bool OnPageRequest(const CString& sURI, CString& sPageRet); virtual bool OnLogin(const CString& sUser, const CString& sPass); - CString Header(const CString& sTitle); - CString Footer(); - - void PrintMainPage(CString& sPageRet) { - sPageRet = Header("Main Page"); - sPageRet += "Welcome to the ZNC webadmin module.\r\n"; - sPageRet += Footer(); - } + void PrintPage(CString& sPageRet, const CString& sTmplName); void GetErrorPage(CString& sPageRet, const CString& sError) { - sPageRet = Header("Error"); - sPageRet += "

" + sError.Escape_n(CString::EHTML) + "

\r\n"; - sPageRet += Footer(); + m_Template["Title"] = "Error"; + m_Template["Error"] = sError; + + PrintPage(sPageRet, "Error.tmpl"); } void ListUsersPage(CString& sPageRet); @@ -40,32 +35,6 @@ public: bool UserPage(CString& sPageRet, CUser* pUser = NULL); CUser* GetNewUser(CString& sPageRet, CUser* pUser); - void ListPage(CString& sPageRet) { - VCString vsParams; - const map& msvsParams = GetParams(); - - sPageRet = Header("fooooooo"); - - if (msvsParams.empty()) { - sPageRet += "You passed in no params.\r\n"; - } else { - sPageRet += "foo [" + GetParamString().Escape_n(CString::EHTML) + "]

"; - - for (map::const_iterator it = msvsParams.begin(); it != msvsParams.end(); it++) { - sPageRet += "

" + it->first + "

\r\n
    \r\n"; - const VCString vsParams = it->second; - - for (unsigned int a = 0; a < vsParams.size(); a++) { - sPageRet += "
  • [" + vsParams[a] + "]
  • \r\n"; - } - - sPageRet += "
\r\n"; - } - } - - sPageRet += Footer(); - } - CString GetModArgs(const CString& sModName, bool bGlobal = false) { if (!bGlobal && !m_pUser) { return ""; @@ -92,6 +61,7 @@ protected: CWebAdminMod* m_pModule; CUser* m_pUser; bool m_bAdmin; + CTemplate m_Template; }; class CWebAdminMod : public CGlobalModule { @@ -151,35 +121,22 @@ private: set m_sSocks; }; -CString CWebAdminSock::Header(const CString& sTitle) { - CString sRet = "\r\n" - "\r\nZNC - " + sTitle.Escape_n(CString::EHTML) + "\r\n" - "\r\n" - "\r\n" - "\r\n" - "\r\n" - "
" - "" - "" - "" - "" - "
 

" + sTitle.Escape_n(CString::EHTML) + "

" + GetUser().Escape_n(CString::EHTML) + "@" + GetRemoteIP().Escape_n(CString::EHTML) + "
" - "
\r\n"; +void CWebAdminSock::PrintPage(CString& sPageRet, const CString& sTmplName) { + sPageRet.clear(); + CString sModPath = CZNC::Get().FindModPath(m_pModule->GetModName()); - if (IsAdmin()) { - sRet += "[Home]
\r\n" - "[Settings]
\r\n" - "[Add User]
\r\n" - "[List Users]
\r\n"; + while (!sModPath.empty() && sModPath.Right(1) != "/") { + sModPath.RightChomp(); } - sRet += "
\r\n"; + if (!m_Template.SetFile(sModPath + "/webadmin/" + sTmplName)) { + return; + } - return sRet; -} + stringstream oStr; + m_Template.Print(oStr); -CString CWebAdminSock::Footer() { - return "
" + CZNC::Get().GetTag().Escape_n(CString::EHTML) + "
\r\n\r\n"; + sPageRet = oStr.str(); } bool CWebAdminSock::OnLogin(const CString& sUser, const CString& sPass) { @@ -204,28 +161,22 @@ bool CWebAdminSock::OnLogin(const CString& sUser, const CString& sPass) { void CWebAdminSock::ListUsersPage(CString& sPageRet) { const map& msUsers = CZNC::Get().GetUserMap(); - sPageRet = Header("List Users"); + m_Template["Title"] = "List Users"; - if (!msUsers.size()) { - sPageRet += "There are no users defined. Click here if you would like to add one.\r\n"; - } else { - sPageRet += "\r\n" - "\t\r\n"; + unsigned int a = 0; - unsigned int a = 0; - - for (map::const_iterator it = msUsers.begin(); it != msUsers.end(); it++, a++) { - CServer* pServer = it->second->GetCurrentServer(); - sPageRet += "\t\r\n\t\t\r\n" - "\t\t\r\n" - "\t\t\r\n" - "\t"; + for (map::const_iterator it = msUsers.begin(); it != msUsers.end(); it++, a++) { + CServer* pServer = it->second->GetCurrentServer(); + CTemplate& l = m_Template.AddRow("UserLoop"); + + l["User"] = it->second->GetUserName(); + + if (pServer) { + l["Server"] = pServer->GetName(); } - - sPageRet +="\r\n
ActionUsernameCurrent Server
[second->GetUserName().Escape_n(CString::EURL) + "\">Edit] [second->GetUserName().Escape_n(CString::EURL) + "\">Delete]" + it->second->GetUserName().Escape_n(CString::EHTML) + "" + CString((pServer) ? pServer->GetName().Escape_n(CString::EHTML) : "-N/A-") + "
\r\n"; } - sPageRet += Footer(); + PrintPage(sPageRet, "ListUsers.tmpl"); } Csock* CWebAdminSock::GetSockObj(const CString& sHost, unsigned short uPort) { @@ -258,13 +209,21 @@ bool CWebAdminSock::OnPageRequest(const CString& sURI, CString& sPageRet) { return false; } + m_Template["User"] = GetUser(); + m_Template["UserIP"] = GetRemoteIP(); + + if (IsAdmin()) { + m_Template["IsAdmin"] = "true"; + } + if (sURI == "/") { if (!IsAdmin()) { Redirect("/edituser"); return false; } - PrintMainPage(sPageRet); + m_Template["Title"] = "Main Page"; + PrintPage(sPageRet, "Main.tmpl"); } else if (sURI == "/settings") { if (!IsAdmin()) { return false; @@ -392,8 +351,6 @@ bool CWebAdminSock::OnPageRequest(const CString& sURI, CString& sPageRet) { } else { GetErrorPage(sPageRet, "No such username"); } - //} else if (sURI == "/list") { - // ListPage(sPageRet); } else { return false; } @@ -403,61 +360,45 @@ bool CWebAdminSock::OnPageRequest(const CString& sURI, CString& sPageRet) { bool CWebAdminSock::SettingsPage(CString& sPageRet) { if (!GetParam("submitted").ToUInt()) { - sPageRet = Header("Settings"); - CString sVHosts, sMotd; + m_Template["Title"] = "Settings"; + m_Template["StatusPrefix"] = CZNC::Get().GetStatusPrefix(); + m_Template["ISpoofFile"] = CZNC::Get().GetISpoofFile(); + m_Template["ISpoofFormat"] = CZNC::Get().GetISpoofFormat(); const VCString& vsVHosts = CZNC::Get().GetVHosts(); for (unsigned int a = 0; a < vsVHosts.size(); a++) { - sVHosts += vsVHosts[a] + "\r\n"; + CTemplate& l = m_Template.AddRow("VHostLoop"); + l["VHost"] = vsVHosts[a]; } const VCString& vsMotd = CZNC::Get().GetMotd(); for (unsigned int b = 0; b < vsMotd.size(); b++) { - sMotd += vsMotd[b] + "\r\n"; + CTemplate& l = m_Template.AddRow("MOTDLoop"); + l["Line"] = vsMotd[b]; } - sPageRet += "
\r\n" - "\r\n" - "
Global Settings
\r\n" - - "
Status Prefix:
\r\n" - "

\r\n" - - "
ISpoofFile:
\r\n" - "
\r\n" - "
ISpoofFormat:
\r\n" - "
\r\n" - - "
MOTD:
\r\n" - "
\r\n" - - "
VHosts:
\r\n" - "
\r\n" - - "


\r\n" - - "
Global Modules
\r\n" - "\r\n" - "\r\n"; - set ssGlobalMods; CZNC::Get().GetModules().GetAvailableMods(ssGlobalMods, true); - unsigned int uIdx = 0; - for (set::iterator it = ssGlobalMods.begin(); it != ssGlobalMods.end(); it++) { const CModInfo& Info = *it; - sPageRet += "" - "" - ""; + CTemplate& l = m_Template.AddRow("ModuleLoop"); + + if (CZNC::Get().GetModules().FindModule(Info.GetName())) { + l["Checked"] = "true"; + } + + if (Info.GetName() == m_pModule->GetModName()) { + l["Disabled"] = "true"; + } + + l["Name"] = Info.GetName(); + l["Description"] = Info.GetDescription(); + l["Args"] = GetModArgs(Info.GetName(), true); } - sPageRet += "
NameArgumentsDescription
GetModName()) ? " DISABLED" : "") + ">GetModName()) ? " DISABLED" : "") + ">" + Info.GetDescription().Escape_n(CString::EHTML) + "



\r\n" - "\r\n" - "
\r\n"; - - sPageRet += Footer(); + PrintPage(sPageRet, "Settings.tmpl"); return true; } @@ -467,7 +408,8 @@ bool CWebAdminSock::SettingsPage(CString& sPageRet) { sArg = GetParam("ispoofformat"); CZNC::Get().SetISpoofFormat(sArg); //sArg = GetParam(""); if (!sArg.empty()) { CZNC::Get().Set(sArg); } - VCString vsArgs = GetParam("motd").Split("\n"); + VCString vsArgs; + GetParam("motd").Split("\n", vsArgs); CZNC::Get().ClearMotd(); unsigned int a = 0; @@ -475,7 +417,7 @@ bool CWebAdminSock::SettingsPage(CString& sPageRet) { CZNC::Get().AddMotd(vsArgs[a].TrimRight_n()); } - vsArgs = GetParam("vhosts").Split("\n"); + GetParam("vhosts").Split("\n", vsArgs); CZNC::Get().ClearVHosts(); for (a = 0; a < vsArgs.size(); a++) { @@ -536,49 +478,39 @@ bool CWebAdminSock::ChanPage(CString& sPageRet, CChan* pChan) { } if (!GetParam("submitted").ToUInt()) { - sPageRet = Header(CString((pChan) ? "Edit" : "Add") + " Channel" + CString((pChan) ? (" [" + pChan->GetName() + "]") : "") + " for User [" + m_pUser->GetUserName() + "]"); - sPageRet += "
\r\n" - "\r\n" - "\r\n"; if (pChan) { - sPageRet += "\r\n"; - } + m_Template["Edit"] = "true"; + m_Template["Title"] = "Edit Channel" + CString(" [" + pChan->GetName() + "]"); + m_Template["ChanName"] = pChan->GetName(); + m_Template["BufferCount"] = CString::ToString(pChan->GetBufferCount()); + m_Template["DefModes"] = pChan->GetDefaultModes(); - sPageRet += "
Channel Info
\r\n" - "\r\n" - "\r\n" - "\r\n"; + if (pChan->InConfig()) { + m_Template["InConfig"] = "true"; + } } else { - sPageRet += "\r\n"; + m_Template["Title"] = "Add Channel" + CString(" for User [" + m_pUser->GetUserName() + "]"); + m_Template["BufferCount"] = "50"; + m_Template["DefModes"] = "+stn"; + m_Template["InConfig"] = "true"; } - sPageRet += "\r\n" + CTemplate& o1 = m_Template.AddRow("OptionLoop"); + o1["Name"] = "autocycle"; + o1["DisplayName"] = "Auto Cycle"; + if (!pChan || pChan->AutoCycle()) { o1["Checked"] = "true"; } - "\r\n" - "\r\n" + CTemplate& o2 = m_Template.AddRow("OptionLoop"); + o2["Name"] = "keepbuffer"; + o2["DisplayName"] = "Keep Buffer"; + if (!pChan || pChan->KeepBuffer()) { o2["Checked"] = "true"; } - "\r\n" - "\r\n" + CTemplate& o3 = m_Template.AddRow("OptionLoop"); + o3["Name"] = "detached"; + o3["DisplayName"] = "Detached"; + if (pChan && pChan->IsDetached()) { o3["Checked"] = "true"; } - "\r\n" - "\r\n" - "
Channel Name:
\r\n"; - - if (pChan) { - sPageRet += "" + pChan->GetName().Escape_n(CString::EHTML) + "
Buffer Count:
\r\n" - "
Default Modes:
\r\n" - "
Save:
\r\n" - "InConfig()) ? " CHECKED" : "") + ">
Options:
\r\n" - "AutoCycle()) ? " CHECKED" : "") + ">\r\n" - "KeepBuffer()) ? " CHECKED" : "") + ">\r\n" - "IsDetached()) ? " CHECKED" : "") + ">\r\n" - "
\r\n" - "


\r\n" - - "\r\n" - "
\r\n"; - - sPageRet += Footer(); + PrintPage(sPageRet, "Channel.tmpl"); return true; } @@ -653,199 +585,146 @@ bool CWebAdminSock::DelChan(CString& sPageRet) { bool CWebAdminSock::UserPage(CString& sPageRet, CUser* pUser) { if (!GetParam("submitted").ToUInt()) { - sPageRet = Header((pUser) ? CString("Edit User [" + pUser->GetUserName() + "]") : CString("Add User")); - CString sAllowedHosts, sServers, sChans, sCTCPReplies; if (pUser) { + m_Template["Title"] = "Edit User [" + pUser->GetUserName() + "]"; + m_Template["Edit"] = "true"; + m_Template["Username"] = pUser->GetUserName(); + m_Template["Nick"] = pUser->GetNick(); + m_Template["AltNick"] = pUser->GetAltNick(); + m_Template["AwaySuffix"] = pUser->GetAwaySuffix(); + m_Template["StatusPrefix"] = pUser->GetStatusPrefix(); + m_Template["Ident"] = pUser->GetIdent(); + m_Template["RealName"] = pUser->GetRealName(); + m_Template["QuitMsg"] = pUser->GetQuitMsg(); + m_Template["DefaultChanModes"] = pUser->GetDefaultChanModes(); + m_Template["BufferCount"] = CString::ToString(pUser->GetBufferCount()); + const set& ssAllowedHosts = pUser->GetAllowedHosts(); for (set::const_iterator it = ssAllowedHosts.begin(); it != ssAllowedHosts.end(); it++) { - sAllowedHosts += *it + "\r\n"; + CTemplate& l = m_Template.AddRow("AllowedHostLoop"); + l["Host"] = *it; } const vector& vServers = pUser->GetServers(); for (unsigned int a = 0; a < vServers.size(); a++) { - sServers += vServers[a]->GetString() + "\r\n"; + CTemplate& l = m_Template.AddRow("ServerLoop"); + l["Server"] = vServers[a]->GetString(); } - const vector& vChans = pUser->GetChans(); - for (unsigned int b = 0; b < vChans.size(); b++) { - CChan* pChan = vChans[b]; - - if (pChan->InConfig()) { - sChans += vChans[b]->GetName() + "\r\n"; - } - } const MCString& msCTCPReplies = pUser->GetCTCPReplies(); for (MCString::const_iterator it2 = msCTCPReplies.begin(); it2 != msCTCPReplies.end(); it2++) { - sCTCPReplies += it2->first + " " + it2->second + "\r\n"; + CTemplate& l = m_Template.AddRow("CTCPLoop"); + l["CTCP"] = it2->first + " " + it2->second; } - } - sPageRet += "
\r\n"; + if (pUser == CZNC::Get().FindUser(GetUser())) { + CString sIP = GetRemoteIP(); - sPageRet += "\r\n" - "
Authentication
\r\n" - "
Username:
\r\n"; + if (!sIP.empty()) { + m_Template["OwnIP"] = sIP.Token(0, false, ".") + "." + sIP.Token(1, false, ".") + "." + sIP.Token(2, false, ".") + ".*"; + } + } - if (pUser) { - sPageRet += "\r\n" - "
\r\n"; + const VCString& vsVHosts = CZNC::Get().GetVHosts(); + for (unsigned int b = 0; b < vsVHosts.size(); b++) { + const CString& sVHost = vsVHosts[b]; + CTemplate& l = m_Template.AddRow("VHostLoop"); + + l["VHost"] = sVHost; + + if (pUser && pUser->GetVHost() == sVHost) { + l["Checked"] = "true"; + } + } + + const vector& Channels = pUser->GetChans(); + for (unsigned int c = 0; c < Channels.size(); c++) { + CChan* pChan = Channels[c]; + CTemplate& l = m_Template.AddRow("ChannelLoop"); + + l["Username"] = pUser->GetUserName(); + l["Name"] = pChan->GetName(); + l["Perms"] = pChan->GetPermStr(); + l["CurModes"] = pChan->GetModeString(); + l["DefModes"] = pChan->GetDefaultModes(); + l["BufferCount"] = CString::ToString(pChan->GetBufferCount()); + l["Options"] = pChan->GetOptions(); + + if (pChan->InConfig()) { + l["InConfig"] = "true"; + } + } } else { - sPageRet += "
\r\n"; + m_Template["Title"] = "Add User"; + m_Template["AwaySuffix"] = "*"; } - CString sIP = GetRemoteIP(); - - sIP = sIP.Token(0, false, ".") + "." + sIP.Token(1, false, ".") + "." + sIP.Token(2, false, ".") + ".*"; - - sPageRet += "Password:

\r\n" - "Confirm Password:


\r\n" - "
Allowed IPs:

\r\n"; - - if (pUser && pUser == CZNC::Get().FindUser(GetUser())) { - sPageRet += "  \r\n"; - } - - sPageRet += "



\r\n" - - "
IRC Information
\r\n" - "
Nick:
\r\n" - "
\r\n" - "
AltNick:
\r\n" - "
\r\n" - "
AwaySuffix:
\r\n" - "
\r\n" - "
StatusPrefix:
\r\n" - "

\r\n" - "
Ident:
\r\n" - "
\r\n" - "
RealName:
\r\n" - "

\r\n"; - - const VCString& vsVHosts = CZNC::Get().GetVHosts(); - - if (vsVHosts.size()) { - sPageRet += "VHost:
\r\n" - "

\r\n"; - } - - sPageRet += "QuitMsg:
\r\n" - "

\r\n" - "
Servers:
\r\n" - "
\r\n" - "


\r\n" - - "
Modules
\r\n" - "\r\n" - "\r\n"; - set ssUserMods; CZNC::Get().GetModules().GetAvailableMods(ssUserMods); - unsigned int uIdx = 0; - for (set::iterator it = ssUserMods.begin(); it != ssUserMods.end(); it++) { const CModInfo& Info = *it; - sPageRet += ""; + CTemplate& l = m_Template.AddRow("ModuleLoop"); + + l["Name"] = Info.GetName(); + l["Description"] = Info.GetDescription(); + l["Args"] = GetModArgs(Info.GetName()); + + if (pUser && pUser->GetModules().FindModule(Info.GetName())) { + l["Checked"] = "true"; + } if (!IsAdmin() && pUser && pUser->DenyLoadMod()) { - CString sArgs = GetModArgs(Info.GetName()).Escape_n(CString::EHTML); - - if (sArgs.empty()) { - sArgs = " "; - } - - sPageRet += ""; - } else { - sPageRet += ""; + l["Disabled"] = "true"; } - - sPageRet += ""; } - sPageRet += "
NameArgumentsDescription
GetModules().FindModule(Info.GetName())) ? " CHECKED" : "") + CString((!IsAdmin() && pUser && pUser->DenyLoadMod()) ? " DISABLED" : "") + ">" + sArgs + "" + Info.GetDescription().Escape_n(CString::EHTML) + "



\r\n" - "
Channels
\r\n" - "Default Modes:
\r\n" - "

\r\n"; + CTemplate& o1 = m_Template.AddRow("OptionLoop"); + o1["Name"] = "keepbuffer"; + o1["DisplayName"] = "Keep Buffer"; + if (!pUser || pUser->KeepBuffer()) { o1["Checked"] = "true"; } - if (pUser) { - CString sURL = "/addchan?user=" + pUser->GetUserName().Escape_n(CString::EURL); + CTemplate& o2 = m_Template.AddRow("OptionLoop"); + o2["Name"] = "autocycle"; + o2["DisplayName"] = "Auto Cycle"; + if (!pUser || pUser->AutoCycle()) { o2["Checked"] = "true"; } - sPageRet += "\r\n" - "\r\n" - "\r\n"; + CTemplate& o3 = m_Template.AddRow("OptionLoop"); + o3["Name"] = "keepnick"; + o3["DisplayName"] = "Keep Nick"; + if (!pUser || pUser->GetKeepNick()) { o3["Checked"] = "true"; } - const vector& Channels = pUser->GetChans(); + CTemplate& o4 = m_Template.AddRow("OptionLoop"); + o4["Name"] = "multiclients"; + o4["DisplayName"] = "Multi Clients"; + if (!pUser || pUser->MultiClients()) { o4["Checked"] = "true"; } - if (!Channels.size()) { - sPageRet += "\r\n"; - } else { - sPageRet += "\r\n" - "\r\n" - "\r\n" - "\r\n" - "\r\n" - "\r\n"; - } + CTemplate& o5 = m_Template.AddRow("OptionLoop"); + o5["Name"] = "bouncedccs"; + o5["DisplayName"] = "Bounce DCCs"; + if (!pUser || pUser->BounceDCCs()) { o5["Checked"] = "true"; } - sPageRet += "\r\n"; - - for (unsigned int a = 0; a < Channels.size(); a++) { - CChan* pChan = Channels[a]; - CString sURL = "user=" + pUser->GetUserName().Escape_n(CString::EURL) + "&chan=" + pChan->GetName().Escape_n(CString::EURL); - - sPageRet += "" - "\r\n" - "\r\n" - "\r\n" - "\r\n" - "\r\n" - "\r\n" - "\r\n" - "\r\n"; - } - - sPageRet += "
[Add  <- Add a channel (opens in same page)  SaveNameCurModesDefModesBufferCountOptions
" - "\r\n" - "[Edit] [DelInConfig()) ? " CHECKED" : "") + "> " + CString(pChan->GetPermStr() + pChan->GetName()).Escape_n(CString::EHTML) + " " + pChan->GetModeString().Escape_n(CString::EHTML) + " " + pChan->GetDefaultModes().Escape_n(CString::EHTML) + " " + CString::ToString(pChan->GetBufferCount()) + " " + pChan->GetOptions().Escape_n(CString::EHTML) + " 
"; - } - - sPageRet += "


\r\n" - "
ZNC Behavior
\r\n" - "Playback Buffer Size:
\r\n" - "

\r\n" - "Options:
\r\n" - "KeepBuffer()) ? " CHECKED" : "") + ">  \r\n" - "AutoCycle()) ? " CHECKED" : "") + ">  \r\n" - "GetKeepNick()) ? " CHECKED" : "") + ">  \r\n" - "MultiClients()) ? " CHECKED" : "") + ">  \r\n" - "BounceDCCs()) ? " CHECKED" : "") + ">  \r\n" - "UseClientIP()) ? " CHECKED" : "") + ">  \r\n"; + CTemplate& o6 = m_Template.AddRow("OptionLoop"); + o6["Name"] = "useclientip"; + o6["DisplayName"] = "Use Client IP"; + if (pUser && pUser->UseClientIP()) { o6["Checked"] = "true"; } if (IsAdmin()) { - sPageRet += "DenyLoadMod()) ? " CHECKED" : "") + ">  \r\n"; + CTemplate& o7 = m_Template.AddRow("OptionLoop"); + o7["Name"] = "denyloadmod"; + o7["DisplayName"] = "Deny LoadMod"; + if (pUser && pUser->DenyLoadMod()) { o7["Checked"] = "true"; } + + CTemplate& o8 = m_Template.AddRow("OptionLoop"); + o8["Name"] = "isadmin"; + o8["DisplayName"] = "Admin"; + if (pUser && pUser->IsAdmin()) { o8["Checked"] = "true"; } + if (pUser && pUser == CZNC::Get().FindUser(GetUser())) { o8["Disabled"] = "true"; } } - if (IsAdmin()) { - sPageRet += "IsAdmin()) ? " CHECKED" : "") + CString((pUser && pUser == CZNC::Get().FindUser(GetUser())) ? " DISABLED" : "") + ">  \r\n"; - } - - sPageRet += "

" - "
CTCP Replies:
" - "
\r\n" - "


\r\n" - - "\r\n" - "
\r\n"; - - sPageRet += Footer(); + PrintPage(sPageRet, "UserPage.tmpl"); return true; }