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.
25 #include "ircd_relay.h"
30 #include "ircd_chattr.h"
31 #include "ircd_reply.h"
32 #include "ircd_string.h"
48 * This file contains message relaying functions for client and server
49 * private messages and notices
50 * TODO: This file contains a lot of cut and paste code, and needs
51 * to be cleaned up a bit. The idea is to factor out the common checks
52 * but not introduce any IsOper/IsUser/MyUser/IsServer etc. stuff.
54 void relay_channel_message(struct Client* sptr, const char* name, const char* text)
56 struct Channel* chptr;
61 if (0 == (chptr = FindChannel(name))) {
62 send_reply(sptr, ERR_NOSUCHCHANNEL, name);
66 * This first: Almost never a server/service
68 if (!client_can_send_to_channel(sptr, chptr)) {
69 send_reply(sptr, ERR_CANNOTSENDTOCHAN, chptr->chname);
72 if ((chptr->mode.mode & MODE_NOPRIVMSGS) &&
73 check_target_limit(sptr, chptr, chptr->chname, 0))
76 sendcmdto_channel_butone(sptr, CMD_PRIVATE, chptr, cli_from(sptr),
77 SKIP_DEAF | SKIP_BURST, "%H :%s", chptr, text);
80 void relay_channel_notice(struct Client* sptr, const char* name, const char* text)
82 struct Channel* chptr;
87 if (0 == (chptr = FindChannel(name)))
90 * This first: Almost never a server/service
92 if (!client_can_send_to_channel(sptr, chptr))
95 if ((chptr->mode.mode & MODE_NOPRIVMSGS) &&
96 check_target_limit(sptr, chptr, chptr->chname, 0))
99 sendcmdto_channel_butone(sptr, CMD_NOTICE, chptr, cli_from(sptr),
100 SKIP_DEAF | SKIP_BURST, "%H :%s", chptr, text);
103 void server_relay_channel_message(struct Client* sptr, const char* name, const char* text)
105 struct Channel* chptr;
110 if (0 == (chptr = FindChannel(name))) {
112 * XXX - do we need to send this back from a remote server?
114 send_reply(sptr, ERR_NOSUCHCHANNEL, name);
118 * This first: Almost never a server/service
119 * Servers may have channel services, need to check for it here
121 if (client_can_send_to_channel(sptr, chptr) || IsChannelService(sptr)) {
122 sendcmdto_channel_butone(sptr, CMD_PRIVATE, chptr, cli_from(sptr),
123 SKIP_DEAF | SKIP_BURST, "%H :%s", chptr, text);
126 send_reply(sptr, ERR_CANNOTSENDTOCHAN, chptr->chname);
129 void server_relay_channel_notice(struct Client* sptr, const char* name, const char* text)
131 struct Channel* chptr;
136 if (0 == (chptr = FindChannel(name)))
139 * This first: Almost never a server/service
140 * Servers may have channel services, need to check for it here
142 if (client_can_send_to_channel(sptr, chptr) || IsChannelService(sptr)) {
143 sendcmdto_channel_butone(sptr, CMD_NOTICE, chptr, cli_from(sptr),
144 SKIP_DEAF | SKIP_BURST, "%H :%s", chptr, text);
149 void relay_directed_message(struct Client* sptr, char* name, char* server, const char* text)
151 struct Client* acptr;
159 if (0 == (acptr = FindServer(server + 1))) {
160 send_reply(sptr, ERR_NOSUCHNICK, name);
164 * NICK[%host]@server addressed? See if <server> is me first
167 sendcmdto_one(sptr, CMD_PRIVATE, acptr, "%s :%s", name, text);
171 * Look for an user whose NICK is equal to <name> and then
172 * check if it's hostname matches <host> and if it's a local
176 if ((host = strchr(name, '%')))
179 if (!(acptr = FindUser(name)) || !MyUser(acptr) ||
180 (!EmptyString(host) && 0 != match(host, cli_user(acptr)->host))) {
181 send_reply(sptr, ERR_NOSUCHNICK, name);
189 if (!(is_silenced(sptr, acptr)))
190 sendcmdto_one(sptr, CMD_PRIVATE, acptr, "%s :%s", name, text);
193 void relay_directed_notice(struct Client* sptr, char* name, char* server, const char* text)
195 struct Client* acptr;
203 if (0 == (acptr = FindServer(server + 1)))
206 * NICK[%host]@server addressed? See if <server> is me first
209 sendcmdto_one(sptr, CMD_NOTICE, acptr, "%s :%s", name, text);
213 * Look for an user whose NICK is equal to <name> and then
214 * check if it's hostname matches <host> and if it's a local
218 if ((host = strchr(name, '%')))
221 if (!(acptr = FindUser(name)) || !MyUser(acptr) ||
222 (!EmptyString(host) && 0 != match(host, cli_user(acptr)->host)))
229 if (!(is_silenced(sptr, acptr)))
230 sendcmdto_one(sptr, CMD_NOTICE, acptr, "%s :%s", name, text);
233 void relay_private_message(struct Client* sptr, const char* name, const char* text)
235 struct Client* acptr;
241 if (0 == (acptr = FindUser(name))) {
242 send_reply(sptr, ERR_NOSUCHNICK, name);
245 if (check_target_limit(sptr, acptr, cli_name(acptr), 0) ||
246 is_silenced(sptr, acptr))
250 * send away message if user away
252 if (cli_user(acptr) && cli_user(acptr)->away)
253 send_reply(sptr, RPL_AWAY, cli_name(acptr), cli_user(acptr)->away);
255 * deliver the message
258 add_target(acptr, sptr);
260 sendcmdto_one(sptr, CMD_PRIVATE, acptr, "%C :%s", acptr, text);
263 void relay_private_notice(struct Client* sptr, const char* name, const char* text)
265 struct Client* acptr;
270 if (0 == (acptr = FindUser(name)))
272 if (check_target_limit(sptr, acptr, cli_name(acptr), 0) ||
273 is_silenced(sptr, acptr))
276 * deliver the message
279 add_target(acptr, sptr);
281 sendcmdto_one(sptr, CMD_NOTICE, acptr, "%C :%s", acptr, text);
284 void server_relay_private_message(struct Client* sptr, const char* name, const char* text)
286 struct Client* acptr;
291 * nickname addressed?
293 if (0 == (acptr = findNUser(name)) || !IsUser(acptr)) {
294 send_reply(sptr, SND_EXPLICIT | ERR_NOSUCHNICK, "* :Target left UnderNet. "
295 "Failed to deliver: [%.20s]", text);
298 if (is_silenced(sptr, acptr))
302 add_target(acptr, sptr);
304 sendcmdto_one(sptr, CMD_PRIVATE, acptr, "%C :%s", acptr, text);
308 void server_relay_private_notice(struct Client* sptr, const char* name, const char* text)
310 struct Client* acptr;
315 * nickname addressed?
317 if (0 == (acptr = findNUser(name)) || !IsUser(acptr))
320 if (is_silenced(sptr, acptr))
324 add_target(acptr, sptr);
326 sendcmdto_one(sptr, CMD_NOTICE, acptr, "%C :%s", acptr, text);
329 void relay_masked_message(struct Client* sptr, const char* mask, const char* text)
338 * look for the last '.' in mask and scan forward
340 if (0 == (s = strrchr(mask, '.'))) {
341 send_reply(sptr, ERR_NOTOPLEVEL, mask);
345 if (*s == '.' || *s == '*' || *s == '?')
348 if (*s == '*' || *s == '?') {
349 send_reply(sptr, ERR_WILDTOPLEVEL, mask);
358 sendcmdto_match_butone(sptr, CMD_PRIVATE, s,
359 IsServer(cli_from(sptr)) ? cli_from(sptr) : 0,
360 host_mask ? MATCH_HOST : MATCH_SERVER,
361 "%s :%s", mask, text);
364 void relay_masked_notice(struct Client* sptr, const char* mask, const char* text)
373 * look for the last '.' in mask and scan forward
375 if (0 == (s = strrchr(mask, '.'))) {
376 send_reply(sptr, ERR_NOTOPLEVEL, mask);
380 if (*s == '.' || *s == '*' || *s == '?')
383 if (*s == '*' || *s == '?') {
384 send_reply(sptr, ERR_WILDTOPLEVEL, mask);
393 sendcmdto_match_butone(sptr, CMD_NOTICE, s,
394 IsServer(cli_from(sptr)) ? cli_from(sptr) : 0,
395 host_mask ? MATCH_HOST : MATCH_SERVER,
396 "%s :%s", mask, text);
399 void server_relay_masked_message(struct Client* sptr, const char* mask, const char* text)
401 const char* s = mask;
411 sendcmdto_match_butone(sptr, CMD_PRIVATE, s,
412 IsServer(cli_from(sptr)) ? cli_from(sptr) : 0,
413 host_mask ? MATCH_HOST : MATCH_SERVER,
414 "%s :%s", mask, text);
417 void server_relay_masked_notice(struct Client* sptr, const char* mask, const char* text)
419 const char* s = mask;
429 sendcmdto_match_butone(sptr, CMD_NOTICE, s,
430 IsServer(cli_from(sptr)) ? cli_from(sptr) : 0,
431 host_mask ? MATCH_HOST : MATCH_SERVER,
432 "%s :%s", mask, text);