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_error_to_client(sptr, ERR_NOSUCHCHANNEL, name);
66 * This first: Almost never a server/service
68 if (!client_can_send_to_channel(sptr, chptr)) {
69 send_error_to_client(sptr, ERR_CANNOTSENDTOCHAN, chptr->chname);
72 if ((chptr->mode.mode & MODE_NOPRIVMSGS) &&
73 check_target_limit(sptr, chptr, chptr->chname, 0))
76 sendmsgto_channel_butone(sptr->from, sptr, chptr, sptr->name,
77 TOK_PRIVATE, chptr->chname, 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 sendmsgto_channel_butone(sptr->from, sptr, chptr, sptr->name,
100 TOK_NOTICE, chptr->chname, 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_error_to_client(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 sendmsgto_channel_butone(sptr->from, sptr, chptr, sptr->name,
123 TOK_PRIVATE, chptr->chname, text);
126 send_error_to_client(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 sendmsgto_channel_butone(sptr->from, sptr, chptr, sptr->name,
144 TOK_NOTICE, chptr->chname, 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_error_to_client(sptr, ERR_NOSUCHNICK, name);
164 * NICK[%host]@server addressed? See if <server> is me first
167 sendto_one(acptr, ":%s %s %s :%s", sptr->name, MSG_PRIVATE, 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, acptr->user->host))) {
181 send_error_to_client(sptr, ERR_NOSUCHNICK, name);
189 if (!(is_silenced(sptr, acptr)))
190 sendto_prefix_one(acptr, sptr, ":%s %s %s :%s",
191 sptr->name, MSG_PRIVATE, name, text);
194 void relay_directed_notice(struct Client* sptr, char* name, char* server, const char* text)
196 struct Client* acptr;
204 if (0 == (acptr = FindServer(server + 1)))
207 * NICK[%host]@server addressed? See if <server> is me first
210 sendto_one(acptr, ":%s %s %s :%s", sptr->name, MSG_NOTICE, name, text);
214 * Look for an user whose NICK is equal to <name> and then
215 * check if it's hostname matches <host> and if it's a local
219 if ((host = strchr(name, '%')))
222 if (!(acptr = FindUser(name)) || !MyUser(acptr) ||
223 (!EmptyString(host) && 0 != match(host, acptr->user->host)))
230 if (!(is_silenced(sptr, acptr)))
231 sendto_prefix_one(acptr, sptr, ":%s %s %s :%s",
232 sptr->name, MSG_NOTICE, 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_error_to_client(sptr, ERR_NOSUCHNICK, name);
247 if (check_target_limit(sptr, acptr, acptr->name, 0) ||
248 is_silenced(sptr, acptr))
252 * send away message if user away
254 if (acptr->user && acptr->user->away)
255 sendto_one(sptr, rpl_str(RPL_AWAY),
256 me.name, sptr->name, acptr->name, acptr->user->away);
258 * deliver the message
261 add_target(acptr, sptr);
262 sendto_prefix_one(acptr, sptr, ":%s %s %s :%s",
263 sptr->name, MSG_PRIVATE, acptr->name, text);
266 sendto_one(acptr, "%s%s %s %s%s :%s", NumNick(sptr),
267 TOK_PRIVATE, NumNick(acptr), text);
270 void relay_private_notice(struct Client* sptr, const char* name, const char* text)
272 struct Client* acptr;
277 if (0 == (acptr = FindUser(name)))
279 if (check_target_limit(sptr, acptr, acptr->name, 0) ||
280 is_silenced(sptr, acptr))
283 * deliver the message
286 add_target(acptr, sptr);
287 sendto_prefix_one(acptr, sptr, ":%s %s %s :%s",
288 sptr->name, MSG_NOTICE, acptr->name, text);
291 sendto_one(acptr, "%s%s %s %s%s :%s", NumNick(sptr),
292 TOK_NOTICE, NumNick(acptr), text);
295 void server_relay_private_message(struct Client* sptr, const char* name, const char* text)
297 struct Client* acptr;
302 * nickname addressed?
304 if (0 == (acptr = findNUser(name)) || !IsUser(acptr)) {
306 ":%s %d %s * :Target left UnderNet. Failed to deliver: [%.20s]",
307 me.name, ERR_NOSUCHNICK, sptr->name, text);
310 if (is_silenced(sptr, acptr))
314 add_target(acptr, sptr);
315 sendto_prefix_one(acptr, sptr, ":%s %s %s :%s",
316 sptr->name, MSG_PRIVATE, acptr->name, text);
320 sendto_one(acptr, "%s %s %s%s :%s", NumServ(sptr),
321 TOK_PRIVATE, NumNick(acptr), text);
323 sendto_one(acptr, "%s%s %s %s%s :%s", NumNick(sptr),
324 TOK_PRIVATE, NumNick(acptr), text);
329 void server_relay_private_notice(struct Client* sptr, const char* name, const char* text)
331 struct Client* acptr;
336 * nickname addressed?
338 if (0 == (acptr = findNUser(name)) || !IsUser(acptr))
341 if (is_silenced(sptr, acptr))
345 add_target(acptr, sptr);
346 sendto_prefix_one(acptr, sptr, ":%s %s %s :%s",
347 sptr->name, MSG_NOTICE, acptr->name, text);
351 sendto_one(acptr, "%s %s %s%s :%s", NumServ(sptr),
352 TOK_NOTICE, NumNick(acptr), text);
354 sendto_one(acptr, "%s%s %s %s%s :%s", NumNick(sptr),
355 TOK_NOTICE, NumNick(acptr), text);
359 void relay_masked_message(struct Client* sptr, const char* mask, const char* text)
368 * look for the last '.' in mask and scan forward
370 if (0 == (s = strrchr(mask, '.'))) {
371 send_error_to_client(sptr, ERR_NOTOPLEVEL, mask);
375 if (*s == '.' || *s == '*' || *s == '?')
378 if (*s == '*' || *s == '?') {
379 send_error_to_client(sptr, ERR_WILDTOPLEVEL, mask);
387 sendto_match_butone(IsServer(sptr->from) ? sptr->from : 0,
388 sptr, s, host_mask ? MATCH_HOST : MATCH_SERVER,
389 ":%s %s %s :%s", sptr->name, MSG_PRIVATE, mask, text);
392 void relay_masked_notice(struct Client* sptr, const char* mask, const char* text)
401 * look for the last '.' in mask and scan forward
403 if (0 == (s = strrchr(mask, '.'))) {
404 send_error_to_client(sptr, ERR_NOTOPLEVEL, mask);
408 if (*s == '.' || *s == '*' || *s == '?')
411 if (*s == '*' || *s == '?') {
412 send_error_to_client(sptr, ERR_WILDTOPLEVEL, mask);
420 sendto_match_butone(IsServer(sptr->from) ? sptr->from : 0,
421 sptr, s, host_mask ? MATCH_HOST : MATCH_SERVER,
422 ":%s %s %s :%s", sptr->name, MSG_NOTICE, mask, text);
425 void server_relay_masked_message(struct Client* sptr, const char* mask, const char* text)
427 const char* s = mask;
437 sendto_match_butone(sptr->from, sptr, s, host_mask ? MATCH_HOST : MATCH_SERVER,
438 ":%s %s %s :%s", sptr->name, MSG_PRIVATE, mask, text);
441 void server_relay_masked_notice(struct Client* sptr, const char* mask, const char* text)
443 const char* s = mask;
453 sendto_match_butone(sptr->from, sptr, s, host_mask ? MATCH_HOST : MATCH_SERVER,
454 ":%s %s %s :%s", sptr->name, MSG_NOTICE, mask, text);