mirror of
https://github.com/znc/znc.git
synced 2026-06-26 21:12:03 +02:00
Added CTemplate support which included upgrading String.cpp/h and FileUtils.cpp/h and fixing some issues
git-svn-id: https://znc.svn.sourceforge.net/svnroot/znc/trunk@603 726aef4b-f618-498e-8847-2d620e286838
This commit is contained in:
+34
-2
@@ -1,4 +1,12 @@
|
||||
#include "FileUtils.h"
|
||||
#include <iostream>
|
||||
|
||||
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; }
|
||||
|
||||
+12
-2
@@ -10,8 +10,6 @@
|
||||
#include <dirent.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "Utils.h"
|
||||
|
||||
#include "String.h"
|
||||
#include <vector>
|
||||
#include <map>
|
||||
@@ -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:
|
||||
|
||||
+2
-2
@@ -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);
|
||||
}
|
||||
|
||||
+2
-2
@@ -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@
|
||||
|
||||
|
||||
+185
-52
@@ -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;
|
||||
|
||||
@@ -1,22 +1,38 @@
|
||||
#ifndef X_STRING_H
|
||||
#define X_STRING_H
|
||||
|
||||
#ifdef USE_PCRE
|
||||
#include <pcre.h>
|
||||
#endif
|
||||
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
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<CString> VCString;
|
||||
typedef set<CString> SCString;
|
||||
typedef map<CString, VCString> MVCString;
|
||||
class MCString;
|
||||
|
||||
typedef set<CString> SCString;
|
||||
typedef vector<CString> VCString;
|
||||
typedef map<CString, VCString> MVCString;
|
||||
typedef vector<MCString> VMCString;
|
||||
typedef multimap<CString, CString> 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:
|
||||
|
||||
+446
@@ -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<CString, vector<CTemplate*> >::iterator it = m_mvLoops.begin(); it != m_mvLoops.end(); it++) {
|
||||
vector<CTemplate*>& 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<CTemplate*>* pvLoop = GetLoop(sName);
|
||||
|
||||
if (pvLoop) {
|
||||
if (pvLoop->size() > uIndex) {
|
||||
return (*pvLoop)[uIndex];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vector<CTemplate*>* CTemplate::GetLoop(const CString& sName) {
|
||||
CTemplateLoopContext* pContext = GetCurLoopContext();
|
||||
|
||||
if (pContext) {
|
||||
CTemplate* pTemplate = pContext->GetCurRow();
|
||||
|
||||
if (pTemplate) {
|
||||
return pTemplate->GetLoop(sName);
|
||||
}
|
||||
}
|
||||
|
||||
map<CString, vector<CTemplate*> >::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("<?");
|
||||
|
||||
if (iPos != CString::npos) {
|
||||
uCurPos += iPos;
|
||||
bFoundOneTag = 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) {
|
||||
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);
|
||||
|
||||
if (!uSkip) {
|
||||
if (sAction.CaseCmp("INC") == 0) {
|
||||
Print(File.GetDir() + sArgs, oOut);
|
||||
} else if (sAction.CaseCmp("ADDROW") == 0) {
|
||||
CString sLoopName = sArgs.Token(0);
|
||||
MCString msRow;
|
||||
|
||||
if (sArgs.Token(1).URLSplit(msRow)) {
|
||||
CTemplate& NewRow = AddRow(sLoopName);
|
||||
|
||||
for (MCString::iterator it = msRow.begin(); it != msRow.end(); it++) {
|
||||
NewRow[it->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<CTemplate*>* 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;
|
||||
}
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
#ifndef _TEMPLATE_H
|
||||
#define _TEMPLATE_H
|
||||
|
||||
#include "FileUtils.h"
|
||||
#include <iostream>
|
||||
|
||||
using std::ostream;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
class CTemplate;
|
||||
|
||||
class CTemplateLoopContext {
|
||||
public:
|
||||
CTemplateLoopContext(unsigned long uFilePos, const CString& sLoopName, vector<CTemplate*>* 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<CTemplate*>* 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 <?LOOP name?> tag
|
||||
unsigned int m_uRowIndex; //! The index of the current row we're on
|
||||
unsigned long m_uFilePosition; //! The file position of the opening <?LOOP?> tag
|
||||
vector<CTemplate*>* 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<CTemplate*>* 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<CString, vector<CTemplate*> > m_mvLoops;
|
||||
vector<CTemplateLoopContext*> m_vLoopContexts;
|
||||
};
|
||||
|
||||
#endif // !_TEMPLATE_H
|
||||
|
||||
+1
-1
@@ -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();
|
||||
}
|
||||
|
||||
+189
-310
@@ -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 += "<h2>" + sError.Escape_n(CString::EHTML) + "</h2>\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<CString, VCString>& msvsParams = GetParams();
|
||||
|
||||
sPageRet = Header("fooooooo");
|
||||
|
||||
if (msvsParams.empty()) {
|
||||
sPageRet += "You passed in no params.\r\n";
|
||||
} else {
|
||||
sPageRet += "foo [" + GetParamString().Escape_n(CString::EHTML) + "]<br><br>";
|
||||
|
||||
for (map<CString, VCString>::const_iterator it = msvsParams.begin(); it != msvsParams.end(); it++) {
|
||||
sPageRet += "<h2>" + it->first + "</h2>\r\n<ul>\r\n";
|
||||
const VCString vsParams = it->second;
|
||||
|
||||
for (unsigned int a = 0; a < vsParams.size(); a++) {
|
||||
sPageRet += "<li>[" + vsParams[a] + "]</li>\r\n";
|
||||
}
|
||||
|
||||
sPageRet += "</ul>\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<CWebAdminSock*> m_sSocks;
|
||||
};
|
||||
|
||||
CString CWebAdminSock::Header(const CString& sTitle) {
|
||||
CString sRet = "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n"
|
||||
"<html>\r\n<head><title>ZNC - " + sTitle.Escape_n(CString::EHTML) + "</title></head>\r\n"
|
||||
"<body bgcolor='#FFFFFF' text='#000000' link='#000000' alink='#000000' vlink='#000000'>\r\n"
|
||||
"<table border='0' cellpadding='10' cellspacing='0' height='100%' width='100%'>\r\n"
|
||||
"<tr><td style='border-bottom: 2px solid #000;' colspan='2' valign='top'>"
|
||||
"<table border='0' cellpadding='0' cellspacing='0' width='100%'><tr>"
|
||||
"<td width='200'> </td>"
|
||||
"<td align='center'><h2 style='white-space: nowrap;'>" + sTitle.Escape_n(CString::EHTML) + "</h2></td>"
|
||||
"<td align='right' width='200'><b>" + GetUser().Escape_n(CString::EHTML) + "@" + GetRemoteIP().Escape_n(CString::EHTML) + "</b></td>"
|
||||
"</tr></table>"
|
||||
"</td></tr>\r\n"
|
||||
"<tr><td style='white-space: nowrap; border-right: 1px solid #000;' valign='top'>\r\n";
|
||||
void CWebAdminSock::PrintPage(CString& sPageRet, const CString& sTmplName) {
|
||||
sPageRet.clear();
|
||||
CString sModPath = CZNC::Get().FindModPath(m_pModule->GetModName());
|
||||
|
||||
if (IsAdmin()) {
|
||||
sRet += "[<a href='/'>Home</a>]<br>\r\n"
|
||||
"[<a href='/settings'>Settings</a>]<br>\r\n"
|
||||
"[<a href='/adduser'>Add User</a>]<br>\r\n"
|
||||
"[<a href='/listusers'>List Users</a>]<br>\r\n";
|
||||
while (!sModPath.empty() && sModPath.Right(1) != "/") {
|
||||
sModPath.RightChomp();
|
||||
}
|
||||
|
||||
sRet += "</td><td height='100%' width='100%' valign='top'>\r\n";
|
||||
if (!m_Template.SetFile(sModPath + "/webadmin/" + sTmplName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
return sRet;
|
||||
}
|
||||
stringstream oStr;
|
||||
m_Template.Print(oStr);
|
||||
|
||||
CString CWebAdminSock::Footer() {
|
||||
return "</td></tr><tr><td colspan='2' align='right' valign='bottom'>" + CZNC::Get().GetTag().Escape_n(CString::EHTML) + "</td></tr>\r\n"
|
||||
"</table></body>\r\n</html>\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<CString,CUser*>& msUsers = CZNC::Get().GetUserMap();
|
||||
sPageRet = Header("List Users");
|
||||
m_Template["Title"] = "List Users";
|
||||
|
||||
if (!msUsers.size()) {
|
||||
sPageRet += "There are no users defined. Click <a href=\"/adduser\">here</a> if you would like to add one.\r\n";
|
||||
} else {
|
||||
sPageRet += "<table style='border: 1px solid #000;' cellspacing='0' cellpadding='4'>\r\n"
|
||||
"\t<thead><tr bgcolor='#FFFF99'><td style='border: 1px solid #000;'><b>Action</b></td><td style='border: 1px solid #000;'><b>Username</b></td><td style='border: 1px solid #000;'><b>Current Server</b></td></tr></thead>\r\n";
|
||||
unsigned int a = 0;
|
||||
|
||||
unsigned int a = 0;
|
||||
|
||||
for (map<CString,CUser*>::const_iterator it = msUsers.begin(); it != msUsers.end(); it++, a++) {
|
||||
CServer* pServer = it->second->GetCurrentServer();
|
||||
sPageRet += "\t<tr bgcolor='" + CString((a %2) ? "#FFFFCC" : "#CCCC99") + "'>\r\n\t\t<td style='border: 1px solid #000;'>[<a href=\"/edituser?user=" + it->second->GetUserName().Escape_n(CString::EURL) + "\">Edit</a>] [<a href=\"/deluser?user=" + it->second->GetUserName().Escape_n(CString::EURL) + "\">Delete</a>]</td>\r\n"
|
||||
"\t\t<td style='border: 1px solid #000;'>" + it->second->GetUserName().Escape_n(CString::EHTML) + "</td>\r\n"
|
||||
"\t\t<td style='border: 1px solid #000;'>" + CString((pServer) ? pServer->GetName().Escape_n(CString::EHTML) : "-N/A-") + "</td>\r\n"
|
||||
"\t</tr>";
|
||||
for (map<CString,CUser*>::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</table>\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 += "<br><form action='/settings' method='POST'>\r\n"
|
||||
"<input type='hidden' name='submitted' value='1'>\r\n"
|
||||
"<div style='white-space: nowrap; margin-top: -8px; margin-right: 8px; margin-left: 8px; padding: 1px 5px 1px 5px; float: left; border: 1px solid #000; font-size: 16px; font-weight: bold; background: #ff9;'>Global Settings</div><div style='padding: 25px 5px 5px 15px; border: 2px solid #000; background: #cc9;'><div style='clear: both;'>\r\n"
|
||||
|
||||
"<div><small><b>Status Prefix:</b></small><br>\r\n"
|
||||
"<input type='text' name='statusprefix' value='" + CZNC::Get().GetStatusPrefix().Escape_n(CString::EHTML) + "' size='32' maxlength='128'></div><br>\r\n"
|
||||
|
||||
"<div style='float: left; margin-right: 10px;'><small><b>ISpoofFile:</b></small><br>\r\n"
|
||||
"<input type='text' name='ispooffile' value='" + CZNC::Get().GetISpoofFile().Escape_n(CString::EHTML) + "' size='32' maxlength='128'></div>\r\n"
|
||||
"<div><small><b>ISpoofFormat:</b></small><br>\r\n"
|
||||
"<input type='text' name='ispoofformat' value='" + CZNC::Get().GetISpoofFormat().Escape_n(CString::EHTML) + "' size='32' maxlength='128'></div>\r\n"
|
||||
|
||||
"<br><div><small><b>MOTD:</b></small><br>\r\n"
|
||||
"<textarea name='motd' cols='80' rows='5'>" + sMotd.Escape_n(CString::EHTML) + "</textarea></div>\r\n"
|
||||
|
||||
"<br><div><small><b>VHosts:</b></small><br>\r\n"
|
||||
"<textarea name='vhosts' cols='40' rows='5'>" + sVHosts.Escape_n(CString::EHTML) + "</textarea></div>\r\n"
|
||||
|
||||
"<br></div></div><br><br>\r\n"
|
||||
|
||||
"<div style='white-space: nowrap; margin-top: -8px; margin-right: 8px; margin-left: 8px; padding: 1px 5px 1px 5px; float: left; border: 1px solid #000; font-size: 16px; font-weight: bold; background: #ff9;'>Global Modules</div><div style='padding: 25px 5px 5px 15px; border: 2px solid #000; background: #cc9;'><div style='clear: both;'>\r\n"
|
||||
"<table cellspacing='0' cellpadding='3' style='border: 1px solid #000;'>\r\n"
|
||||
"<tr style='font-weight: bold; background: #ff9;'><td style='border: 1px solid #000;'>Name</td><td style='border: 1px solid #000;'>Arguments</td><td style='border: 1px solid #000;'>Description</td></tr>\r\n";
|
||||
|
||||
set<CModInfo> ssGlobalMods;
|
||||
CZNC::Get().GetModules().GetAvailableMods(ssGlobalMods, true);
|
||||
|
||||
unsigned int uIdx = 0;
|
||||
|
||||
for (set<CModInfo>::iterator it = ssGlobalMods.begin(); it != ssGlobalMods.end(); it++) {
|
||||
const CModInfo& Info = *it;
|
||||
sPageRet += "<tr style='background: " + CString((uIdx++ %2) ? "#ffc" : "#cc9") + "'><td style='border: 1px solid #000;'><input type='checkbox' name='loadmod' id='lm_" + Info.GetName().Escape_n(CString::EHTML) + "' value='" + Info.GetName().Escape_n(CString::EHTML) + "'" + CString((CZNC::Get().GetModules().FindModule(Info.GetName())) ? " CHECKED" : "") + CString((Info.GetName() == m_pModule->GetModName()) ? " DISABLED" : "") + "><label for='lm_" + Info.GetName().Escape_n(CString::EHTML) + "'> " + Info.GetName().Escape_n(CString::EHTML) + "</label></td>"
|
||||
"<td style='border: 1px solid #000;'><input type='text' name='modargs_" + Info.GetName().Escape_n(CString::EHTML) + "' value='" + GetModArgs(Info.GetName(), true) + "'" + CString((Info.GetName() == m_pModule->GetModName()) ? " DISABLED" : "") + "></td>"
|
||||
"<td style='border: 1px solid #000;'>" + Info.GetDescription().Escape_n(CString::EHTML) + "</td></tr>";
|
||||
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 += "</table><br></div></div><br><br>\r\n"
|
||||
"<input type='submit' value='Submit'>\r\n"
|
||||
"</form>\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 += "<br><form action='" + CString((pChan) ? "/editchan" : "/addchan") + "' method='POST'>\r\n"
|
||||
"<input type='hidden' name='submitted' value='1'>\r\n"
|
||||
"<input type='hidden' name='user' value='" + m_pUser->GetUserName().Escape_n(CString::EHTML) + "'>\r\n";
|
||||
if (pChan) {
|
||||
sPageRet += "<input type='hidden' name='chan' value='" + pChan->GetName().Escape_n(CString::EHTML) + "'>\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 += "<div style='white-space: nowrap; margin-top: -8px; margin-right: 8px; margin-left: 8px; padding: 1px 5px 1px 5px; float: left; border: 1px solid #000; font-size: 16px; font-weight: bold; background: #ff9;'>Channel Info</div><div style='padding: 25px 5px 5px 15px; border: 2px solid #000; background: #cc9;'><div style='clear: both;'>\r\n"
|
||||
"<table border='0' cellpadding='12' cellspacing='0'>\r\n"
|
||||
"<tr>\r\n"
|
||||
"<td><small><b>Channel Name:</b></small><br>\r\n";
|
||||
|
||||
if (pChan) {
|
||||
sPageRet += "<input type='hidden' name='name' value='" + pChan->GetName().Escape_n(CString::EHTML) + "'>" + pChan->GetName().Escape_n(CString::EHTML) + "</td>\r\n";
|
||||
if (pChan->InConfig()) {
|
||||
m_Template["InConfig"] = "true";
|
||||
}
|
||||
} else {
|
||||
sPageRet += "<input type='text' name='name' value='' size='32'></td>\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 += "<td><small><b>Buffer Count:</b></small><br>\r\n"
|
||||
"<input type='text' name='buffercount' value='" + CString((pChan) ? CString::ToString(pChan->GetBufferCount()) : "50") + "' size='8'></td>\r\n"
|
||||
CTemplate& o1 = m_Template.AddRow("OptionLoop");
|
||||
o1["Name"] = "autocycle";
|
||||
o1["DisplayName"] = "Auto Cycle";
|
||||
if (!pChan || pChan->AutoCycle()) { o1["Checked"] = "true"; }
|
||||
|
||||
"<td><small><b>Default Modes:</b></small><br>\r\n"
|
||||
"<input type='text' name='defmodes' value='" + CString((pChan) ? pChan->GetDefaultModes().Escape_n(CString::EHTML) : "+stn") + "' size='16'></td>\r\n"
|
||||
"</tr>\r\n"
|
||||
CTemplate& o2 = m_Template.AddRow("OptionLoop");
|
||||
o2["Name"] = "keepbuffer";
|
||||
o2["DisplayName"] = "Keep Buffer";
|
||||
if (!pChan || pChan->KeepBuffer()) { o2["Checked"] = "true"; }
|
||||
|
||||
"<tr>\r\n"
|
||||
"<td><small><b>Save:</b></small><br>\r\n"
|
||||
"<input type='checkbox' name='save' id='save' value='true'" + CString((!pChan || pChan->InConfig()) ? " CHECKED" : "") + "><label for='save'> Save to config</label></td>\r\n"
|
||||
CTemplate& o3 = m_Template.AddRow("OptionLoop");
|
||||
o3["Name"] = "detached";
|
||||
o3["DisplayName"] = "Detached";
|
||||
if (pChan && pChan->IsDetached()) { o3["Checked"] = "true"; }
|
||||
|
||||
"<td colspan='2'><small><b>Options:</b></small><br>\r\n"
|
||||
"<input type='checkbox' name='autocycle' id='autocycle' value='true'" + CString((!pChan || pChan->AutoCycle()) ? " CHECKED" : "") + "><label for='autocycle'> AutoCycle</label>\r\n"
|
||||
"<input type='checkbox' name='keepbuffer' id='keepbuffer' value='true'" + CString((!pChan || pChan->KeepBuffer()) ? " CHECKED" : "") + "><label for='keepbuffer'> KeepBuffer</label>\r\n"
|
||||
"<input type='checkbox' name='detached' id='detached' value='true'" + CString((pChan && pChan->IsDetached()) ? " CHECKED" : "") + "><label for='detached'> Detached</label>\r\n"
|
||||
"</td>\r\n"
|
||||
"</tr>\r\n"
|
||||
"</table>\r\n"
|
||||
"</div></div><br><br>\r\n"
|
||||
|
||||
"<input type='submit' value='" + CString((pChan) ? "Save" : "Add Channel") + "'>\r\n"
|
||||
"</form>\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<CString>& ssAllowedHosts = pUser->GetAllowedHosts();
|
||||
for (set<CString>::const_iterator it = ssAllowedHosts.begin(); it != ssAllowedHosts.end(); it++) {
|
||||
sAllowedHosts += *it + "\r\n";
|
||||
CTemplate& l = m_Template.AddRow("AllowedHostLoop");
|
||||
l["Host"] = *it;
|
||||
}
|
||||
|
||||
const vector<CServer*>& 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<CChan*>& 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 += "<br><form action='/" + CString((pUser) ? "edituser" : "adduser") + "' method='POST'>\r\n";
|
||||
if (pUser == CZNC::Get().FindUser(GetUser())) {
|
||||
CString sIP = GetRemoteIP();
|
||||
|
||||
sPageRet += "<input type='hidden' name='submitted' value='1'>\r\n"
|
||||
"<div style='white-space: nowrap; margin-top: -8px; margin-right: 8px; margin-left: 8px; padding: 1px 5px 1px 5px; float: left; border: 1px solid #000; font-size: 16px; font-weight: bold; background: #ff9;'>Authentication</div><div style='padding: 25px 5px 5px 15px; border: 2px solid #000; background: #cc9;'><div style='clear: both;'>\r\n"
|
||||
"<div style='float: left; margin-right: 20px;'><small><b>Username:</b></small><br>\r\n";
|
||||
if (!sIP.empty()) {
|
||||
m_Template["OwnIP"] = sIP.Token(0, false, ".") + "." + sIP.Token(1, false, ".") + "." + sIP.Token(2, false, ".") + ".*";
|
||||
}
|
||||
}
|
||||
|
||||
if (pUser) {
|
||||
sPageRet += "<input type='hidden' name='user' value='" + pUser->GetUserName().Escape_n(CString::EHTML) + "'>\r\n"
|
||||
"<input type='text' name='newuser' value='" + pUser->GetUserName().Escape_n(CString::EHTML) + "' size='32' maxlength='12' DISABLED><br>\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<CChan*>& 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 += "<input type='text' name='user' value='' size='32' maxlength='12'><br>\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 += "<small><b>Password:</b></small><br><input type='password' name='password' size='32' maxlength='16'><br>\r\n"
|
||||
"<small><b>Confirm Password:</b></small><br><input type='password' name='password2' size='32' maxlength='16'><br><br></div>\r\n"
|
||||
"<div><small><b>Allowed IPs:</b></small><br><textarea name='allowedips' cols='40' rows='5'>" + sAllowedHosts.Escape_n(CString::EHTML) + "</textarea><br>\r\n";
|
||||
|
||||
if (pUser && pUser == CZNC::Get().FindUser(GetUser())) {
|
||||
sPageRet += "<span style='white-space: nowrap;'><input type='checkbox' name='ownip' id='ownip' value='" + sIP.Escape_n(CString::EHTML) + "' CHECKED><label for='ownip'> " + sIP.Escape_n(CString::EHTML) + " (your current ip)</label></span> \r\n";
|
||||
}
|
||||
|
||||
sPageRet += "</div><br></div></div><br><br>\r\n"
|
||||
|
||||
"<div style='white-space: nowrap; margin-top: -8px; margin-right: 8px; margin-left: 8px; padding: 1px 5px 1px 5px; float: left; border: 1px solid #000; font-size: 16px; font-weight: bold; background: #ff9;'>IRC Information</div><div style='padding: 25px 5px 5px 15px; border: 2px solid #000; background: #cc9;'><div style='clear: both;'>\r\n"
|
||||
"<div style='float: left; margin-right: 10px;'><small><b>Nick:</b></small><br>\r\n"
|
||||
"<input type='text' name='nick' value='" + CString((pUser) ? pUser->GetNick().Escape_n(CString::EHTML) : "") + "' size='22' maxlength='128'></div>\r\n"
|
||||
"<div style='float: left; margin-right: 10px;'><small><b>AltNick:</b></small><br>\r\n"
|
||||
"<input type='text' name='altnick' value='" + CString((pUser) ? pUser->GetAltNick().Escape_n(CString::EHTML) : "") + "' size='22' maxlength='128'></div>\r\n"
|
||||
"<div style='float: left; margin-right: 10px;'><small><b>AwaySuffix:</b></small><br>\r\n"
|
||||
"<input type='text' name='awaysuffix' value='" + CString((pUser) ? pUser->GetAwaySuffix().Escape_n(CString::EHTML) : "") + "' size='18' maxlength='128'></div>\r\n"
|
||||
"<div><small><b>StatusPrefix:</b></small><br>\r\n"
|
||||
"<input type='text' name='statusprefix' value='" + CString((pUser) ? pUser->GetStatusPrefix().Escape_n(CString::EHTML) : "*") + "' size='16' maxlength='5'></div><br>\r\n"
|
||||
"<div style='float: left; margin-right: 10px;'><small><b>Ident:</b></small><br>\r\n"
|
||||
"<input type='text' name='ident' value='" + CString((pUser) ? pUser->GetIdent().Escape_n(CString::EHTML) : "") + "' size='22' maxlength='128'></div>\r\n"
|
||||
"<div><small><b>RealName:</b></small><br>\r\n"
|
||||
"<input type='text' name='realname' value='" + CString((pUser) ? pUser->GetRealName().Escape_n(CString::EHTML) : "") + "' size='68' maxlength='256'></div><br>\r\n";
|
||||
|
||||
const VCString& vsVHosts = CZNC::Get().GetVHosts();
|
||||
|
||||
if (vsVHosts.size()) {
|
||||
sPageRet += "<small><b>VHost:</b></small><br>\r\n"
|
||||
"<select name='vhost'>\r\n<option value=''>- None -</option>\r\n";
|
||||
|
||||
for (unsigned int a = 0; a < vsVHosts.size(); a++) {
|
||||
sPageRet += "<option value='" + vsVHosts[a].Escape_n(CString::EHTML) + "'" + CString((pUser && pUser->GetVHost() == vsVHosts[a]) ? " SELECTED" : "") + ">" + vsVHosts[a].Escape_n(CString::EHTML) + "</option>\r\n";
|
||||
}
|
||||
|
||||
sPageRet += "</select><br><br>\r\n";
|
||||
}
|
||||
|
||||
sPageRet += "<small><b>QuitMsg:</b></small><br>\r\n"
|
||||
"<input type='text' name='quitmsg' value='" + CString((pUser) ? pUser->GetQuitMsg().Escape_n(CString::EHTML) : "") + "' size='96' maxlength='256'><br><br>\r\n"
|
||||
"<div><small><b>Servers:</b></small><br>\r\n"
|
||||
"<textarea name='servers' cols='40' rows='5'>" + sServers.Escape_n(CString::EHTML) + "</textarea></div>\r\n"
|
||||
"<br></div></div><br><br>\r\n"
|
||||
|
||||
"<div style='white-space: nowrap; margin-top: -8px; margin-right: 8px; margin-left: 8px; padding: 1px 5px 1px 5px; float: left; border: 1px solid #000; font-size: 16px; font-weight: bold; background: #ff9;'>Modules</div><div style='padding: 25px 5px 5px 15px; border: 2px solid #000; background: #cc9;'><div style='clear: both;'>\r\n"
|
||||
"<table cellspacing='0' cellpadding='3' style='border: 1px solid #000;'>\r\n"
|
||||
"<tr style='font-weight: bold; background: #ff9;'><td style='border: 1px solid #000;'>Name</td><td style='border: 1px solid #000;'>Arguments</td><td style='border: 1px solid #000;'>Description</td></tr>\r\n";
|
||||
|
||||
set<CModInfo> ssUserMods;
|
||||
CZNC::Get().GetModules().GetAvailableMods(ssUserMods);
|
||||
|
||||
unsigned int uIdx = 0;
|
||||
|
||||
for (set<CModInfo>::iterator it = ssUserMods.begin(); it != ssUserMods.end(); it++) {
|
||||
const CModInfo& Info = *it;
|
||||
sPageRet += "<tr style='background: " + CString((uIdx++ %2) ? "#ffc" : "#cc9") + ";'><td style='border: 1px solid #000;'><input type='checkbox' name='loadmod' id='lm_" + Info.GetName().Escape_n(CString::EHTML) + "' value='" + Info.GetName().Escape_n(CString::EHTML) + "'" + CString((pUser && pUser->GetModules().FindModule(Info.GetName())) ? " CHECKED" : "") + CString((!IsAdmin() && pUser && pUser->DenyLoadMod()) ? " DISABLED" : "") + "><label for='lm_" + Info.GetName().Escape_n(CString::EHTML) + "'> " + Info.GetName().Escape_n(CString::EHTML) + "</label></td>";
|
||||
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 += "<td style='border: 1px solid #000;'>" + sArgs + "</td>";
|
||||
} else {
|
||||
sPageRet += "<td style='border: 1px solid #000;'><input type='text' name='modargs_" + Info.GetName().Escape_n(CString::EHTML) + "' value='" + GetModArgs(Info.GetName()).Escape_n(CString::EHTML) + "'></td>";
|
||||
l["Disabled"] = "true";
|
||||
}
|
||||
|
||||
sPageRet += "<td style='border: 1px solid #000;'>" + Info.GetDescription().Escape_n(CString::EHTML) + "</td></tr>";
|
||||
}
|
||||
|
||||
sPageRet += "</table><br></div></div><br><br>\r\n"
|
||||
"<div style='white-space: nowrap; margin-top: -8px; margin-right: 8px; margin-left: 8px; padding: 1px 5px 1px 5px; float: left; border: 1px solid #000; font-size: 16px; font-weight: bold; background: #ff9;'>Channels</div><div style='padding: 25px 5px 5px 15px; border: 2px solid #000; background: #cc9;'><div style='clear: both;'>\r\n"
|
||||
"<small><b>Default Modes:</b></small><br>\r\n"
|
||||
"<input type='text' name='chanmodes' value='" + CString((pUser) ? pUser->GetDefaultChanModes().Escape_n(CString::EHTML) : "") + "' size='32' maxlength='32'><br><br>\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 += "<table cellspacing='0' cellpadding='3' style='border: 1px solid #000;'>\r\n"
|
||||
"<tr style='font-weight: bold; background: #ff9;'>\r\n"
|
||||
"<td style='border: 1px solid #000;'>[<a href='" + sURL.Escape_n(CString::EHTML) + "'>Add</a>] </td>\r\n";
|
||||
CTemplate& o3 = m_Template.AddRow("OptionLoop");
|
||||
o3["Name"] = "keepnick";
|
||||
o3["DisplayName"] = "Keep Nick";
|
||||
if (!pUser || pUser->GetKeepNick()) { o3["Checked"] = "true"; }
|
||||
|
||||
const vector<CChan*>& 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 += "<td style='border: 1px solid #000;'> <- Add a channel (opens in same page) </td>\r\n";
|
||||
} else {
|
||||
sPageRet += "<td style='border: 1px solid #000;'>Save</td>\r\n"
|
||||
"<td style='border: 1px solid #000;'>Name</td>\r\n"
|
||||
"<td style='border: 1px solid #000;'>CurModes</td>\r\n"
|
||||
"<td style='border: 1px solid #000;'>DefModes</td>\r\n"
|
||||
"<td style='border: 1px solid #000;'>BufferCount</td>\r\n"
|
||||
"<td style='border: 1px solid #000;'>Options</td>\r\n";
|
||||
}
|
||||
CTemplate& o5 = m_Template.AddRow("OptionLoop");
|
||||
o5["Name"] = "bouncedccs";
|
||||
o5["DisplayName"] = "Bounce DCCs";
|
||||
if (!pUser || pUser->BounceDCCs()) { o5["Checked"] = "true"; }
|
||||
|
||||
sPageRet += "</tr>\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 += "<tr style='background: " + CString((a %2) ? "#ffc" : "#cc9") + ";'>"
|
||||
"<td style='border: 1px solid #000;'>"
|
||||
"<input type='hidden' name='channel' value='" + pChan->GetName().Escape_n(CString::EHTML) + "'>\r\n"
|
||||
"[<a href='/editchan?" + sURL.Escape_n(CString::EHTML) + "'>Edit</a>] [<a href='/delchan?" + sURL.Escape_n(CString::EHTML) + "'>Del</a>] </td>\r\n"
|
||||
"<td style='border: 1px solid #000;'><input type='checkbox' name='save_" + pChan->GetName().Escape_n(CString::EHTML) + "'" + CString((pChan->InConfig()) ? " CHECKED" : "") + "> </td>\r\n"
|
||||
"<td style='border: 1px solid #000;'>" + CString(pChan->GetPermStr() + pChan->GetName()).Escape_n(CString::EHTML) + " </td>\r\n"
|
||||
"<td style='border: 1px solid #000;'>" + pChan->GetModeString().Escape_n(CString::EHTML) + " </td>\r\n"
|
||||
"<td style='border: 1px solid #000;'>" + pChan->GetDefaultModes().Escape_n(CString::EHTML) + " </td>\r\n"
|
||||
"<td style='border: 1px solid #000;'>" + CString::ToString(pChan->GetBufferCount()) + " </td>\r\n"
|
||||
"<td style='border: 1px solid #000;'>" + pChan->GetOptions().Escape_n(CString::EHTML) + " </td>\r\n"
|
||||
"</tr>\r\n";
|
||||
}
|
||||
|
||||
sPageRet += "</table>";
|
||||
}
|
||||
|
||||
sPageRet += "<br></div></div><br><br>\r\n"
|
||||
"<div style='white-space: nowrap; margin-top: -8px; margin-right: 8px; margin-left: 8px; padding: 1px 5px 1px 5px; float: left; border: 1px solid #000; font-size: 16px; font-weight: bold; background: #ff9;'>ZNC Behavior</div><div style='padding: 25px 5px 5px 15px; border: 2px solid #000; background: #cc9;'><div style='clear: both;'>\r\n"
|
||||
"<small><b>Playback Buffer Size:</b></small><br>\r\n"
|
||||
"<input type='text' name='bufsize' value='" + CString((pUser) ? CString::ToString(pUser->GetBufferCount()) : "") + "' size='32' maxlength='9'><br><br>\r\n"
|
||||
"<small><b>Options:</b></small><br>\r\n"
|
||||
"<span style='white-space: nowrap;'><input type='checkbox' name='keepbuffer' id='keepbuffer' value='1'" + CString((!pUser || pUser->KeepBuffer()) ? " CHECKED" : "") + "><label for='keepbuffer'>Keep Buffer</label></span> \r\n"
|
||||
"<span style='white-space: nowrap;'><input type='checkbox' name='autocycle' id='autocycle' value='1'" + CString((!pUser || pUser->AutoCycle()) ? " CHECKED" : "") + "><label for='autocycle'>Auto Cycle</label></span> \r\n"
|
||||
"<span style='white-space: nowrap;'><input type='checkbox' name='keepnick' id='keepnick' value='1'" + CString((!pUser || pUser->GetKeepNick()) ? " CHECKED" : "") + "><label for='keepnick'>Keep Nick</label></span> \r\n"
|
||||
"<span style='white-space: nowrap;'><input type='checkbox' name='multiclients' id='multiclients' value='1'" + CString((!pUser || pUser->MultiClients()) ? " CHECKED" : "") + "><label for='multiclients'>Multi Clients</label></span> \r\n"
|
||||
"<span style='white-space: nowrap;'><input type='checkbox' name='bouncedccs' id='bouncedccs' value='1'" + CString((!pUser || pUser->BounceDCCs()) ? " CHECKED" : "") + "><label for='bouncedccs'>Bounce DCCs</label></span> \r\n"
|
||||
"<span style='white-space: nowrap;'><input type='checkbox' name='useclientip' id='useclientip' value='1'" + CString((pUser && pUser->UseClientIP()) ? " CHECKED" : "") + "><label for='useclientip'>Use Client IP</label></span> \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 += "<span style='white-space: nowrap;'><input type='checkbox' name='denyloadmod' id='denyloadmod' value='1'" + CString((pUser && pUser->DenyLoadMod()) ? " CHECKED" : "") + "><label for='denyloadmod'>Deny LoadMod</label></span> \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 += "<span style='white-space: nowrap;'><input type='checkbox' name='isadmin' id='isadmin' value='1'" + CString((pUser && pUser->IsAdmin()) ? " CHECKED" : "") + CString((pUser && pUser == CZNC::Get().FindUser(GetUser())) ? " DISABLED" : "") + "><label for='isadmin'>Admin</label></span> \r\n";
|
||||
}
|
||||
|
||||
sPageRet += "<br><br>"
|
||||
"<div><small><b>CTCP Replies:</b></small><br>"
|
||||
"<textarea name='ctcpreplies' cols='40' rows='5'>" + sCTCPReplies.Escape_n(CString::EHTML) + "</textarea></div>\r\n"
|
||||
"<br></div></div><br><br>\r\n"
|
||||
|
||||
"<input type='submit' value='Submit'>\r\n"
|
||||
"</form>\r\n";
|
||||
|
||||
sPageRet += Footer();
|
||||
PrintPage(sPageRet, "UserPage.tmpl");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user