1 Add usermode +q which requires users /msg'ing or /notice'ing you to be in at least one common channel.
2 This is designed to stop the spam bots which sit outside a channel, while a spy sits inside, preventing channel operators dealing with the problem.
3 We currently also block invites, this might not be such a good idea, but these days everyone can get Q.
5 diff -r ed4109685dc2 include/channel.h
6 --- a/include/channel.h
7 +++ b/include/channel.h
9 extern void free_ban(struct Ban *ban);
11 extern unsigned int get_channel_marker(void);
12 +extern int common_chan_count(struct Client *a, struct Client *b, int max);
14 #endif /* INCLUDED_channel_h */
15 diff -r ed4109685dc2 include/client.h
16 --- a/include/client.h
17 +++ b/include/client.h
19 #define FlagClr(set,flag) ((set)->bits[FLAGSET_INDEX(flag)] &= ~FLAGSET_MASK(flag))
21 /** String containing valid user modes, in no particular order. */
22 -#define infousermodes "dioOswkghxRXInP"
23 +#define infousermodes "dioOswkghxRXInPq"
25 /** Character to indicate no oper name available */
26 #define NOOPERNAMECHARACTER '-'
28 FLAG_NOIDLE, /**< user's idletime is hidden */
29 FLAG_XTRAOP, /**< oper has special powers */
30 FLAG_OPERNAME, /**< Server sends oper name in mode string */
32 + FLAG_COMMONCHANSONLY, /**< SNIRCD_q: hide privmsgs/notices if in no
33 + common channels (with +ok exceptions) */
34 FLAG_LAST_FLAG, /**< number of flags */
35 FLAG_LOCAL_UMODES = FLAG_LOCOP, /**< First local mode flag */
36 FLAG_GLOBAL_UMODES = FLAG_OPER /**< First global mode flag */
38 #define IsParanoid(x) HasFlag(x, FLAG_PARANOID)
39 /** Return non-zero if the server should send opername information */
40 #define IsSendOperName(x) HasFlag(x, FLAG_OPERNAME)
41 +/** Return non-zero if the client has set mode +q (common chans only). */
42 +#define IsCommonChansOnly(x) HasFlag(x, FLAG_COMMONCHANSONLY)
44 /** Return non-zero if the client has operator or server privileges. */
45 #define IsPrivileged(x) (IsAnOper(x) || IsServer(x))
47 #define SetAccountOnly(x) SetFlag(x, FLAG_ACCOUNTONLY)
48 /** Mark a client as having mode +P (paranoid). */
49 #define SetParanoid(x) SetFlag(x, FLAG_PARANOID)
50 +/** Mark a client as having mode +q (common chans only). */
51 +#define SetCommonChansOnly(x) SetFlag(x, FLAG_COMMONCHANSONLY)
53 /** Return non-zero if \a sptr sees \a acptr as an operator. */
54 #define SeeOper(sptr,acptr) (IsAnOper(acptr) && (HasPriv(acptr, PRIV_DISPLAY) \
56 #define ClearAccountOnly(x) ClrFlag(x, FLAG_ACCOUNTONLY)
57 /** Remove mode +P (paranoid) from a client */
58 #define ClearParanoid(x) ClrFlag(x, FLAG_PARANOID)
59 +/** Remove mode +q (common chans only) from a client */
60 +#define ClearCommonChansOnly(x) ClrFlag(x, FLAG_COMMONCHANSONLY)
63 #define FREEFLAG_SOCKET 0x0001 /**< socket needs to be freed */
64 diff -r ed4109685dc2 include/numeric.h
65 --- a/include/numeric.h
66 +++ b/include/numeric.h
68 /* ERR_HTMDISABLED 486 unreal */
69 #define ERR_ACCOUNTONLY 486 /* QuakeNet/ASUKA extension */
70 /* ERR_CHANTOORECENT 487 IRCnet extension (?) */
71 +#define ERR_COMMONCHANSONLY 487 /* QuakeNet/snircd extension */
72 /* ERR_TSLESSCHAN 488 IRCnet extension (?) */
73 #define ERR_VOICENEEDED 489 /* Undernet extension */
75 diff -r ed4109685dc2 ircd/channel.c
78 @@ -3818,3 +3818,39 @@
83 +/* Returns the number of common channels between two users, upto max. */
84 +int common_chan_count(struct Client *a, struct Client *b, int max)
87 + struct Membership *cptr;
88 + struct User *ua, *ub;
89 + unsigned int marker = get_client_marker();
94 + /* makes no difference to the big O complexity I know */
95 + if(ua->joined > ub->joined)
97 + struct User *swapee = ua;
102 + for (cptr=ua->channel;cptr;cptr=cptr->next_channel)
104 + cptr->channel->marker = marker;
107 + for (cptr=ub->channel;cptr;cptr=cptr->next_channel)
109 + if (cptr->channel->marker == marker) {
111 + if (max && (count >= max))
118 diff -r ed4109685dc2 ircd/ircd_relay.c
119 --- a/ircd/ircd_relay.c
120 +++ b/ircd/ircd_relay.c
122 if (IsAccountOnly(acptr) && !IsAccount(sptr) && !IsXtraOp(sptr))
125 + /* slug: same applies here, since only opers can be +k */
126 + if (IsCommonChansOnly(acptr) && !IsXtraOp(sptr) && !common_chan_count(acptr, sptr, 1))
129 if (!(is_silenced(sptr, acptr)))
130 sendcmdto_one(sptr, CMD_PRIVATE, acptr, "%s :%s", name, text);
133 if (IsAccountOnly(acptr) && !IsAccount(sptr) && !IsXtraOp(sptr))
136 + if (IsCommonChansOnly(acptr) && !IsXtraOp(sptr) && !common_chan_count(acptr, sptr, 1))
139 if (!(is_silenced(sptr, acptr)))
140 sendcmdto_one(sptr, CMD_NOTICE, acptr, "%s :%s", name, text);
146 + if (IsCommonChansOnly(acptr) && !IsXtraOp(sptr) && !common_chan_count(acptr, sptr, 1)) {
147 + send_reply(sptr, ERR_COMMONCHANSONLY, cli_name(acptr));
152 * send away message if user away
155 if (IsAccountOnly(acptr) && !IsAccount(sptr) && !IsXtraOp(sptr))
158 + if (IsCommonChansOnly(acptr) && !IsXtraOp(sptr) && !common_chan_count(acptr, sptr, 1))
162 * deliver the message
164 diff -r ed4109685dc2 ircd/m_invite.c
165 --- a/ircd/m_invite.c
166 +++ b/ircd/m_invite.c
171 + if (IsCommonChansOnly(acptr) && !IsXtraOp(sptr) && !common_chan_count(acptr, sptr, 1))
174 if (check_target_limit(sptr, acptr, cli_name(acptr), 0))
177 diff -r ed4109685dc2 ircd/s_err.c
180 @@ -1006,7 +1006,7 @@
182 { ERR_ACCOUNTONLY, "%s :You must be authed in order to message this user -- For details of how to obtain an account visit %s", "486" },
185 + { ERR_COMMONCHANSONLY, "%s :You must share at least one channel with this user in order to message them", "487" },
189 diff -r ed4109685dc2 ircd/s_user.c
193 { FLAG_NOCHAN, 'n' },
194 { FLAG_NOIDLE, 'I' },
195 { FLAG_SETHOST, 'h' },
196 - { FLAG_PARANOID, 'P' }
197 + { FLAG_PARANOID, 'P' },
198 + { FLAG_COMMONCHANSONLY, 'q' }
201 /** Length of #userModeList. */
203 send_reply(source, ERR_ACCOUNTONLY, cli_name(dest), feature_str(FEAT_URLREG));
208 + /* No check here for IsCommonChansOnly since by definition we share at least one! */
211 sendcmdto_one(source, CMD_NOTICE, dest, "%C :%s", dest, text);
213 @@ -1319,6 +1322,12 @@
218 + if (what == MODE_ADD)
219 + SetCommonChansOnly(sptr);
221 + ClearCommonChansOnly(sptr);
224 if ((what == MODE_ADD) && *(p + 1)) {