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_reply.h"
34 #include "ircd_string.h"
50 * This file contains message relaying functions for client and server
51 * private messages and notices
52 * TODO: This file contains a lot of cut and paste code, and needs
53 * to be cleaned up a bit. The idea is to factor out the common checks
54 * but not introduce any IsOper/IsUser/MyUser/IsServer etc. stuff.
56 void relay_channel_message(struct Client* sptr, const char* name, const char* text)
58 struct Channel* chptr;
63 if (0 == (chptr = FindChannel(name))) {
64 send_reply(sptr, ERR_NOSUCHCHANNEL, name);
68 * This first: Almost never a server/service
70 if (!client_can_send_to_channel(sptr, chptr)) {
71 send_reply(sptr, ERR_CANNOTSENDTOCHAN, chptr->chname);
74 if ((chptr->mode.mode & MODE_NOPRIVMSGS) &&
75 check_target_limit(sptr, chptr, chptr->chname, 0))
78 sendcmdto_channel_butone(sptr, CMD_PRIVATE, chptr, cli_from(sptr),
79 SKIP_DEAF | SKIP_BURST, "%H :%s", chptr, text);
82 void relay_channel_notice(struct Client* sptr, const char* name, const char* text)
84 struct Channel* chptr;
89 if (0 == (chptr = FindChannel(name)))
92 * This first: Almost never a server/service
94 if (!client_can_send_to_channel(sptr, chptr))
97 if ((chptr->mode.mode & MODE_NOPRIVMSGS) &&
98 check_target_limit(sptr, chptr, chptr->chname, 0))
101 sendcmdto_channel_butone(sptr, CMD_NOTICE, chptr, cli_from(sptr),
102 SKIP_DEAF | SKIP_BURST, "%H :%s", chptr, text);
105 void server_relay_channel_message(struct Client* sptr, const char* name, const char* text)
107 struct Channel* chptr;
112 if (0 == (chptr = FindChannel(name))) {
114 * XXX - do we need to send this back from a remote server?
116 send_reply(sptr, ERR_NOSUCHCHANNEL, name);
120 * This first: Almost never a server/service
121 * Servers may have channel services, need to check for it here
123 if (client_can_send_to_channel(sptr, chptr) || IsChannelService(sptr)) {
124 sendcmdto_channel_butone(sptr, CMD_PRIVATE, chptr, cli_from(sptr),
125 SKIP_DEAF | SKIP_BURST, "%H :%s", chptr, text);
128 send_reply(sptr, ERR_CANNOTSENDTOCHAN, chptr->chname);
131 void server_relay_channel_notice(struct Client* sptr, const char* name, const char* text)
133 struct Channel* chptr;
138 if (0 == (chptr = FindChannel(name)))
141 * This first: Almost never a server/service
142 * Servers may have channel services, need to check for it here
144 if (client_can_send_to_channel(sptr, chptr) || IsChannelService(sptr)) {
145 sendcmdto_channel_butone(sptr, CMD_NOTICE, chptr, cli_from(sptr),
146 SKIP_DEAF | SKIP_BURST, "%H :%s", chptr, text);
151 void relay_directed_message(struct Client* sptr, char* name, char* server, const char* text)
153 struct Client* acptr;
161 if ((acptr = FindServer(server + 1)) == NULL ||
162 !IsChannelService(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 " NETWORK ". "
317 "Failed to deliver: [%.20s]", text);
320 if (is_silenced(sptr, acptr))
324 add_target(acptr, sptr);
326 sendcmdto_one(sptr, CMD_PRIVATE, acptr, "%C :%s", acptr, text);
330 void server_relay_private_notice(struct Client* sptr, const char* name, const char* text)
332 struct Client* acptr;
337 * nickname addressed?
339 if (0 == (acptr = findNUser(name)) || !IsUser(acptr))
342 if (is_silenced(sptr, acptr))
346 add_target(acptr, sptr);
348 sendcmdto_one(sptr, CMD_NOTICE, acptr, "%C :%s", acptr, text);
351 void relay_masked_message(struct Client* sptr, const char* mask, const char* text)
360 * look for the last '.' in mask and scan forward
362 if (0 == (s = strrchr(mask, '.'))) {
363 send_reply(sptr, ERR_NOTOPLEVEL, mask);
367 if (*s == '.' || *s == '*' || *s == '?')
370 if (*s == '*' || *s == '?') {
371 send_reply(sptr, ERR_WILDTOPLEVEL, mask);
380 sendcmdto_match_butone(sptr, CMD_PRIVATE, s,
381 IsServer(cli_from(sptr)) ? cli_from(sptr) : 0,
382 host_mask ? MATCH_HOST : MATCH_SERVER,
383 "%s :%s", mask, text);
386 void relay_masked_notice(struct Client* sptr, const char* mask, const char* text)
395 * look for the last '.' in mask and scan forward
397 if (0 == (s = strrchr(mask, '.'))) {
398 send_reply(sptr, ERR_NOTOPLEVEL, mask);
402 if (*s == '.' || *s == '*' || *s == '?')
405 if (*s == '*' || *s == '?') {
406 send_reply(sptr, ERR_WILDTOPLEVEL, mask);
415 sendcmdto_match_butone(sptr, CMD_NOTICE, s,
416 IsServer(cli_from(sptr)) ? cli_from(sptr) : 0,
417 host_mask ? MATCH_HOST : MATCH_SERVER,
418 "%s :%s", mask, text);
421 void server_relay_masked_message(struct Client* sptr, const char* mask, const char* text)
423 const char* s = mask;
433 sendcmdto_match_butone(sptr, CMD_PRIVATE, s,
434 IsServer(cli_from(sptr)) ? cli_from(sptr) : 0,
435 host_mask ? MATCH_HOST : MATCH_SERVER,
436 "%s :%s", mask, text);
439 void server_relay_masked_notice(struct Client* sptr, const char* mask, const char* text)
441 const char* s = mask;
451 sendcmdto_match_butone(sptr, CMD_NOTICE, s,
452 IsServer(cli_from(sptr)) ? cli_from(sptr) : 0,
453 host_mask ? MATCH_HOST : MATCH_SERVER,
454 "%s :%s", mask, text);