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 ((!IsChannelService(acptr) &&
248 check_target_limit(sptr, acptr, cli_name(acptr), 0)) ||
249 is_silenced(sptr, acptr))
253 * send away message if user away
255 if (cli_user(acptr) && cli_user(acptr)->away)
256 send_reply(sptr, RPL_AWAY, cli_name(acptr), cli_user(acptr)->away);
258 * deliver the message
261 add_target(acptr, sptr);
263 sendcmdto_one(sptr, CMD_PRIVATE, acptr, "%C :%s", acptr, text);
266 void relay_private_notice(struct Client* sptr, const char* name, const char* text)
268 struct Client* acptr;
273 if (0 == (acptr = FindUser(name)))
275 if ((!IsChannelService(acptr) &&
276 check_target_limit(sptr, acptr, cli_name(acptr), 0)) ||
277 is_silenced(sptr, acptr))
280 * deliver the message
283 add_target(acptr, sptr);
285 sendcmdto_one(sptr, CMD_NOTICE, acptr, "%C :%s", acptr, text);
288 void server_relay_private_message(struct Client* sptr, const char* name, const char* text)
290 struct Client* acptr;
295 * nickname addressed?
297 if (0 == (acptr = findNUser(name)) || !IsUser(acptr)) {
298 send_reply(sptr, SND_EXPLICIT | ERR_NOSUCHNICK, "* :Target left UnderNet. "
299 "Failed to deliver: [%.20s]", text);
302 if (is_silenced(sptr, acptr))
306 add_target(acptr, sptr);
308 sendcmdto_one(sptr, CMD_PRIVATE, acptr, "%C :%s", acptr, text);
312 void server_relay_private_notice(struct Client* sptr, const char* name, const char* text)
314 struct Client* acptr;
319 * nickname addressed?
321 if (0 == (acptr = findNUser(name)) || !IsUser(acptr))
324 if (is_silenced(sptr, acptr))
328 add_target(acptr, sptr);
330 sendcmdto_one(sptr, CMD_NOTICE, acptr, "%C :%s", acptr, text);
333 void relay_masked_message(struct Client* sptr, const char* mask, const char* text)
342 * look for the last '.' in mask and scan forward
344 if (0 == (s = strrchr(mask, '.'))) {
345 send_reply(sptr, ERR_NOTOPLEVEL, mask);
349 if (*s == '.' || *s == '*' || *s == '?')
352 if (*s == '*' || *s == '?') {
353 send_reply(sptr, ERR_WILDTOPLEVEL, mask);
362 sendcmdto_match_butone(sptr, CMD_PRIVATE, s,
363 IsServer(cli_from(sptr)) ? cli_from(sptr) : 0,
364 host_mask ? MATCH_HOST : MATCH_SERVER,
365 "%s :%s", mask, text);
368 void relay_masked_notice(struct Client* sptr, const char* mask, const char* text)
377 * look for the last '.' in mask and scan forward
379 if (0 == (s = strrchr(mask, '.'))) {
380 send_reply(sptr, ERR_NOTOPLEVEL, mask);
384 if (*s == '.' || *s == '*' || *s == '?')
387 if (*s == '*' || *s == '?') {
388 send_reply(sptr, ERR_WILDTOPLEVEL, mask);
397 sendcmdto_match_butone(sptr, CMD_NOTICE, s,
398 IsServer(cli_from(sptr)) ? cli_from(sptr) : 0,
399 host_mask ? MATCH_HOST : MATCH_SERVER,
400 "%s :%s", mask, text);
403 void server_relay_masked_message(struct Client* sptr, const char* mask, const char* text)
405 const char* s = mask;
415 sendcmdto_match_butone(sptr, CMD_PRIVATE, 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_notice(struct Client* sptr, const char* mask, const char* text)
423 const char* s = mask;
433 sendcmdto_match_butone(sptr, CMD_NOTICE, s,
434 IsServer(cli_from(sptr)) ? cli_from(sptr) : 0,
435 host_mask ? MATCH_HOST : MATCH_SERVER,
436 "%s :%s", mask, text);