unsigned search_chan:1;
unsigned ip_show:1;
unsigned realhost_show:1;
+ unsigned maskhost_show:1;
unsigned client_type_plus:1;
} SOpts;
#define RWO_MATCHES 0x2000
#define RWO_CHANNEL 0x4000
#define RWO_PROB 0x8000
+#define RWO_MASKED_HOST 0x10000
+#define RWO_UNMASKED_HOST 0x20000
/* miscellaneous flags */
#define RWC_SHOWIP 0x0001 /* WHO compatibility */
#define RWC_CHANNEL 0x0002 /* WHO compatibility */
#define RWC_TIME 0x0004 /* show timing stats */
+#ifdef USER_HOSTMASKING
+#define RWHO_HOST(cptr) IsUmodeH(cptr)?cptr->user->mhost:cptr->user->host
+#else
+#define RWHO_HOST(cptr) cptr->user->host
+#endif
+
static const char *rwho_help[] = {
"RWHO <[+|-]matchflags>[/<outputflags>[:<cookie>]] <args>",
"Match flags are specified like channel modes,",
" :<cookie> - supplied cookie (useful for scripts)",
" n - user's nick",
" u - user's username",
+#ifdef USER_HOSTMASKING
+ " h - user's current host",
+ " H - user's masked host",
+ " R - user's real/unmasked host",
+#else
" h - user's host",
+#endif
" i - user's IP",
" s - user's server",
" f - standard WHO flags (GH*%@+)",
#endif
} rwho_opts;
-static char rwhobuf[1024];
+static char rwhobuf[2048];
static char scratch[1024];
case 'n': rwho_opts.rplfields |= RWO_NICK; sfl++; break;
case 'u': rwho_opts.rplfields |= RWO_USER; sfl++; break;
case 'h': rwho_opts.rplfields |= RWO_HOST; sfl++; break;
+#ifdef USER_HOSTMASKING
+ case 'H': rwho_opts.rplfields |= RWO_MASKED_HOST; sfl++; break;
+ case 'R': rwho_opts.rplfields |= RWO_UNMASKED_HOST; sfl++; break;
+#endif
case 'i': rwho_opts.rplfields |= RWO_IP; sfl++; break;
case 's': rwho_opts.rplfields |= RWO_SERVER; sfl++; break;
case 'f': rwho_opts.rplfields |= RWO_FLAGS; sfl++; break;
}
if ((rwho_opts.check[0] & RWM_HOST) &&
- rwho_opts.host_func[0](rwho_opts.host_pat[0], cptr->user->host))
+ rwho_opts.host_func[0](rwho_opts.host_pat[0], cptr->user->host) && rwho_opts.host_func[0](rwho_opts.host_pat[0], cptr->user->mhost))
return 0;
if ((rwho_opts.check[1] & RWM_HOST) &&
- !rwho_opts.host_func[1](rwho_opts.host_pat[1], cptr->user->host))
+ !rwho_opts.host_func[1](rwho_opts.host_pat[1], cptr->user->host) && !rwho_opts.host_func[1](rwho_opts.host_pat[1], cptr->user->mhost))
return 0;
#ifdef RWHO_PROBABILITY
if (rwho_opts.misc & RWC_SHOWIP)
src = ac->hostip;
else
- src = ac->user->host;
+ src = RWHO_HOST(ac);
ircsprintf(buf, getreply(RPL_WHOREPLY), me.name, cptr->name,
rwho_opts.chptr ? rwho_opts.chptr->chname : chname,
}
if (rwho_opts.rplfields & RWO_HOST)
+ {
+ src = RWHO_HOST(ac);
+ *dst++ = ' ';
+ while (*src)
+ *dst++ = *src++;
+ }
+
+#ifdef USER_HOSTMASKING
+ if (rwho_opts.rplfields & RWO_MASKED_HOST)
+ {
+ src = ac->user->mhost;
+ *dst++ = ' ';
+ while (*src)
+ *dst++ = *src++;
+ }
+ if (rwho_opts.rplfields & RWO_UNMASKED_HOST)
{
src = ac->user->host;
*dst++ = ' ';
while (*src)
*dst++ = *src++;
}
+#endif
if (rwho_opts.rplfields & RWO_IP)
{
{
static char *who_oper_help[] =
{
- "/WHO [+|-][acghilmnstuCM] [args]",
+#ifdef USER_HOSTMASKING
+ "/WHO [+|-][acghilmnstuCHIMR] [args]",
+#else
+ "/WHO [+|-][acghilmnstuCIM] [args]",
+#endif
"Flags are specified like channel modes,",
"The flags cghimnsu all have arguments",
"Flags are set to a positive check by +, a negative check by -",
"Flag M: check for user in channels I am a member of",
"Flag I: always show IPs instead of hosts",
#ifdef USER_HOSTMASKING
+ "Flag H: show the masked host even if the user's host is not masked (umode -H)",
"Flag R: show the real host even if the user's host is masked (umode +H)",
#endif
NULL
wsopts.ip_show = change;
break;
#ifdef USER_HOSTMASKING
+ case 'H':
+ if(!IsAnOper(sptr))
+ {
+ sendto_one(sptr, getreply(ERR_NOPRIVILEGES), me.name, parv[0]);
+ return 0;
+ }
+ wsopts.maskhost_show = change;
+ break;
case 'R':
if(!IsAnOper(sptr))
{
(!wsopts.user_plus && !uchkfn(wsopts.user, ac->user->username)))
return 0;
- if(wsopts.nick!=NULL)
- if((wsopts.nick_plus && nchkfn(wsopts.nick, ac->name)) ||
- (!wsopts.nick_plus && !nchkfn(wsopts.nick, ac->name)))
- return 0;
+ if(wsopts.host!=NULL)
+ {
+#ifdef USER_HOSTMASKING
+ if(IsAnOper(sptr))
+ {
+ if((wsopts.host_plus && hchkfn(wsopts.host, ac->user->host) && hchkfn(wsopts.host, ac->user->mhost)) ||
+ (!wsopts.host_plus && (!hchkfn(wsopts.host, ac->user->host) || !hchkfn(wsopts.host, ac->user->mhost))))
+ return 0;
+ }
+ else
+ {
+ if((wsopts.host_plus && hchkfn(wsopts.host, IsUmodeH(ac)?ac->user->mhost:ac->user->host)) ||
+ (!wsopts.host_plus && !hchkfn(wsopts.host, IsUmodeH(ac)?ac->user->mhost:ac->user->host)))
+ return 0;
+ }
+#else
+ if((wsopts.host_plus && hchkfn(wsopts.host, ac->user->host)) ||
+ (!wsopts.host_plus && !hchkfn(wsopts.host, ac->user->host)))
+ return 0;
+#endif
+ }
if(wsopts.host!=NULL)
if((wsopts.host_plus && hchkfn(wsopts.host, ac->user->host)) ||
/*
* For the below options, a value of two means '+',
* a value of 1 means '-', and a value of 0 means
- * not speficied.
+ * not specified.
*/
if(wsopts.ts_value == 2 && /* +t */
#define WHO_HOPCOUNT(s, a) ( ( (IsULine((a)) || IsUmodeI((a))) && !IsAnOper((s)) ) ? 0 : a->hopcount)
#define WHO_SERVER(s ,a) ((IsUmodeI((a)) && !IsAnOper((s))) ? HIDDEN_SERVER_NAME : a->user->server)
#ifdef USER_HOSTMASKING
-#define WHO_HOST(s, a) ((wsopts.ip_show) ? (a)->hostip : (IsUmodeH((a)) && !wsopts.realhost_show) ? (a)->user->mhost : (a)->user->host)
+#define WHO_HOST(s, a) ((wsopts.ip_show) ? (a)->hostip : ((IsUmodeH((a)) && !wsopts.realhost_show) || wsopts.maskhost_show) ? (a)->user->mhost : (a)->user->host)
#else
#define WHO_HOST(s, a) ((wsopts.ip_show) ? (a)->hostip : (a)->user->host)
#endif