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 (0 == (acptr = FindServer(server + 1))) {
162 send_reply(sptr, ERR_NOSUCHNICK, name);
166 * NICK[%host]@server addressed? See if <server> is me first
169 sendcmdto_one(sptr, CMD_PRIVATE, acptr, "%s :%s", name, text);
173 * Look for an user whose NICK is equal to <name> and then
174 * check if it's hostname matches <host> and if it's a local
178 if ((host = strchr(name, '%')))
181 /* As reported by Vampire-, it's possible to brute force finding users
182 * by sending a message to each server and see which one succeeded.
183 * This means we have to remove error reporting. Sigh. Better than
184 * removing the ability to send directed messages to client servers
185 * Thanks for the suggestion Vampire=. -- Isomer 2001-08-28
186 * Argh, /ping nick@server, disallow messages to non +k clients :/ I hate
187 * this. -- Isomer 2001-09-16
189 if (!(acptr = FindUser(name)) || !MyUser(acptr) ||
190 (!EmptyString(host) && 0 != match(host, cli_user(acptr)->host)) ||
191 !IsChannelService(acptr)) {
193 send_reply(sptr, ERR_NOSUCHNICK, name);
202 if (!(is_silenced(sptr, acptr)))
203 sendcmdto_one(sptr, CMD_PRIVATE, acptr, "%s :%s", name, text);
206 void relay_directed_notice(struct Client* sptr, char* name, char* server, const char* text)
208 struct Client* acptr;
216 if (0 == (acptr = FindServer(server + 1)))
219 * NICK[%host]@server addressed? See if <server> is me first
222 sendcmdto_one(sptr, CMD_NOTICE, acptr, "%s :%s", name, text);
226 * Look for an user whose NICK is equal to <name> and then
227 * check if it's hostname matches <host> and if it's a local
231 if ((host = strchr(name, '%')))
234 if (!(acptr = FindUser(name)) || !MyUser(acptr) ||
235 (!EmptyString(host) && 0 != match(host, cli_user(acptr)->host)))
242 if (!(is_silenced(sptr, acptr)))
243 sendcmdto_one(sptr, CMD_NOTICE, acptr, "%s :%s", name, text);
246 void relay_private_message(struct Client* sptr, const char* name, const char* text)
248 struct Client* acptr;
254 if (0 == (acptr = FindUser(name))) {
255 send_reply(sptr, ERR_NOSUCHNICK, name);
258 if ((!IsChannelService(acptr) &&
259 check_target_limit(sptr, acptr, cli_name(acptr), 0)) ||
260 is_silenced(sptr, acptr))
264 * send away message if user away
266 if (cli_user(acptr) && cli_user(acptr)->away)
267 send_reply(sptr, RPL_AWAY, cli_name(acptr), cli_user(acptr)->away);
269 * deliver the message
272 add_target(acptr, sptr);
274 sendcmdto_one(sptr, CMD_PRIVATE, acptr, "%C :%s", acptr, text);
277 void relay_private_notice(struct Client* sptr, const char* name, const char* text)
279 struct Client* acptr;
284 if (0 == (acptr = FindUser(name)))
286 if ((!IsChannelService(acptr) &&
287 check_target_limit(sptr, acptr, cli_name(acptr), 0)) ||
288 is_silenced(sptr, acptr))
291 * deliver the message
294 add_target(acptr, sptr);
296 sendcmdto_one(sptr, CMD_NOTICE, acptr, "%C :%s", acptr, text);
299 void server_relay_private_message(struct Client* sptr, const char* name, const char* text)
301 struct Client* acptr;
306 * nickname addressed?
308 if (0 == (acptr = findNUser(name)) || !IsUser(acptr)) {
309 send_reply(sptr, SND_EXPLICIT | ERR_NOSUCHNICK, "* :Target left " NETWORK ". "
310 "Failed to deliver: [%.20s]", text);
313 if (is_silenced(sptr, acptr))
317 add_target(acptr, sptr);
319 sendcmdto_one(sptr, CMD_PRIVATE, acptr, "%C :%s", acptr, text);
323 void server_relay_private_notice(struct Client* sptr, const char* name, const char* text)
325 struct Client* acptr;
330 * nickname addressed?
332 if (0 == (acptr = findNUser(name)) || !IsUser(acptr))
335 if (is_silenced(sptr, acptr))
339 add_target(acptr, sptr);
341 sendcmdto_one(sptr, CMD_NOTICE, acptr, "%C :%s", acptr, text);
344 void relay_masked_message(struct Client* sptr, const char* mask, const char* text)
353 * look for the last '.' in mask and scan forward
355 if (0 == (s = strrchr(mask, '.'))) {
356 send_reply(sptr, ERR_NOTOPLEVEL, mask);
360 if (*s == '.' || *s == '*' || *s == '?')
363 if (*s == '*' || *s == '?') {
364 send_reply(sptr, ERR_WILDTOPLEVEL, mask);
373 sendcmdto_match_butone(sptr, CMD_PRIVATE, s,
374 IsServer(cli_from(sptr)) ? cli_from(sptr) : 0,
375 host_mask ? MATCH_HOST : MATCH_SERVER,
376 "%s :%s", mask, text);
379 void relay_masked_notice(struct Client* sptr, const char* mask, const char* text)
388 * look for the last '.' in mask and scan forward
390 if (0 == (s = strrchr(mask, '.'))) {
391 send_reply(sptr, ERR_NOTOPLEVEL, mask);
395 if (*s == '.' || *s == '*' || *s == '?')
398 if (*s == '*' || *s == '?') {
399 send_reply(sptr, ERR_WILDTOPLEVEL, mask);
408 sendcmdto_match_butone(sptr, CMD_NOTICE, s,
409 IsServer(cli_from(sptr)) ? cli_from(sptr) : 0,
410 host_mask ? MATCH_HOST : MATCH_SERVER,
411 "%s :%s", mask, text);
414 void server_relay_masked_message(struct Client* sptr, const char* mask, const char* text)
416 const char* s = mask;
426 sendcmdto_match_butone(sptr, CMD_PRIVATE, s,
427 IsServer(cli_from(sptr)) ? cli_from(sptr) : 0,
428 host_mask ? MATCH_HOST : MATCH_SERVER,
429 "%s :%s", mask, text);
432 void server_relay_masked_notice(struct Client* sptr, const char* mask, const char* text)
434 const char* s = mask;
444 sendcmdto_match_butone(sptr, CMD_NOTICE, s,
445 IsServer(cli_from(sptr)) ? cli_from(sptr) : 0,
446 host_mask ? MATCH_HOST : MATCH_SERVER,
447 "%s :%s", mask, text);