Author: Bleep <tomh@inxpress.net>
[ircu2.10.12-pk.git] / ircd / m_names.c
1 /*
2  * IRC - Internet Relay Chat, ircd/m_names.c
3  * Copyright (C) 1990 Jarkko Oikarinen and
4  *                    University of Oulu, Computing Center
5  *
6  * See file AUTHORS in IRC package for additional names of
7  * the programmers.
8  *
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)
12  * any later version.
13  *
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.
18  *
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.
22  *
23  * $Id$
24  */
25
26 /*
27  * m_functions execute protocol messages on this server:
28  *
29  *    cptr    is always NON-NULL, pointing to a *LOCAL* client
30  *            structure (with an open socket connected!). This
31  *            identifies the physical socket where the message
32  *            originated (or which caused the m_function to be
33  *            executed--some m_functions may call others...).
34  *
35  *    sptr    is the source of the message, defined by the
36  *            prefix part of the message if present. If not
37  *            or prefix not found, then sptr==cptr.
38  *
39  *            (!IsServer(cptr)) => (cptr == sptr), because
40  *            prefixes are taken *only* from servers...
41  *
42  *            (IsServer(cptr))
43  *                    (sptr == cptr) => the message didn't
44  *                    have the prefix.
45  *
46  *                    (sptr != cptr && IsServer(sptr) means
47  *                    the prefix specified servername. (?)
48  *
49  *                    (sptr != cptr && !IsServer(sptr) means
50  *                    that message originated from a remote
51  *                    user (not local).
52  *
53  *            combining
54  *
55  *            (!IsServer(sptr)) means that, sptr can safely
56  *            taken as defining the target structure of the
57  *            message in this server.
58  *
59  *    *Always* true (if 'parse' and others are working correct):
60  *
61  *    1)      sptr->from == cptr  (note: cptr->from == cptr)
62  *
63  *    2)      MyConnect(sptr) <=> sptr == cptr (e.g. sptr
64  *            *cannot* be a local connection, unless it's
65  *            actually cptr!). [MyConnect(x) should probably
66  *            be defined as (x == x->from) --msa ]
67  *
68  *    parc    number of variable parameter strings (if zero,
69  *            parv is allowed to be NULL)
70  *
71  *    parv    a NULL terminated list of parameter pointers,
72  *
73  *                    parv[0], sender (prefix string), if not present
74  *                            this points to an empty string.
75  *                    parv[1]...parv[parc-1]
76  *                            pointers to additional parameters
77  *                    parv[parc] == NULL, *always*
78  *
79  *            note:   it is guaranteed that parv[0]..parv[parc-1] are all
80  *                    non-NULL pointers.
81  */
82 #if 0
83 /*
84  * No need to include handlers.h here the signatures must match
85  * and we don't need to force a rebuild of all the handlers everytime
86  * we add a new one to the list. --Bleep
87  */
88 #include "handlers.h"
89 #endif /* 0 */
90 #include "channel.h"
91 #include "client.h"
92 #include "hash.h"
93 #include "ircd.h"
94 #include "ircd_reply.h"
95 #include "ircd_string.h"
96 #include "msg.h"
97 #include "numeric.h"
98 #include "numnicks.h"
99 #include "s_user.h"
100 #include "send.h"
101
102 #include <assert.h>
103 #include <string.h>
104
105 /*
106  * m_names - generic message handler
107  *
108  * parv[0] = sender prefix
109  * parv[1] = channel
110  */
111 int m_names(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
112 {
113   struct Channel *chptr;
114   struct Client *c2ptr;
115   struct Membership* member;
116   struct Channel *ch2ptr = 0;
117   int idx, flag, len, mlen;
118   char *s, *para = parc > 1 ? parv[1] : 0;
119   char buf[BUFSIZE];
120
121   if (parc > 2 && hunt_server(1, cptr, sptr, "%s%s " TOK_NAMES " %s %s", 2, parc, parv))
122     return 0;
123
124   mlen = strlen(me.name) + 10 + strlen(sptr->name);
125
126   if (!EmptyString(para))
127   {
128     s = strchr(para, ',');
129     if (s)
130     {
131       parv[1] = ++s;
132       m_names(cptr, sptr, parc, parv);
133     }
134     clean_channelname(para);
135     ch2ptr = FindChannel(para);
136   }
137
138   /*
139    * First, do all visible channels (public and the one user self is)
140    */
141
142   for (chptr = GlobalChannelList; chptr; chptr = chptr->next)
143   {
144     if ((chptr != ch2ptr) && !EmptyString(para))
145       continue;                 /* -- wanted a specific channel */
146     if (!MyConnect(sptr) && EmptyString(para))
147       continue;
148 #ifndef GODMODE
149     if (!ShowChannel(sptr, chptr))
150       continue;                 /* -- users on this are not listed */
151 #endif
152
153     /* Find users on same channel (defined by chptr) */
154
155     strcpy(buf, "* ");
156     len = strlen(chptr->chname);
157     strcpy(buf + 2, chptr->chname);
158     strcpy(buf + 2 + len, " :");
159
160     if (PubChannel(chptr))
161       *buf = '=';
162     else if (SecretChannel(chptr))
163       *buf = '@';
164     idx = len + 4;
165     flag = 1;
166     for (member = chptr->members; member; member = member->next_member)
167     {
168       c2ptr = member->user;
169 #ifndef GODMODE
170       if (sptr != c2ptr && IsInvisible(c2ptr) && !find_channel_member(sptr, chptr))
171         continue;
172 #endif
173       if (IsZombie(member))
174       {
175         if (member->user != sptr)
176           continue;
177         else
178         {
179           strcat(buf, "!");
180           idx++;
181         }
182       }
183       else if (IsChanOp(member))
184       {
185         strcat(buf, "@");
186         idx++;
187       }
188       else if (HasVoice(member))
189       {
190         strcat(buf, "+");
191         idx++;
192       }
193       strcat(buf, c2ptr->name);
194       strcat(buf, " ");
195       idx += strlen(c2ptr->name) + 1;
196       flag = 1;
197 #ifdef GODMODE
198       {
199         char yxx[6];
200         sprintf_irc(yxx, "%s%s", NumNick(c2ptr));
201         assert(c2ptr == findNUser(yxx));
202         sprintf_irc(buf + strlen(buf), "(%s) ", yxx);
203         idx += 6;
204       }
205       if (mlen + idx + NICKLEN + 11 > BUFSIZE)
206 #else
207       if (mlen + idx + NICKLEN + 5 > BUFSIZE)
208 #endif
209         /* space, modifier, nick, \r \n \0 */
210       {
211         sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf);
212         strcpy(buf, "* ");
213         ircd_strncpy(buf + 2, chptr->chname, len + 1);
214         buf[len + 2] = 0;
215         strcat(buf, " :");
216         if (PubChannel(chptr))
217           *buf = '=';
218         else if (SecretChannel(chptr))
219           *buf = '@';
220         idx = len + 4;
221         flag = 0;
222       }
223     }
224     if (flag)
225       sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf);
226   }
227   if (!EmptyString(para))
228   {
229     sendto_one(sptr, rpl_str(RPL_ENDOFNAMES), me.name, parv[0],
230         ch2ptr ? ch2ptr->chname : para);
231     return (1);
232   }
233
234   /* Second, do all non-public, non-secret channels in one big sweep */
235
236   strcpy(buf, "* * :");
237   idx = 5;
238   flag = 0;
239   for (c2ptr = GlobalClientList; c2ptr; c2ptr = c2ptr->next)
240   {
241     struct Channel *ch3ptr;
242     int showflag = 0, secret = 0;
243
244 #ifndef GODMODE
245     if (!IsUser(c2ptr) || (sptr != c2ptr && IsInvisible(c2ptr)))
246 #else
247     if (!IsUser(c2ptr))
248 #endif
249       continue;
250     member = c2ptr->user->channel;
251     /*
252      * Don't show a client if they are on a secret channel or when
253      * they are on a channel sptr is on since they have already
254      * been show earlier. -avalon
255      */
256     while (member)
257     {
258       ch3ptr = member->channel;
259 #ifndef GODMODE
260       if (PubChannel(ch3ptr) || find_channel_member(sptr, ch3ptr))
261 #endif
262         showflag = 1;
263       if (SecretChannel(ch3ptr))
264         secret = 1;
265       member = member->next_channel;
266     }
267     if (showflag)               /* Have we already shown them ? */
268       continue;
269 #ifndef GODMODE
270     if (secret)                 /* On any secret channels ? */
271       continue;
272 #endif
273     strcat(buf, c2ptr->name);
274     strcat(buf, " ");
275     idx += strlen(c2ptr->name) + 1;
276     flag = 1;
277 #ifdef GODMODE
278     {
279       char yxx[6];
280       sprintf_irc(yxx, "%s%s", NumNick(c2ptr));
281       assert(c2ptr == findNUser(yxx));
282       sprintf_irc(buf + strlen(buf), "(%s) ", yxx);
283       idx += 6;
284     }
285 #endif
286 #ifdef GODMODE
287     if (mlen + idx + NICKLEN + 9 > BUFSIZE)
288 #else
289     if (mlen + idx + NICKLEN + 3 > BUFSIZE)     /* space, \r\n\0 */
290 #endif
291     {
292       sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf);
293       strcpy(buf, "* * :");
294       idx = 5;
295       flag = 0;
296     }
297   }
298   if (flag)
299     sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf);
300   sendto_one(sptr, rpl_str(RPL_ENDOFNAMES), me.name, parv[0], "*");
301   return 1;
302   return 0;
303 }
304
305 /*
306  * ms_names - server message handler
307  *
308  * parv[0] = sender prefix
309  * parv[1] = channel
310  */
311 int ms_names(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
312 {
313   struct Channel *chptr;
314   struct Client *c2ptr;
315   struct Membership* member;
316   struct Channel *ch2ptr = 0;
317   int idx, flag, len, mlen;
318   char *s, *para = parc > 1 ? parv[1] : 0;
319   char buf[BUFSIZE];
320
321   if (parc > 2 && hunt_server(1, cptr, sptr, "%s%s " TOK_NAMES " %s %s", 2, parc, parv))
322     return 0;
323
324   mlen = strlen(me.name) + 10 + strlen(sptr->name);
325
326   if (!EmptyString(para))
327   {
328     s = strchr(para, ',');
329     if (s)
330     {
331       parv[1] = ++s;
332       m_names(cptr, sptr, parc, parv);
333     }
334     clean_channelname(para);
335     ch2ptr = FindChannel(para);
336   }
337
338   /*
339    * First, do all visible channels (public and the one user self is)
340    */
341
342   for (chptr = GlobalChannelList; chptr; chptr = chptr->next)
343   {
344     if ((chptr != ch2ptr) && !EmptyString(para))
345       continue;                 /* -- wanted a specific channel */
346     if (!MyConnect(sptr) && EmptyString(para))
347       continue;
348 #ifndef GODMODE
349     if (!ShowChannel(sptr, chptr))
350       continue;                 /* -- users on this are not listed */
351 #endif
352
353     /* Find users on same channel (defined by chptr) */
354
355     strcpy(buf, "* ");
356     len = strlen(chptr->chname);
357     strcpy(buf + 2, chptr->chname);
358     strcpy(buf + 2 + len, " :");
359
360     if (PubChannel(chptr))
361       *buf = '=';
362     else if (SecretChannel(chptr))
363       *buf = '@';
364     idx = len + 4;
365     flag = 1;
366     for (member = chptr->members; member; member = member->next_member)
367     {
368       c2ptr = member->user;
369 #ifndef GODMODE
370       if (sptr != c2ptr && IsInvisible(c2ptr) && !find_channel_member(sptr, chptr))
371         continue;
372 #endif
373       if (IsZombie(member))
374       {
375         if (member->user != sptr)
376           continue;
377         else
378         {
379           strcat(buf, "!");
380           idx++;
381         }
382       }
383       else if (IsChanOp(member))
384       {
385         strcat(buf, "@");
386         idx++;
387       }
388       else if (HasVoice(member))
389       {
390         strcat(buf, "+");
391         idx++;
392       }
393       strcat(buf, c2ptr->name);
394       strcat(buf, " ");
395       idx += strlen(c2ptr->name) + 1;
396       flag = 1;
397 #ifdef GODMODE
398       {
399         char yxx[6];
400         sprintf_irc(yxx, "%s%s", NumNick(c2ptr));
401         assert(c2ptr == findNUser(yxx));
402         sprintf_irc(buf + strlen(buf), "(%s) ", yxx);
403         idx += 6;
404       }
405       if (mlen + idx + NICKLEN + 11 > BUFSIZE)
406 #else
407       if (mlen + idx + NICKLEN + 5 > BUFSIZE)
408 #endif
409         /* space, modifier, nick, \r \n \0 */
410       {
411         sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf);
412         strcpy(buf, "* ");
413         ircd_strncpy(buf + 2, chptr->chname, len + 1);
414         buf[len + 2] = 0;
415         strcat(buf, " :");
416         if (PubChannel(chptr))
417           *buf = '=';
418         else if (SecretChannel(chptr))
419           *buf = '@';
420         idx = len + 4;
421         flag = 0;
422       }
423     }
424     if (flag)
425       sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf);
426   }
427   if (!EmptyString(para))
428   {
429     sendto_one(sptr, rpl_str(RPL_ENDOFNAMES), me.name, parv[0],
430         ch2ptr ? ch2ptr->chname : para);
431     return (1);
432   }
433
434   /* Second, do all non-public, non-secret channels in one big sweep */
435
436   strcpy(buf, "* * :");
437   idx = 5;
438   flag = 0;
439   for (c2ptr = GlobalClientList; c2ptr; c2ptr = c2ptr->next)
440   {
441     struct Channel *ch3ptr;
442     int showflag = 0, secret = 0;
443
444 #ifndef GODMODE
445     if (!IsUser(c2ptr) || (sptr != c2ptr && IsInvisible(c2ptr)))
446 #else
447     if (!IsUser(c2ptr))
448 #endif
449       continue;
450     member = c2ptr->user->channel;
451     /*
452      * Don't show a client if they are on a secret channel or when
453      * they are on a channel sptr is on since they have already
454      * been show earlier. -avalon
455      */
456     while (member)
457     {
458       ch3ptr = member->channel;
459 #ifndef GODMODE
460       if (PubChannel(ch3ptr) || find_channel_member(sptr, ch3ptr))
461 #endif
462         showflag = 1;
463       if (SecretChannel(ch3ptr))
464         secret = 1;
465       member = member->next_channel;
466     }
467     if (showflag)               /* Have we already shown them ? */
468       continue;
469 #ifndef GODMODE
470     if (secret)                 /* On any secret channels ? */
471       continue;
472 #endif
473     strcat(buf, c2ptr->name);
474     strcat(buf, " ");
475     idx += strlen(c2ptr->name) + 1;
476     flag = 1;
477 #ifdef GODMODE
478     {
479       char yxx[6];
480       sprintf_irc(yxx, "%s%s", NumNick(c2ptr));
481       assert(c2ptr == findNUser(yxx));
482       sprintf_irc(buf + strlen(buf), "(%s) ", yxx);
483       idx += 6;
484     }
485 #endif
486 #ifdef GODMODE
487     if (mlen + idx + NICKLEN + 9 > BUFSIZE)
488 #else
489     if (mlen + idx + NICKLEN + 3 > BUFSIZE)     /* space, \r\n\0 */
490 #endif
491     {
492       sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf);
493       strcpy(buf, "* * :");
494       idx = 5;
495       flag = 0;
496     }
497   }
498   if (flag)
499     sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf);
500   sendto_one(sptr, rpl_str(RPL_ENDOFNAMES), me.name, parv[0], "*");
501   return 1;
502   return 0;
503 }
504
505
506 #if 0
507 /*
508  * m_names                              - Added by Jto 27 Apr 1989
509  *
510  * parv[0] = sender prefix
511  * parv[1] = channel
512  */
513 int m_names(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
514 {
515   struct Channel *chptr;
516   struct Client *c2ptr;
517   struct Membership* member;
518   struct Channel *ch2ptr = 0;
519   int idx, flag, len, mlen;
520   char *s, *para = parc > 1 ? parv[1] : 0;
521   char buf[BUFSIZE];
522
523   if (parc > 2 && hunt_server(1, cptr, sptr, "%s%s " TOK_NAMES " %s %s", 2, parc, parv))
524     return 0;
525
526   mlen = strlen(me.name) + 10 + strlen(sptr->name);
527
528   if (!EmptyString(para))
529   {
530     s = strchr(para, ',');
531     if (s)
532     {
533       parv[1] = ++s;
534       m_names(cptr, sptr, parc, parv);
535     }
536     clean_channelname(para);
537     ch2ptr = FindChannel(para);
538   }
539
540   /*
541    * First, do all visible channels (public and the one user self is)
542    */
543
544   for (chptr = GlobalChannelList; chptr; chptr = chptr->next)
545   {
546     if ((chptr != ch2ptr) && !EmptyString(para))
547       continue;                 /* -- wanted a specific channel */
548     if (!MyConnect(sptr) && EmptyString(para))
549       continue;
550 #ifndef GODMODE
551     if (!ShowChannel(sptr, chptr))
552       continue;                 /* -- users on this are not listed */
553 #endif
554
555     /* Find users on same channel (defined by chptr) */
556
557     strcpy(buf, "* ");
558     len = strlen(chptr->chname);
559     strcpy(buf + 2, chptr->chname);
560     strcpy(buf + 2 + len, " :");
561
562     if (PubChannel(chptr))
563       *buf = '=';
564     else if (SecretChannel(chptr))
565       *buf = '@';
566     idx = len + 4;
567     flag = 1;
568     for (member = chptr->members; member; member = member->next_member)
569     {
570       c2ptr = member->user;
571 #ifndef GODMODE
572       if (sptr != c2ptr && IsInvisible(c2ptr) && !find_channel_member(sptr, chptr))
573         continue;
574 #endif
575       if (IsZombie(member))
576       {
577         if (member->user != sptr)
578           continue;
579         else
580         {
581           strcat(buf, "!");
582           idx++;
583         }
584       }
585       else if (IsChanOp(member))
586       {
587         strcat(buf, "@");
588         idx++;
589       }
590       else if (HasVoice(member))
591       {
592         strcat(buf, "+");
593         idx++;
594       }
595       strcat(buf, c2ptr->name);
596       strcat(buf, " ");
597       idx += strlen(c2ptr->name) + 1;
598       flag = 1;
599 #ifdef GODMODE
600       {
601         char yxx[6];
602         sprintf_irc(yxx, "%s%s", NumNick(c2ptr));
603         assert(c2ptr == findNUser(yxx));
604         sprintf_irc(buf + strlen(buf), "(%s) ", yxx);
605         idx += 6;
606       }
607       if (mlen + idx + NICKLEN + 11 > BUFSIZE)
608 #else
609       if (mlen + idx + NICKLEN + 5 > BUFSIZE)
610 #endif
611         /* space, modifier, nick, \r \n \0 */
612       {
613         sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf);
614         strcpy(buf, "* ");
615         ircd_strncpy(buf + 2, chptr->chname, len + 1);
616         buf[len + 2] = 0;
617         strcat(buf, " :");
618         if (PubChannel(chptr))
619           *buf = '=';
620         else if (SecretChannel(chptr))
621           *buf = '@';
622         idx = len + 4;
623         flag = 0;
624       }
625     }
626     if (flag)
627       sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf);
628   }
629   if (!EmptyString(para))
630   {
631     sendto_one(sptr, rpl_str(RPL_ENDOFNAMES), me.name, parv[0],
632         ch2ptr ? ch2ptr->chname : para);
633     return (1);
634   }
635
636   /* Second, do all non-public, non-secret channels in one big sweep */
637
638   strcpy(buf, "* * :");
639   idx = 5;
640   flag = 0;
641   for (c2ptr = GlobalClientList; c2ptr; c2ptr = c2ptr->next)
642   {
643     struct Channel *ch3ptr;
644     int showflag = 0, secret = 0;
645
646 #ifndef GODMODE
647     if (!IsUser(c2ptr) || (sptr != c2ptr && IsInvisible(c2ptr)))
648 #else
649     if (!IsUser(c2ptr))
650 #endif
651       continue;
652     member = c2ptr->user->channel;
653     /*
654      * Don't show a client if they are on a secret channel or when
655      * they are on a channel sptr is on since they have already
656      * been show earlier. -avalon
657      */
658     while (member)
659     {
660       ch3ptr = member->channel;
661 #ifndef GODMODE
662       if (PubChannel(ch3ptr) || find_channel_member(sptr, ch3ptr))
663 #endif
664         showflag = 1;
665       if (SecretChannel(ch3ptr))
666         secret = 1;
667       member = member->next_channel;
668     }
669     if (showflag)               /* Have we already shown them ? */
670       continue;
671 #ifndef GODMODE
672     if (secret)                 /* On any secret channels ? */
673       continue;
674 #endif
675     strcat(buf, c2ptr->name);
676     strcat(buf, " ");
677     idx += strlen(c2ptr->name) + 1;
678     flag = 1;
679 #ifdef GODMODE
680     {
681       char yxx[6];
682       sprintf_irc(yxx, "%s%s", NumNick(c2ptr));
683       assert(c2ptr == findNUser(yxx));
684       sprintf_irc(buf + strlen(buf), "(%s) ", yxx);
685       idx += 6;
686     }
687 #endif
688 #ifdef GODMODE
689     if (mlen + idx + NICKLEN + 9 > BUFSIZE)
690 #else
691     if (mlen + idx + NICKLEN + 3 > BUFSIZE)     /* space, \r\n\0 */
692 #endif
693     {
694       sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf);
695       strcpy(buf, "* * :");
696       idx = 5;
697       flag = 0;
698     }
699   }
700   if (flag)
701     sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf);
702   sendto_one(sptr, rpl_str(RPL_ENDOFNAMES), me.name, parv[0], "*");
703   return 1;
704 }
705 #endif /* 0 */
706