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 if (!(acptr = FindUser(name)) || !MyUser(acptr) ||
182 (!EmptyString(host) && 0 != match(host, cli_user(acptr)->host))) {
183 send_reply(sptr, ERR_NOSUCHNICK, name);
191 if (!(is_silenced(sptr, acptr)))
192 sendcmdto_one(sptr, CMD_PRIVATE, acptr, "%s :%s", name, text);
195 void relay_directed_notice(struct Client* sptr, char* name, char* server, const char* text)
197 struct Client* acptr;
205 if (0 == (acptr = FindServer(server + 1)))
208 * NICK[%host]@server addressed? See if <server> is me first
211 sendcmdto_one(sptr, CMD_NOTICE, acptr, "%s :%s", name, text);
215 * Look for an user whose NICK is equal to <name> and then
216 * check if it's hostname matches <host> and if it's a local
220 if ((host = strchr(name, '%')))
223 if (!(acptr = FindUser(name)) || !MyUser(acptr) ||
224 (!EmptyString(host) && 0 != match(host, cli_user(acptr)->host)))
231 if (!(is_silenced(sptr, acptr)))
232 sendcmdto_one(sptr, CMD_NOTICE, acptr, "%s :%s", name, text);
235 void relay_private_message(struct Client* sptr, const char* name, const char* text)
237 struct Client* acptr;
243 if (0 == (acptr = FindUser(name))) {
244 send_reply(sptr, ERR_NOSUCHNICK, name);
247 if (check_target_limit(sptr, acptr, cli_name(acptr), 0) ||
248 is_silenced(sptr, acptr))
252 * send away message if user away
254 if (cli_user(acptr) && cli_user(acptr)->away)
255 send_reply(sptr, RPL_AWAY, cli_name(acptr), cli_user(acptr)->away);
257 * deliver the message
260 add_target(acptr, sptr);
262 sendcmdto_one(sptr, CMD_PRIVATE, acptr, "%C :%s", acptr, text);
265 void relay_private_notice(struct Client* sptr, const char* name, const char* text)
267 struct Client* acptr;
272 if (0 == (acptr = FindUser(name)))
274 if (check_target_limit(sptr, acptr, cli_name(acptr), 0) ||
275 is_silenced(sptr, acptr))
278 * deliver the message
281 add_target(acptr, sptr);
283 sendcmdto_one(sptr, CMD_NOTICE, acptr, "%C :%s", acptr, text);
286 void server_relay_private_message(struct Client* sptr, const char* name, const char* text)
288 struct Client* acptr;
293 * nickname addressed?
295 if (0 == (acptr = findNUser(name)) || !IsUser(acptr)) {
296 send_reply(sptr, SND_EXPLICIT | ERR_NOSUCHNICK, "* :Target left UnderNet. "
297 "Failed to deliver: [%.20s]", text);
300 if (is_silenced(sptr, acptr))
304 add_target(acptr, sptr);
306 sendcmdto_one(sptr, CMD_PRIVATE, acptr, "%C :%s", acptr, text);
310 void server_relay_private_notice(struct Client* sptr, const char* name, const char* text)
312 struct Client* acptr;
317 * nickname addressed?
319 if (0 == (acptr = findNUser(name)) || !IsUser(acptr))
322 if (is_silenced(sptr, acptr))
326 add_target(acptr, sptr);
328 sendcmdto_one(sptr, CMD_NOTICE, acptr, "%C :%s", acptr, text);
331 void relay_masked_message(struct Client* sptr, const char* mask, const char* text)
340 * look for the last '.' in mask and scan forward
342 if (0 == (s = strrchr(mask, '.'))) {
343 send_reply(sptr, ERR_NOTOPLEVEL, mask);
347 if (*s == '.' || *s == '*' || *s == '?')
350 if (*s == '*' || *s == '?') {
351 send_reply(sptr, ERR_WILDTOPLEVEL, mask);
360 sendcmdto_match_butone(sptr, CMD_PRIVATE, s,
361 IsServer(cli_from(sptr)) ? cli_from(sptr) : 0,
362 host_mask ? MATCH_HOST : MATCH_SERVER,
363 "%s :%s", mask, text);
366 void relay_masked_notice(struct Client* sptr, const char* mask, const char* text)
375 * look for the last '.' in mask and scan forward
377 if (0 == (s = strrchr(mask, '.'))) {
378 send_reply(sptr, ERR_NOTOPLEVEL, mask);
382 if (*s == '.' || *s == '*' || *s == '?')
385 if (*s == '*' || *s == '?') {
386 send_reply(sptr, ERR_WILDTOPLEVEL, mask);
395 sendcmdto_match_butone(sptr, CMD_NOTICE, s,
396 IsServer(cli_from(sptr)) ? cli_from(sptr) : 0,
397 host_mask ? MATCH_HOST : MATCH_SERVER,
398 "%s :%s", mask, text);
401 void server_relay_masked_message(struct Client* sptr, const char* mask, const char* text)
403 const char* s = mask;
413 sendcmdto_match_butone(sptr, CMD_PRIVATE, s,
414 IsServer(cli_from(sptr)) ? cli_from(sptr) : 0,
415 host_mask ? MATCH_HOST : MATCH_SERVER,
416 "%s :%s", mask, text);
419 void server_relay_masked_notice(struct Client* sptr, const char* mask, const char* text)
421 const char* s = mask;
431 sendcmdto_match_butone(sptr, CMD_NOTICE, s,
432 IsServer(cli_from(sptr)) ? cli_from(sptr) : 0,
433 host_mask ? MATCH_HOST : MATCH_SERVER,
434 "%s :%s", mask, text);