Example #1
0
	virtual bool OnLoad(const CString& sArgs, CString& sMessage) {
		VCString vsChans;
		sArgs.Split(" ", vsChans, false);

		for (VCString::const_iterator it = vsChans.begin(); it != vsChans.end(); ++it) {
			CString sAdd = *it;
			bool bNegated = sAdd.TrimPrefix("!");
			CString sChan = sAdd.Token(0);
			CString sHost = sAdd.Token(1, true);

			if (!Add(bNegated, sChan, sHost)) {
				PutModule("Unable to add [" + *it + "]");
			}
		}

		// Load our saved settings, ignore errors
		MCString::iterator it;
		for (it = BeginNV(); it != EndNV(); ++it) {
			CString sAdd = it->first;
			bool bNegated = sAdd.TrimPrefix("!");
			CString sChan = sAdd.Token(0);
			CString sHost = sAdd.Token(1, true);

			Add(bNegated, sChan, sHost);
		}

		return true;
	}
Example #2
0
File: Message.cpp Project: BtbN/znc
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();
}
Example #3
0
bool CClient::OnOtherMessage(CMessage& Message) {
    const CString& sCommand = Message.GetCommand();

    if (sCommand.Equals("ZNC")) {
        CString sTarget = Message.GetParam(0);
        CString sModCommand;

        if (sTarget.TrimPrefix(m_pUser->GetStatusPrefix())) {
            sModCommand = Message.GetParams(1);
        } else {
            sTarget = "status";
            sModCommand = Message.GetParams(0);
        }

        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 true;
    } else if (sCommand.Equals("ATTACH")) {
Example #4
0
	virtual EModRet OnUserRaw(CString& sLine)
	{
		CString sCmd = sLine.Token(0).AsUpper();

		if (!m_pNetwork->GetIRCSock())
			return CONTINUE;

		if (sCmd.Equals("MODE")) {
			// Check if this is a mode request that needs to be handled

			// If there are arguments to a mode change,
			// we must not route it.
			if (!sLine.Token(3, true).empty())
				return CONTINUE;

			// Grab the mode change parameter
			CString sMode = sLine.Token(2);

			// If this is a channel mode request, znc core replies to it
			if (sMode.empty())
				return CONTINUE;

			// Check if this is a mode change or a specific
			// mode request (the later needs to be routed).
			sMode.TrimPrefix("+");
			if (sMode.length() != 1)
				return CONTINUE;

			// Now just check if it's one of the supported modes
			switch (sMode[0]) {
			case 'I':
			case 'b':
			case 'e':
				break;
			default:
				return CONTINUE;
			}

			// Ok, this looks like we should route it.
			// Fall through to the next loop
		}

		for (size_t i = 0; vRouteReplies[i].szRequest != NULL; i++) {
			if (vRouteReplies[i].szRequest == sCmd) {
				struct queued_req req = {
					sLine, vRouteReplies[i].vReplies
				};
				m_vsPending[m_pClient].push_back(req);
				SendRequest();

				return HALTCORE;
			}
		}

		return CONTINUE;
	}
Example #5
0
	void HandleDel(const CString& sLine) {
		CString sMsg  = sLine.Token(1, true);
		bool bNegated = sMsg.TrimPrefix("!");
		CString sChan = sMsg.Token(0);
		CString sHost = sMsg.Token(1);

		if (Del(bNegated, sChan, sHost)) {
			PutModule("Removed " + sChan + " from list");
		} else {
			PutModule("Usage: Del [!]<#chan> <host>");
		}
	}
Example #6
0
	EBufferType DecryptBuffer(const CString& sPath, CString& sBuffer, CString& sName)
	{
		CString sContent;
		sBuffer = "";

		CFile File(sPath);

		if (sPath.empty() || !File.Open() || !File.ReadFile(sContent))
			 return EmptyBuffer;

		File.Close();

		if (!sContent.empty())
		{
			CBlowfish c(m_sPassword, BF_DECRYPT);
			sBuffer = c.Crypt(sContent);

			if (sBuffer.TrimPrefix(LEGACY_VERIFICATION_TOKEN))
			{
				sName = FindLegacyBufferName(sPath);
				return ChanBuffer;
			}
			else if (sBuffer.TrimPrefix(CHAN_VERIFICATION_TOKEN))
			{
				sName = sBuffer.FirstLine();
				if (sBuffer.TrimLeft(sName + "\n"))
					return ChanBuffer;
			}
			else if (sBuffer.TrimPrefix(QUERY_VERIFICATION_TOKEN))
			{
				sName = sBuffer.FirstLine();
				if (sBuffer.TrimLeft(sName + "\n"))
					return QueryBuffer;
			}

			PutModule("Unable to decode Encrypted file [" + sPath + "]");
			return InvalidBuffer;
		}
		return EmptyBuffer;
	}
Example #7
0
	virtual void OnModCommand(const CString& sCommand) {
		CString sCmd = sCommand.Token(0);

		if (sCmd.Equals("DELKEY")) {
			CString sTarget = sCommand.Token(1);

			if (!sTarget.empty()) {
				if (DelNV(sTarget.AsLower())) {
					PutModule("Target [" + sTarget + "] deleted");
				} else {
					PutModule("Target [" + sTarget + "] not found");
				}
			} else {
				PutModule("Usage DelKey <#chan|Nick>");
			}
		} else if (sCmd.Equals("SETKEY")) {
			CString sTarget = sCommand.Token(1);
			CString sKey = sCommand.Token(2, true);

			// Strip "cbc:" from beginning of string incase someone pastes directly from mircryption
			sKey.TrimPrefix("cbc:");

			if (!sKey.empty()) {
				SetNV(sTarget.AsLower(), sKey);
				PutModule("Set encryption key for [" + sTarget + "] to [" + sKey + "]");
			} else {
				PutModule("Usage: SetKey <#chan|Nick> <Key>");
			}
		} else if (sCmd.Equals("LISTKEYS")) {
			if (BeginNV() == EndNV()) {
				PutModule("You have no encryption keys set.");
			} else {
				CTable Table;
				Table.AddColumn("Target");
				Table.AddColumn("Key");

				for (MCString::iterator it = BeginNV(); it != EndNV(); ++it) {
					Table.AddRow();
					Table.SetCell("Target", it->first);
					Table.SetCell("Key", it->second);
				}

				PutModule(Table);
			}
		} else if (sCmd.Equals("HELP")) {
			PutModule("Try: SetKey, DelKey, ListKeys");
		} else {
			PutModule("Unknown command, try 'Help'");
		}
	}
Example #8
0
File: Message.cpp Project: BtbN/znc
void CMessage::InitType() {
    if (m_sCommand.length() == 3 && isdigit(m_sCommand[0]) &&
        isdigit(m_sCommand[1]) && isdigit(m_sCommand[2])) {
        m_eType = Type::Numeric;
    } else if (m_sCommand.Equals("PRIVMSG")) {
        CString sParam = GetParam(1);
        if (sParam.TrimPrefix("\001") && sParam.EndsWith("\001")) {
            if (sParam.StartsWith("ACTION ")) {
                m_eType = Type::Action;
            } else {
                m_eType = Type::CTCP;
            }
        } else {
            m_eType = Type::Text;
        }
    } else if (m_sCommand.Equals("NOTICE")) {
        CString sParam = GetParam(1);
        if (sParam.StartsWith("\001") && sParam.EndsWith("\001")) {
            m_eType = Type::CTCP;
        } else {
            m_eType = Type::Notice;
        }
    } else {
        std::map<CString, Type> mTypes = {
            {"ACCOUNT", Type::Account},
            {"AWAY", Type::Away},
            {"CAP", Type::Capability},
            {"ERROR", Type::Error},
            {"INVITE", Type::Invite},
            {"JOIN", Type::Join},
            {"KICK", Type::Kick},
            {"MODE", Type::Mode},
            {"NICK", Type::Nick},
            {"PART", Type::Part},
            {"PING", Type::Ping},
            {"PONG", Type::Pong},
            {"QUIT", Type::Quit},
            {"TOPIC", Type::Topic},
            {"WALLOPS", Type::Wallops},
        };
        auto it = mTypes.find(m_sCommand.AsUpper());
        if (it != mTypes.end()) {
            m_eType = it->second;
        } else {
            m_eType = Type::Unknown;
        }
    }
}
Example #9
0
	void HandleAdd(const CString& sLine) {
		CString sMsg = sLine.Token(1, true);
		bool bHelp = false;
		bool bNegated = sMsg.TrimPrefix("!");
		CString sChan = sMsg.Token(0);
		CString sHost = sMsg.Token(1);

		if (sChan.empty()) {
			bHelp = true;
		} else if (Add(bNegated, sChan, sHost)) {
			PutModule("Added to list");
		} else {
			PutModule(sLine.Token(1, true) + " is already added");
			bHelp = true;
		}
		if (bHelp) {
			PutModule("Usage: Add [!]<#chan> <host>");
			PutModule("Wildcards are allowed");
		}
	}
Example #10
0
bool CIRCNetwork::AddServer(const CString& sName) {
    if (sName.empty()) {
        return false;
    }

    bool bSSL = false;
    CString sLine = sName;
    sLine.Trim();

    CString sHost = sLine.Token(0);
    CString sPort = sLine.Token(1);

    if (sPort.TrimPrefix("+")) {
        bSSL = true;
    }

    unsigned short uPort = sPort.ToUShort();
    CString sPass = sLine.Token(2, true);

    return AddServer(sHost, uPort, sPass, bSSL);
}
Example #11
0
void CClient::HandleCap(const CMessage& Message) {
    CString sSubCmd = Message.GetParam(0);

    if (sSubCmd.Equals("LS")) {
        SCString ssOfferCaps;
        for (const auto& it : m_mCoreCaps) {
            bool bServerDependent = std::get<0>(it.second);
            if (!bServerDependent ||
                m_ssServerDependentCaps.count(it.first) > 0)
                ssOfferCaps.insert(it.first);
        }
        GLOBALMODULECALL(OnClientCapLs(this, ssOfferCaps), NOTHING);
        CString sRes =
            CString(" ").Join(ssOfferCaps.begin(), ssOfferCaps.end());
        RespondCap("LS :" + sRes);
        m_bInCap = true;
        if (Message.GetParam(1).ToInt() >= 302) {
            m_bCapNotify = true;
        }
    } else if (sSubCmd.Equals("END")) {
        m_bInCap = false;
        if (!IsAttached()) {
            if (!m_pUser && m_bGotUser && !m_bGotPass) {
                SendRequiredPasswordNotice();
            } else {
                AuthUser();
            }
        }
    } else if (sSubCmd.Equals("REQ")) {
        VCString vsTokens;
        Message.GetParam(1).Split(" ", vsTokens, false);

        for (const CString& sToken : vsTokens) {
            bool bVal = true;
            CString sCap = sToken;
            if (sCap.TrimPrefix("-")) bVal = false;

            bool bAccepted = false;
            const auto& it = m_mCoreCaps.find(sCap);
            if (m_mCoreCaps.end() != it) {
                bool bServerDependent = std::get<0>(it->second);
                bAccepted = !bServerDependent ||
                            m_ssServerDependentCaps.count(sCap) > 0;
            }
            GLOBALMODULECALL(IsClientCapSupported(this, sCap, bVal),
                             &bAccepted);

            if (!bAccepted) {
                // Some unsupported capability is requested
                RespondCap("NAK :" + Message.GetParam(1));
                return;
            }
        }

        // All is fine, we support what was requested
        for (const CString& sToken : vsTokens) {
            bool bVal = true;
            CString sCap = sToken;
            if (sCap.TrimPrefix("-")) bVal = false;

            auto handler_it = m_mCoreCaps.find(sCap);
            if (m_mCoreCaps.end() != handler_it) {
                const auto& handler = std::get<1>(handler_it->second);
                handler(bVal);
            }
            GLOBALMODULECALL(OnClientCapRequest(this, sCap, bVal), NOTHING);

            if (bVal) {
                m_ssAcceptedCaps.insert(sCap);
            } else {
                m_ssAcceptedCaps.erase(sCap);
            }
        }

        RespondCap("ACK :" + Message.GetParam(1));
    } else if (sSubCmd.Equals("LIST")) {
        CString sList =
            CString(" ").Join(m_ssAcceptedCaps.begin(), m_ssAcceptedCaps.end());
        RespondCap("LIST :" + sList);
    } else {
        PutClient(":irc.znc.in 410 " + GetNick() + " " + sSubCmd +
                  " :Invalid CAP subcommand");
    }
}
Example #12
0
void CClient::ReadLine(const CString& sData) {
	CString sLine = sData;

	sLine.TrimRight("\n\r");

	DEBUG("(" << GetFullName() << ") CLI -> ZNC [" << sLine << "]");

	if (sLine.Left(1) == "@") {
		// TODO support message-tags properly
		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.Left(1) == ":") {
		// 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")) {