void SendNotification(CModule& module, const CString& sSender, const CString& sNotification, const CChan *pChannel) { // todo parse from m_sPushEndpoint bool bUseTLS = true; CString sHostname = "api.palaverapp.com"; unsigned short uPort = 443; CString sPath = "/1/push"; CString sJSON = "{"; sJSON += "\"message\": \"" + sNotification.Replace_n("\"", "\\\"") + "\""; sJSON += ",\"sender\": \"" + sSender.Replace_n("\"", "\\\"") + "\""; if (pChannel) { sJSON += ",\"channel\": \"" + pChannel->GetName().Replace_n("\"", "\\\"") + "\""; } sJSON += "}"; CSocket *pSocket = new CSocket(&module); pSocket->Connect(sHostname, uPort, bUseTLS); pSocket->Write("POST " + sPath + " HTTP/1.1\r\n"); pSocket->Write("Host: " + sHostname + "\r\n"); pSocket->Write("Authorization: Bearer " + GetToken() + "\r\n"); pSocket->Write("Connection: close\r\n"); pSocket->Write("User-Agent: ZNC\r\n"); pSocket->Write("Content-Type: application/json\r\n"); pSocket->Write("Content-Length: " + CString(sJSON.length()) + "\r\n"); pSocket->Write("\r\n"); pSocket->Write(sJSON); pSocket->Close(Csock::CLT_AFTERWRITE); module.AddSocket(pSocket); }
CString CDir::CheckPathPrefix(const CString& sPath, const CString& sAdd, const CString& sHomeDir) { CString sPrefix = sPath.Replace_n("//", "/").TrimRight_n("/") + "/"; CString sAbsolutePath = ChangeDir(sPrefix, sAdd, sHomeDir); if (!sAbsolutePath.StartsWith(sPrefix)) return ""; return sAbsolutePath; }
CString CDir::CheckPathPrefix(const CString& sPath, const CString& sAdd, const CString& sHomeDir) { CString sPrefix = sPath.Replace_n("//", "/").TrimRight_n("/") + "/"; CString sAbsolutePath = ChangeDir(sPrefix, sAdd, sHomeDir); if (sAbsolutePath.Left(sPrefix.length()) != sPrefix) return ""; return sAbsolutePath; }
set<CChan*> CClient::MatchChans(const CString& sPatterns) const { VCString vsPatterns; sPatterns.Replace_n(",", " ") .Split(" ", vsPatterns, false, "", "", true, true); set<CChan*> sChans; for (const CString& sPattern : vsPatterns) { vector<CChan*> vChans = m_pNetwork->FindChans(sPattern); sChans.insert(vChans.begin(), vChans.end()); } return sChans; }
set<CQuery*> CClient::MatchQueries(const CString& sPatterns) const { VCString vsPatterns; sPatterns.Replace_n(",", " ").Split(" ", vsPatterns, false, "", "", true, true); set<CQuery*> sQueries; for (const CString& sPattern : vsPatterns) { vector<CQuery*> vQueries = m_pNetwork->FindQueries(sPattern); sQueries.insert(vQueries.begin(), vQueries.end()); } return sQueries; }
void CLogMod::PutLog(const CString& sLine, const CString& sWindow /*= "Status"*/) { if (!TestRules(sWindow)) { return; } CString sPath; time_t curtime; time(&curtime); // Generate file name sPath = CUtils::FormatTime(curtime, m_sLogPath, GetUser()->GetTimezone()); if (sPath.empty()) { DEBUG("Could not format log path [" << sPath << "]"); return; } // TODO: Properly handle IRC case mapping // $WINDOW has to be handled last, since it can contain % sPath.Replace("$USER", CString((GetUser() ? GetUser()->GetUserName() : "UNKNOWN"))); sPath.Replace("$NETWORK", CString((GetNetwork() ? GetNetwork()->GetName() : "znc"))); sPath.Replace("$WINDOW", CString(sWindow.Replace_n("/", "-") .Replace_n("\\", "-")).AsLower()); // Check if it's allowed to write in this specific path sPath = CDir::CheckPathPrefix(GetSavePath(), sPath); if (sPath.empty()) { DEBUG("Invalid log path [" << m_sLogPath << "]."); return; } CFile LogFile(sPath); CString sLogDir = LogFile.GetDir(); struct stat ModDirInfo; CFile::GetInfo(GetSavePath(), ModDirInfo); if (!CFile::Exists(sLogDir)) CDir::MakeDir(sLogDir, ModDirInfo.st_mode); if (LogFile.Open(O_WRONLY | O_APPEND | O_CREAT)) { LogFile.Write(CUtils::FormatTime(curtime, m_sTimestamp, GetUser()->GetTimezone()) + " " + (m_bSanitize ? sLine.StripControls_n() : sLine) + "\n"); } else DEBUG("Could not open log file [" << sPath << "]: " << strerror(errno)); }
void CLogMod::PutLog(const CString& sLine, const CString& sWindow /*= "Status"*/) { CString sPath; time_t curtime; tm* timeinfo; char buffer[1024]; time(&curtime); // Don't forget the user's timezone offset setenv("TZ", m_pUser->GetTimezone().c_str(), 1); timeinfo = localtime(&curtime); // Generate file name if (!strftime(buffer, sizeof(buffer), m_sLogPath.c_str(), timeinfo)) { DEBUG("Could not format log path [" << sPath << "]"); return; } sPath = buffer; // $WINDOW has to be handled last, since it can contain % sPath.Replace("$NETWORK", (m_pNetwork ? m_pNetwork->GetName() : "znc")); sPath.Replace("$WINDOW", sWindow.Replace_n("/", "?")); sPath.Replace("$USER", (m_pUser ? m_pUser->GetUserName() : "UNKNOWN")); // Check if it's allowed to write in this specific path sPath = CDir::CheckPathPrefix(GetSavePath(), sPath); if (sPath.empty()) { DEBUG("Invalid log path ["<<m_sLogPath<<"]."); return; } CFile LogFile(sPath); CString sLogDir = LogFile.GetDir(); if (!CFile::Exists(sLogDir)) CDir::MakeDir(sLogDir); if (LogFile.Open(O_WRONLY | O_APPEND | O_CREAT)) { snprintf(buffer, sizeof(buffer), "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); LogFile.Write(buffer + sLine + "\n"); } else DEBUG("Could not open log file [" << sPath << "]: " << strerror(errno)); }
void CFile::SetFileName(const CString& sLongName) { #ifdef _WIN32 // :TODO: Convert filenames to Unicode. See Issue 1. m_sLongName = sLongName.Replace_n("/", "\\"); m_sLongName.TrimRight("\\"); m_sShortName = PathFindFileName(m_sLongName.c_str()); #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); } #endif }
void CLogMod::PutLog(const CString& sLine, const CString& sWindow /*= "Status"*/) { CString sPath; time_t curtime; time(&curtime); // Generate file name sPath = CUtils::FormatTime(curtime, m_sLogPath, m_pUser->GetTimezone()); if (sPath.empty()) { DEBUG("Could not format log path [" << sPath << "]"); return; } // $WINDOW has to be handled last, since it can contain % sPath.Replace("$NETWORK", (m_pNetwork ? m_pNetwork->GetName() : "znc")); sPath.Replace("$WINDOW", sWindow.Replace_n("/", "?")); sPath.Replace("$USER", (m_pUser ? m_pUser->GetUserName() : "UNKNOWN")); // Check if it's allowed to write in this specific path sPath = CDir::CheckPathPrefix(GetSavePath(), sPath); if (sPath.empty()) { DEBUG("Invalid log path ["<<m_sLogPath<<"]."); return; } CFile LogFile(sPath); CString sLogDir = LogFile.GetDir(); if (!CFile::Exists(sLogDir)) CDir::MakeDir(sLogDir); if (LogFile.Open(O_WRONLY | O_APPEND | O_CREAT)) { LogFile.Write(CUtils::FormatTime(curtime, "[%H:%M:%S] ", m_pUser->GetTimezone()) + sLine + "\n"); } else DEBUG("Could not open log file [" << sPath << "]: " << strerror(errno)); }
CString CIdentServer::GetResponse(const CString& sLine, const CString& sSocketIP, const CString& sRemoteIP) { unsigned short uLocalPort = 0; // local port that ZNC connected to IRC FROM unsigned short uRemotePort = 0; // remote server port that ZNC connected TO, e.g. 6667 CString sResponseType = "ERROR"; CString sAddInfo = "INVALID-PORT"; DEBUG("IDENT request: " << sLine << " from " << sRemoteIP << " on " << sSocketIP); if(sscanf(sLine.c_str(), "%hu , %hu", &uLocalPort, &uRemotePort) == 2) { sAddInfo = "NO-USER"; for(auto itu = CZNC::Get().GetUserMap().begin(); itu != CZNC::Get().GetUserMap().end(); ++itu) { CUser* pUser = itu->second; bool bFound = false; for(CIRCNetwork* pNetwork : pUser->GetNetworks()) { CIRCSock *pSock = pNetwork->GetIRCSock(); if(!pSock) continue; DEBUG("Checking user (" << pSock->GetLocalPort() << ", " << pSock->GetRemotePort() << ", " << pSock->GetLocalIP() << ")"); if(pSock->GetLocalPort() == uLocalPort && pSock->GetRemotePort() == uRemotePort && AreIPStringsEqual(pSock->GetLocalIP(), sSocketIP)) { sResponseType = "USERID"; sAddInfo = "UNIX : " + pUser->GetIdent(); // exact match found, leave the loop: bFound = true; break; } DEBUG("Checking user fallback (" << pSock->GetRemoteIP() << ", " << pSock->GetRemotePort() << ", " << pSock->GetLocalIP() << ")"); if(pSock->GetRemoteIP() == sRemoteIP && pSock->GetRemotePort() == uRemotePort && AreIPStringsEqual(pSock->GetLocalIP(), sSocketIP)) { sResponseType = "USERID"; sAddInfo = "UNIX : " + pUser->GetIdent(); // keep looping, we may find something better } } if(bFound) break; } } CString sReply = CString(uLocalPort) + ", " + CString(uRemotePort) + " : " + sResponseType + " : " + sAddInfo; DEBUG("IDENT response: " << sReply); CIdentServerMod *pMod = reinterpret_cast<CIdentServerMod*>(m_pModule); if(pMod) { pMod->SetLastRequest(sLine.Replace_n("\r", "").Replace_n("\n", " ") + "from " + sRemoteIP + " on " + sSocketIP); pMod->SetLastReply(sReply); } return sReply; }