bool IsOnlineModNick(const CString& sNick) { const CString& sPrefix = GetUser()->GetStatusPrefix(); if (!sNick.StartsWith(sPrefix)) return false; CString sModNick = sNick.substr(sPrefix.length()); if (sModNick.Equals("status") || GetNetwork()->GetModules().FindModule(sModNick) || GetUser()->GetModules().FindModule(sModNick) || CZNC::Get().GetModules().FindModule(sModNick)) return true; return false; }
void CMessage::Parse(CString sMessage) { // <tags> m_mssTags.clear(); if (sMessage.StartsWith("@")) { VCString vsTags; sMessage.Token(0).TrimPrefix_n("@").Split(";", vsTags, false); for (const CString& sTag : vsTags) { CString sKey = sTag.Token(0, false, "=", true); CString sValue = sTag.Token(1, true, "=", true); m_mssTags[sKey] = sValue.Escape(CString::EMSGTAG, CString::CString::EASCII); } sMessage = sMessage.Token(1, true); } // <message> ::= [':' <prefix> <SPACE> ] <command> <params> <crlf> // <prefix> ::= <servername> | <nick> [ '!' <user> ] [ '@' <host> ] // <command> ::= <letter> { <letter> } | <number> <number> <number> // <SPACE> ::= ' ' { ' ' } // <params> ::= <SPACE> [ ':' <trailing> | <middle> <params> ] // <middle> ::= <Any *non-empty* sequence of octets not including SPACE // or NUL or CR or LF, the first of which may not be ':'> // <trailing> ::= <Any, possibly *empty*, sequence of octets not including // NUL or CR or LF> // <prefix> if (sMessage.TrimPrefix(":")) { m_Nick.Parse(sMessage.Token(0)); sMessage = sMessage.Token(1, true); } // <command> m_sCommand = sMessage.Token(0); sMessage = sMessage.Token(1, true); // <params> m_bColon = false; m_vsParams.clear(); while (!sMessage.empty()) { m_bColon = sMessage.TrimPrefix(":"); if (m_bColon) { m_vsParams.push_back(sMessage); sMessage.clear(); } else { m_vsParams.push_back(sMessage.Token(0)); sMessage = sMessage.Token(1, true); } } InitType(); }
void CFile::SetFileName(const CString& sLongName) { if (sLongName.StartsWith("~/")) { m_sLongName = CFile::GetHomePath() + sLongName.substr(1); } else m_sLongName = sLongName; m_sShortName = sLongName; m_sShortName.TrimRight("/"); CString::size_type uPos = m_sShortName.rfind('/'); if (uPos != CString::npos) { m_sShortName = m_sShortName.substr(uPos +1); } }
bool CHTTPSock::Redirect(const CString& sURL) { if (SentHeader()) { DEBUG("Redirect() - Header was already sent"); return false; } else if(!sURL.StartsWith("/")) { // HTTP/1.1 only admits absolute URIs for the Location header. DEBUG("Redirect to relative URI [" + sURL + "] is not allowed."); return false; } else { CString location = m_sURIPrefix + sURL; DEBUG("- Redirect to [" << location << "] with prefix [" + m_sURIPrefix + "]"); AddHeader("Location", location); PrintErrorPage(302, "Found", "The document has moved <a href=\"" + location.Escape_n(CString::EHTML) + "\">here</a>."); return true; } }
CString CMessage::GetParamsColon(unsigned int uIdx, unsigned int uLen) const { if (m_vsParams.empty() || uLen == 0) { return ""; } if (uLen > m_vsParams.size() - uIdx - 1) { uLen = m_vsParams.size() - uIdx; } VCString vsParams; unsigned uParams = m_vsParams.size(); for (unsigned int i = uIdx; i < uIdx + uLen; ++i) { CString sParam = m_vsParams[i]; if (i == uParams - 1 && (m_bColon || sParam.empty() || sParam.StartsWith(":") || sParam.Contains(" "))) { sParam = ":" + sParam; } vsParams.push_back(sParam); } return CString(" ").Join(vsParams.begin(), vsParams.end()); }
void ext_param::traverse_cline_internal(cgiOutStream& CGIStream, const CString& arg){ if (arg == "equiv") output_current_equivs(CGIStream); else if (arg == "nocache") entry_manager::set_value("CACHED", "0"); else if (arg == "admin") output_current_admins(CGIStream); else if (arg.StartsWith("access")) { CString passwd = arg.Copy(strlen("access"), arg.StrLength()); if (check_root_access(passwd)) cgi_error(CGIStream, "access denied"); output_current_access(CGIStream); } else if (arg == "version") { CGIStream << "(" << __DATE__ ") Daniel Doubrovkine - University of Geneva" << elf; CGIStream << "© Vestris Inc. - 1994-1998 - All Rights Reserved" << elf; } else if (arg == "environ") { #ifdef ANSI extern char **environ; char ** _environ = environ; #endif int i=0; while (_environ[i]) CGIStream << _environ[i++]<<elf; } }
bool CDir::MakeDir(const CString& sPath, mode_t iMode) { CString sDir; VCString dirs; VCString::iterator it; // Just in case someone tries this... if (sPath.empty()) { errno = ENOENT; return false; } // If this is an absolute path, we need to handle this now! if (sPath.StartsWith("/")) sDir = "/"; // For every single subpath, do... sPath.Split("/", dirs, false); for (it = dirs.begin(); it != dirs.end(); ++it) { // Add this to the path we already created sDir += *it; int i = mkdir(sDir.c_str(), iMode); if (i != 0) { // All errors except EEXIST are fatal if (errno != EEXIST) return false; // If it's EEXIST we have to make sure it's a dir if (!CFile::IsDir(sDir)) return false; } sDir += "/"; } // All went well return true; }
bool CHTTPSock::PrintFile(const CString& sFileName, CString sContentType) { CString sFilePath = sFileName; if (!m_sDocRoot.empty()) { sFilePath.TrimLeft("/"); sFilePath = CDir::CheckPathPrefix(m_sDocRoot, sFilePath, m_sDocRoot); if (sFilePath.empty()) { PrintErrorPage(403, "Forbidden", "You don't have permission to access that file on this server."); DEBUG("THIS FILE: [" << sFilePath << "] does not live in ..."); DEBUG("DOCUMENT ROOT: [" << m_sDocRoot << "]"); return false; } } CFile File(sFilePath); if (!File.Open()) { PrintNotFound(); return false; } if (sContentType.empty()) { if (sFileName.EndsWith(".html") || sFileName.EndsWith(".htm")) { sContentType = "text/html; charset=utf-8"; } else if (sFileName.EndsWith(".css")) { sContentType = "text/css; charset=utf-8"; } else if (sFileName.EndsWith(".js")) { sContentType = "application/x-javascript; charset=utf-8"; } else if (sFileName.EndsWith(".jpg")) { sContentType = "image/jpeg"; } else if (sFileName.EndsWith(".gif")) { sContentType = "image/gif"; } else if (sFileName.EndsWith(".ico")) { sContentType = "image/x-icon"; } else if (sFileName.EndsWith(".png")) { sContentType = "image/png"; } else if (sFileName.EndsWith(".bmp")) { sContentType = "image/bmp"; } else { sContentType = "text/plain; charset=utf-8"; } } const time_t iMTime = File.GetMTime(); bool bNotModified = false; CString sETag; if (iMTime > 0 && !m_bHTTP10Client) { sETag = "-" + CString(iMTime); // lighttpd style ETag AddHeader("Last-Modified", GetDate(iMTime)); AddHeader("ETag", "\"" + sETag + "\""); AddHeader("Cache-Control", "public"); if (!m_sIfNoneMatch.empty()) { m_sIfNoneMatch.Trim("\\\"'"); bNotModified = (m_sIfNoneMatch.Equals(sETag, CString::CaseSensitive)); } } if (bNotModified) { PrintHeader(0, sContentType, 304, "Not Modified"); } else { off_t iSize = File.GetSize(); // Don't try to send files over 16 MiB, because it might block // the whole process and use huge amounts of memory. if (iSize > 16 * 1024 * 1024) { DEBUG("- Abort: File is over 16 MiB big: " << iSize); PrintErrorPage(500, "Internal Server Error", "File too big"); return true; } #ifdef HAVE_ZLIB bool bGzip = m_bAcceptGzip && (sContentType.StartsWith("text/") || sFileName.EndsWith(".js")); if (bGzip) { DEBUG("- Sending gzip-compressed."); AddHeader("Content-Encoding", "gzip"); PrintHeader(0, sContentType); // we do not know the compressed data's length WriteFileGzipped(File); } else #endif { PrintHeader(iSize, sContentType); WriteFileUncompressed(File); } } DEBUG("- ETag: [" << sETag << "] / If-None-Match [" << m_sIfNoneMatch << "]"); Close(Csock::CLT_AFTERWRITE); return true; }
void CClient::ReadLine(const CString& sData) { CLanguageScope user_lang(GetUser() ? GetUser()->GetLanguage() : ""); CString sLine = sData; sLine.TrimRight("\n\r"); DEBUG("(" << GetFullName() << ") CLI -> ZNC [" << sLine << "]"); MCString mssTags; if (sLine.StartsWith("@")) { mssTags = CUtils::GetMessageTags(sLine); sLine = sLine.Token(1, true); } bool bReturn = false; if (IsAttached()) { NETWORKMODULECALL(OnUserRaw(sLine), m_pUser, m_pNetwork, this, &bReturn); } else { GLOBALMODULECALL(OnUnknownUserRaw(this, sLine), &bReturn); } if (bReturn) return; CMessage Message(sLine); Message.SetClient(this); Message.SetTags(mssTags); if (IsAttached()) { NETWORKMODULECALL(OnUserRawMessage(Message), m_pUser, m_pNetwork, this, &bReturn); } else { GLOBALMODULECALL(OnUnknownUserRawMessage(Message), &bReturn); } if (bReturn) return; CString sCommand = Message.GetCommand(); if (!IsAttached()) { // The following commands happen before authentication with ZNC if (sCommand.Equals("PASS")) { m_bGotPass = true; CString sAuthLine = Message.GetParam(0); ParsePass(sAuthLine); AuthUser(); // Don't forward this msg. ZNC has already registered us. return; } else if (sCommand.Equals("NICK")) { CString sNick = Message.GetParam(0); m_sNick = sNick; m_bGotNick = true; AuthUser(); // Don't forward this msg. ZNC will handle nick changes until auth // is complete return; } else if (sCommand.Equals("USER")) { CString sAuthLine = Message.GetParam(0); if (m_sUser.empty() && !sAuthLine.empty()) { ParseUser(sAuthLine); } m_bGotUser = true; if (m_bGotPass) { AuthUser(); } else if (!m_bInCap) { SendRequiredPasswordNotice(); } // Don't forward this msg. ZNC has already registered us. return; } } if (Message.GetType() == CMessage::Type::Capability) { HandleCap(Message); // Don't let the client talk to the server directly about CAP, // we don't want anything enabled that ZNC does not support. return; } if (!m_pUser) { // Only CAP, NICK, USER and PASS are allowed before login return; } switch (Message.GetType()) { case CMessage::Type::Action: bReturn = OnActionMessage(Message); break; case CMessage::Type::CTCP: bReturn = OnCTCPMessage(Message); break; case CMessage::Type::Join: bReturn = OnJoinMessage(Message); break; case CMessage::Type::Mode: bReturn = OnModeMessage(Message); break; case CMessage::Type::Notice: bReturn = OnNoticeMessage(Message); break; case CMessage::Type::Part: bReturn = OnPartMessage(Message); break; case CMessage::Type::Ping: bReturn = OnPingMessage(Message); break; case CMessage::Type::Pong: bReturn = OnPongMessage(Message); break; case CMessage::Type::Quit: bReturn = OnQuitMessage(Message); break; case CMessage::Type::Text: bReturn = OnTextMessage(Message); break; case CMessage::Type::Topic: bReturn = OnTopicMessage(Message); break; default: bReturn = OnOtherMessage(Message); break; } if (bReturn) return; PutIRC(Message.ToString(CMessage::ExcludePrefix | CMessage::ExcludeTags)); }
void OnModCommand(const CString& sCommand) override { CString sCom = sCommand.Token(0); CString sArgs = sCommand.Token(1, true); if (sCom.Equals("chat") && !sArgs.empty()) { CString sNick = "(s)" + sArgs; set<CSocket*>::const_iterator it; for (it = BeginSockets(); it != EndSockets(); ++it) { CSChatSock* pSock = (CSChatSock*)*it; if (pSock->GetChatNick().Equals(sNick)) { PutModule("Already Connected to [" + sArgs + "]"); return; } } CSChatSock* pSock = new CSChatSock(this, sNick); pSock->SetCipher("HIGH"); pSock->SetPemLocation(m_sPemFile); u_short iPort = GetManager()->ListenRand( pSock->GetSockName() + "::LISTENER", GetUser()->GetLocalDCCIP(), true, SOMAXCONN, pSock, 60); if (iPort == 0) { PutModule("Failed to start chat!"); return; } stringstream s; s << "PRIVMSG " << sArgs << " :\001"; s << "DCC SCHAT chat "; s << CUtils::GetLongIP(GetUser()->GetLocalDCCIP()); s << " " << iPort << "\001"; PutIRC(s.str()); } else if (sCom.Equals("list")) { CTable Table; Table.AddColumn("Nick"); Table.AddColumn("Created"); Table.AddColumn("Host"); Table.AddColumn("Port"); Table.AddColumn("Status"); Table.AddColumn("Cipher"); set<CSocket*>::const_iterator it; for (it = BeginSockets(); it != EndSockets(); ++it) { Table.AddRow(); CSChatSock* pSock = (CSChatSock*)*it; Table.SetCell("Nick", pSock->GetChatNick()); unsigned long long iStartTime = pSock->GetStartTime(); time_t iTime = iStartTime / 1000; char* pTime = ctime(&iTime); if (pTime) { CString sTime = pTime; sTime.Trim(); Table.SetCell("Created", sTime); } if (pSock->GetType() != CSChatSock::LISTENER) { Table.SetCell("Status", "Established"); Table.SetCell("Host", pSock->GetRemoteIP()); Table.SetCell("Port", CString(pSock->GetRemotePort())); SSL_SESSION* pSession = pSock->GetSSLSession(); if (pSession && pSession->cipher && pSession->cipher->name) Table.SetCell("Cipher", pSession->cipher->name); } else { Table.SetCell("Status", "Waiting"); Table.SetCell("Port", CString(pSock->GetLocalPort())); } } if (Table.size()) { PutModule(Table); } else PutModule("No SDCCs currently in session"); } else if (sCom.Equals("close")) { if (!sArgs.StartsWith("(s)")) sArgs = "(s)" + sArgs; set<CSocket*>::const_iterator it; for (it = BeginSockets(); it != EndSockets(); ++it) { CSChatSock* pSock = (CSChatSock*)*it; if (sArgs.Equals(pSock->GetChatNick())) { pSock->Close(); return; } } PutModule("No Such Chat [" + sArgs + "]"); } else if (sCom.Equals("showsocks") && GetUser()->IsAdmin()) { CTable Table; Table.AddColumn("SockName"); Table.AddColumn("Created"); Table.AddColumn("LocalIP:Port"); Table.AddColumn("RemoteIP:Port"); Table.AddColumn("Type"); Table.AddColumn("Cipher"); set<CSocket*>::const_iterator it; for (it = BeginSockets(); it != EndSockets(); ++it) { Table.AddRow(); Csock* pSock = *it; Table.SetCell("SockName", pSock->GetSockName()); unsigned long long iStartTime = pSock->GetStartTime(); time_t iTime = iStartTime / 1000; char* pTime = ctime(&iTime); if (pTime) { CString sTime = pTime; sTime.Trim(); Table.SetCell("Created", sTime); } if (pSock->GetType() != Csock::LISTENER) { if (pSock->GetType() == Csock::OUTBOUND) Table.SetCell("Type", "Outbound"); else Table.SetCell("Type", "Inbound"); Table.SetCell("LocalIP:Port", pSock->GetLocalIP() + ":" + CString(pSock->GetLocalPort())); Table.SetCell("RemoteIP:Port", pSock->GetRemoteIP() + ":" + CString(pSock->GetRemotePort())); SSL_SESSION* pSession = pSock->GetSSLSession(); if (pSession && pSession->cipher && pSession->cipher->name) Table.SetCell("Cipher", pSession->cipher->name); else Table.SetCell("Cipher", "None"); } else { Table.SetCell("Type", "Listener"); Table.SetCell("LocalIP:Port", pSock->GetLocalIP() + ":" + CString(pSock->GetLocalPort())); Table.SetCell("RemoteIP:Port", "0.0.0.0:0"); } } if (Table.size()) PutModule(Table); else PutModule("Error Finding Sockets"); } else if (sCom.Equals("help")) { PutModule("Commands are:"); PutModule(" help - This text."); PutModule(" chat <nick> - Chat a nick."); PutModule(" list - List current chats."); PutModule(" close <nick> - Close a chat to a nick."); PutModule(" timers - Shows related timers."); if (GetUser()->IsAdmin()) { PutModule(" showsocks - Shows all socket connections."); } } else if (sCom.Equals("timers")) ListTimers(); else PutModule("Unknown command [" + sCom + "] [" + sArgs + "]"); }
void CClient::ReadLine(const CString& sData) { CString sLine = sData; sLine.TrimRight("\n\r"); DEBUG("(" << GetFullName() << ") CLI -> ZNC [" << sLine << "]"); MCString mssTags; if (sLine.StartsWith("@")) { mssTags = CUtils::GetMessageTags(sLine); sLine = sLine.Token(1, true); } bool bReturn = false; if (IsAttached()) { NETWORKMODULECALL(OnUserRaw(sLine), m_pUser, m_pNetwork, this, &bReturn); } else { GLOBALMODULECALL(OnUnknownUserRaw(this, sLine), &bReturn); } if (bReturn) return; CString sCommand = sLine.Token(0); if (sCommand.StartsWith(":")) { // Evil client! Sending a nickmask prefix on client's command // is bad, bad, bad, bad, bad, bad, bad, bad, BAD, B A D! sLine = sLine.Token(1, true); sCommand = sLine.Token(0); } if (!IsAttached()) { // The following commands happen before authentication with ZNC if (sCommand.Equals("PASS")) { m_bGotPass = true; CString sAuthLine = sLine.Token(1, true).TrimPrefix_n(); ParsePass(sAuthLine); AuthUser(); return; // Don't forward this msg. ZNC has already registered us. } else if (sCommand.Equals("NICK")) { CString sNick = sLine.Token(1).TrimPrefix_n(); m_sNick = sNick; m_bGotNick = true; AuthUser(); return; // Don't forward this msg. ZNC will handle nick changes until auth is complete } else if (sCommand.Equals("USER")) { CString sAuthLine = sLine.Token(1); if (m_sUser.empty() && !sAuthLine.empty()) { ParseUser(sAuthLine); } m_bGotUser = true; if (m_bGotPass) { AuthUser(); } else if (!m_bInCap) { SendRequiredPasswordNotice(); } return; // Don't forward this msg. ZNC has already registered us. } } if (sCommand.Equals("CAP")) { HandleCap(sLine); // Don't let the client talk to the server directly about CAP, // we don't want anything enabled that ZNC does not support. return; } if (!m_pUser) { // Only CAP, NICK, USER and PASS are allowed before login return; } if (sCommand.Equals("ZNC")) { CString sTarget = sLine.Token(1); CString sModCommand; if (sTarget.TrimPrefix(m_pUser->GetStatusPrefix())) { sModCommand = sLine.Token(2, true); } else { sTarget = "status"; sModCommand = sLine.Token(1, true); } if (sTarget.Equals("status")) { if (sModCommand.empty()) PutStatus("Hello. How may I help you?"); else UserCommand(sModCommand); } else { if (sModCommand.empty()) CALLMOD(sTarget, this, m_pUser, m_pNetwork, PutModule("Hello. How may I help you?")) else CALLMOD(sTarget, this, m_pUser, m_pNetwork, OnModCommand(sModCommand)) } return; } else if (sCommand.Equals("PING")) {