Author: Maniac <maniac@cetlink.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;
118   int flag;
119   int len;
120   int mlen;
121   char* s;
122   char* para = parc > 1 ? parv[1] : 0;
123   char buf[BUFSIZE];
124
125   if (parc > 2 && hunt_server(1, cptr, sptr, "%s%s " TOK_NAMES " %s %s", 2, parc, parv))
126     return 0;
127
128   mlen = strlen(me.name) + 10 + strlen(sptr->name);
129
130   if (EmptyString(para))
131     return 0;
132   else if (*para == '0')
133     *para = '\0';
134   
135   s = strchr(para, ',');
136   if (s) {
137     parv[1] = ++s;
138     m_names(cptr, sptr, parc, parv);
139   }
140   clean_channelname(para);
141   ch2ptr = FindChannel(para);
142
143   /*
144    * First, do all visible channels (public and the one user self is)
145    */
146
147   for (chptr = GlobalChannelList; chptr; chptr = chptr->next)
148   {
149     if ((chptr != ch2ptr) && !EmptyString(para))
150       continue;                 /* -- wanted a specific channel */
151     if (!MyConnect(sptr) && EmptyString(para))
152       continue;
153 #ifndef GODMODE
154     if (!ShowChannel(sptr, chptr))
155       continue;                 /* -- users on this are not listed */
156 #endif
157
158     /* Find users on same channel (defined by chptr) */
159
160     strcpy(buf, "* ");
161     len = strlen(chptr->chname);
162     strcpy(buf + 2, chptr->chname);
163     strcpy(buf + 2 + len, " :");
164
165     if (PubChannel(chptr))
166       *buf = '=';
167     else if (SecretChannel(chptr))
168       *buf = '@';
169     idx = len + 4;
170     flag = 1;
171     for (member = chptr->members; member; member = member->next_member)
172     {
173       c2ptr = member->user;
174 #ifndef GODMODE
175       if (sptr != c2ptr && IsInvisible(c2ptr) && !find_channel_member(sptr, chptr))
176         continue;
177 #endif
178       if (IsZombie(member))
179       {
180         if (member->user != sptr)
181           continue;
182         else
183         {
184           strcat(buf, "!");
185           idx++;
186         }
187       }
188       else if (IsChanOp(member))
189       {
190         strcat(buf, "@");
191         idx++;
192       }
193       else if (HasVoice(member))
194       {
195         strcat(buf, "+");
196         idx++;
197       }
198       strcat(buf, c2ptr->name);
199       strcat(buf, " ");
200       idx += strlen(c2ptr->name) + 1;
201       flag = 1;
202 #ifdef GODMODE
203       {
204         char yxx[6];
205         sprintf_irc(yxx, "%s%s", NumNick(c2ptr));
206         assert(c2ptr == findNUser(yxx));
207         sprintf_irc(buf + strlen(buf), "(%s) ", yxx);
208         idx += 6;
209       }
210       if (mlen + idx + NICKLEN + 11 > BUFSIZE)
211 #else
212       if (mlen + idx + NICKLEN + 5 > BUFSIZE)
213 #endif
214         /* space, modifier, nick, \r \n \0 */
215       {
216         sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf);
217         strcpy(buf, "* ");
218         ircd_strncpy(buf + 2, chptr->chname, len + 1);
219         buf[len + 2] = 0;
220         strcat(buf, " :");
221         if (PubChannel(chptr))
222           *buf = '=';
223         else if (SecretChannel(chptr))
224           *buf = '@';
225         idx = len + 4;
226         flag = 0;
227       }
228     }
229     if (flag)
230       sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf);
231   }
232   if (!EmptyString(para))
233   {
234     sendto_one(sptr, rpl_str(RPL_ENDOFNAMES), me.name, parv[0],
235         ch2ptr ? ch2ptr->chname : para);
236     return (1);
237   }
238
239   /* Second, do all non-public, non-secret channels in one big sweep */
240
241   strcpy(buf, "* * :");
242   idx = 5;
243   flag = 0;
244   for (c2ptr = GlobalClientList; c2ptr; c2ptr = c2ptr->next)
245   {
246     struct Channel *ch3ptr;
247     int showflag = 0, secret = 0;
248
249 #ifndef GODMODE
250     if (!IsUser(c2ptr) || (sptr != c2ptr && IsInvisible(c2ptr)))
251 #else
252     if (!IsUser(c2ptr))
253 #endif
254       continue;
255     member = c2ptr->user->channel;
256     /*
257      * Don't show a client if they are on a secret channel or when
258      * they are on a channel sptr is on since they have already
259      * been show earlier. -avalon
260      */
261     while (member)
262     {
263       ch3ptr = member->channel;
264 #ifndef GODMODE
265       if (PubChannel(ch3ptr) || find_channel_member(sptr, ch3ptr))
266 #endif
267         showflag = 1;
268       if (SecretChannel(ch3ptr))
269         secret = 1;
270       member = member->next_channel;
271     }
272     if (showflag)               /* Have we already shown them ? */
273       continue;
274 #ifndef GODMODE
275     if (secret)                 /* On any secret channels ? */
276       continue;
277 #endif
278     strcat(buf, c2ptr->name);
279     strcat(buf, " ");
280     idx += strlen(c2ptr->name) + 1;
281     flag = 1;
282 #ifdef GODMODE
283     {
284       char yxx[6];
285       sprintf_irc(yxx, "%s%s", NumNick(c2ptr));
286       assert(c2ptr == findNUser(yxx));
287       sprintf_irc(buf + strlen(buf), "(%s) ", yxx);
288       idx += 6;
289     }
290 #endif
291 #ifdef GODMODE
292     if (mlen + idx + NICKLEN + 9 > BUFSIZE)
293 #else
294     if (mlen + idx + NICKLEN + 3 > BUFSIZE)     /* space, \r\n\0 */
295 #endif
296     {
297       sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf);
298       strcpy(buf, "* * :");
299       idx = 5;
300       flag = 0;
301     }
302   }
303   if (flag)
304     sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf);
305   sendto_one(sptr, rpl_str(RPL_ENDOFNAMES), me.name, parv[0], "*");
306   return 1;
307   return 0;
308 }
309
310 /*
311  * ms_names - server message handler
312  *
313  * parv[0] = sender prefix
314  * parv[1] = channel
315  */
316 int ms_names(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
317 {
318   struct Channel *chptr;
319   struct Client *c2ptr;
320   struct Membership* member;
321   struct Channel *ch2ptr = 0;
322   int idx, flag, len, mlen;
323   char *s, *para = parc > 1 ? parv[1] : 0;
324   char buf[BUFSIZE];
325
326   if (parc > 2 && hunt_server(1, cptr, sptr, "%s%s " TOK_NAMES " %s %s", 2, parc, parv))
327     return 0;
328
329   mlen = strlen(me.name) + 10 + strlen(sptr->name);
330
331   if (!EmptyString(para))
332   {
333     s = strchr(para, ',');
334     if (s)
335     {
336       parv[1] = ++s;
337       m_names(cptr, sptr, parc, parv);
338     }
339     clean_channelname(para);
340     ch2ptr = FindChannel(para);
341   }
342
343   /*
344    * First, do all visible channels (public and the one user self is)
345    */
346
347   for (chptr = GlobalChannelList; chptr; chptr = chptr->next)
348   {
349     if ((chptr != ch2ptr) && !EmptyString(para))
350       continue;                 /* -- wanted a specific channel */
351     if (!MyConnect(sptr) && EmptyString(para))
352       continue;
353 #ifndef GODMODE
354     if (!ShowChannel(sptr, chptr))
355       continue;                 /* -- users on this are not listed */
356 #endif
357
358     /* Find users on same channel (defined by chptr) */
359
360     strcpy(buf, "* ");
361     len = strlen(chptr->chname);
362     strcpy(buf + 2, chptr->chname);
363     strcpy(buf + 2 + len, " :");
364
365     if (PubChannel(chptr))
366       *buf = '=';
367     else if (SecretChannel(chptr))
368       *buf = '@';
369     idx = len + 4;
370     flag = 1;
371     for (member = chptr->members; member; member = member->next_member)
372     {
373       c2ptr = member->user;
374 #ifndef GODMODE
375       if (sptr != c2ptr && IsInvisible(c2ptr) && !find_channel_member(sptr, chptr))
376         continue;
377 #endif
378       if (IsZombie(member))
379       {
380         if (member->user != sptr)
381           continue;
382         else
383         {
384           strcat(buf, "!");
385           idx++;
386         }
387       }
388       else if (IsChanOp(member))
389       {
390         strcat(buf, "@");
391         idx++;
392       }
393       else if (HasVoice(member))
394       {
395         strcat(buf, "+");
396         idx++;
397       }
398       strcat(buf, c2ptr->name);
399       strcat(buf, " ");
400       idx += strlen(c2ptr->name) + 1;
401       flag = 1;
402 #ifdef GODMODE
403       {
404         char yxx[6];
405         sprintf_irc(yxx, "%s%s", NumNick(c2ptr));
406         assert(c2ptr == findNUser(yxx));
407         sprintf_irc(buf + strlen(buf), "(%s) ", yxx);
408         idx += 6;
409       }
410       if (mlen + idx + NICKLEN + 11 > BUFSIZE)
411 #else
412       if (mlen + idx + NICKLEN + 5 > BUFSIZE)
413 #endif
414         /* space, modifier, nick, \r \n \0 */
415       {
416         sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf);
417         strcpy(buf, "* ");
418         ircd_strncpy(buf + 2, chptr->chname, len + 1);
419         buf[len + 2] = 0;
420         strcat(buf, " :");
421         if (PubChannel(chptr))
422           *buf = '=';
423         else if (SecretChannel(chptr))
424           *buf = '@';
425         idx = len + 4;
426         flag = 0;
427       }
428     }
429     if (flag)
430       sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf);
431   }
432   if (!EmptyString(para))
433   {
434     sendto_one(sptr, rpl_str(RPL_ENDOFNAMES), me.name, parv[0],
435         ch2ptr ? ch2ptr->chname : para);
436     return (1);
437   }
438
439   /* Second, do all non-public, non-secret channels in one big sweep */
440
441   strcpy(buf, "* * :");
442   idx = 5;
443   flag = 0;
444   for (c2ptr = GlobalClientList; c2ptr; c2ptr = c2ptr->next)
445   {
446     struct Channel *ch3ptr;
447     int showflag = 0, secret = 0;
448
449 #ifndef GODMODE
450     if (!IsUser(c2ptr) || (sptr != c2ptr && IsInvisible(c2ptr)))
451 #else
452     if (!IsUser(c2ptr))
453 #endif
454       continue;
455     member = c2ptr->user->channel;
456     /*
457      * Don't show a client if they are on a secret channel or when
458      * they are on a channel sptr is on since they have already
459      * been show earlier. -avalon
460      */
461     while (member)
462     {
463       ch3ptr = member->channel;
464 #ifndef GODMODE
465       if (PubChannel(ch3ptr) || find_channel_member(sptr, ch3ptr))
466 #endif
467         showflag = 1;
468       if (SecretChannel(ch3ptr))
469         secret = 1;
470       member = member->next_channel;
471     }
472     if (showflag)               /* Have we already shown them ? */
473       continue;
474 #ifndef GODMODE
475     if (secret)                 /* On any secret channels ? */
476       continue;
477 #endif
478     strcat(buf, c2ptr->name);
479     strcat(buf, " ");
480     idx += strlen(c2ptr->name) + 1;
481     flag = 1;
482 #ifdef GODMODE
483     {
484       char yxx[6];
485       sprintf_irc(yxx, "%s%s", NumNick(c2ptr));
486       assert(c2ptr == findNUser(yxx));
487       sprintf_irc(buf + strlen(buf), "(%s) ", yxx);
488       idx += 6;
489     }
490 #endif
491 #ifdef GODMODE
492     if (mlen + idx + NICKLEN + 9 > BUFSIZE)
493 #else
494     if (mlen + idx + NICKLEN + 3 > BUFSIZE)     /* space, \r\n\0 */
495 #endif
496     {
497       sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf);
498       strcpy(buf, "* * :");
499       idx = 5;
500       flag = 0;
501     }
502   }
503   if (flag)
504     sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf);
505   sendto_one(sptr, rpl_str(RPL_ENDOFNAMES), me.name, parv[0], "*");
506   return 1;
507   return 0;
508 }
509
510
511 #if 0
512 /*
513  * m_names                              - Added by Jto 27 Apr 1989
514  *
515  * parv[0] = sender prefix
516  * parv[1] = channel
517  */
518 int m_names(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
519 {
520   struct Channel *chptr;
521   struct Client *c2ptr;
522   struct Membership* member;
523   struct Channel *ch2ptr = 0;
524   int idx, flag, len, mlen;
525   char *s, *para = parc > 1 ? parv[1] : 0;
526   char buf[BUFSIZE];
527
528   if (parc > 2 && hunt_server(1, cptr, sptr, "%s%s " TOK_NAMES " %s %s", 2, parc, parv))
529     return 0;
530
531   mlen = strlen(me.name) + 10 + strlen(sptr->name);
532
533   if (!EmptyString(para))
534   {
535     s = strchr(para, ',');
536     if (s)
537     {
538       parv[1] = ++s;
539       m_names(cptr, sptr, parc, parv);
540     }
541     clean_channelname(para);
542     ch2ptr = FindChannel(para);
543   }
544
545   /*
546    * First, do all visible channels (public and the one user self is)
547    */
548
549   for (chptr = GlobalChannelList; chptr; chptr = chptr->next)
550   {
551     if ((chptr != ch2ptr) && !EmptyString(para))
552       continue;                 /* -- wanted a specific channel */
553     if (!MyConnect(sptr) && EmptyString(para))
554       continue;
555 #ifndef GODMODE
556     if (!ShowChannel(sptr, chptr))
557       continue;                 /* -- users on this are not listed */
558 #endif
559
560     /* Find users on same channel (defined by chptr) */
561
562     strcpy(buf, "* ");
563     len = strlen(chptr->chname);
564     strcpy(buf + 2, chptr->chname);
565     strcpy(buf + 2 + len, " :");
566
567     if (PubChannel(chptr))
568       *buf = '=';
569     else if (SecretChannel(chptr))
570       *buf = '@';
571     idx = len + 4;
572     flag = 1;
573     for (member = chptr->members; member; member = member->next_member)
574     {
575       c2ptr = member->user;
576 #ifndef GODMODE
577       if (sptr != c2ptr && IsInvisible(c2ptr) && !find_channel_member(sptr, chptr))
578         continue;
579 #endif
580       if (IsZombie(member))
581       {
582         if (member->user != sptr)
583           continue;
584         else
585         {
586           strcat(buf, "!");
587           idx++;
588         }
589       }
590       else if (IsChanOp(member))
591       {
592         strcat(buf, "@");
593         idx++;
594       }
595       else if (HasVoice(member))
596       {
597         strcat(buf, "+");
598         idx++;
599       }
600       strcat(buf, c2ptr->name);
601       strcat(buf, " ");
602       idx += strlen(c2ptr->name) + 1;
603       flag = 1;
604 #ifdef GODMODE
605       {
606         char yxx[6];
607         sprintf_irc(yxx, "%s%s", NumNick(c2ptr));
608         assert(c2ptr == findNUser(yxx));
609         sprintf_irc(buf + strlen(buf), "(%s) ", yxx);
610         idx += 6;
611       }
612       if (mlen + idx + NICKLEN + 11 > BUFSIZE)
613 #else
614       if (mlen + idx + NICKLEN + 5 > BUFSIZE)
615 #endif
616         /* space, modifier, nick, \r \n \0 */
617       {
618         sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf);
619         strcpy(buf, "* ");
620         ircd_strncpy(buf + 2, chptr->chname, len + 1);
621         buf[len + 2] = 0;
622         strcat(buf, " :");
623         if (PubChannel(chptr))
624           *buf = '=';
625         else if (SecretChannel(chptr))
626           *buf = '@';
627         idx = len + 4;
628         flag = 0;
629       }
630     }
631     if (flag)
632       sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf);
633   }
634   if (!EmptyString(para))
635   {
636     sendto_one(sptr, rpl_str(RPL_ENDOFNAMES), me.name, parv[0],
637         ch2ptr ? ch2ptr->chname : para);
638     return (1);
639   }
640
641   /* Second, do all non-public, non-secret channels in one big sweep */
642
643   strcpy(buf, "* * :");
644   idx = 5;
645   flag = 0;
646   for (c2ptr = GlobalClientList; c2ptr; c2ptr = c2ptr->next)
647   {
648     struct Channel *ch3ptr;
649     int showflag = 0, secret = 0;
650
651 #ifndef GODMODE
652     if (!IsUser(c2ptr) || (sptr != c2ptr && IsInvisible(c2ptr)))
653 #else
654     if (!IsUser(c2ptr))
655 #endif
656       continue;
657     member = c2ptr->user->channel;
658     /*
659      * Don't show a client if they are on a secret channel or when
660      * they are on a channel sptr is on since they have already
661      * been show earlier. -avalon
662      */
663     while (member)
664     {
665       ch3ptr = member->channel;
666 #ifndef GODMODE
667       if (PubChannel(ch3ptr) || find_channel_member(sptr, ch3ptr))
668 #endif
669         showflag = 1;
670       if (SecretChannel(ch3ptr))
671         secret = 1;
672       member = member->next_channel;
673     }
674     if (showflag)               /* Have we already shown them ? */
675       continue;
676 #ifndef GODMODE
677     if (secret)                 /* On any secret channels ? */
678       continue;
679 #endif
680     strcat(buf, c2ptr->name);
681     strcat(buf, " ");
682     idx += strlen(c2ptr->name) + 1;
683     flag = 1;
684 #ifdef GODMODE
685     {
686       char yxx[6];
687       sprintf_irc(yxx, "%s%s", NumNick(c2ptr));
688       assert(c2ptr == findNUser(yxx));
689       sprintf_irc(buf + strlen(buf), "(%s) ", yxx);
690       idx += 6;
691     }
692 #endif
693 #ifdef GODMODE
694     if (mlen + idx + NICKLEN + 9 > BUFSIZE)
695 #else
696     if (mlen + idx + NICKLEN + 3 > BUFSIZE)     /* space, \r\n\0 */
697 #endif
698     {
699       sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf);
700       strcpy(buf, "* * :");
701       idx = 5;
702       flag = 0;
703     }
704   }
705   if (flag)
706     sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf);
707   sendto_one(sptr, rpl_str(RPL_ENDOFNAMES), me.name, parv[0], "*");
708   return 1;
709 }
710 #endif /* 0 */
711