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
|
||||
* Oper-override (modehacking only) -- override
|
||||
* 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_nonotice";
|
||||
|
@ -110,6 +111,7 @@
|
|||
#loadmodule "extensions/sno_globaloper";
|
||||
#loadmodule "extensions/override";
|
||||
#loadmodule "extensions/no_kill_services";
|
||||
#loadmodule "extensions/umode_hide_idle_time";
|
||||
|
||||
/* serverinfo {}: Contains information about the server. (OLD M:) */
|
||||
serverinfo {
|
||||
|
@ -474,6 +476,8 @@ privset "local_op" {
|
|||
* oper:receive_immunity:
|
||||
* confers the benefits of chmode +M (operpeace) (from extensions/chm_operpeace)
|
||||
* 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,
|
||||
usermode:servnotice, auspex:oper, auspex:hostname, auspex:umodes, auspex:cmodes;
|
||||
|
|
|
@ -66,6 +66,7 @@ extension_LTLIBRARIES = \
|
|||
identify_msg.la \
|
||||
cap_realhost.la \
|
||||
invex_regonly.la \
|
||||
umode_hide_idle_time.la \
|
||||
cap_oper.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
|
||||
with you from messaging you and inviting you to channels.
|
||||
This is a softer form of +g.
|
||||
? +I - Hides your idle time.
|
||||
+Q - Prevents you from being affected by channel forwarding.
|
||||
+R - Prevents unidentified users that you have not accepted from
|
||||
messaging you.
|
||||
|
|
|
@ -21,6 +21,14 @@ enum hook_priority
|
|||
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);
|
||||
|
||||
extern int h_iosend_id;
|
||||
|
|
|
@ -60,11 +60,13 @@ struct Message stats_msgtab = {
|
|||
|
||||
int doing_stats_hook;
|
||||
int doing_stats_p_hook;
|
||||
int doing_stats_show_idle_hook;
|
||||
|
||||
mapi_clist_av1 stats_clist[] = { &stats_msgtab, NULL };
|
||||
mapi_hlist_av1 stats_hlist[] = {
|
||||
{ "doing_stats", &doing_stats_hook },
|
||||
{ "doing_stats_p", &doing_stats_p_hook },
|
||||
{ "doing_stats_show_idle", &doing_stats_show_idle_hook },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
@ -1621,19 +1623,27 @@ stats_l_client(struct Client *source_p, struct Client *target_p,
|
|||
|
||||
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,
|
||||
show_ip(source_p, target_p) ?
|
||||
(IsUpper(statchar) ?
|
||||
get_client_name(target_p, SHOW_IP) :
|
||||
get_client_name(target_p, HIDE_IP)) :
|
||||
get_client_name(target_p, MASK_IP),
|
||||
(int) rb_linebuf_len(&target_p->localClient->buf_sendq),
|
||||
(int) target_p->localClient->sendM,
|
||||
(int) target_p->localClient->sendK,
|
||||
(int) target_p->localClient->receiveM,
|
||||
(int) target_p->localClient->receiveK,
|
||||
hdata_showidle.approved ? (int) rb_linebuf_len(&target_p->localClient->buf_sendq) : 0,
|
||||
hdata_showidle.approved ? (int) target_p->localClient->sendM : 0,
|
||||
hdata_showidle.approved ? (int) target_p->localClient->sendK : 0,
|
||||
hdata_showidle.approved ? (int) target_p->localClient->receiveM : 0,
|
||||
hdata_showidle.approved ? (int) target_p->localClient->receiveK : 0,
|
||||
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,
|
||||
"-");
|
||||
}
|
||||
|
|
|
@ -52,10 +52,12 @@ struct Message trace_msgtab = {
|
|||
};
|
||||
|
||||
int doing_trace_hook;
|
||||
int doing_trace_show_idle_hook;
|
||||
|
||||
mapi_clist_av1 trace_clist[] = { &trace_msgtab, NULL };
|
||||
mapi_hlist_av1 trace_hlist[] = {
|
||||
{ "doing_trace", &doing_trace_hook },
|
||||
{ "doing_trace_show_idle", &doing_trace_show_idle_hook },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
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:
|
||||
{
|
||||
/* 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,
|
||||
SeesOper(target_p, source_p) ? RPL_TRACEOPERATOR : RPL_TRACEUSER,
|
||||
SeesOper(target_p, source_p) ? form_str(RPL_TRACEOPERATOR) : form_str(RPL_TRACEUSER),
|
||||
class_name, name,
|
||||
show_ip(source_p, target_p) ? ip : empty_sockhost,
|
||||
(unsigned long)(rb_current_time() - target_p->localClient->lasttime),
|
||||
(unsigned long)(rb_current_time() - target_p->localClient->last));
|
||||
hdata_showidle.approved ? (unsigned long)(rb_current_time() - target_p->localClient->lasttime) : 0,
|
||||
hdata_showidle.approved ? (unsigned long)(rb_current_time() - target_p->localClient->last) : 0);
|
||||
|
||||
cnt++;
|
||||
}
|
||||
|
|
|
@ -91,8 +91,14 @@ _moddeinit(void)
|
|||
delete_isupport("WHOX");
|
||||
}
|
||||
|
||||
int doing_who_show_idle_hook;
|
||||
|
||||
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
|
||||
|
@ -531,7 +537,19 @@ do_who(struct Client *source_p, struct Client *target_p, struct membership *mspt
|
|||
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);
|
||||
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)
|
||||
{
|
||||
/* display as in whois */
|
||||
|
|
|
@ -60,12 +60,14 @@ struct Message whois_msgtab = {
|
|||
int doing_whois_hook;
|
||||
int doing_whois_global_hook;
|
||||
int doing_whois_channel_visibility_hook;
|
||||
int doing_whois_show_idle_hook;
|
||||
|
||||
mapi_clist_av1 whois_clist[] = { &whois_msgtab, NULL };
|
||||
mapi_hlist_av1 whois_hlist[] = {
|
||||
{ "doing_whois", &doing_whois_hook },
|
||||
{ "doing_whois_global", &doing_whois_global_hook },
|
||||
{ "doing_whois_channel_visibility", &doing_whois_channel_visibility_hook },
|
||||
{ "doing_whois_show_idle", &doing_whois_show_idle_hook },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
@ -373,10 +375,23 @@ single_whois(struct Client *source_p, struct Client *target_p, int operspy)
|
|||
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),
|
||||
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);
|
||||
|
||||
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
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue