ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/branches/8.2.x/modules/core/m_join.c
(Generate patch)

Comparing ircd-hybrid-7.2/modules/core/m_join.c (file contents):
Revision 487 by michael, Wed Mar 1 10:54:20 2006 UTC vs.
Revision 488 by michael, Wed Mar 1 12:40:31 2006 UTC

# Line 43 | Line 43
43   #include "modules.h"
44  
45  
46 struct entity
47 {
48  struct Channel *chptr;
49  char *key;
50  int flags;
51 };
52
53 static struct entity targets[IRCD_BUFSIZE];
54 static int ntargets, join_0;
55
56 static int build_target_list(struct Client *, char *, char *);
57 static int is_target(struct Channel *);
58
46   static void m_join(struct Client *, struct Client *, int, char **);
47   static void ms_join(struct Client *, struct Client *, int, char **);
48   static void do_join_0(struct Client *client_p, struct Client *source_p);
# Line 75 | Line 62 | struct Message join_msgtab = {
62   };
63  
64   #ifndef STATIC_MODULES
78
65   void
66   _modinit(void)
67   {
# Line 91 | Line 77 | _moddeinit(void)
77   const char *_version = "$Revision$";
78   #endif
79  
80 + /* last0() stolen from ircu */
81 + static char *
82 + last0(struct Client *client_p, struct Client *source_p, char *chanlist)
83 + {
84 +  char *p;
85 +  int join0 = 0;
86 +
87 +  for (p = chanlist; *p; ++p) /* find last "JOIN 0" */
88 +  {
89 +    if (*p == '0' && (*(p + 1) == ',' || *(p + 1) == '\0'))
90 +    {
91 +      if ((*p + 1) == ',')
92 +        ++p;
93 +
94 +      chanlist = p + 1;
95 +      join0 = 1;
96 +    }
97 +    else
98 +    {
99 +      while (*p != ',' && *p != '\0') /* skip past channel name */
100 +        ++p;
101 +
102 +      if (*p == '\0') /* hit the end */
103 +        break;
104 +    }
105 +  }
106 +
107 +  if (join0)
108 +    do_join_0(client_p, source_p);
109 +
110 +  return chanlist;
111 + }
112 +
113   /* m_join()
114   *      parv[0] = sender prefix
115   *      parv[1] = channel
# Line 100 | Line 119 | static void
119   m_join(struct Client *client_p, struct Client *source_p,
120         int parc, char *parv[])
121   {
122 +  char *p = NULL;
123 +  char *key_list = NULL;
124 +  char *chan_list = NULL;
125 +  char *chan = NULL;
126    struct Channel *chptr = NULL;
127 <  char *key = NULL;
105 <  int i, a;
127 >  int i = 0;
128    unsigned int flags = 0;
129 +  unsigned int error_reported = 0;
130  
131    if (*parv[1] == '\0')
132    {
# Line 114 | Line 137 | m_join(struct Client *client_p, struct C
137  
138    assert(client_p == source_p);
139  
140 <  build_target_list(source_p, parv[1], parv[2]);
141 <
119 <  if ((a = (join_0 >= 0) ? join_0 : 0))
120 <    do_join_0(client_p, source_p);
140 >  key_list = parv[2];
141 >  chan_list = last0(client_p, source_p, parv[1]);
142  
143 <  for (; a < ntargets; a++)
143 >  for (chan = strtoken(&p, chan_list, ","); chan;
144 >       chan = strtoken(&p, NULL,      ","))
145    {
146 <    chptr = targets[a].chptr;
125 <    key = targets[a].key;
126 <    flags = targets[a].flags;
146 >    char *key = NULL;
147  
148 <    if (IsMember(source_p, chptr))
148 >    /* If we have any more keys, take the first for this channel. */
149 >    if (!EmptyString(key_list) && (key_list = strchr(key = key_list, ',')))
150 >      *key_list++ = '\0';
151 >
152 >    /* Empty keys are the same as no keys. */
153 >    if (key && *key == '\0')
154 >      key = NULL;
155 >
156 >    if (!IsChanPrefix(*chan) || !check_channel_name(chan))
157 >    {
158 >      sendto_one(source_p, form_str(ERR_BADCHANNAME),
159 >                 me.name, source_p->name, chan);
160 >      continue;
161 >    }
162 >
163 >    if (ConfigChannel.disable_local_channels && (*chan == '&'))
164 >    {
165 >      sendto_one(source_p, form_str(ERR_NOSUCHCHANNEL),
166 >                 me.name, source_p->name, chan);
167 >      continue;
168 >    }
169 >
170 >    if (strlen(chan) > LOCAL_CHANNELLEN)
171 >    {
172 >      sendto_one(source_p, form_str(ERR_BADCHANNAME),
173 >                 me.name, source_p->name, chan);
174        continue;
175 +    }
176 +
177 +    if (!IsExemptResv(source_p) &&
178 +        !(IsOper(source_p) && ConfigFileEntry.oper_pass_resv) &&
179 +        (!hash_find_resv(chan) == ConfigChannel.restrict_channels))
180 +    {
181 +      sendto_one(source_p, form_str(ERR_BADCHANNAME),
182 +                 me.name, source_p->name, chan);
183 +      sendto_realops_flags(UMODE_SPY, L_ALL,
184 +                           "User %s (%s@%s) is attempting to join locally juped channel %s",
185 +                           source_p->name, source_p->username, source_p->host, chan);
186 +      continue;
187 +    }
188 +
189 +    if ((dlink_list_length(&source_p->channel) >= ConfigChannel.max_chans_per_user) &&
190 +        (!IsOper(source_p) || (dlink_list_length(&source_p->channel) >=
191 +                               ConfigChannel.max_chans_per_user * 3)))
192 +    {
193 +      if (!error_reported++)
194 +        sendto_one(source_p, form_str(ERR_TOOMANYCHANNELS),
195 +                   me.name, source_p->name, chan);
196 +      continue;
197 +    }
198 +
199 +    if ((chptr = hash_find_channel(chan)) != NULL)
200 +    {
201 +      if (IsMember(source_p, chptr))
202 +        continue;
203 +
204 +      if (splitmode && !IsOper(source_p) && (*chan != '&') &&
205 +          ConfigChannel.no_join_on_split)
206 +      {
207 +        sendto_one(source_p, form_str(ERR_UNAVAILRESOURCE),
208 +                   me.name, source_p->name, chan);
209 +        continue;
210 +      }
211 +
212 +      /*
213 +       * This should never be the case unless there is some sort of
214 +       * persistant channels.
215 +       */
216 +      if (dlink_list_length(&chptr->members) == 0)
217 +        flags = CHFL_CHANOP;
218 +      else
219 +        flags = 0;
220 +    }
221 +    else
222 +    {
223 +      if (splitmode && !IsOper(source_p) && (*chan != '&') &&
224 +          (ConfigChannel.no_create_on_split || ConfigChannel.no_join_on_split))
225 +      {
226 +        sendto_one(source_p, form_str(ERR_UNAVAILRESOURCE),
227 +                   me.name, source_p->name, chan);
228 +        continue;
229 +      }
230 +
231 +      flags = CHFL_CHANOP;
232 +
233 +      if ((chptr = get_or_create_channel(source_p, chan, NULL)) == NULL)
234 +      {
235 +        sendto_one(source_p, form_str(ERR_UNAVAILRESOURCE),
236 +                   me.name, source_p->name, chan);
237 +        continue;
238 +      }
239 +    }
240  
241      if (!IsOper(source_p))
242        check_spambot_warning(source_p, chptr->chname);
# Line 136 | Line 246 | m_join(struct Client *client_p, struct C
246       */
247      if ((i = can_join(source_p, chptr, key)))
248      {
249 <      sendto_one(source_p, form_str(i), me.name, source_p->name, chptr->chname);
249 >      sendto_one(source_p, form_str(i), me.name,
250 >                 source_p->name, chptr->chname);
251        continue;
252      }
253  
143    /* add the user to the channel */
254      add_user_to_channel(chptr, source_p, flags, YES);
255  
256      /*
257 <    **  Set timestamp if appropriate, and propagate
258 <    */
257 >     *  Set timestamp if appropriate, and propagate
258 >     */
259      if (flags & CHFL_CHANOP)
260      {
261        chptr->channelts = CurrentTime;
# Line 163 | Line 273 | m_join(struct Client *client_p, struct C
273        /*
274         * notify all other users on the new channel
275         */
166      /* XXX just exactly who is going to be =on= this new channel
167       * other than just the creator at this time? ? ?
168       */
276        sendto_channel_local(ALL_MEMBERS, NO, chptr, ":%s!%s@%s JOIN :%s",
277                             source_p->name, source_p->username,
278                             source_p->host, chptr->chname);
279 <
173 <      sendto_channel_local(ALL_MEMBERS, NO, chptr,
174 <                           ":%s MODE %s +nt",
279 >      sendto_channel_local(ALL_MEMBERS, NO, chptr, ":%s MODE %s +nt",
280                             me.name, chptr->chname);
281      }
282      else
# Line 406 | Line 511 | static void
511   do_join_0(struct Client *client_p, struct Client *source_p)
512   {
513    struct Channel *chptr = NULL;
514 <  dlink_node *ptr, *ptr_next;
514 >  dlink_node *ptr = NULL, *ptr_next = NULL;
515  
516 <  if (source_p->channel.head != NULL &&
412 <      MyConnect(source_p) && !IsOper(source_p))
516 >  if (source_p->channel.head && MyConnect(source_p) && !IsOper(source_p))
517      check_spambot_warning(source_p, NULL);
518  
519    DLINK_FOREACH_SAFE(ptr, ptr_next, source_p->channel.head)
520    {
521      chptr = ((struct Membership *)ptr->data)->chptr;
522  
523 <    /* if the last occurance of this chan is before a 0, leave */
524 <    if (is_target(chptr) < join_0)
525 <    {
526 <      sendto_server(client_p, NULL, chptr, CAP_TS6, NOCAPS, NOFLAGS,
527 <                    ":%s PART %s", ID(source_p), chptr->chname);
528 <      sendto_server(client_p, NULL, chptr, NOCAPS, CAP_TS6, NOFLAGS,
529 <                    ":%s PART %s", source_p->name, chptr->chname);
426 <      sendto_channel_local(ALL_MEMBERS, NO, chptr, ":%s!%s@%s PART %s",
427 <                           source_p->name, source_p->username,
428 <                           source_p->host, chptr->chname);
429 <      remove_user_from_channel(ptr->data);
430 <    }
431 <  }
432 < }
433 <
434 < /* build_target_list()
435 < *
436 < * inputs       - pointer to given client_p (server)
437 < *              - pointer to given source (oper/client etc.)
438 < *              - pointer to list of channels
439 < *              - pointer to list of keys
440 < * output       - number of valid entities
441 < * side effects - targets list is modified to contain a list of
442 < *                pointers to channels.  display whatever errors
443 < *                that result from a join attempt to the user.
444 < *
445 < */
446 < static int
447 < build_target_list(struct Client *source_p, char *channels, char *keys)
448 < {
449 <  int error_reported = 0, flags = 0;
450 <  char *p = NULL, *p2 = NULL, *chan, *key = keys;
451 <  struct Channel *chptr = NULL;
452 <
453 <  ntargets = 0;
454 <  join_0 = -1;
455 <
456 <  key = key ? strtoken(&p2, keys, ",") : NULL;
457 <
458 <  for (chan = strtoken(&p, channels, ","); chan;
459 <       key  = key ? strtoken(&p2, NULL, ",") : NULL,
460 <       chan = strtoken(&p, NULL, ","))
461 <  {
462 <    if (!check_channel_name(chan))
463 <    {
464 <      sendto_one(source_p, form_str(ERR_BADCHANNAME),
465 <                 me.name, source_p->name, chan);
466 <      continue;
467 <    }
468 <
469 <    if (*chan == '0' && !atoi(chan))
470 <    {
471 <      targets[ntargets].chptr = NULL;
472 <      targets[ntargets].key = NULL;
473 <      targets[ntargets++].flags = 0;
474 <
475 <      join_0 = ntargets;
476 <      continue;
477 <    }
478 <    else if (!IsChanPrefix(*chan))
479 <    {
480 <      sendto_one(source_p, form_str(ERR_NOSUCHCHANNEL),
481 <                 me.name, source_p->name, chan);
482 <      continue;
483 <    }
484 <
485 <    if (ConfigChannel.disable_local_channels && (*chan == '&'))
486 <    {
487 <      sendto_one(source_p, form_str(ERR_NOSUCHCHANNEL),
488 <                 me.name, source_p->name, chan);
489 <      continue;
490 <    }
491 <
492 <    if (strlen(chan) > LOCAL_CHANNELLEN)
493 <    {
494 <      sendto_one(source_p, form_str(ERR_BADCHANNAME),
495 <                 me.name, source_p->name, chan);
496 <      continue;
497 <    }
498 <
499 <    if (!IsExemptResv(source_p) &&
500 <        !(IsOper(source_p) && ConfigFileEntry.oper_pass_resv) &&
501 <        (!hash_find_resv(chan) == ConfigChannel.restrict_channels))
502 <    {
503 <      sendto_one(source_p, form_str(ERR_BADCHANNAME),
504 <                 me.name, source_p->name, chan);
505 <      sendto_realops_flags(UMODE_SPY, L_ALL,
506 <                           "User %s (%s@%s) is attempting to join locally juped channel %s",
507 <                           source_p->name, source_p->username, source_p->host, chan);
508 <      continue;
509 <    }
510 <
511 <    if ((dlink_list_length(&source_p->channel)+ntargets >= ConfigChannel.max_chans_per_user) &&
512 <        (!IsOper(source_p) || (dlink_list_length(&source_p->channel)+ntargets >=
513 <                               ConfigChannel.max_chans_per_user * 3)))
514 <    {
515 <      if (!error_reported++)
516 <        sendto_one(source_p, form_str(ERR_TOOMANYCHANNELS),
517 <                   me.name, source_p->name, chan);
518 <      continue;
519 <    }
520 <
521 <    if ((chptr = hash_find_channel(chan)) != NULL)
522 <    {
523 <      if (splitmode && !IsOper(source_p) && (*chan != '&') &&
524 <          ConfigChannel.no_join_on_split)
525 <      {
526 <        sendto_one(source_p, form_str(ERR_UNAVAILRESOURCE),
527 <                   me.name, source_p->name, chan);
528 <        continue;
529 <      }
530 <
531 <      if (dlink_list_length(&chptr->members) == 0)
532 <        flags = CHFL_CHANOP;
533 <      else
534 <        flags = 0;
535 <    }
536 <    else
537 <    {
538 <      if (splitmode && !IsOper(source_p) && (*chan != '&') &&
539 <          (ConfigChannel.no_create_on_split || ConfigChannel.no_join_on_split))
540 <      {
541 <        sendto_one(source_p, form_str(ERR_UNAVAILRESOURCE),
542 <                   me.name, source_p->name, chan);
543 <        continue;
544 <      }
545 <
546 <      flags = CHFL_CHANOP;
547 <      if (!ServerInfo.hub)
548 <      {
549 <        if ((*chan != '&') && uplink && IsCapable(uplink, CAP_LL))
550 <        {
551 <          sendto_one(uplink, ":%s CBURST %s %s %s",
552 <                     me.name, chan, source_p->name, key ? key : "");
553 <          continue;
554 <        }
555 <      }
556 <
557 <      if ((chptr = get_or_create_channel(source_p, chan, NULL)) == NULL)
558 <      {
559 <        sendto_one(source_p, form_str(ERR_UNAVAILRESOURCE),
560 <                   me.name, source_p->name, chan);
561 <        continue;
562 <      }
563 <    }
564 <
565 <    if (is_target(chptr))
566 <      continue;
567 <
568 <    targets[ntargets].chptr = chptr;
569 <    targets[ntargets].key = key;
570 <    targets[ntargets++].flags = flags;
571 <  }
572 <
573 <  return ((ntargets) ? 1 : 0);
574 < }
575 <
576 < /* is_target()
577 < *
578 < * inputs       - channel to check
579 < * output       - YES if duplicate pointer in table, NO if not.
580 < *                note, this does the canonize using pointers
581 < * side effects - NONE
582 < */
583 < static int
584 < is_target(struct Channel *chptr)
585 < {
586 <  int i;
523 >    sendto_server(client_p, NULL, chptr, CAP_TS6, NOCAPS, NOFLAGS,
524 >                  ":%s PART %s", ID(source_p), chptr->chname);
525 >    sendto_server(client_p, NULL, chptr, NOCAPS, CAP_TS6, NOFLAGS,
526 >                  ":%s PART %s", source_p->name, chptr->chname);
527 >    sendto_channel_local(ALL_MEMBERS, NO, chptr, ":%s!%s@%s PART %s",
528 >                         source_p->name, source_p->username,
529 >                         source_p->host, chptr->chname);
530  
531 <  /*
589 <   * we step through this backwards for do_join_0()s sake.
590 <   * if the returned value is > join_0 (the highest 0 in the targets)
591 <   * we know they are supposed to stay in that channel.
592 <   */
593 <  for (i = ntargets-1; i >=0; i--)
594 <  {
595 <    if (targets[i].chptr == chptr)
596 <      return i;
531 >    remove_user_from_channel(ptr->data);
532    }
598
599  return 0;
533   }
534  
535   /* set_final_mode()

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines