Beispiel #1
0
	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;
	}
Beispiel #2
0
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();
}
Beispiel #3
0
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);
	}
}
Beispiel #4
0
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;
	}
}
Beispiel #5
0
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());
}
Beispiel #6
0
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 << "&copy; 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;
	}
}
Beispiel #7
0
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;
}
Beispiel #8
0
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;
}
Beispiel #9
0
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));
}
Beispiel #10
0
    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 + "]");
    }
Beispiel #11
0
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")) {