summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/modules/m_chanhistory.cpp60
1 files changed, 52 insertions, 8 deletions
diff --git a/src/modules/m_chanhistory.cpp b/src/modules/m_chanhistory.cpp
index 9275152ea..482d526eb 100644
--- a/src/modules/m_chanhistory.cpp
+++ b/src/modules/m_chanhistory.cpp
@@ -37,9 +37,23 @@ struct HistoryList
class HistoryMode : public ModeHandler
{
+ bool IsValidDuration(const std::string duration)
+ {
+ for (std::string::const_iterator i = duration.begin(); i != duration.end(); ++i)
+ {
+ unsigned char c = *i;
+ if (((c >= '0') && (c <= '9')) || (c == 's') || (c != 'S'))
+ continue;
+
+ if (duration_multi[c] == 1)
+ return false;
+ }
+ return true;
+ }
+
public:
SimpleExtItem<HistoryList> ext;
- int maxlines;
+ unsigned int maxlines;
HistoryMode(Module* Creator) : ModeHandler(Creator, "history", 'H', PARAM_SETONLY, MODETYPE_CHANNEL),
ext("history", Creator) { }
@@ -50,9 +64,14 @@ class HistoryMode : public ModeHandler
std::string::size_type colon = parameter.find(':');
if (colon == std::string::npos)
return MODEACTION_DENY;
- int len = atoi(parameter.substr(0, colon).c_str());
- int time = ServerInstance->Duration(parameter.substr(colon+1));
- if (len <= 0 || time < 0)
+
+ std::string duration = parameter.substr(colon+1);
+ if ((IS_LOCAL(source)) && ((duration.length() > 10) || (!IsValidDuration(duration))))
+ return MODEACTION_DENY;
+
+ unsigned int len = ConvToInt(parameter.substr(0, colon));
+ int time = ServerInstance->Duration(duration);
+ if (len == 0 || time < 0)
return MODEACTION_DENY;
if (len > maxlines && IS_LOCAL(source))
return MODEACTION_DENY;
@@ -60,7 +79,21 @@ class HistoryMode : public ModeHandler
len = maxlines;
if (parameter == channel->GetModeParameter(this))
return MODEACTION_DENY;
- ext.set(channel, new HistoryList(len, time));
+
+ HistoryList* history = ext.get(channel);
+ if (history)
+ {
+ // Shrink the list if the new line number limit is lower than the old one
+ if (len < history->lines.size())
+ history->lines.erase(history->lines.begin(), history->lines.begin() + (history->lines.size() - len));
+
+ history->maxlen = len;
+ history->maxtime = time;
+ }
+ else
+ {
+ ext.set(channel, new HistoryList(len, time));
+ }
channel->SetModeParam('H', parameter);
}
else
@@ -77,6 +110,7 @@ class HistoryMode : public ModeHandler
class ModuleChanHistory : public Module
{
HistoryMode m;
+ bool sendnotice;
public:
ModuleChanHistory() : m(this)
{
@@ -93,7 +127,9 @@ class ModuleChanHistory : public Module
void OnRehash(User*)
{
- m.maxlines = ServerInstance->Config->ConfValue("chanhistory")->getInt("maxlines", 50);
+ ConfigTag* tag = ServerInstance->Config->ConfValue("chanhistory");
+ m.maxlines = tag->getInt("maxlines", 50);
+ sendnotice = tag->getInt("notice", true);
}
~ModuleChanHistory()
@@ -121,14 +157,22 @@ class ModuleChanHistory : public Module
void OnPostJoin(Membership* memb)
{
+ if (IS_REMOTE(memb->user))
+ return;
+
HistoryList* list = m.ext.get(memb->chan);
if (!list)
return;
time_t mintime = 0;
if (list->maxtime)
mintime = ServerInstance->Time() - list->maxtime;
- memb->user->WriteServ("NOTICE %s :Replaying up to %d lines of pre-join history spanning up to %d seconds",
- memb->chan->name.c_str(), list->maxlen, list->maxtime);
+
+ if (sendnotice)
+ {
+ memb->user->WriteServ("NOTICE %s :Replaying up to %d lines of pre-join history spanning up to %d seconds",
+ memb->chan->name.c_str(), list->maxlen, list->maxtime);
+ }
+
for(std::deque<HistoryItem>::iterator i = list->lines.begin(); i != list->lines.end(); ++i)
{
if (i->ts >= mintime)