Add umode +I to allow users to hide their idle time (#220)
This commit is contained in:
parent
1e7fd14296
commit
01fb744c40
9 changed files with 161 additions and 13 deletions
|
@ -78,6 +78,7 @@
|
||||||
* Global nick-change notices -- sno_globalnickchange
|
* Global nick-change notices -- sno_globalnickchange
|
||||||
* Oper-override (modehacking only) -- override
|
* Oper-override (modehacking only) -- override
|
||||||
* Stop services kills -- no_kill_services
|
* Stop services kills -- no_kill_services
|
||||||
|
* Allows you to hide your idle time (umode +I) -- umode_hide_idle_time
|
||||||
*/
|
*/
|
||||||
#loadmodule "extensions/chm_adminonly";
|
#loadmodule "extensions/chm_adminonly";
|
||||||
#loadmodule "extensions/chm_nonotice";
|
#loadmodule "extensions/chm_nonotice";
|
||||||
|
@ -110,6 +111,7 @@
|
||||||
#loadmodule "extensions/sno_globaloper";
|
#loadmodule "extensions/sno_globaloper";
|
||||||
#loadmodule "extensions/override";
|
#loadmodule "extensions/override";
|
||||||
#loadmodule "extensions/no_kill_services";
|
#loadmodule "extensions/no_kill_services";
|
||||||
|
#loadmodule "extensions/umode_hide_idle_time";
|
||||||
|
|
||||||
/* serverinfo {}: Contains information about the server. (OLD M:) */
|
/* serverinfo {}: Contains information about the server. (OLD M:) */
|
||||||
serverinfo {
|
serverinfo {
|
||||||
|
@ -474,6 +476,8 @@ privset "local_op" {
|
||||||
* oper:receive_immunity:
|
* oper:receive_immunity:
|
||||||
* confers the benefits of chmode +M (operpeace) (from extensions/chm_operpeace)
|
* confers the benefits of chmode +M (operpeace) (from extensions/chm_operpeace)
|
||||||
* usermode:helpops allows setting +h (from extensions/helpops)
|
* usermode:helpops allows setting +h (from extensions/helpops)
|
||||||
|
* auspex:usertimes:
|
||||||
|
* allows viewing user idle/connect times even when +I is set (from extensions/umode_hide_idle_time)
|
||||||
*/
|
*/
|
||||||
privs = oper:general, oper:privs, oper:testline, oper:kill, oper:operwall, oper:message,
|
privs = oper:general, oper:privs, oper:testline, oper:kill, oper:operwall, oper:message,
|
||||||
usermode:servnotice, auspex:oper, auspex:hostname, auspex:umodes, auspex:cmodes;
|
usermode:servnotice, auspex:oper, auspex:hostname, auspex:umodes, auspex:cmodes;
|
||||||
|
|
|
@ -66,6 +66,7 @@ extension_LTLIBRARIES = \
|
||||||
identify_msg.la \
|
identify_msg.la \
|
||||||
cap_realhost.la \
|
cap_realhost.la \
|
||||||
invex_regonly.la \
|
invex_regonly.la \
|
||||||
|
umode_hide_idle_time.la \
|
||||||
cap_oper.la \
|
cap_oper.la \
|
||||||
example_module.la
|
example_module.la
|
||||||
|
|
||||||
|
|
80
extensions/umode_hide_idle_time.c
Normal file
80
extensions/umode_hide_idle_time.c
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 David Schultz <me@zpld.me>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||||
|
* USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "stdinc.h"
|
||||||
|
#include "modules.h"
|
||||||
|
#include "client.h"
|
||||||
|
#include "hook.h"
|
||||||
|
#include "ircd.h"
|
||||||
|
#include "logger.h"
|
||||||
|
#include "send.h"
|
||||||
|
#include "s_conf.h"
|
||||||
|
#include "s_user.h"
|
||||||
|
#include "s_newconf.h"
|
||||||
|
|
||||||
|
static const char hide_desc[] = "Provides user mode +I to hide a user's idle time";
|
||||||
|
|
||||||
|
static void h_huc_doing_idle_time_hook(void *);
|
||||||
|
|
||||||
|
mapi_hfn_list_av1 huc_hfnlist[] = {
|
||||||
|
{ "doing_whois_show_idle", h_huc_doing_idle_time_hook },
|
||||||
|
{ "doing_trace_show_idle", h_huc_doing_idle_time_hook },
|
||||||
|
{ "doing_stats_show_idle", h_huc_doing_idle_time_hook },
|
||||||
|
{ "doing_who_show_idle", h_huc_doing_idle_time_hook },
|
||||||
|
{ NULL, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
h_huc_doing_idle_time_hook(void *data_)
|
||||||
|
{
|
||||||
|
hook_data_client_approval *data = data_;
|
||||||
|
|
||||||
|
if (data->approved == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (data->target->umodes & user_modes['I'])
|
||||||
|
{
|
||||||
|
if (HasPrivilege(data->client, "auspex:usertimes"))
|
||||||
|
data->approved = WHOIS_IDLE_AUSPEX;
|
||||||
|
else if (data->client != data->target)
|
||||||
|
data->approved = WHOIS_IDLE_HIDE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_modinit(void)
|
||||||
|
{
|
||||||
|
user_modes['I'] = find_umode_slot();
|
||||||
|
construct_umodebuf();
|
||||||
|
if (!user_modes['I'])
|
||||||
|
{
|
||||||
|
ierror("umode_hide_idle_time: unable to allocate usermode slot for +I, unloading extension");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_moddeinit(void)
|
||||||
|
{
|
||||||
|
user_modes['I'] = 0;
|
||||||
|
construct_umodebuf();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_MODULE_AV2(hide_idle_time, _modinit, _moddeinit, NULL, NULL, huc_hfnlist, NULL, NULL, hide_desc);
|
|
@ -19,6 +19,7 @@ User modes: (? designates that the umode is provided by an extension
|
||||||
+G - Deny users not on your /ACCEPT list and not in a channel
|
+G - Deny users not on your /ACCEPT list and not in a channel
|
||||||
with you from messaging you and inviting you to channels.
|
with you from messaging you and inviting you to channels.
|
||||||
This is a softer form of +g.
|
This is a softer form of +g.
|
||||||
|
? +I - Hides your idle time.
|
||||||
+Q - Prevents you from being affected by channel forwarding.
|
+Q - Prevents you from being affected by channel forwarding.
|
||||||
+R - Prevents unidentified users that you have not accepted from
|
+R - Prevents unidentified users that you have not accepted from
|
||||||
messaging you.
|
messaging you.
|
||||||
|
|
|
@ -21,6 +21,14 @@ enum hook_priority
|
||||||
HOOK_MONITOR = 100
|
HOOK_MONITOR = 100
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* for idle time privacy features */
|
||||||
|
enum whois_idle_approval
|
||||||
|
{
|
||||||
|
WHOIS_IDLE_HIDE = 0,
|
||||||
|
WHOIS_IDLE_SHOW = 1,
|
||||||
|
WHOIS_IDLE_AUSPEX = 2
|
||||||
|
};
|
||||||
|
|
||||||
typedef void (*hookfn) (void *data);
|
typedef void (*hookfn) (void *data);
|
||||||
|
|
||||||
extern int h_iosend_id;
|
extern int h_iosend_id;
|
||||||
|
|
|
@ -60,11 +60,13 @@ struct Message stats_msgtab = {
|
||||||
|
|
||||||
int doing_stats_hook;
|
int doing_stats_hook;
|
||||||
int doing_stats_p_hook;
|
int doing_stats_p_hook;
|
||||||
|
int doing_stats_show_idle_hook;
|
||||||
|
|
||||||
mapi_clist_av1 stats_clist[] = { &stats_msgtab, NULL };
|
mapi_clist_av1 stats_clist[] = { &stats_msgtab, NULL };
|
||||||
mapi_hlist_av1 stats_hlist[] = {
|
mapi_hlist_av1 stats_hlist[] = {
|
||||||
{ "doing_stats", &doing_stats_hook },
|
{ "doing_stats", &doing_stats_hook },
|
||||||
{ "doing_stats_p", &doing_stats_p_hook },
|
{ "doing_stats_p", &doing_stats_p_hook },
|
||||||
|
{ "doing_stats_show_idle", &doing_stats_show_idle_hook },
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1621,19 +1623,27 @@ stats_l_client(struct Client *source_p, struct Client *target_p,
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
/* fire the doing_stats_show_idle hook to allow modules to tell us whether to show the idle time */
|
||||||
|
hook_data_client_approval hdata_showidle;
|
||||||
|
|
||||||
|
hdata_showidle.client = source_p;
|
||||||
|
hdata_showidle.target = target_p;
|
||||||
|
hdata_showidle.approved = WHOIS_IDLE_SHOW;
|
||||||
|
|
||||||
|
call_hook(doing_stats_show_idle_hook, &hdata_showidle);
|
||||||
sendto_one_numeric(source_p, RPL_STATSLINKINFO, Lformat,
|
sendto_one_numeric(source_p, RPL_STATSLINKINFO, Lformat,
|
||||||
show_ip(source_p, target_p) ?
|
show_ip(source_p, target_p) ?
|
||||||
(IsUpper(statchar) ?
|
(IsUpper(statchar) ?
|
||||||
get_client_name(target_p, SHOW_IP) :
|
get_client_name(target_p, SHOW_IP) :
|
||||||
get_client_name(target_p, HIDE_IP)) :
|
get_client_name(target_p, HIDE_IP)) :
|
||||||
get_client_name(target_p, MASK_IP),
|
get_client_name(target_p, MASK_IP),
|
||||||
(int) rb_linebuf_len(&target_p->localClient->buf_sendq),
|
hdata_showidle.approved ? (int) rb_linebuf_len(&target_p->localClient->buf_sendq) : 0,
|
||||||
(int) target_p->localClient->sendM,
|
hdata_showidle.approved ? (int) target_p->localClient->sendM : 0,
|
||||||
(int) target_p->localClient->sendK,
|
hdata_showidle.approved ? (int) target_p->localClient->sendK : 0,
|
||||||
(int) target_p->localClient->receiveM,
|
hdata_showidle.approved ? (int) target_p->localClient->receiveM : 0,
|
||||||
(int) target_p->localClient->receiveK,
|
hdata_showidle.approved ? (int) target_p->localClient->receiveK : 0,
|
||||||
rb_current_time() - target_p->localClient->firsttime,
|
rb_current_time() - target_p->localClient->firsttime,
|
||||||
(rb_current_time() > target_p->localClient->lasttime) ?
|
(rb_current_time() > target_p->localClient->lasttime) && hdata_showidle.approved ?
|
||||||
(rb_current_time() - target_p->localClient->lasttime) : 0,
|
(rb_current_time() - target_p->localClient->lasttime) : 0,
|
||||||
"-");
|
"-");
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,10 +52,12 @@ struct Message trace_msgtab = {
|
||||||
};
|
};
|
||||||
|
|
||||||
int doing_trace_hook;
|
int doing_trace_hook;
|
||||||
|
int doing_trace_show_idle_hook;
|
||||||
|
|
||||||
mapi_clist_av1 trace_clist[] = { &trace_msgtab, NULL };
|
mapi_clist_av1 trace_clist[] = { &trace_msgtab, NULL };
|
||||||
mapi_hlist_av1 trace_hlist[] = {
|
mapi_hlist_av1 trace_hlist[] = {
|
||||||
{ "doing_trace", &doing_trace_hook },
|
{ "doing_trace", &doing_trace_hook },
|
||||||
|
{ "doing_trace_show_idle", &doing_trace_show_idle_hook },
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
DECLARE_MODULE_AV2(trace, NULL, NULL, trace_clist, trace_hlist, NULL, NULL, NULL, trace_desc);
|
DECLARE_MODULE_AV2(trace, NULL, NULL, trace_clist, trace_hlist, NULL, NULL, NULL, trace_desc);
|
||||||
|
@ -381,13 +383,22 @@ report_this_status(struct Client *source_p, struct Client *target_p)
|
||||||
|
|
||||||
case STAT_CLIENT:
|
case STAT_CLIENT:
|
||||||
{
|
{
|
||||||
|
/* fire the doing_trace_show_idle hook to allow modules to tell us whether to show the idle time */
|
||||||
|
hook_data_client_approval hdata_showidle;
|
||||||
|
|
||||||
|
hdata_showidle.client = source_p;
|
||||||
|
hdata_showidle.target = target_p;
|
||||||
|
hdata_showidle.approved = WHOIS_IDLE_SHOW;
|
||||||
|
|
||||||
|
call_hook(doing_trace_show_idle_hook, &hdata_showidle);
|
||||||
|
|
||||||
sendto_one_numeric(source_p,
|
sendto_one_numeric(source_p,
|
||||||
SeesOper(target_p, source_p) ? RPL_TRACEOPERATOR : RPL_TRACEUSER,
|
SeesOper(target_p, source_p) ? RPL_TRACEOPERATOR : RPL_TRACEUSER,
|
||||||
SeesOper(target_p, source_p) ? form_str(RPL_TRACEOPERATOR) : form_str(RPL_TRACEUSER),
|
SeesOper(target_p, source_p) ? form_str(RPL_TRACEOPERATOR) : form_str(RPL_TRACEUSER),
|
||||||
class_name, name,
|
class_name, name,
|
||||||
show_ip(source_p, target_p) ? ip : empty_sockhost,
|
show_ip(source_p, target_p) ? ip : empty_sockhost,
|
||||||
(unsigned long)(rb_current_time() - target_p->localClient->lasttime),
|
hdata_showidle.approved ? (unsigned long)(rb_current_time() - target_p->localClient->lasttime) : 0,
|
||||||
(unsigned long)(rb_current_time() - target_p->localClient->last));
|
hdata_showidle.approved ? (unsigned long)(rb_current_time() - target_p->localClient->last) : 0);
|
||||||
|
|
||||||
cnt++;
|
cnt++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,8 +91,14 @@ _moddeinit(void)
|
||||||
delete_isupport("WHOX");
|
delete_isupport("WHOX");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int doing_who_show_idle_hook;
|
||||||
|
|
||||||
mapi_clist_av1 who_clist[] = { &who_msgtab, NULL };
|
mapi_clist_av1 who_clist[] = { &who_msgtab, NULL };
|
||||||
DECLARE_MODULE_AV2(who, _modinit, _moddeinit, who_clist, NULL, NULL, NULL, NULL, who_desc);
|
mapi_hlist_av1 who_hlist[] = {
|
||||||
|
{ "doing_who_show_idle", &doing_who_show_idle_hook },
|
||||||
|
{ NULL, NULL }
|
||||||
|
};
|
||||||
|
DECLARE_MODULE_AV2(who, _modinit, _moddeinit, who_clist, who_hlist, NULL, NULL, NULL, who_desc);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** m_who
|
** m_who
|
||||||
|
@ -531,7 +537,19 @@ do_who(struct Client *source_p, struct Client *target_p, struct membership *mspt
|
||||||
if (fmt->fields & FIELD_HOP)
|
if (fmt->fields & FIELD_HOP)
|
||||||
append_format(str, sizeof str, &pos, " %d", ConfigServerHide.flatten_links && !IsOperGeneral(source_p) && !IsExemptShide(source_p) ? 0 : target_p->hopcount);
|
append_format(str, sizeof str, &pos, " %d", ConfigServerHide.flatten_links && !IsOperGeneral(source_p) && !IsExemptShide(source_p) ? 0 : target_p->hopcount);
|
||||||
if (fmt->fields & FIELD_IDLE)
|
if (fmt->fields & FIELD_IDLE)
|
||||||
append_format(str, sizeof str, &pos, " %d", (int)(MyClient(target_p) ? rb_current_time() - target_p->localClient->last : 0));
|
{
|
||||||
|
/* fire the doing_who_show_idle hook to allow modules to tell us whether to show the idle time */
|
||||||
|
hook_data_client_approval hdata_showidle;
|
||||||
|
|
||||||
|
hdata_showidle.client = source_p;
|
||||||
|
hdata_showidle.target = target_p;
|
||||||
|
hdata_showidle.approved = WHOIS_IDLE_SHOW;
|
||||||
|
|
||||||
|
call_hook(doing_who_show_idle_hook, &hdata_showidle);
|
||||||
|
|
||||||
|
append_format(str, sizeof str, &pos, " %d",
|
||||||
|
hdata_showidle.approved ? (int)(MyClient(target_p) ? rb_current_time() - target_p->localClient->last : 0) : 0);
|
||||||
|
}
|
||||||
if (fmt->fields & FIELD_ACCOUNT)
|
if (fmt->fields & FIELD_ACCOUNT)
|
||||||
{
|
{
|
||||||
/* display as in whois */
|
/* display as in whois */
|
||||||
|
|
|
@ -60,12 +60,14 @@ struct Message whois_msgtab = {
|
||||||
int doing_whois_hook;
|
int doing_whois_hook;
|
||||||
int doing_whois_global_hook;
|
int doing_whois_global_hook;
|
||||||
int doing_whois_channel_visibility_hook;
|
int doing_whois_channel_visibility_hook;
|
||||||
|
int doing_whois_show_idle_hook;
|
||||||
|
|
||||||
mapi_clist_av1 whois_clist[] = { &whois_msgtab, NULL };
|
mapi_clist_av1 whois_clist[] = { &whois_msgtab, NULL };
|
||||||
mapi_hlist_av1 whois_hlist[] = {
|
mapi_hlist_av1 whois_hlist[] = {
|
||||||
{ "doing_whois", &doing_whois_hook },
|
{ "doing_whois", &doing_whois_hook },
|
||||||
{ "doing_whois_global", &doing_whois_global_hook },
|
{ "doing_whois_global", &doing_whois_global_hook },
|
||||||
{ "doing_whois_channel_visibility", &doing_whois_channel_visibility_hook },
|
{ "doing_whois_channel_visibility", &doing_whois_channel_visibility_hook },
|
||||||
|
{ "doing_whois_show_idle", &doing_whois_show_idle_hook },
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -373,10 +375,23 @@ single_whois(struct Client *source_p, struct Client *target_p, int operspy)
|
||||||
target_p->name, buf);
|
target_p->name, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* fire the doing_whois_show_idle hook to allow modules to tell us whether to show the idle time */
|
||||||
|
hook_data_client_approval hdata_showidle;
|
||||||
|
|
||||||
|
hdata_showidle.client = source_p;
|
||||||
|
hdata_showidle.target = target_p;
|
||||||
|
hdata_showidle.approved = WHOIS_IDLE_SHOW;
|
||||||
|
|
||||||
|
call_hook(doing_whois_show_idle_hook, &hdata_showidle);
|
||||||
|
|
||||||
sendto_one_numeric(source_p, RPL_WHOISIDLE, form_str(RPL_WHOISIDLE),
|
sendto_one_numeric(source_p, RPL_WHOISIDLE, form_str(RPL_WHOISIDLE),
|
||||||
target_p->name,
|
target_p->name,
|
||||||
(long)(rb_current_time() - target_p->localClient->last),
|
hdata_showidle.approved ? (long)(rb_current_time() - target_p->localClient->last) : 0,
|
||||||
(unsigned long)target_p->localClient->firsttime);
|
(unsigned long)target_p->localClient->firsttime);
|
||||||
|
|
||||||
|
if (hdata_showidle.approved == WHOIS_IDLE_AUSPEX || hdata_showidle.approved == WHOIS_IDLE_HIDE)
|
||||||
|
/* if the target has hidden their idle time, notify the source */
|
||||||
|
sendto_one_numeric(source_p, RPL_WHOISTEXT, form_str(RPL_WHOISTEXT), target_p->name, "is using a private idle time");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue