2 * IRC - Internet Relay Chat, ircd/ircd_relay.c
3 * Copyright (C) 1990 Jarkko Oikarinen and
4 * University of Oulu, Computing Center
6 * See file AUTHORS in IRC package for additional names of
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 1, or (at your option)
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 #include "ircd_relay.h"
32 #include "ircd_chattr.h"
33 #include "ircd_features.h"
34 #include "ircd_reply.h"
35 #include "ircd_string.h"
51 * This file contains message relaying functions for client and server
52 * private messages and notices
53 * TODO: This file contains a lot of cut and paste code, and needs
54 * to be cleaned up a bit. The idea is to factor out the common checks
55 * but not introduce any IsOper/IsUser/MyUser/IsServer etc. stuff.
57 void relay_channel_message(struct Client* sptr, const char* name, const char* text)
59 struct Channel* chptr;
64 if (0 == (chptr = FindChannel(name))) {
65 send_reply(sptr, ERR_NOSUCHCHANNEL, name);
69 * This first: Almost never a server/service
71 if (!client_can_send_to_channel(sptr, chptr, 1)) {
72 send_reply(sptr, ERR_CANNOTSENDTOCHAN, chptr->chname);
75 if ((chptr->mode.mode & MODE_NOPRIVMSGS) &&
76 check_target_limit(sptr, chptr, chptr->chname, 0))
79 sendcmdto_channel_butone(sptr, CMD_PRIVATE, chptr, cli_from(sptr),
80 SKIP_DEAF | SKIP_BURST, "%H :%s", chptr, text);
83 void relay_channel_notice(struct Client* sptr, const char* name, const char* text)
85 struct Channel* chptr;
90 if (0 == (chptr = FindChannel(name)))
93 * This first: Almost never a server/service
95 if (!client_can_send_to_channel(sptr, chptr, 1))
98 if ((chptr->mode.mode & MODE_NOPRIVMSGS) &&
99 check_target_limit(sptr, chptr, chptr->chname, 0))
102 sendcmdto_channel_butone(sptr, CMD_NOTICE, chptr, cli_from(sptr),
103 SKIP_DEAF | SKIP_BURST, "%H :%s", chptr, text);
106 void server_relay_channel_message(struct Client* sptr, const char* name, const char* text)
108 struct Channel* chptr;
113 if (IsLocalChannel(name) || 0 == (chptr = FindChannel(name))) {
115 * XXX - do we need to send this back from a remote server?
117 send_reply(sptr, ERR_NOSUCHCHANNEL, name);
121 * This first: Almost never a server/service
122 * Servers may have channel services, need to check for it here
124 if (client_can_send_to_channel(sptr, chptr, 1) || IsChannelService(sptr)) {
125 sendcmdto_channel_butone(sptr, CMD_PRIVATE, chptr, cli_from(sptr),
126 SKIP_DEAF | SKIP_BURST, "%H :%s", chptr, text);
129 send_reply(sptr, ERR_CANNOTSENDTOCHAN, chptr->chname);
132 void server_relay_channel_notice(struct Client* sptr, const char* name, const char* text)
134 struct Channel* chptr;
139 if (IsLocalChannel(name) || 0 == (chptr = FindChannel(name)))
142 * This first: Almost never a server/service
143 * Servers may have channel services, need to check for it here
145 if (client_can_send_to_channel(sptr, chptr, 1) || IsChannelService(sptr)) {
146 sendcmdto_channel_butone(sptr, CMD_NOTICE, chptr, cli_from(sptr),
147 SKIP_DEAF | SKIP_BURST, "%H :%s", chptr, text);
152 void relay_directed_message(struct Client* sptr, char* name, char* server, const char* text)
154 struct Client* acptr;
162 if ((acptr = FindServer(server + 1)) == NULL || !IsService(acptr))
164 send_reply(sptr, ERR_NOSUCHNICK, name);
168 * NICK[%host]@server addressed? See if <server> is me first
172 sendcmdto_one(sptr, CMD_PRIVATE, acptr, "%s :%s", name, text);
176 * Look for an user whose NICK is equal to <name> and then
177 * check if it's hostname matches <host> and if it's a local
181 if ((host = strchr(name, '%')))
184 /* As reported by Vampire-, it's possible to brute force finding users
185 * by sending a message to each server and see which one succeeded.
186 * This means we have to remove error reporting. Sigh. Better than
187 * removing the ability to send directed messages to client servers
188 * Thanks for the suggestion Vampire=. -- Isomer 2001-08-28
189 * Argh, /ping nick@server, disallow messages to non +k clients :/ I hate
190 * this. -- Isomer 2001-09-16
192 if (!(acptr = FindUser(name)) || !MyUser(acptr) ||
193 (!EmptyString(host) && 0 != match(host, cli_user(acptr)->host)) ||
194 !IsChannelService(acptr))
197 * By this stage we might as well not bother because they will
198 * know that this server is currently linked because of the
201 send_reply(sptr, ERR_NOSUCHNICK, name);
209 if (!(is_silenced(sptr, acptr)))
210 sendcmdto_one(sptr, CMD_PRIVATE, acptr, "%s :%s", name, text);
213 void relay_directed_notice(struct Client* sptr, char* name, char* server, const char* text)
215 struct Client* acptr;
223 if (0 == (acptr = FindServer(server + 1)))
226 * NICK[%host]@server addressed? See if <server> is me first
229 sendcmdto_one(sptr, CMD_NOTICE, acptr, "%s :%s", name, text);
233 * Look for an user whose NICK is equal to <name> and then
234 * check if it's hostname matches <host> and if it's a local
238 if ((host = strchr(name, '%')))
241 if (!(acptr = FindUser(name)) || !MyUser(acptr) ||
242 (!EmptyString(host) && 0 != match(host, cli_user(acptr)->host)))
249 if (!(is_silenced(sptr, acptr)))
250 sendcmdto_one(sptr, CMD_NOTICE, acptr, "%s :%s", name, text);
253 void relay_private_message(struct Client* sptr, const char* name, const char* text)
255 struct Client* acptr;
261 if (0 == (acptr = FindUser(name))) {
262 send_reply(sptr, ERR_NOSUCHNICK, name);
265 if ((!IsChannelService(acptr) &&
266 check_target_limit(sptr, acptr, cli_name(acptr), 0)) ||
267 is_silenced(sptr, acptr))
271 * send away message if user away
273 if (cli_user(acptr) && cli_user(acptr)->away)
274 send_reply(sptr, RPL_AWAY, cli_name(acptr), cli_user(acptr)->away);
276 * deliver the message
279 add_target(acptr, sptr);
281 sendcmdto_one(sptr, CMD_PRIVATE, acptr, "%C :%s", acptr, text);
284 void relay_private_notice(struct Client* sptr, const char* name, const char* text)
286 struct Client* acptr;
291 if (0 == (acptr = FindUser(name)))
293 if ((!IsChannelService(acptr) &&
294 check_target_limit(sptr, acptr, cli_name(acptr), 0)) ||
295 is_silenced(sptr, acptr))
298 * deliver the message
301 add_target(acptr, sptr);
303 sendcmdto_one(sptr, CMD_NOTICE, acptr, "%C :%s", acptr, text);
306 void server_relay_private_message(struct Client* sptr, const char* name, const char* text)
308 struct Client* acptr;
313 * nickname addressed?
315 if (0 == (acptr = findNUser(name)) || !IsUser(acptr)) {
316 send_reply(sptr, SND_EXPLICIT | ERR_NOSUCHNICK, "* :Target left %s. "
317 "Failed to deliver: [%.20s]", feature_str(FEAT_NETWORK),
321 if (is_silenced(sptr, acptr))
325 add_target(acptr, sptr);
327 sendcmdto_one(sptr, CMD_PRIVATE, acptr, "%C :%s", acptr, text);
331 void server_relay_private_notice(struct Client* sptr, const char* name, const char* text)
333 struct Client* acptr;
338 * nickname addressed?
340 if (0 == (acptr = findNUser(name)) || !IsUser(acptr))
343 if (is_silenced(sptr, acptr))
347 add_target(acptr, sptr);
349 sendcmdto_one(sptr, CMD_NOTICE, acptr, "%C :%s", acptr, text);
352 void relay_masked_message(struct Client* sptr, const char* mask, const char* text)
361 * look for the last '.' in mask and scan forward
363 if (0 == (s = strrchr(mask, '.'))) {
364 send_reply(sptr, ERR_NOTOPLEVEL, mask);
368 if (*s == '.' || *s == '*' || *s == '?')
371 if (*s == '*' || *s == '?') {
372 send_reply(sptr, ERR_WILDTOPLEVEL, mask);
381 sendcmdto_match_butone(sptr, CMD_PRIVATE, s,
382 IsServer(cli_from(sptr)) ? cli_from(sptr) : 0,
383 host_mask ? MATCH_HOST : MATCH_SERVER,
384 "%s :%s", mask, text);
387 void relay_masked_notice(struct Client* sptr, const char* mask, const char* text)
396 * look for the last '.' in mask and scan forward
398 if (0 == (s = strrchr(mask, '.'))) {
399 send_reply(sptr, ERR_NOTOPLEVEL, mask);
403 if (*s == '.' || *s == '*' || *s == '?')
406 if (*s == '*' || *s == '?') {
407 send_reply(sptr, ERR_WILDTOPLEVEL, mask);
416 sendcmdto_match_butone(sptr, CMD_NOTICE, s,
417 IsServer(cli_from(sptr)) ? cli_from(sptr) : 0,
418 host_mask ? MATCH_HOST : MATCH_SERVER,
419 "%s :%s", mask, text);
422 void server_relay_masked_message(struct Client* sptr, const char* mask, const char* text)
424 const char* s = mask;
434 sendcmdto_match_butone(sptr, CMD_PRIVATE, s,
435 IsServer(cli_from(sptr)) ? cli_from(sptr) : 0,
436 host_mask ? MATCH_HOST : MATCH_SERVER,
437 "%s :%s", mask, text);
440 void server_relay_masked_notice(struct Client* sptr, const char* mask, const char* text)
442 const char* s = mask;
452 sendcmdto_match_butone(sptr, CMD_NOTICE, s,
453 IsServer(cli_from(sptr)) ? cli_from(sptr) : 0,
454 host_mask ? MATCH_HOST : MATCH_SERVER,
455 "%s :%s", mask, text);