awaystore: Modernize and add test. Fixed various bugs.

Fixed 'pass' command to save password in CBlowfish(MD5(...)) instead of plaintext.

Fixed 'away' command not updating with a new away message if already away.

Fixed default timer in SetArgsHelpText to match SetAwayTime().

Fixed broken 'Messages' command.

Fixed 'replay' command with IPv6

Fixes #815
This commit is contained in:
RealKindOne authored and Alexey Sokolov committed 2026-09-13 11:27:31 +01:00
1 parent 375e744298
commit ff65bc01fb
2 files changed
+155 -33

No files matched your search

+42 -33
View File
@@ -70,7 +70,8 @@ class CAway : public CModule {
GetUser()->GetTimezone());
}
Away(false, sReason);
// Update with new message if already away.
Away(true, sReason);
}
void BackCommand(const CString& sCommand) {
@@ -88,8 +89,8 @@ class CAway : public CModule {
void ReplayCommand(const CString& sCommand) {
CString nick = GetClient()->GetNick();
for (u_int a = 0; a < m_vMessages.size(); a++) {
CString sWhom = m_vMessages[a].Token(1, false, ":");
CString sMessage = m_vMessages[a].Token(2, true, ":");
CString sWhom = m_vMessages[a].Token(1, false, " ");
CString sMessage = m_vMessages[a].Token(2, true, " ");
PutUser(":" + sWhom + " PRIVMSG " + nick + " :" + sMessage);
}
}
@@ -131,8 +132,10 @@ class CAway : public CModule {
}
void PassCommand(const CString& sCommand) {
m_sPassword = sCommand.Token(1);
PutModNotice(t_f("Password updated to [{1}]")(m_sPassword));
CString sNewPass = sCommand.Token(1);
m_sPassword = CBlowfish::MD5(sNewPass);
SaveBufferToDisk();
PutModNotice(t_f("Password updated to [{1}]")(sNewPass));
}
void ShowCommand(const CString& sCommand) {
@@ -223,7 +226,7 @@ class CAway : public CModule {
static_cast<CModCommand::ModCmdFunc>(&CAway::BackCommand),
"[-quiet]");
AddCommand("Messages",
static_cast<CModCommand::ModCmdFunc>(&CAway::BackCommand));
static_cast<CModCommand::ModCmdFunc>(&CAway::MessagesCommand));
AddCommand("Delete",
static_cast<CModCommand::ModCmdFunc>(&CAway::DeleteCommand),
"delete <num|all>");
@@ -392,47 +395,53 @@ class CAway : public CModule {
m_sReason = "";
}
EModRet OnPrivMsg(CNick& Nick, CString& sMessage) override {
if (m_bIsAway) AddMessage(time(nullptr), Nick, sMessage);
return (CONTINUE);
}
EModRet OnChanMsg(CNick& nick, CChan& channel, CString& sMessage) override {
if (m_bIsAway && m_chanMessages &&
sMessage.AsLower().find(m_pNetwork->GetCurNick().AsLower()) !=
CString::npos) {
AddMessage(time(nullptr), nick, channel.GetName() + " " + sMessage);
}
return (CONTINUE);
}
EModRet OnPrivAction(CNick& Nick, CString& sMessage) override {
EModRet OnPrivTextMessage(CTextMessage& Message) override {
if (m_bIsAway) {
const CNick& Nick = Message.GetNick();
CString sMessage = Message.GetText();
AddMessage(time(nullptr), Nick, sMessage);
}
return CONTINUE;
}
EModRet OnChanTextMessage(CTextMessage& Message) override {
if (m_bIsAway && m_chanMessages) {
const CNick& nick = Message.GetNick();
CChan& channel = *Message.GetChan();
CString sMessage = Message.GetText();
if (sMessage.AsLower().find(m_pNetwork->GetCurNick().AsLower()) != CString::npos) {
AddMessage(time(nullptr), nick, channel.GetName() + " " + sMessage);
}
}
return CONTINUE;
}
EModRet OnPrivActionMessage(CActionMessage& Message) override {
if (m_bIsAway) {
const CNick& Nick = Message.GetNick();
CString sMessage = Message.GetText();
AddMessage(time(nullptr), Nick, "* " + sMessage);
}
return (CONTINUE);
return CONTINUE;
}
EModRet OnUserNotice(CString& sTarget, CString& sMessage) override {
EModRet OnUserTextMessage(CTextMessage& Message) override {
Ping();
if (m_bIsAway) Back();
return (CONTINUE);
return CONTINUE;
}
EModRet OnUserMsg(CString& sTarget, CString& sMessage) override {
EModRet OnUserNoticeMessage(CNoticeMessage& Message) override {
Ping();
if (m_bIsAway) Back();
return (CONTINUE);
return CONTINUE;
}
EModRet OnUserAction(CString& sTarget, CString& sMessage) override {
EModRet OnUserActionMessage(CActionMessage& Message) override {
Ping();
if (m_bIsAway) Back();
return (CONTINUE);
return CONTINUE;
}
time_t GetTimeStamp() const { return (m_iLastSentData); }
@@ -514,7 +523,7 @@ void TModInfo<CAway>(CModInfo& Info) {
Info.SetHasArgs(true);
Info.SetArgsHelpText(Info.t_s(
"[ -notimer | -timer N ] [-chans] passw0rd . N is number of seconds, "
"600 by default."));
"300 by default."));
}
NETWORKMODULEDEFS(
+113
View File
@@ -1043,6 +1043,119 @@ TEST_F(ZNCTest, StickyChanModule) {
client.ReadUntil("InConfig = true");
}
TEST_F(ZNCTest, AwayStoreModule) {
auto znc = Run();
auto ircd = ConnectIRCd();
auto client = LoginClient();
client.Write("znc loadmod awaystore testpass");
client.ReadUntil("Loaded module");
ircd.Write(":server 001 nick :Hello");
client.ReadUntil("001");
client.Write("PRIVMSG *awaystore :timer");
client.ReadUntil("Current timer setting");
client.Write("PRIVMSG *awaystore :settimer 1");
client.ReadUntil("Timer set to 1");
client.Write("PRIVMSG *awaystore :away Test reason");
client.ReadUntil("You have been marked as away");
ircd.ReadUntil("AWAY :Test reason");
ircd.Write(":TestUser!test@host PRIVMSG nick :Normal message");
// Test for #815 - awaystore replay does not work
ircd.Write(":TestUser!test@host PRIVMSG nick :AAA:BBB:CCC");
ircd.Write(":TestUser!test@host PRIVMSG nick :\001ACTION does something\001");
// Test for #267 - AwayStore IPv6 parsing issue
ircd.Write(":IPv6!test@2001:db8:1234:5678:abcd:ef01:2345:6789 PRIVMSG nick :Normal message");
ircd.Write(":IPv6!test@2001:db8:1234:5678:abcd:ef01:2345:6789 PRIVMSG nick :AAA:BBB:CCC");
ircd.Write(":IPv6!test@2001:db8:1234:5678:abcd:ef01:2345:6789 PRIVMSG nick :\001ACTION does something\001");
client.Write("PRIVMSG *awaystore :messages");
client.ReadUntil("TestUser!test@host Normal message");
client.ReadUntil("TestUser!test@host AAA:BBB:CCC");
client.ReadUntil("TestUser!test@host * does something");
client.ReadUntil("IPv6!test@2001:db8:1234:5678:abcd:ef01:2345:6789 Normal message");
client.ReadUntil("IPv6!test@2001:db8:1234:5678:abcd:ef01:2345:6789 AAA:BBB:CCC");
client.ReadUntil("IPv6!test@2001:db8:1234:5678:abcd:ef01:2345:6789 * does something");
client.Write("PRIVMSG *awaystore :show");
client.ReadUntil("IPv6!test@2001:db8:1234:5678:abcd:ef01:2345:6789");
client.ReadUntil("Normal message");
client.ReadUntil("AAA:BBB:CCC");
client.ReadUntil("* does something");
client.ReadUntil("TestUser!test@host");
client.ReadUntil("Normal message");
client.ReadUntil("AAA:BBB:CCC");
client.ReadUntil("* does something");
client.ReadUntil("#--- End of messages");
client.Write("PRIVMSG *awaystore :delete 0");
client.ReadUntil("Message erased");
client.Write("PRIVMSG *awaystore :back");
client.ReadUntil("Welcome back!");
ircd.ReadUntil("away");
client.Write("PRIVMSG *awaystore :replay");
client.ReadUntil(":TestUser!test@host PRIVMSG nick :AAA:BBB:CCC");
client.ReadUntil(":TestUser!test@host PRIVMSG nick :* does something");
client.Write("PRIVMSG *awaystore :save");
client.ReadUntil("Messages saved to disk");
client.Write("PRIVMSG *awaystore :delete all");
client.ReadUntil("Deleted 5 messages");
client.Write("PRIVMSG *awaystore :save");
client.ReadUntil("Messages saved to disk");
client.Write("PRIVMSG *status :unloadmod awaystore");
client.ReadUntil("unloaded");
// Begin 'pass' bug not using CBlowfish::MD5()
client.Write("znc loadmod awaystore testpass");
client.ReadUntil("Loaded module");
client.Write("PRIVMSG *awaystore :away Not here");
client.ReadUntil("You have been marked as away");
ircd.Write(":TestUser!test@host PRIVMSG nick :should survive");
client.Write("PRIVMSG *awaystore :pass newpass");
client.ReadUntil("Password updated to [newpass]");
client.Write("PRIVMSG *awaystore :save");
client.ReadUntil("Messages saved to disk");
client.Write("znc unloadmod awaystore");
client.ReadUntil("unloaded");
client.Write("znc loadmod awaystore newpass");
client.ReadUntil("Loaded module");
client.Write("znc unloadmod awaystore");
client.ReadUntil("unloaded");
// End 'pass' bug test
// Begin 'away' not updating bug test
client.Write("znc loadmod awaystore newpass");
client.ReadUntil("Loaded module");
client.Write("PRIVMSG *awaystore :away first reason");
client.ReadUntil("You have been marked as away");
ircd.ReadUntil("AWAY :first reason");
client.Write("PRIVMSG *awaystore :away second reason");
client.ReadUntil("You have been marked as away");
ircd.ReadUntil("AWAY :second reason");
// End 'away' bug test
}
} // namespace
} // namespace znc_inttest