1 /*
2 * Unreal Internet Relay Chat Daemon, src/send.c
3 * Copyright (C) 1990 Jarkko Oikarinen and
4 * University of Oulu, Computing Center
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 1, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 /* -- Jto -- 16 Jun 1990
22 * Added Armin's PRIVMSG patches...
23 */
24
25 #ifndef CLEAN_COMPILE
26 static char sccsid[] =
27 "@(#)send.c 2.32 2/28/94 (C) 1988 University of Oulu, Computing Center and Jarkko Oikarinen";
28 #endif
29
30 #include "struct.h"
31 #include "numeric.h"
32 #include "common.h"
33 #include "sys.h"
34 #include "h.h"
35 #include "msg.h"
36 #include <stdarg.h>
37 #include <stdio.h>
38 #ifdef _WIN32
39 #include <io.h>
40 #endif
41 #include <string.h>
42
43 void vsendto_one(aClient *to, char *pattern, va_list vl);
44 void sendbufto_one(aClient *to, char *msg, unsigned int quick);
45 int vmakebuf_local_withprefix(char *buf, struct Client *from, const char *pattern, va_list vl);
46
47 #define ADD_CRLF(buf, len) { if (len > 510) len = 510; \
48 buf[len++] = '\r'; buf[len++] = '\n'; buf[len] = '\0'; } while(0)
49
50 #ifndef NO_FDLIST
51 extern fdlist serv_fdlist;
52 extern fdlist oper_fdlist;
53 #endif
54
55 #define NEWLINE "\r\n"
56
57 static char sendbuf[2048];
58 static char tcmd[2048];
59 static char ccmd[2048];
60 static char xcmd[2048];
61 static char wcmd[2048];
62
63 /* this array is used to ensure we send a msg only once to a remote
64 ** server. like, when we are sending a message to all channel members
65 ** send the message to those that are directly connected to us and once
66 ** to each server that has these members. the servers then forward the
67 ** message to other servers and to those channel members that are directly
68 ** connected to them
69 */
70 static int sentalong[MAXCONNECTIONS];
71
72 void vsendto_prefix_one(struct Client *to, struct Client *from,
73 const char *pattern, va_list vl);
74
75 MODVAR int sentalong_marker;
76 MODVAR int sendanyways = 0;
77 /*
78 ** dead_link
79 ** An error has been detected. The link *must* be closed,
80 ** but *cannot* call ExitClient (m_bye) from here.
81 ** Instead, mark it with FLAGS_DEADSOCKET. This should
82 ** generate ExitClient from the main loop.
83 **
84 ** notice will be the quit message. notice will also be
85 ** sent to failops in case 'to' is a server.
86 */
dead_link(aClient * to,char * notice)87 static int dead_link(aClient *to, char *notice)
88 {
89
90 to->flags |= FLAGS_DEADSOCKET;
91 /*
92 * If because of BUFFERPOOL problem then clean dbuf's now so that
93 * notices don't hurt operators below.
94 */
95 DBufClear(&to->recvQ);
96 DBufClear(&to->sendQ);
97
98 if (!IsPerson(to) && !IsUnknown(to) && !(to->flags & FLAGS_CLOSING))
99 (void)sendto_failops_whoare_opers("Closing link: %s - %s",
100 notice, get_client_name(to, FALSE));
101 Debug((DEBUG_ERROR, "dead_link: %s - %s", notice, get_client_name(to, FALSE)));
102 to->error_str = strdup(notice);
103 return -1;
104 }
105
106 /*
107 ** flush_connections
108 ** Used to empty all output buffers for all connections. Should only
109 ** be called once per scan of connections. There should be a select in
110 ** here perhaps but that means either forcing a timeout or doing a poll.
111 ** When flushing, all we do is empty the obuffer array for each local
112 ** client and try to send it. if we cant send it, it goes into the sendQ
113 ** -avalon
114 */
flush_connections(aClient * cptr)115 void flush_connections(aClient* cptr)
116 {
117 int i;
118 aClient *acptr;
119
120 if (&me == cptr)
121 {
122 for (i = LastSlot; i >= 0; i--)
123 if ((acptr = local[i]) && !(acptr->flags & FLAGS_BLOCKED)
124 && ((DBufLength(&acptr->sendQ) > 0)
125 #ifdef ZIP_LINKS
126 || (IsZipped(acptr) && acptr->zip->outcount)
127 #endif /* ZIP_LINKS */
128 ) )
129 send_queued(acptr);
130 }
131 else if (cptr->fd >= 0 && !(cptr->flags & FLAGS_BLOCKED)
132 && ((DBufLength(&cptr->sendQ) > 0)
133 #ifdef ZIP_LINKS
134 || (IsZipped(cptr) && cptr->zip->outcount)
135 #endif /* ZIP_LINKS */
136 ) )
137 send_queued(cptr);
138
139 }
140 /* flush an fdlist intelligently */
141 #ifndef NO_FDLIST
flush_fdlist_connections(fdlist * listp)142 void flush_fdlist_connections(fdlist * listp)
143 {
144 int i, fd;
145 aClient *cptr;
146
147 for (fd = listp->entry[i = 1]; i <= listp->last_entry;
148 fd = listp->entry[++i])
149 if ((cptr = local[fd]) && !(cptr->flags & FLAGS_BLOCKED)
150 && DBufLength(&cptr->sendQ) > 0)
151 send_queued(cptr);
152 }
153 #endif
154
155 /*
156 ** send_queued
157 ** This function is called from the main select-loop (or whatever)
158 ** when there is a chance the some output would be possible. This
159 ** attempts to empty the send queue as far as possible...
160 */
send_queued(aClient * to)161 int send_queued(aClient *to)
162 {
163 char *msg;
164 int len, rlen;
165 #ifdef ZIP_LINKS
166 int more = 0;
167 #endif
168 if (IsBlocked(to))
169 return -1; /* Can't write to already blocked socket */
170
171 /*
172 ** Once socket is marked dead, we cannot start writing to it,
173 ** even if the error is removed...
174 */
175 if (IsDead(to))
176 {
177 /*
178 ** Actually, we should *NEVER* get here--something is
179 ** not working correct if send_queued is called for a
180 ** dead socket... --msa
181 */
182 return -1;
183 }
184 #ifdef ZIP_LINKS
185 /*
186 ** Here, we must make sure than nothing will be left in to->zip->outbuf
187 ** This buffer needs to be compressed and sent if all the sendQ is sent
188 */
189 if ((IsZipped(to)) && to->zip->outcount) {
190 if (DBufLength(&to->sendQ) > 0) {
191 more = 1;
192 } else {
193 msg = zip_buffer(to, NULL, &len, 1);
194 if (len == -1)
195 return dead_link(to, "fatal error in zip_buffer()");
196 if (!dbuf_put(&to->sendQ, msg, len))
197 return dead_link(to, "Buffer allocation error");
198 }
199 }
200 #endif
201 while (DBufLength(&to->sendQ) > 0)
202 {
203 msg = dbuf_map(&to->sendQ, &len);
204 /* Returns always len > 0 */
205 if ((rlen = deliver_it(to, msg, len)) < 0)
206 {
207 char buf[256];
208 snprintf(buf, 256, "Write error: %s", STRERROR(ERRNO));
209 return dead_link(to, buf);
210 }
211 (void)dbuf_delete(&to->sendQ, rlen);
212 to->lastsq = DBufLength(&to->sendQ) / 1024;
213 if (rlen < len)
214 {
215 /* If we can't write full message, mark the socket
216 * as "blocking" and stop trying. -Donwulff */
217 SetBlocked(to);
218 break;
219 }
220 #ifdef ZIP_LINKS
221 if (DBufLength(&to->sendQ) == 0 && more) {
222 /*
223 ** The sendQ is now empty, compress what's left
224 ** uncompressed and try to send it too
225 */
226 more = 0;
227 msg = zip_buffer(to, NULL, &len, 1);
228 if (len == -1)
229 return dead_link(to, "fatal error in zip_buffer()");
230 if (!dbuf_put(&to->sendQ, msg, len))
231 return dead_link(to, "Buffer allocation error");
232 }
233 #endif
234 }
235
236 return (IsDead(to)) ? -1 : 0;
237 }
238
239 /*
240 * send message to single client
241 */
sendto_one(aClient * to,char * pattern,...)242 void sendto_one(aClient *to, char *pattern, ...)
243 {
244 va_list vl;
245 va_start(vl, pattern);
246 vsendto_one(to, pattern, vl);
247 va_end(vl);
248 }
249
vsendto_one(aClient * to,char * pattern,va_list vl)250 void vsendto_one(aClient *to, char *pattern, va_list vl)
251 {
252 ircvsprintf(sendbuf, pattern, vl);
253 sendbufto_one(to, sendbuf, 0);
254 }
255
256
257 /* sendbufto_one:
258 * to: the client to which the buffer should be send
259 * msg: the message
260 * quick: normally set to 0, see later.
261 * NOTES:
262 * - neither to or msg can be NULL
263 * - if quick is set to 0, the length is calculated, the string is cutoff
264 * at 510 bytes if needed, and \r\n is added if needed.
265 * if quick is >0 it is assumed the message has \r\n and 'quick' is used
266 * as length. Of course you should be very careful with that.
267 */
sendbufto_one(aClient * to,char * msg,unsigned int quick)268 void sendbufto_one(aClient *to, char *msg, unsigned int quick)
269 {
270 int len;
271 Hook *h;
272
273 Debug((DEBUG_ERROR, "Sending [%s] to %s", msg, to->name));
274
275 if (to->from)
276 to = to->from;
277 if (IsDead(to))
278 return; /* This socket has already
279 been marked as dead */
280 if (to->fd < 0)
281 {
282 /* This is normal when 'to' was being closed (via exit_client
283 * and close_connection) --Run
284 * Print the debug message anyway...
285 */
286 Debug((DEBUG_ERROR,
287 "Local socket %s with negative fd %d... AARGH!", to->name,
288 to->fd));
289 return;
290 }
291
292 if (!quick)
293 {
294 len = strlen(msg);
295 if (!len || (msg[len - 1] != '\n'))
296 {
297 if (len > 510)
298 len = 510;
299 msg[len++] = '\r';
300 msg[len++] = '\n';
301 msg[len] = '\0';
302 }
303 } else
304 len = quick;
305
306 if (len > 512)
307 {
308 ircd_log(LOG_ERROR, "sendbufto_one: len=%u, quick=%u", len, quick);
309 abort();
310 }
311
312 if (IsMe(to))
313 {
314 char tmp_msg[500], *p;
315
316 p = strchr(msg, '\r');
317 if (p) *p = '\0';
318 snprintf(tmp_msg, 500, "Trying to send data to myself! '%s'", msg);
319 ircd_log(LOG_ERROR, "%s", tmp_msg);
320 sendto_ops("%s", tmp_msg); /* recursion? */
321 return;
322 }
323 for(h = Hooks[HOOKTYPE_PACKET]; h; h = h->next) {
324 (*(h->func.intfunc))(&me, to, &msg, &len);
325 if(!msg) return;
326 }
327 if (DBufLength(&to->sendQ) > get_sendq(to))
328 {
329 if (IsServer(to))
330 sendto_ops("Max SendQ limit exceeded for %s: %u > %d",
331 get_client_name(to, FALSE), DBufLength(&to->sendQ),
332 get_sendq(to));
333 dead_link(to, "Max SendQ exceeded");
334 return;
335 }
336
337 #ifdef ZIP_LINKS
338 /*
339 ** data is first stored in to->zip->outbuf until
340 ** it's big enough to be compressed and stored in the sendq.
341 ** send_queued is then responsible to never let the sendQ
342 ** be empty and to->zip->outbuf not empty.
343 */
344 if (IsZipped(to))
345 msg = zip_buffer(to, msg, &len, 0);
346
347 if (len && !dbuf_put(&to->sendQ, msg, len))
348 #else
349 if (!dbuf_put(&to->sendQ, msg, len))
350 #endif
351 {
352 dead_link(to, "Buffer allocation error");
353 return;
354 }
355 /*
356 * Update statistics. The following is slightly incorrect
357 * because it counts messages even if queued, but bytes
358 * only really sent. Queued bytes get updated in SendQueued.
359 */
360 to->sendM += 1;
361 me.sendM += 1;
362 if (to->listener != &me)
363 to->listener->sendM += 1;
364 /*
365 * This little bit is to stop the sendQ from growing too large when
366 * there is no need for it to. Thus we call send_queued() every time
367 * 2k has been added to the queue since the last non-fatal write.
368 * Also stops us from deliberately building a large sendQ and then
369 * trying to flood that link with data (possible during the net
370 * relinking done by servers with a large load).
371 */
372 if (DBufLength(&to->sendQ) / 1024 > to->lastsq)
373 send_queued(to);
374 }
375
sendto_channel_butone(aClient * one,aClient * from,aChannel * chptr,char * pattern,...)376 void sendto_channel_butone(aClient *one, aClient *from, aChannel *chptr,
377 char *pattern, ...)
378 {
379 va_list vl;
380 Member *lp;
381 aClient *acptr;
382 int i;
383
384 va_start(vl, pattern);
385
386 ++sentalong_marker;
387 for (lp = chptr->members; lp; lp = lp->next)
388 {
389 acptr = lp->cptr;
390 /* skip the one and deaf clients (unless sendanyways is set) */
391 if (acptr->from == one || (IsDeaf(acptr) && !(sendanyways == 1)))
392 continue;
393 if (MyConnect(acptr)) /* (It is always a client) */
394 vsendto_prefix_one(acptr, from, pattern, vl);
395 else if (sentalong[(i = acptr->from->slot)] != sentalong_marker)
396 {
397 sentalong[i] = sentalong_marker;
398 /*
399 * Burst messages comes here..
400 */
401 va_start(vl, pattern);
402 vsendto_prefix_one(acptr, from, pattern, vl);
403 va_end(vl);
404 }
405 }
406 va_end(vl);
407 }
408
sendto_channelprefix_butone(aClient * one,aClient * from,aChannel * chptr,int prefix,char * pattern,...)409 void sendto_channelprefix_butone(aClient *one, aClient *from, aChannel *chptr,
410 int prefix,
411 char *pattern, ...)
412 {
413 va_list vl;
414 Member *lp;
415 aClient *acptr;
416 int i;
417
418 va_start(vl, pattern);
419
420 ++sentalong_marker;
421 for (lp = chptr->members; lp; lp = lp->next)
422 {
423 acptr = lp->cptr;
424 if (acptr->from == one)
425 continue; /* ...was the one I should skip
426 or user not not a channel op */
427 if ((prefix & PREFIX_HALFOP) && (lp->flags & CHFL_HALFOP))
428 goto good;
429 if ((prefix & PREFIX_VOICE) && (lp->flags & CHFL_VOICE))
430 goto good;
431 if ((prefix & PREFIX_OP) && (lp->flags & CHFL_CHANOP))
432 goto good;
433 #ifdef PREFIX_AQ
434 if ((prefix & PREFIX_ADMIN) && (lp->flags & CHFL_CHANPROT))
435 goto good;
436 if ((prefix & PREFIX_OWNER) && (lp->flags & CHFL_CHANOWNER))
437 goto good;
438 #endif
439 continue;
440
441 good:
442 i = acptr->from->slot;
443 if (MyConnect(acptr) && IsRegisteredUser(acptr))
444 {
445 #ifdef SECURECHANMSGSONLYGOTOSECURE
446 if (chptr->mode.mode & MODE_ONLYSECURE)
447 if (!IsSecure(acptr))
448 continue;
449 #endif
450 va_start(vl, pattern);
451 vsendto_prefix_one(acptr, from, pattern, vl);
452 va_end(vl);
453 sentalong[i] = sentalong_marker;
454 }
455 else
456 {
457 /* Now check whether a message has been sent to this
458 * remote link already */
459 if (sentalong[i] != sentalong_marker)
460 {
461 #ifdef SECURECHANMSGSONLYGOTOSECURE
462 if (chptr->mode.mode & MODE_ONLYSECURE)
463 if (!IsSecure(acptr->from))
464 continue;
465 #endif
466 va_start(vl, pattern);
467 vsendto_prefix_one(acptr, from, pattern, vl);
468 va_end(vl);
469 sentalong[i] = sentalong_marker;
470 }
471 }
472 va_end(vl);
473 }
474 va_end(vl);
475 return;
476 }
477
sendto_channelprefix_butone_tok(aClient * one,aClient * from,aChannel * chptr,int prefix,char * cmd,char * tok,char * nick,char * text,char do_send_check)478 void sendto_channelprefix_butone_tok(aClient *one, aClient *from, aChannel *chptr,
479 int prefix,
480 char *cmd, char *tok, char *nick, char *text, char do_send_check)
481 {
482 Member *lp;
483 aClient *acptr;
484 int i;
485 char is_ctcp = 0;
486 unsigned int tlen, clen, xlen, wlen = 0;
487 char *p;
488
489 /* For servers with token capability */
490 p = ircsprintf(tcmd, ":%s %s %s :%s", from->name, tok, nick, text);
491 tlen = (int)(p - tcmd);
492 ADD_CRLF(tcmd, tlen);
493
494 /* For dumb servers without tokens */
495 p = ircsprintf(ccmd, ":%s %s %s :%s", from->name, cmd, nick, text);
496 clen = (int)(p - ccmd);
497 ADD_CRLF(ccmd, clen);
498
499 /* For our users... */
500 if (IsPerson(from))
501 p = ircsprintf(xcmd, ":%s!%s@%s %s %s :%s",
502 from->name, from->user->username, GetHost(from), cmd, nick, text);
503 else
504 p = ircsprintf(xcmd, ":%s %s %s :%s", from->name, cmd, nick, text);
505 xlen = (int)(p - xcmd);
506 ADD_CRLF(xcmd, xlen);
507
508 /* For our webtv friends... */
509 if (!strcmp(cmd, "NOTICE"))
510 {
511 char *chan = strchr(nick, '#'); /* impossible to become NULL? */
512 if (IsPerson(from))
513 p = ircsprintf(wcmd, ":%s!%s@%s %s %s :%s",
514 from->name, from->user->username, GetHost(from), MSG_PRIVATE, chan, text);
515 else
516 p = ircsprintf(wcmd, ":%s %s %s :%s", from->name, MSG_PRIVATE, chan, text);
517 wlen = (int)(p - wcmd);
518 ADD_CRLF(wcmd, wlen);
519 }
520
521 if (do_send_check && *text == 1 && myncmp(text+1,"ACTION ",7) && myncmp(text+1,"DCC ",4))
522 is_ctcp = 1;
523
524
525 ++sentalong_marker;
526 for (lp = chptr->members; lp; lp = lp->next)
527 {
528 acptr = lp->cptr;
529 if (acptr->from == one)
530 continue; /* ...was the one I should skip
531 or user not not a channel op */
532 if (prefix == PREFIX_ALL)
533 goto good;
534 if ((prefix & PREFIX_HALFOP) && (lp->flags & CHFL_HALFOP))
535 goto good;
536 if ((prefix & PREFIX_VOICE) && (lp->flags & CHFL_VOICE))
537 goto good;
538 if ((prefix & PREFIX_OP) && (lp->flags & CHFL_CHANOP))
539 goto good;
540 #ifdef PREFIX_AQ
541 if ((prefix & PREFIX_ADMIN) && (lp->flags & CHFL_CHANPROT))
542 goto good;
543 if ((prefix & PREFIX_OWNER) && (lp->flags & CHFL_CHANOWNER))
544 goto good;
545 #endif
546 continue;
547
548 good:
549 i = acptr->from->slot;
550 if (IsDeaf(acptr) && !sendanyways)
551 continue;
552 if (MyConnect(acptr) && IsRegisteredUser(acptr))
553 {
554 if (IsNoCTCP(acptr) && !IsOper(from) && is_ctcp)
555 continue;
556
557 if (IsWebTV(acptr) && wlen)
558 sendbufto_one(acptr, wcmd, wlen);
559 else
560 sendbufto_one(acptr, xcmd, xlen);
561 sentalong[i] = sentalong_marker;
562 }
563 else
564 {
565 /* Now check whether a message has been sent to this
566 * remote link already */
567 if (sentalong[i] != sentalong_marker)
568 {
569 if (IsToken(acptr->from))
570 sendbufto_one(acptr, tcmd, tlen);
571 else
572 sendbufto_one(acptr, ccmd, clen);
573 sentalong[i] = sentalong_marker;
574 }
575 }
576 }
577 return;
578 }
579
580 /* weird channelmode +mu crap:
581 * - local: deliver msgs to chanops (and higher) like <IRC> SrcNick: hi all
582 * - remote: deliver msgs to every server once (if needed) with real sourcenick.
583 * The problem is we can't send to remote servers with sourcenick (prefix) 'IRC'
584 * because that's a virtual user... Fun... -- Syzop.
585 */
sendto_chmodemucrap(aClient * from,aChannel * chptr,char * text)586 void sendto_chmodemucrap(aClient *from, aChannel *chptr, char *text)
587 {
588 Member *lp;
589 aClient *acptr;
590 int i;
591 int remote = MyClient(from) ? 0 : 1;
592
593 sprintf(tcmd, ":%s %s %s :%s", from->name, TOK_PRIVATE, chptr->chname, text); /* token */
594 sprintf(ccmd, ":%s %s %s :%s", from->name, MSG_PRIVATE, chptr->chname, text); /* msg */
595 sprintf(xcmd, ":IRC!IRC@%s PRIVMSG %s :%s: %s", me.name, chptr->chname, from->name, text); /* local */
596
597 ++sentalong_marker;
598 for (lp = chptr->members; lp; lp = lp->next)
599 {
600 acptr = lp->cptr;
601
602 if (IsDeaf(acptr) && !sendanyways)
603 continue;
604 if (!(lp->flags & (CHFL_CHANOP|CHFL_CHANOWNER|CHFL_CHANPROT)))
605 continue;
606 if (remote && (acptr->from == from->from)) /* don't send it back to where it came from */
607 continue;
608 i = acptr->from->slot;
609 if (MyConnect(acptr) && IsRegisteredUser(acptr))
610 {
611 sendto_one(acptr, "%s", xcmd);
612 sentalong[i] = sentalong_marker;
613 }
614 else
615 {
616 /* Now check whether a message has been sent to this
617 * remote link already */
618 if (sentalong[i] != sentalong_marker)
619 {
620 if (IsToken(acptr->from))
621 sendto_one(acptr, "%s", tcmd);
622 else
623 sendto_one(acptr, "%s", ccmd);
624 sentalong[i] = sentalong_marker;
625 }
626 }
627 }
628 return;
629 }
630
631
632 /*
633 sendto_chanops_butone -Stskeeps
634 */
635
sendto_chanops_butone(aClient * one,aChannel * chptr,char * pattern,...)636 void sendto_chanops_butone(aClient *one, aChannel *chptr, char *pattern, ...)
637 {
638 va_list vl;
639 Member *lp;
640 aClient *acptr;
641
642 va_start(vl, pattern);
643 for (lp = chptr->members; lp; lp = lp->next)
644 {
645 acptr = lp->cptr;
646 if (acptr == one || !(lp->flags & (CHFL_CHANOP|CHFL_CHANOWNER|CHFL_CHANPROT)))
647 continue; /* ...was the one I should skip
648 or user not not a channel op */
649 if (MyConnect(acptr) && IsRegisteredUser(acptr))
650 {
651 va_start(vl, pattern);
652 vsendto_one(acptr, pattern, vl);
653 va_end(vl);
654 }
655 }
656 va_end(vl);
657 }
658
659 /*
660 * sendto_server_butone
661 *
662 * Send a message to all connected servers except the client 'one'.
663 */
sendto_serv_butone(aClient * one,char * pattern,...)664 void sendto_serv_butone(aClient *one, char *pattern, ...)
665 {
666 va_list vl;
667 int i;
668 aClient *cptr;
669 #ifndef NO_FDLIST
670 int j;
671 #endif
672
673 va_start(vl, pattern);
674 #ifdef NO_FDLIST
675 for (i = 0; i <= LastSlot; i++)
676 #else
677 for (i = serv_fdlist.entry[j = 1]; j <= serv_fdlist.last_entry; i = serv_fdlist.entry[++j])
678 #endif
679 {
680 if (!(cptr = local[i]) || (one && cptr == one->from))
681 continue;
682 va_start(vl, pattern);
683
684 #ifdef NO_FDLIST
685 if (IsServer(cptr))
686 #endif
687 vsendto_one(cptr, pattern, vl);
688 va_end(vl);
689 }
690 va_end(vl);
691 return;
692 }
693
694 /*
695 * sendto_server_butone_token
696 *
697 * Send a message to all connected servers except the client 'one'.
698 * with capab to tokenize
699 */
700
sendto_serv_butone_token(aClient * one,char * prefix,char * command,char * token,char * pattern,...)701 void sendto_serv_butone_token(aClient *one, char *prefix, char *command,
702 char *token, char *pattern, ...)
703 {
704 va_list vl;
705 int i;
706 aClient *cptr;
707 aClient *acptr;
708 #ifndef NO_FDLIST
709 int j;
710 #endif
711 static char buff[2048];
712 static char pref[100];
713 va_start(vl, pattern);
714
715 pref[0] = '\0';
716 if (strchr(prefix, '.'))
717 {
718 acptr = (aClient *) find_server_quick(prefix);
719 if (acptr->serv->numeric)
720 {
721 strcpy(pref, base64enc(acptr->serv->numeric));
722 }
723 }
724 strcpy(tcmd, token);
725 strcpy(ccmd, command);
726 strcat(tcmd, " ");
727 strcat(ccmd, " ");
728 ircvsprintf(buff, pattern, vl);
729 strcat(tcmd, buff);
730 strcat(ccmd, buff);
731
732 #ifdef NO_FDLIST
733 for (i = 0; i <= LastSlot; i++)
734 #else
735 for (i = serv_fdlist.entry[j = 1]; j <= serv_fdlist.last_entry; i = serv_fdlist.entry[++j])
736 #endif
737 {
738 if (!(cptr = local[i]) || (one && cptr == one->from))
739 continue;
740 #ifdef NO_FDLIST
741 if (IsServer(cptr))
742 #endif
743 if (IsToken(cptr))
744 {
745 if (SupportNS(cptr) && pref[0])
746 {
747 sendto_one(cptr, "@%s %s",
748 pref, tcmd);
749 }
750 else
751 {
752 sendto_one(cptr, ":%s %s",
753 prefix, tcmd);
754 }
755 }
756 else
757 {
758 if (SupportNS(cptr) && pref[0])
759 {
760 sendto_one(cptr, "@%s %s",
761 pref, ccmd);
762 }
763 else
764 {
765 sendto_one(cptr, ":%s %s", prefix,
766 ccmd);
767 }
768 }
769 }
770 va_end(vl);
771 return;
772 }
773
774 /*
775 * sendto_server_butone_token_opt
776 *
777 * Send a message to all connected servers except the client 'one'.
778 * with capab to tokenize, opt
779 */
780
sendto_serv_butone_token_opt(aClient * one,int opt,char * prefix,char * command,char * token,char * pattern,...)781 void sendto_serv_butone_token_opt(aClient *one, int opt, char *prefix, char *command,
782 char *token, char *pattern, ...)
783 {
784 va_list vl;
785 int i;
786 aClient *cptr;
787 aClient *acptr;
788 #ifndef NO_FDLIST
789 int j;
790 #endif
791 static char tcmd[2048];
792 static char ccmd[2048];
793 static char buff[2048];
794 static char pref[100];
795
796 va_start(vl, pattern);
797
798 pref[0] = '\0';
799 if (strchr(prefix, '.'))
800 {
801 acptr = (aClient *) find_server_quick(prefix);
802 if (acptr && acptr->serv)
803 if (acptr->serv->numeric)
804 {
805 strcpy(pref, base64enc(acptr->serv->numeric));
806 }
807 }
808
809 strcpy(tcmd, token);
810 strcpy(ccmd, command);
811 strcat(tcmd, " ");
812 strcat(ccmd, " ");
813 ircvsprintf(buff, pattern, vl);
814 strcat(tcmd, buff);
815 strcat(ccmd, buff);
816
817 #ifdef NO_FDLIST
818 for (i = 0; i <= LastSlot; i++)
819 #else
820 for (i = serv_fdlist.entry[j = 1]; j <= serv_fdlist.last_entry; i = serv_fdlist.entry[++j])
821 #endif
822 {
823 if (!(cptr = local[i]) || (one && cptr == one->from))
824 continue;
825 #ifdef NO_FDLIST
826 if (IsServer(cptr))
827 #endif
828
829 if ((opt & OPT_NOT_SJOIN) && SupportSJOIN(cptr))
830 continue;
831 if ((opt & OPT_NOT_NICKv2) && SupportNICKv2(cptr))
832 continue;
833 if ((opt & OPT_NOT_SJOIN2) && SupportSJOIN2(cptr))
834 continue;
835 if ((opt & OPT_NOT_UMODE2) && SupportUMODE2(cptr))
836 continue;
837 if ((opt & OPT_NOT_SJ3) && SupportSJ3(cptr))
838 continue;
839 if ((opt & OPT_NICKv2) && !SupportNICKv2(cptr))
840 continue;
841 if ((opt & OPT_SJOIN) && !SupportSJOIN(cptr))
842 continue;
843 if ((opt & OPT_SJOIN2) && !SupportSJOIN2(cptr))
844 continue;
845 if ((opt & OPT_UMODE2) && !SupportUMODE2(cptr))
846 continue;
847 if ((opt & OPT_SJ3) && !SupportSJ3(cptr))
848 continue;
849 if ((opt & OPT_SJB64) && !(cptr->proto & PROTO_SJB64))
850 continue;
851 if ((opt & OPT_NOT_SJB64) && (cptr->proto & PROTO_SJB64))
852 continue;
853 if ((opt & OPT_VHP) && !(cptr->proto & PROTO_VHP))
854 continue;
855 if ((opt & OPT_NOT_VHP) && (cptr->proto & PROTO_VHP))
856 continue;
857 if ((opt & OPT_TKLEXT) && !(cptr->proto & PROTO_TKLEXT))
858 continue;
859 if ((opt & OPT_NOT_TKLEXT) && (cptr->proto & PROTO_TKLEXT))
860 continue;
861 if ((opt & OPT_NICKIP) && !(cptr->proto & PROTO_TKLEXT))
862 continue;
863 if ((opt & OPT_NOT_NICKIP) && (cptr->proto & PROTO_NICKIP))
864 continue;
865
866 if (IsToken(cptr))
867 {
868 if (SupportNS(cptr) && pref[0])
869 {
870 sendto_one(cptr, "@%s %s",
871 pref, tcmd);
872 }
873 else
874 {
875 sendto_one(cptr, ":%s %s",
876 prefix, tcmd);
877 }
878 }
879 else
880 {
881 if (SupportNS(cptr) && pref[0])
882 {
883 sendto_one(cptr, "@%s %s",
884 pref, ccmd);
885 }
886 else
887 {
888 sendto_one(cptr, ":%s %s", prefix,
889 ccmd);
890 }
891 }
892 }
893 va_end(vl);
894 return;
895 }
896
897 /*
898 * sendto_serv_butone_quit
899 *
900 * Send a message to all connected servers except the client 'one'.
901 * BUT, don't send to NOQUIT servers.
902 */
sendto_serv_butone_quit(aClient * one,char * pattern,...)903 void sendto_serv_butone_quit(aClient *one, char *pattern, ...)
904 {
905 va_list vl;
906 int i;
907 aClient *cptr;
908 #ifndef NO_FDLIST
909 int j;
910 #endif
911 va_start(vl, pattern);
912
913 #ifdef NO_FDLIST
914 for (i = 0; i <= LastSlot; i++)
915 #else
916 for (i = serv_fdlist.entry[j = 1]; j <= serv_fdlist.last_entry; i = serv_fdlist.entry[++j])
917 #endif
918 {
919 if (!(cptr = local[i]) || (one && cptr == one->from))
920 continue;
921 va_start(vl, pattern);
922
923 #ifdef NO_FDLIST
924 if (IsServer(cptr) && !DontSendQuit(cptr))
925 #else
926 if (!DontSendQuit(cptr))
927 #endif
928 vsendto_one(cptr, pattern, vl);
929 va_end(vl);
930 }
931 va_end(vl);
932 return;
933 }
934
935 /*
936 * sendto_serv_butone_sjoin
937 *
938 * Send a message to all connected servers except the client 'one'.
939 * BUT, don't send to SJOIN servers.
940 */
sendto_serv_butone_sjoin(aClient * one,char * pattern,...)941 void sendto_serv_butone_sjoin(aClient *one, char *pattern, ...)
942 {
943 va_list vl;
944 int i;
945 aClient *cptr;
946 #ifndef NO_FDLIST
947 int j;
948 #endif
949 va_start(vl, pattern);
950 #ifdef NO_FDLIST
951 for (i = 0; i <= LastSlot; i++)
952 #else
953 for (i = serv_fdlist.entry[j = 1]; j <= serv_fdlist.last_entry; i = serv_fdlist.entry[++j])
954 #endif
955 {
956 if (!(cptr = local[i]) || (one && cptr == one->from))
957 continue;
958 va_start(vl, pattern);
959
960 #ifdef NO_FDLIST
961 if (IsServer(cptr) && !SupportSJOIN(cptr))
962 #else
963 if (!SupportSJOIN(cptr))
964 #endif
965 vsendto_one(cptr, pattern, vl);
966 va_end(vl);
967 }
968 va_end(vl);
969 return;
970 }
971
972 /*
973 * sendto_serv_sjoin
974 *
975 * Send a message to all connected servers except the client 'one'.
976 * BUT only send to SJOIN servers.
977 */
sendto_serv_sjoin(aClient * one,char * pattern,...)978 void sendto_serv_sjoin(aClient *one, char *pattern, ...)
979 {
980 va_list vl;
981 int i;
982 aClient *cptr;
983 #ifndef NO_FDLIST
984 int j;
985 #endif
986 va_start(vl, pattern);
987
988 #ifdef NO_FDLIST
989 for (i = 0; i <= LastSlot; i++)
990 #else
991 for (i = serv_fdlist.entry[j = 1]; j <= serv_fdlist.last_entry; i = serv_fdlist.entry[++j])
992 #endif
993 {
994 if (!(cptr = local[i]) || (one && cptr == one->from))
995 continue;
996 va_start(vl, pattern);
997
998 #ifdef NO_FDLIST
999 if (IsServer(cptr) && SupportSJOIN(cptr))
1000 #else
1001 if (SupportSJOIN(cptr))
1002 #endif
1003 vsendto_one(cptr, pattern, vl);
1004 va_end(vl);
1005 }
1006 va_end(vl);
1007 return;
1008 }
1009
1010 /*
1011 * sendto_serv_butone_nickv2
1012 *
1013 * Send a message to all connected servers except the client 'one'.
1014 * BUT, don't send to NICKv2 servers.
1015 */
sendto_serv_butone_nickv2(aClient * one,char * pattern,...)1016 void sendto_serv_butone_nickv2(aClient *one, char *pattern, ...)
1017 {
1018 va_list vl;
1019 int i;
1020 aClient *cptr;
1021 #ifndef NO_FDLIST
1022 int j;
1023 #endif
1024 va_start(vl, pattern);
1025
1026 #ifdef NO_FDLIST
1027 for (i = 0; i <= LastSlot; i++)
1028 #else
1029 for (i = serv_fdlist.entry[j = 1]; j <= serv_fdlist.last_entry; i = serv_fdlist.entry[++j])
1030 #endif
1031 {
1032 if (!(cptr = local[i]) || (one && cptr == one->from))
1033 continue;
1034 va_start(vl, pattern);
1035
1036 #ifdef NO_FDLIST
1037 if (IsServer(cptr) && !SupportNICKv2(cptr))
1038 #else
1039 if (!SupportNICKv2(cptr))
1040 #endif
1041 vsendto_one(cptr, pattern, vl);
1042 va_end(vl);
1043 }
1044 va_end(vl);
1045 return;
1046 }
1047
1048 /*
1049 * sendto_serv_nickv2
1050 *
1051 * Send a message to all connected servers except the client 'one'.
1052 * BUT only send to NICKv2 servers.
1053 */
sendto_serv_nickv2(aClient * one,char * pattern,...)1054 void sendto_serv_nickv2(aClient *one, char *pattern, ...)
1055 {
1056 va_list vl;
1057 int i;
1058 aClient *cptr;
1059 #ifndef NO_FDLIST
1060 int j;
1061 #endif
1062 va_start(vl, pattern);
1063
1064 #ifdef NO_FDLIST
1065 for (i = 0; i <= LastSlot; i++)
1066 #else
1067 for (i = serv_fdlist.entry[j = 1]; j <= serv_fdlist.last_entry; i = serv_fdlist.entry[++j])
1068 #endif
1069 {
1070 if (!(cptr = local[i]) || (one && cptr == one->from))
1071 continue;
1072 va_start(vl, pattern);
1073
1074 #ifdef NO_FDLIST
1075 if (IsServer(cptr) && SupportNICKv2(cptr))
1076 #else
1077 if (SupportNICKv2(cptr))
1078 #endif
1079 vsendto_one(cptr, pattern, vl);
1080 va_end(vl);
1081 }
1082 va_end(vl);
1083 return;
1084 }
1085
1086
1087 /*
1088 * sendto_serv_nickv2_token
1089 *
1090 * Send a message to all connected servers except the client 'one'.
1091 * BUT only send to NICKv2 servers. As of Unreal3.1 it uses two patterns now
1092 * one for non token and one for tokens */
sendto_serv_nickv2_token(aClient * one,char * pattern,char * tokpattern,...)1093 void sendto_serv_nickv2_token(aClient *one, char *pattern, char *tokpattern,
1094 ...)
1095 {
1096 va_list vl;
1097 int i;
1098 aClient *cptr;
1099 #ifndef NO_FDLIST
1100 int j;
1101 #endif
1102 va_start(vl, tokpattern);
1103
1104 #ifdef NO_FDLIST
1105 for (i = 0; i <= LastSlot; i++)
1106 #else
1107 for (i = serv_fdlist.entry[j = 1]; j <= serv_fdlist.last_entry; i = serv_fdlist.entry[++j])
1108 #endif
1109 {
1110 if (!(cptr = local[i]) || (one && cptr == one->from))
1111 continue;
1112 va_start(vl, tokpattern);
1113
1114 #ifdef NO_FDLIST
1115 if (IsServer(cptr) && SupportNICKv2(cptr) && !IsToken(cptr))
1116 #else
1117 if (SupportNICKv2(cptr) && !IsToken(cptr))
1118 #endif
1119 vsendto_one(cptr, pattern, vl);
1120 else
1121 #ifdef NO_FDLIST
1122 if (IsServer(cptr) && SupportNICKv2(cptr) && IsToken(cptr))
1123 #else
1124 if (SupportNICKv2(cptr) && IsToken(cptr))
1125 #endif
1126 vsendto_one(cptr, tokpattern, vl);
1127 va_end(vl);
1128 }
1129 va_end(vl);
1130 return;
1131 }
1132
1133 /*
1134 * sendto_common_channels()
1135 *
1136 * Sends a message to all people (including user) on local server who are
1137 * in same channel with user.
1138 */
sendto_common_channels(aClient * user,char * pattern,...)1139 void sendto_common_channels(aClient *user, char *pattern, ...)
1140 {
1141 va_list vl;
1142
1143 Membership *channels;
1144 Member *users;
1145 aClient *cptr;
1146 int sendlen;
1147
1148 /* We now create the buffer _before_ we send it to the clients. -- Syzop */
1149 *sendbuf = '\0';
1150 va_start(vl, pattern);
1151 sendlen = vmakebuf_local_withprefix(sendbuf, user, pattern, vl);
1152 va_end(vl);
1153
1154 ++sentalong_marker;
1155 if (user->fd >= 0)
1156 sentalong[user->slot] = sentalong_marker;
1157 if (user->user)
1158 for (channels = user->user->channel; channels; channels = channels->next)
1159 for (users = channels->chptr->members; users; users = users->next)
1160 {
1161 cptr = users->cptr;
1162 if (!MyConnect(cptr) || (cptr->slot < 0) || (sentalong[cptr->slot] == sentalong_marker))
1163 continue;
1164 if ((channels->chptr->mode.mode & MODE_AUDITORIUM) &&
1165 !(is_chanownprotop(user, channels->chptr) || is_chanownprotop(cptr, channels->chptr)))
1166 continue;
1167 sentalong[cptr->slot] = sentalong_marker;
1168 sendbufto_one(cptr, sendbuf, sendlen);
1169 }
1170
1171 if (MyConnect(user))
1172 sendbufto_one(user, sendbuf, sendlen);
1173
1174 return;
1175 }
1176
1177 /*
1178 * sendto_common_channels_local_butone()
1179 *
1180 * Sends a message to all people on local server who are
1181 * in same channel with user and have the specified capability.
1182 */
sendto_common_channels_local_butone(aClient * user,int cap,char * pattern,...)1183 void sendto_common_channels_local_butone(aClient *user, int cap, char *pattern, ...)
1184 {
1185 va_list vl;
1186
1187 Membership *channels;
1188 Member *users;
1189 aClient *cptr;
1190 int sendlen;
1191
1192 /* We now create the buffer _before_ we send it to the clients. -- Syzop */
1193 *sendbuf = '\0';
1194 va_start(vl, pattern);
1195 sendlen = vmakebuf_local_withprefix(sendbuf, user, pattern, vl);
1196 va_end(vl);
1197
1198 ++sentalong_marker;
1199 if (user->fd >= 0)
1200 sentalong[user->slot] = sentalong_marker;
1201 if (user->user)
1202 {
1203 for (channels = user->user->channel; channels; channels = channels->next)
1204 for (users = channels->chptr->members; users; users = users->next)
1205 {
1206 cptr = users->cptr;
1207 if (!MyConnect(cptr) || (cptr->slot < 0) || (sentalong[cptr->slot] == sentalong_marker) ||
1208 !CHECKPROTO(cptr, cap))
1209 continue;
1210 if ((channels->chptr->mode.mode & MODE_AUDITORIUM) &&
1211 !(is_chanownprotop(user, channels->chptr) || is_chanownprotop(cptr, channels->chptr)))
1212 continue;
1213 sentalong[cptr->slot] = sentalong_marker;
1214 sendbufto_one(cptr, sendbuf, sendlen);
1215 }
1216 }
1217
1218 return;
1219 }
1220
1221 /*
1222 * sendto_channel_butserv
1223 *
1224 * Send a message to all members of a channel that are connected to this
1225 * server.
1226 */
1227
sendto_channel_butserv(aChannel * chptr,aClient * from,char * pattern,...)1228 void sendto_channel_butserv(aChannel *chptr, aClient *from, char *pattern, ...)
1229 {
1230 va_list vl;
1231 Member *lp;
1232 aClient *acptr;
1233 int sendlen;
1234
1235 /* We now create the buffer _before_ we send it to the clients. Rather than
1236 * rebuilding the buffer 1000 times for a 1000 local-users channel. -- Syzop
1237 */
1238 *sendbuf = '\0';
1239 va_start(vl, pattern);
1240 sendlen = vmakebuf_local_withprefix(sendbuf, from, pattern, vl);
1241 va_end(vl);
1242
1243 for (lp = chptr->members; lp; lp = lp->next)
1244 if (MyConnect(acptr = lp->cptr))
1245 sendbufto_one(acptr, sendbuf, sendlen);
1246
1247 return;
1248 }
1249
sendto_channel_butserv_butone(aChannel * chptr,aClient * from,aClient * one,char * pattern,...)1250 void sendto_channel_butserv_butone(aChannel *chptr, aClient *from, aClient *one, char *pattern, ...)
1251 {
1252 va_list vl;
1253 Member *lp;
1254 aClient *acptr;
1255
1256 for (va_start(vl, pattern), lp = chptr->members; lp; lp = lp->next)
1257 {
1258 if (lp->cptr == one)
1259 continue;
1260 if (MyConnect(acptr = lp->cptr))
1261 {
1262 va_start(vl, pattern);
1263 vsendto_prefix_one(acptr, from, pattern, vl);
1264 va_end(vl);
1265 }
1266 }
1267 va_end(vl);
1268 return;
1269 }
1270
1271 /*
1272 ** send a msg to all ppl on servers/hosts that match a specified mask
1273 ** (used for enhanced PRIVMSGs)
1274 **
1275 ** addition -- Armin, 8jun90 (gruner@informatik.tu-muenchen.de)
1276 */
1277
match_it(one,mask,what)1278 static int match_it(one, mask, what)
1279 aClient *one;
1280 char *mask;
1281 int what;
1282 {
1283 switch (what)
1284 {
1285 case MATCH_HOST:
1286 return (match(mask, one->user->realhost) == 0);
1287 case MATCH_SERVER:
1288 default:
1289 return (match(mask, one->user->server) == 0);
1290 }
1291 }
1292
1293 /*
1294 * sendto_match_servs
1295 *
1296 * send to all servers which match the mask at the end of a channel name
1297 * (if there is a mask present) or to all if no mask.
1298 */
sendto_match_servs(aChannel * chptr,aClient * from,char * format,...)1299 void sendto_match_servs(aChannel *chptr, aClient *from, char *format, ...)
1300 {
1301 va_list vl;
1302 int i;
1303 aClient *cptr;
1304 char *mask;
1305
1306 va_start(vl, format);
1307
1308 if (chptr)
1309 {
1310 if (*chptr->chname == '&')
1311 return;
1312 if ((mask = (char *)rindex(chptr->chname, ':')))
1313 mask++;
1314 }
1315 else
1316 mask = (char *)NULL;
1317
1318 for (i = 0; i <= LastSlot; i++)
1319 {
1320 if (!(cptr = local[i]))
1321 continue;
1322 if ((cptr == from) || !IsServer(cptr))
1323 continue;
1324 if (!BadPtr(mask) && IsServer(cptr) && match(mask, cptr->name))
1325 continue;
1326 va_start(vl, format);
1327 vsendto_one(cptr, format, vl);
1328 va_end(vl);
1329 }
1330 va_end(vl);
1331 }
1332
1333 /*
1334 * sendto_match_butone
1335 *
1336 * Send to all clients which match the mask in a way defined on 'what';
1337 * either by user hostname or user servername.
1338 */
sendto_match_butone(aClient * one,aClient * from,char * mask,int what,char * pattern,...)1339 void sendto_match_butone(aClient *one, aClient *from, char *mask, int what,
1340 char *pattern, ...)
1341 {
1342 va_list vl;
1343 int i;
1344 aClient *cptr, *acptr;
1345 char cansendlocal, cansendglobal;
1346
1347 va_start(vl, pattern);
1348 if (MyConnect(from))
1349 {
1350 cansendlocal = (OPCanLNotice(from)) ? 1 : 0;
1351 cansendglobal = (OPCanGNotice(from)) ? 1 : 0;
1352 }
1353 else
1354 cansendlocal = cansendglobal = 1;
1355
1356 for (i = 0; i <= LastSlot; i++)
1357 {
1358 if (!(cptr = local[i]))
1359 continue; /* that clients are not mine */
1360 if (cptr == one) /* must skip the origin !! */
1361 continue;
1362 if (IsServer(cptr))
1363 {
1364 if (!cansendglobal)
1365 continue;
1366 for (acptr = client; acptr; acptr = acptr->next)
1367 if (IsRegisteredUser(acptr)
1368 && match_it(acptr, mask, what)
1369 && acptr->from == cptr)
1370 break;
1371 /* a person on that server matches the mask, so we
1372 ** send *one* msg to that server ...
1373 */
1374 if (acptr == NULL)
1375 continue;
1376 /* ... but only if there *IS* a matching person */
1377 }
1378 /* my client, does he match ? */
1379 else if (!cansendlocal || (!(IsRegisteredUser(cptr) &&
1380 match_it(cptr, mask, what))))
1381 continue;
1382 va_start(vl, pattern);
1383 vsendto_prefix_one(cptr, from, pattern, vl);
1384 va_end(vl);
1385 }
1386 va_end(vl);
1387 return;
1388 }
1389
1390 /*
1391 * sendto_all_butone.
1392 *
1393 * Send a message to all connections except 'one'. The basic wall type
1394 * message generator.
1395 */
1396
sendto_all_butone(aClient * one,aClient * from,char * pattern,...)1397 void sendto_all_butone(aClient *one, aClient *from, char *pattern, ...)
1398 {
1399 va_list vl;
1400 int i;
1401 aClient *cptr;
1402
1403 for (va_start(vl, pattern), i = 0; i <= LastSlot; i++)
1404 if ((cptr = local[i]) && !IsMe(cptr) && one != cptr)
1405 {
1406 va_start(vl, pattern);
1407 vsendto_prefix_one(cptr, from, pattern, vl);
1408 va_end(vl);
1409 }
1410 va_end(vl);
1411 return;
1412 }
1413
1414 /*
1415 * sendto_ops
1416 *
1417 * Send to *local* ops only.
1418 */
sendto_ops(char * pattern,...)1419 void sendto_ops(char *pattern, ...)
1420 {
1421 va_list vl;
1422 aClient *cptr;
1423 int i;
1424 char nbuf[1024];
1425
1426 va_start(vl, pattern);
1427 for (i = 0; i <= LastSlot; i++)
1428 if ((cptr = local[i]) && !IsServer(cptr) && !IsMe(cptr) && SendServNotice(cptr))
1429 {
1430 (void)ircsprintf(nbuf, ":%s NOTICE %s :*** Notice -- ", me.name, cptr->name);
1431 (void)strncat(nbuf, pattern, sizeof(nbuf) - strlen(nbuf));
1432 va_start(vl, pattern);
1433 vsendto_one(cptr, nbuf, vl);
1434 va_end(vl);
1435 }
1436 va_end(vl);
1437 return;
1438 }
1439
1440 /*
1441 * sendto_failops
1442 *
1443 * Send to *local* mode +g ops only.
1444 */
sendto_failops(char * pattern,...)1445 void sendto_failops(char *pattern, ...)
1446 {
1447 va_list vl;
1448 aClient *cptr;
1449 int i;
1450 char nbuf[1024];
1451
1452 va_start(vl, pattern);
1453 for (i = 0; i <= LastSlot; i++)
1454 if ((cptr = local[i]) && !IsServer(cptr) && !IsMe(cptr) &&
1455 SendFailops(cptr))
1456 {
1457 (void)ircsprintf(nbuf, ":%s NOTICE %s :*** Global -- ",
1458 me.name, cptr->name);
1459 (void)strncat(nbuf, pattern,
1460 sizeof(nbuf) - strlen(nbuf));
1461 va_start(vl, pattern);
1462 vsendto_one(cptr, nbuf, vl);
1463 va_end(vl);
1464 }
1465 va_end(vl);
1466 return;
1467 }
1468
1469 /*
1470 * sendto_umode
1471 *
1472 * Send to specified umode
1473 */
sendto_umode(int umodes,char * pattern,...)1474 void sendto_umode(int umodes, char *pattern, ...)
1475 {
1476 va_list vl;
1477 aClient *cptr;
1478 int i;
1479 char nbuf[1024];
1480 va_start(vl, pattern);
1481 for (i = 0; i <= LastSlot; i++)
1482 if ((cptr = local[i]) && IsPerson(cptr) && (cptr->umodes & umodes) == umodes)
1483 {
1484 (void)ircsprintf(nbuf, ":%s NOTICE %s :",
1485 me.name, cptr->name);
1486 (void)strncat(nbuf, pattern,
1487 sizeof(nbuf) - strlen(nbuf));
1488 va_start(vl, pattern);
1489 vsendto_one(cptr, nbuf, vl);
1490 va_end(vl);
1491 }
1492 va_end(vl);
1493 return;
1494 }
1495
1496 /*
1497 * sendto_umode_raw
1498 *
1499 * Send to specified umode , raw, not a notice
1500 */
sendto_umode_raw(int umodes,char * pattern,...)1501 void sendto_umode_raw(int umodes, char *pattern, ...)
1502 {
1503 va_list vl;
1504 aClient *cptr;
1505 int i;
1506 va_start(vl, pattern);
1507 for (i = 0; i <= LastSlot; i++)
1508 if ((cptr = local[i]) && IsPerson(cptr) && (cptr->umodes & umodes) == umodes)
1509 {
1510 va_start(vl, pattern);
1511 vsendto_one(cptr, pattern, vl);
1512 va_end(vl);
1513 }
1514 va_end(vl);
1515 return;
1516 }
1517 /** Send to specified snomask - local / operonly.
1518 * @param snomask Snomask to send to (can be a bitmask [AND])
1519 * @param pattern printf-style pattern, followed by parameters.
1520 * This function does not send snomasks to non-opers.
1521 */
sendto_snomask(int snomask,char * pattern,...)1522 void sendto_snomask(int snomask, char *pattern, ...)
1523 {
1524 va_list vl;
1525 aClient *cptr;
1526 int i, j;
1527 char nbuf[2048];
1528
1529 va_start(vl, pattern);
1530 ircvsprintf(nbuf, pattern, vl);
1531 va_end(vl);
1532
1533 for (i = oper_fdlist.entry[j = 1]; j <= oper_fdlist.last_entry; i = oper_fdlist.entry[++j])
1534 if (((cptr = local[i])) && (cptr->user->snomask & snomask))
1535 sendto_one(cptr, ":%s NOTICE %s :%s", me.name, cptr->name, nbuf);
1536 }
1537
1538 /** Send to specified snomask - global / operonly.
1539 * @param snomask Snomask to send to (can be a bitmask [AND])
1540 * @param pattern printf-style pattern, followed by parameters
1541 * This function does not send snomasks to non-opers.
1542 */
sendto_snomask_global(int snomask,char * pattern,...)1543 void sendto_snomask_global(int snomask, char *pattern, ...)
1544 {
1545 va_list vl;
1546 aClient *cptr;
1547 int i, j;
1548 char nbuf[2048], snobuf[32], *p;
1549
1550 va_start(vl, pattern);
1551 ircvsprintf(nbuf, pattern, vl);
1552 va_end(vl);
1553
1554 for (i = oper_fdlist.entry[j = 1]; j <= oper_fdlist.last_entry; i = oper_fdlist.entry[++j])
1555 if (((cptr = local[i])) && (cptr->user->snomask & snomask))
1556 sendto_one(cptr, ":%s NOTICE %s :%s", me.name, cptr->name, nbuf);
1557
1558 /* Build snomasks-to-send-to buffer */
1559 snobuf[0] = '\0';
1560 for (i = 0, p=snobuf; i<= Snomask_highest; i++)
1561 if (snomask & Snomask_Table[i].mode)
1562 *p++ = Snomask_Table[i].flag;
1563 *p = '\0';
1564
1565 sendto_serv_butone_token(NULL, me.name, MSG_SENDSNO, TOK_SENDSNO,
1566 "%s :%s", snobuf, nbuf);
1567 }
1568
1569 /** Send to specified snomask - local.
1570 * @param snomask Snomask to send to (can be a bitmask [AND])
1571 * @param pattern printf-style pattern, followed by parameters.
1572 * This function also delivers to non-opers w/the snomask if needed.
1573 */
sendto_snomask_normal(int snomask,char * pattern,...)1574 void sendto_snomask_normal(int snomask, char *pattern, ...)
1575 {
1576 va_list vl;
1577 aClient *cptr;
1578 int i;
1579 char nbuf[2048];
1580
1581 va_start(vl, pattern);
1582 ircvsprintf(nbuf, pattern, vl);
1583 va_end(vl);
1584
1585 for (i = LastSlot; i >= 0; i--)
1586 if ((cptr = local[i]) && IsPerson(cptr) && (cptr->user->snomask & snomask))
1587 sendto_one(cptr, ":%s NOTICE %s :%s", me.name, cptr->name, nbuf);
1588 }
1589
1590 /** Send to specified snomask - global.
1591 * @param snomask Snomask to send to (can be a bitmask [AND])
1592 * @param pattern printf-style pattern, followed by parameters
1593 * This function also delivers to non-opers w/the snomask if needed.
1594 */
sendto_snomask_normal_global(int snomask,char * pattern,...)1595 void sendto_snomask_normal_global(int snomask, char *pattern, ...)
1596 {
1597 va_list vl;
1598 aClient *cptr;
1599 int i;
1600 char nbuf[2048], snobuf[32], *p;
1601
1602 va_start(vl, pattern);
1603 ircvsprintf(nbuf, pattern, vl);
1604 va_end(vl);
1605
1606 for (i = LastSlot; i >= 0; i--)
1607 if ((cptr = local[i]) && IsPerson(cptr) && (cptr->user->snomask & snomask))
1608 sendto_one(cptr, ":%s NOTICE %s :%s", me.name, cptr->name, nbuf);
1609
1610 /* Build snomasks-to-send-to buffer */
1611 snobuf[0] = '\0';
1612 for (i = 0, p=snobuf; i<= Snomask_highest; i++)
1613 if (snomask & Snomask_Table[i].mode)
1614 *p++ = Snomask_Table[i].flag;
1615 *p = '\0';
1616
1617 sendto_serv_butone_token(NULL, me.name, MSG_SENDSNO, TOK_SENDSNO,
1618 "%s :%s", snobuf, nbuf);
1619 }
1620
1621
1622 /*
1623 * sendto_failops_whoare_opers
1624 *
1625 * Send to *local* mode +g ops only who are also +o.
1626 */
sendto_failops_whoare_opers(char * pattern,...)1627 void sendto_failops_whoare_opers(char *pattern, ...)
1628 {
1629 va_list vl;
1630 aClient *cptr;
1631 int i;
1632 char nbuf[1024];
1633
1634 va_start(vl, pattern);
1635 for (i = 0; i <= LastSlot; i++)
1636 if ((cptr = local[i]) && !IsServer(cptr) && !IsMe(cptr) &&
1637 SendFailops(cptr) && IsAnOper(cptr))
1638 {
1639 (void)ircsprintf(nbuf, ":%s NOTICE %s :*** Global -- ",
1640 me.name, cptr->name);
1641 (void)strncat(nbuf, pattern,
1642 sizeof(nbuf) - strlen(nbuf));
1643 va_start(vl, pattern);
1644 vsendto_one(cptr, nbuf, vl);
1645 va_end(vl);
1646 }
1647 va_end(vl);
1648 return;
1649 }
1650 /*
1651 * sendto_locfailops
1652 *
1653 * Send to *local* mode +g ops only who are also +o.
1654 */
sendto_locfailops(char * pattern,...)1655 void sendto_locfailops(char *pattern, ...)
1656 {
1657 va_list vl;
1658 aClient *cptr;
1659 int i;
1660 char nbuf[1024];
1661
1662 va_start(vl, pattern);
1663 for (i = 0; i <= LastSlot; i++)
1664 if ((cptr = local[i]) && !IsServer(cptr) && !IsMe(cptr) &&
1665 SendFailops(cptr) && IsAnOper(cptr))
1666 {
1667 (void)ircsprintf(nbuf, ":%s NOTICE %s :*** LocOps -- ",
1668 me.name, cptr->name);
1669 (void)strncat(nbuf, pattern,
1670 sizeof(nbuf) - strlen(nbuf));
1671 va_start(vl, pattern);
1672 vsendto_one(cptr, nbuf, vl);
1673 va_end(vl);
1674 }
1675 va_end(vl);
1676 return;
1677 }
1678 /*
1679 * sendto_opers
1680 *
1681 * Send to *local* ops only. (all +O or +o people)
1682 */
sendto_opers(char * pattern,...)1683 void sendto_opers(char *pattern, ...)
1684 {
1685 va_list vl;
1686 aClient *cptr;
1687 int i;
1688 char nbuf[1024];
1689
1690 va_start(vl, pattern);
1691 for (i = 0; i <= LastSlot; i++)
1692 if ((cptr = local[i]) && !IsServer(cptr) && !IsMe(cptr) &&
1693 IsAnOper(cptr))
1694 {
1695 (void)ircsprintf(nbuf, ":%s NOTICE %s :*** Oper -- ",
1696 me.name, cptr->name);
1697 (void)strncat(nbuf, pattern,
1698 sizeof(nbuf) - strlen(nbuf));
1699 va_start(vl, pattern);
1700 vsendto_one(cptr, nbuf, vl);
1701 va_end(vl);
1702 }
1703 va_end(vl);
1704 return;
1705 }
1706
1707 /* ** sendto_ops_butone
1708 ** Send message to all operators.
1709 ** one - client not to send message to
1710 ** from- client which message is from *NEVER* NULL!!
1711 */
sendto_ops_butone(aClient * one,aClient * from,char * pattern,...)1712 void sendto_ops_butone(aClient *one, aClient *from, char *pattern, ...)
1713 {
1714 va_list vl;
1715 int i;
1716 aClient *cptr;
1717
1718 va_start(vl, pattern);
1719
1720 ++sentalong_marker;
1721 for (cptr = client; cptr; cptr = cptr->next)
1722 {
1723 if (!SendWallops(cptr))
1724 continue;
1725 i = cptr->from->slot; /* find connection oper is on */
1726 if (sentalong[i] == sentalong_marker) /* sent message along it already ? */
1727 continue;
1728 if (cptr->from == one)
1729 continue; /* ...was the one I should skip */
1730 sentalong[i] = sentalong_marker;
1731 va_start(vl, pattern);
1732 vsendto_prefix_one(cptr->from, from, pattern, vl);
1733 va_end(vl);
1734 }
1735 va_end(vl);
1736 return;
1737 }
1738
1739 /*
1740 ** sendto_ops_butone
1741 ** Send message to all operators regardless of whether they are +w or
1742 ** not..
1743 ** one - client not to send message to
1744 ** from- client which message is from *NEVER* NULL!!
1745 */
sendto_opers_butone(aClient * one,aClient * from,char * pattern,...)1746 void sendto_opers_butone(aClient *one, aClient *from, char *pattern, ...)
1747 {
1748 va_list vl;
1749 int i;
1750 aClient *cptr;
1751
1752 va_start(vl, pattern);
1753
1754 ++sentalong_marker;
1755 for (cptr = client; cptr; cptr = cptr->next)
1756 {
1757 if (!IsAnOper(cptr))
1758 continue;
1759 i = cptr->from->slot; /* find connection oper is on */
1760 if (sentalong[i] == sentalong_marker) /* sent message along it already ? */
1761 continue;
1762 if (cptr->from == one)
1763 continue; /* ...was the one I should skip */
1764 sentalong[i] = sentalong_marker;
1765 va_start(vl, pattern);
1766 vsendto_prefix_one(cptr->from, from, pattern, vl);
1767 va_end(vl);
1768 }
1769 va_end(vl);
1770 return;
1771 }
1772 /*
1773 ** sendto_ops_butme
1774 ** Send message to all operators except local ones
1775 ** from- client which message is from *NEVER* NULL!!
1776 */
sendto_ops_butme(aClient * from,char * pattern,...)1777 void sendto_ops_butme(aClient *from, char *pattern, ...)
1778 {
1779 va_list vl;
1780 int i;
1781 aClient *cptr;
1782
1783 va_start(vl, pattern);
1784
1785 ++sentalong_marker;
1786 for (cptr = client; cptr; cptr = cptr->next)
1787 {
1788 if (!SendWallops(cptr))
1789 continue;
1790 i = cptr->from->slot; /* find connection oper is on */
1791 if (sentalong[i] == sentalong_marker) /* sent message along it already ? */
1792 continue;
1793 if (!strcmp(cptr->user->server, me.name)) /* a locop */
1794 continue;
1795 sentalong[i] = sentalong_marker;
1796 va_start(vl, pattern);
1797 vsendto_prefix_one(cptr->from, from, pattern, vl);
1798 va_end(vl);
1799 }
1800 va_end(vl);
1801 return;
1802 }
1803
1804 /* Prepare buffer based on format string and 'from' for LOCAL delivery.
1805 * The prefix (:<something>) will be expanded to :nick!user@host if 'from'
1806 * is a person, taking into account the rules for hidden/cloaked host.
1807 * NOTE: Do not send this prepared buffer to remote clients or servers,
1808 * they do not want or need the expanded prefix. In that case, simply
1809 * use ircvsprintf() directly.
1810 */
vmakebuf_local_withprefix(char * buf,struct Client * from,const char * pattern,va_list vl)1811 int vmakebuf_local_withprefix(char *buf, struct Client *from, const char *pattern, va_list vl)
1812 {
1813 int len;
1814
1815 if (from && from->user)
1816 {
1817 char *par;
1818
1819 par = va_arg(vl, char *); /* eat first parameter */
1820
1821 *buf = ':';
1822 strcpy(buf+1, from->name);
1823
1824 if (IsPerson(from))
1825 {
1826 char *username = from->user->username;
1827 char *host = GetHost(from);
1828
1829 if (*username)
1830 {
1831 strcat(buf, "!");
1832 strcat(buf, username);
1833 }
1834 if (*host)
1835 {
1836 strcat(buf, "@");
1837 strcat(buf, host);
1838 }
1839 }
1840
1841 /* Assuming 'pattern' always starts with ":%s ..." */
1842 if (!strcmp(&pattern[3], "%s"))
1843 strcpy(buf + strlen(buf), va_arg(vl, char *)); /* This can speed things up by 30% -- Syzop */
1844 else
1845 ircvsprintf(buf + strlen(buf), &pattern[3], vl);
1846 }
1847 else
1848 ircvsprintf(buf, pattern, vl);
1849
1850 len = strlen(buf);
1851 ADD_CRLF(buf, len);
1852 return len;
1853 }
1854
vsendto_prefix_one(struct Client * to,struct Client * from,const char * pattern,va_list vl)1855 void vsendto_prefix_one(struct Client *to, struct Client *from,
1856 const char *pattern, va_list vl)
1857 {
1858 if (to && from && MyClient(to) && from->user)
1859 vmakebuf_local_withprefix(sendbuf, from, pattern, vl);
1860 else
1861 ircvsprintf(sendbuf, pattern, vl);
1862
1863 sendbufto_one(to, sendbuf, 0);
1864 }
1865
1866 /*
1867 * sendto_prefix_one
1868 *
1869 * to - destination client
1870 * from - client which message is from
1871 *
1872 * NOTE: NEITHER OF THESE SHOULD *EVER* BE NULL!!
1873 * -avalon
1874 */
1875
sendto_prefix_one(aClient * to,aClient * from,const char * pattern,...)1876 void sendto_prefix_one(aClient *to, aClient *from, const char *pattern, ...)
1877 {
1878 va_list vl;
1879 va_start(vl, pattern);
1880 vsendto_prefix_one(to, from, pattern, vl);
1881 va_end(vl);
1882 }
1883
1884 /*
1885 * sendto_realops
1886 *
1887 * Send to *local* ops only but NOT +s nonopers.
1888 */
sendto_realops(char * pattern,...)1889 void sendto_realops(char *pattern, ...)
1890 {
1891 va_list vl;
1892 aClient *cptr;
1893 int i;
1894 #ifndef NO_FDLIST
1895 int j;
1896 #endif
1897 char nbuf[1024];
1898
1899 va_start(vl, pattern);
1900 #ifdef NO_FDLIST
1901 for (i = 0; i <= LastSlot; i++)
1902 #else
1903 for (i = oper_fdlist.entry[j = 1]; j <= oper_fdlist.last_entry; i = oper_fdlist.entry[++j])
1904 #endif
1905 #ifdef NO_FDLIST
1906 if ((cptr = local[i]) && !IsServer(cptr) && !IsMe(cptr) &&
1907 IsOper(cptr))
1908 #else
1909 if ((cptr = local[i]))
1910 #endif
1911 {
1912 (void)ircsprintf(nbuf, ":%s NOTICE %s :*** Notice -- ",
1913 me.name, cptr->name);
1914 (void)strncat(nbuf, pattern,
1915 sizeof(nbuf) - strlen(nbuf));
1916 va_start(vl, pattern);
1917 vsendto_one(cptr, nbuf, vl);
1918 va_end(vl);
1919 }
1920 va_end(vl);
1921 return;
1922 }
1923
sendto_connectnotice(char * nick,anUser * user,aClient * sptr,int disconnect,char * comment)1924 void sendto_connectnotice(char *nick, anUser *user, aClient *sptr, int disconnect, char *comment)
1925 {
1926 aClient *cptr;
1927 int i, j;
1928 char connectd[1024];
1929 char connecth[1024];
1930
1931 if (!disconnect)
1932 {
1933 RunHook(HOOKTYPE_LOCAL_CONNECT, sptr);
1934 ircsprintf(connectd,
1935 "*** Notice -- Client connecting on port %d: %s (%s@%s) [%s] %s%s%s",
1936 sptr->listener->port, nick, user->username, user->realhost,
1937 sptr->class ? sptr->class->name : "",
1938 #ifdef USE_SSL
1939 IsSecure(sptr) ? "[secure " : "",
1940 IsSecure(sptr) ? SSL_get_cipher((SSL *)sptr->ssl) : "",
1941 IsSecure(sptr) ? "]" : "");
1942 #else
1943 "", "", "");
1944 #endif
1945 ircsprintf(connecth,
1946 "*** Notice -- Client connecting: %s (%s@%s) [%s] {%s}", nick,
1947 user->username, user->realhost, Inet_ia2p(&sptr->ip),
1948 sptr->class ? sptr->class->name : "0");
1949 }
1950 else
1951 {
1952 ircsprintf(connectd, "*** Notice -- Client exiting: %s (%s@%s) [%s]",
1953 nick, user->username, user->realhost, comment);
1954 ircsprintf(connecth, "*** Notice -- Client exiting: %s (%s@%s) [%s] [%s]",
1955 nick, user->username, user->realhost, comment, Inet_ia2p(&sptr->ip));
1956 }
1957
1958 for (i = oper_fdlist.entry[j = 1]; j <= oper_fdlist.last_entry; i = oper_fdlist.entry[++j])
1959 if (((cptr = local[i])) && (cptr->user->snomask & SNO_CLIENT))
1960 {
1961 if (IsHybNotice(cptr))
1962 sendto_one(cptr, ":%s NOTICE %s :%s", me.name,
1963 cptr->name, connecth);
1964 else
1965 sendto_one(cptr, ":%s NOTICE %s :%s", me.name,
1966 cptr->name, connectd);
1967
1968 }
1969 }
1970
sendto_fconnectnotice(char * nick,anUser * user,aClient * sptr,int disconnect,char * comment)1971 void sendto_fconnectnotice(char *nick, anUser *user, aClient *sptr, int disconnect, char *comment)
1972 {
1973 aClient *cptr;
1974 int i, j;
1975 char connectd[1024];
1976 char connecth[1024];
1977
1978 if (!disconnect)
1979 {
1980 ircsprintf(connectd, "*** Notice -- Client connecting at %s: %s (%s@%s)",
1981 user->server, nick, user->username, user->realhost);
1982 ircsprintf(connecth,
1983 "*** Notice -- Client connecting at %s: %s (%s@%s) [%s] {0}", user->server, nick,
1984 user->username, user->realhost, user->ip_str ? user->ip_str : "0");
1985 }
1986 else
1987 {
1988 ircsprintf(connectd, "*** Notice -- Client exiting at %s: %s!%s@%s (%s)",
1989 user->server, nick, user->username, user->realhost, comment);
1990 ircsprintf(connecth, "*** Notice -- Client exiting at %s: %s (%s@%s) [%s] [%s]",
1991 user->server, nick, user->username, user->realhost, comment,
1992 user->ip_str ? user->ip_str : "0");
1993 }
1994
1995 for (i = oper_fdlist.entry[j = 1]; j <= oper_fdlist.last_entry; i = oper_fdlist.entry[++j])
1996 if (((cptr = local[i])) && (cptr->user->snomask & SNO_FCLIENT))
1997 {
1998 if (IsHybNotice(cptr))
1999 sendto_one(cptr, ":%s NOTICE %s :%s", me.name,
2000 cptr->name, connecth);
2001 else
2002 sendto_one(cptr, ":%s NOTICE %s :%s", me.name,
2003 cptr->name, connectd);
2004
2005 }
2006 }
2007
2008 /*
2009 * sendto_server_butone_nickcmd
2010 *
2011 * Send a message to all connected servers except the client 'one'.
2012 */
sendto_serv_butone_nickcmd(aClient * one,aClient * sptr,char * nick,int hopcount,long lastnick,char * username,char * realhost,char * server,char * svid,char * info,char * umodes,char * virthost)2013 void sendto_serv_butone_nickcmd(aClient *one, aClient *sptr,
2014 char *nick, int hopcount,
2015 long lastnick, char *username, char *realhost, char *server,
2016 char *svid, char *info, char *umodes, char *virthost)
2017 {
2018 int i;
2019 aClient *cptr;
2020 #ifndef NO_FDLIST
2021 int j;
2022 #endif
2023
2024 #ifdef NO_FDLIST
2025 for (i = 0; i <= LastSlot; i++)
2026 #else
2027 for (i = serv_fdlist.entry[j = 1]; j <= serv_fdlist.last_entry; i = serv_fdlist.entry[++j])
2028 #endif
2029 {
2030 if (!(cptr = local[i]) || (one && cptr == one->from))
2031 continue;
2032 #ifdef NO_FDLIST
2033 if (IsServer(cptr))
2034 #endif
2035 {
2036 char *vhost;
2037 if (SupportVHP(cptr))
2038 {
2039 if (IsHidden(sptr))
2040 vhost = sptr->user->virthost;
2041 else
2042 vhost = sptr->user->realhost;
2043 }
2044 else
2045 {
2046 if (IsHidden(sptr) && sptr->umodes & UMODE_SETHOST)
2047 vhost = sptr->user->virthost;
2048 else
2049 vhost = "*";
2050 }
2051
2052 if (SupportNICKv2(cptr))
2053 {
2054 if (sptr->srvptr->serv->numeric && SupportNS(cptr))
2055 sendto_one(cptr,
2056 (cptr->proto & PROTO_SJB64) ?
2057 /* Ugly double %s to prevent excessive spaces */
2058 "%s %s %d %B %s %s %b %s %s %s %s%s%s%s:%s"
2059 :
2060 "%s %s %d %lu %s %s %b %s %s %s %s%s%s%s:%s"
2061 ,
2062 (IsToken(cptr) ? TOK_NICK : MSG_NICK), nick,
2063 hopcount, (long)lastnick, username, realhost,
2064 (long)(sptr->srvptr->serv->numeric),
2065 svid, umodes, vhost,
2066 SupportCLK(cptr) ? getcloak(sptr) : "",
2067 SupportCLK(cptr) ? " " : "",
2068 SupportNICKIP(cptr) ? encode_ip(sptr->user->ip_str) : "",
2069 SupportNICKIP(cptr) ? " " : "",
2070 info);
2071 else
2072 sendto_one(cptr,
2073 "%s %s %d %d %s %s %s %s %s %s %s%s%s%s:%s",
2074 (IsToken(cptr) ? TOK_NICK : MSG_NICK), nick,
2075 hopcount, lastnick, username, realhost,
2076 SupportNS(cptr) && sptr->srvptr->serv->numeric ? base64enc(sptr->srvptr->serv->numeric) : server,
2077 svid, umodes, vhost,
2078 SupportCLK(cptr) ? getcloak(sptr) : "",
2079 SupportCLK(cptr) ? " " : "",
2080 SupportNICKIP(cptr) ? encode_ip(sptr->user->ip_str) : "",
2081 SupportNICKIP(cptr) ? " " : "",
2082 info);
2083
2084 }
2085 else
2086 {
2087 sendto_one(cptr, "%s %s %d %d %s %s %s %s :%s",
2088 (IsToken(cptr) ? TOK_NICK : MSG_NICK),
2089 nick, hopcount, lastnick, username,
2090 realhost,
2091 server, svid, info);
2092 if (strcmp(umodes, "+"))
2093 {
2094 sendto_one(cptr, ":%s %s %s :%s",
2095 nick,
2096 (IsToken(cptr) ? TOK_MODE :
2097 MSG_MODE), nick, umodes);
2098 }
2099 if (IsHidden(sptr) && (sptr->umodes & UMODE_SETHOST))
2100 {
2101 sendto_one(cptr, ":%s %s %s",
2102 nick,
2103 (IsToken(cptr) ? TOK_SETHOST :
2104 MSG_SETHOST), virthost);
2105 }
2106 else if (SupportVHP(cptr))
2107 {
2108 sendto_one(cptr, ":%s %s %s",
2109 nick,
2110 (IsToken(cptr) ? TOK_SETHOST :
2111 MSG_SETHOST), (IsHidden(sptr) ? virthost :
2112 realhost));
2113 }
2114 }
2115 }
2116 }
2117 return;
2118 }
2119
2120 /*
2121 * sendto_one_nickcmd
2122 *
2123 */
sendto_one_nickcmd(aClient * cptr,aClient * sptr,char * umodes)2124 void sendto_one_nickcmd(aClient *cptr, aClient *sptr, char *umodes)
2125 {
2126 if (SupportNICKv2(cptr))
2127 {
2128 char *vhost;
2129 if (SupportVHP(cptr))
2130 {
2131 if (IsHidden(sptr))
2132 vhost = sptr->user->virthost;
2133 else
2134 vhost = sptr->user->realhost;
2135 }
2136 else
2137 {
2138 if (IsHidden(sptr) && sptr->umodes & UMODE_SETHOST)
2139 vhost = sptr->user->virthost;
2140 else
2141 vhost = "*";
2142 }
2143 if (sptr->srvptr->serv->numeric && SupportNS(cptr))
2144 sendto_one(cptr,
2145 (cptr->proto & PROTO_SJB64) ?
2146 /* Ugly double %s to prevent excessive spaces */
2147 "%s %s %d %B %s %s %b %s %s %s %s%s:%s"
2148 :
2149 "%s %s %d %lu %s %s %b %s %s %s %s%s:%s"
2150 ,
2151 (IsToken(cptr) ? TOK_NICK : MSG_NICK), sptr->name,
2152 sptr->hopcount+1, (long)sptr->lastnick, sptr->user->username,
2153 sptr->user->realhost, (long)(sptr->srvptr->serv->numeric),
2154 sptr->user->svid, umodes, vhost,
2155 SupportNICKIP(cptr) ? encode_ip(sptr->user->ip_str) : "",
2156 SupportNICKIP(cptr) ? " " : "", sptr->info);
2157 else
2158 sendto_one(cptr,
2159 "%s %s %d %d %s %s %s %lu %s %s %s%s:%s",
2160 (IsToken(cptr) ? TOK_NICK : MSG_NICK), sptr->name,
2161 sptr->hopcount+1, sptr->lastnick, sptr->user->username,
2162 sptr->user->realhost, SupportNS(cptr) &&
2163 sptr->srvptr->serv->numeric ? base64enc(sptr->srvptr->serv->numeric)
2164 : sptr->user->server, sptr->user->svid, umodes, vhost,
2165 SupportNICKIP(cptr) ? encode_ip(sptr->user->ip_str) : "",
2166 SupportNICKIP(cptr) ? " " : "", sptr->info);
2167 }
2168 else
2169 {
2170 sendto_one(cptr, "%s %s %d %d %s %s %s %s :%s",
2171 (IsToken(cptr) ? TOK_NICK : MSG_NICK),
2172 sptr->name, sptr->hopcount+1, sptr->lastnick, sptr->user->username,
2173 sptr->user->realhost, sptr->user->server, sptr->user->svid,
2174 sptr->info);
2175 if (strcmp(umodes, "+"))
2176 {
2177 sendto_one(cptr, ":%s %s %s :%s",
2178 sptr->name, (IsToken(cptr) ? TOK_MODE :
2179 MSG_MODE), sptr->name, umodes);
2180 }
2181 if (IsHidden(sptr) && (sptr->umodes & UMODE_SETHOST))
2182 {
2183 sendto_one(cptr, ":%s %s %s",
2184 sptr->name, (IsToken(cptr) ? TOK_SETHOST :
2185 MSG_SETHOST), sptr->user->virthost);
2186 }
2187 else if (SupportVHP(cptr))
2188 {
2189 sendto_one(cptr, ":%s %s %s", sptr->name,
2190 (IsToken(cptr) ? TOK_SETHOST : MSG_SETHOST),
2191 (IsHidden(sptr) ? sptr->user->virthost :
2192 sptr->user->realhost));
2193 }
2194 }
2195 return;
2196 }
2197
sendto_message_one(aClient * to,aClient * from,char * sender,char * cmd,char * nick,char * msg)2198 void sendto_message_one(aClient *to, aClient *from, char *sender,
2199 char *cmd, char *nick, char *msg)
2200 {
2201 if(IsServer(to->from) && IsToken(to->from)) {
2202 if(*cmd == 'P') cmd = TOK_PRIVATE;
2203 if(*cmd == 'N') cmd = TOK_NOTICE;
2204 }
2205 sendto_prefix_one(to, from, ":%s %s %s :%s",
2206 sender, cmd, nick, msg);
2207 }
2208
2209 /* sidenote: sendnotice() and sendtxtnumeric() assume no client or server
2210 * has a % in their nick, which is a safe assumption since % is illegal.
2211 */
2212
sendnotice(aClient * to,char * pattern,...)2213 void sendnotice(aClient *to, char *pattern, ...)
2214 {
2215 static char realpattern[1024];
2216 va_list vl;
2217 char *name = *to->name ? to->name : "*";
2218
2219 if (!IsWebTV(to))
2220 ircsprintf(realpattern, ":%s NOTICE %s :%s", me.name, name, pattern);
2221 else
2222 ircsprintf(realpattern, ":%s PRIVMSG %s :%s", me.name, name, pattern);
2223
2224 va_start(vl, pattern);
2225 vsendto_one(to, realpattern, vl);
2226 va_end(vl);
2227 }
2228
sendtxtnumeric(aClient * to,char * pattern,...)2229 void sendtxtnumeric(aClient *to, char *pattern, ...)
2230 {
2231 static char realpattern[1024];
2232 va_list vl;
2233
2234 if (!IsWebTV(to))
2235 ircsprintf(realpattern, ":%s %d %s :%s", me.name, RPL_TEXT, to->name, pattern);
2236 else
2237 ircsprintf(realpattern, ":%s PRIVMSG %s :%s", me.name, to->name, pattern);
2238
2239 va_start(vl, pattern);
2240 vsendto_one(to, realpattern, vl);
2241 va_end(vl);
2242 }
2243