ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/channel.c
(Generate patch)

Comparing:
ircd-hybrid/src/channel.c (file contents), Revision 32 by knight, Sun Oct 2 20:41:23 2005 UTC vs.
ircd-hybrid-7.2/src/channel.c (file contents), Revision 1013 by michael, Sun Oct 18 14:26:49 2009 UTC

# Line 25 | Line 25
25   */
26  
27   #include "stdinc.h"
28 < #include "tools.h"
28 > #include "list.h"
29   #include "channel.h"
30   #include "channel_mode.h"
31   #include "client.h"
32   #include "common.h"
33   #include "hash.h"
34 + #include "hostmask.h"
35   #include "irc_string.h"
36   #include "sprintf_irc.h"
37   #include "ircd.h"
37 #include "list.h"
38   #include "numeric.h"
39   #include "s_serv.h"             /* captab */
40   #include "s_user.h"
# Line 46 | Line 46
46  
47   struct config_channel_entry ConfigChannel;
48   dlink_list global_channel_list = { NULL, NULL, 0 };
49 dlink_list lazylink_channels = { NULL, NULL, 0 };
49   BlockHeap *ban_heap;    /*! \todo ban_heap shouldn't be a global var */
50  
51   static BlockHeap *topic_heap = NULL;
# Line 63 | Line 62 | static char parabuf[MODEBUFLEN];
62   void
63   init_channels(void)
64   {
66  /*
67   * XXX - These should get moved to somwhere else once we have
68   * a modular channelmode system
69   */
65    add_capability("EX", CAP_EX, 1);
66    add_capability("IE", CAP_IE, 1);
67    add_capability("CHW", CAP_CHW, 1);
# Line 127 | Line 122 | add_user_to_channel(struct Channel *chpt
122    ms->flags = flags;
123  
124    dlinkAdd(ms, &ms->channode, &chptr->members);
130
131  if (MyConnect(who))
132    dlinkAdd(ms, &ms->locchannode, &chptr->locmembers);
133
125    dlinkAdd(ms, &ms->usernode, &who->channel);
126   }
127  
# Line 145 | Line 136 | remove_user_from_channel(struct Membersh
136    struct Channel *chptr = member->chptr;
137  
138    dlinkDelete(&member->channode, &chptr->members);
148
149  if (MyConnect(client_p))
150    dlinkDelete(&member->locchannode, &chptr->locmembers);
151
139    dlinkDelete(&member->usernode, &client_p->channel);
140  
141    BlockHeapFree(member_heap, member);
142  
143 <  if (dlink_list_length(&chptr->members) == 0)
157 <  {
158 <    assert(dlink_list_length(&chptr->locmembers) == 0);
143 >  if (chptr->members.head == NULL)
144      destroy_channel(chptr);
160  }
145   }
146  
147   /* send_members()
# Line 190 | Line 174 | send_members(struct Client *client_p, st
174      if (ms->flags & CHFL_CHANOP)
175        tlen++;
176   #ifdef HALFOPS
177 <    if (ms->flags & CHFL_HALFOP)
177 >    else if (ms->flags & CHFL_HALFOP)
178        tlen++;
179   #endif
180      if (ms->flags & CHFL_VOICE)
# Line 206 | Line 190 | send_members(struct Client *client_p, st
190        t = start;
191      }
192  
193 <    strcpy(t, get_member_status(ms, YES));
194 <    t += strlen(t);
193 >    if ((ms->flags & (CHFL_CHANOP | CHFL_HALFOP)))
194 >      *t++ = (!(ms->flags & CHFL_CHANOP) && IsCapable(client_p, CAP_HOPS)) ?
195 >        '%' : '@';
196 >    if ((ms->flags & CHFL_VOICE))
197 >      *t++ = '+';
198  
199      if (IsCapable(client_p, CAP_TS6))
200        strcpy(t, ID(ms->client_p));
# Line 319 | Line 306 | send_channel_modes(struct Client *client
306  
307   /*! \brief check channel name for invalid characters
308   * \param name pointer to channel name string
309 < * \return TRUE (1) if name ok, FALSE (0) otherwise
309 > * \param local indicates whether it's a local or remote creation
310 > * \return 0 if invalid, 1 otherwise
311   */
312   int
313 < check_channel_name(const char *name)
313 > check_channel_name(const char *name, int local)
314   {
315 <  const unsigned char *p = (const unsigned char *)name;
315 >  const char *p = name;
316 >  int max_length = local ? LOCAL_CHANNELLEN : CHANNELLEN;
317    assert(name != NULL);
318  
319 <  for (; *p; ++p)
320 <    if (!IsChanChar(*p))
321 <      return 0;
319 >  if (!IsChanPrefix(*p))
320 >    return 0;
321 >
322 >  if (!local || !ConfigChannel.disable_fake_channels)
323 >  {
324 >    while (*++p)
325 >      if (!IsChanChar(*p))
326 >        return 0;
327 >  }
328 >  else
329 >  {
330 >    while (*++p)
331 >      if (!IsVisibleChanChar(*p))
332 >        return 0;
333 >  }
334  
335 <  return 1;
335 >  return p - name <= max_length;
336   }
337  
338   void
# Line 366 | Line 367 | free_channel_list(dlink_list *list)
367  
368   /*! \brief Get Channel block for chname (and allocate a new channel
369   *         block, if it didn't exist before)
370 < * \param client_p client pointer
371 < * \param chname   channel name
371 < * \param isnew    pointer to int flag whether channel was newly created or not
372 < * \return channel block or NULL if illegal name
370 > * \param chname channel name
371 > * \return channel block
372   */
373   struct Channel *
374 < get_or_create_channel(struct Client *client_p, const char *chname, int *isnew)
374 > make_channel(const char *chname)
375   {
376    struct Channel *chptr = NULL;
378  int len;
377  
378 <  if (EmptyString(chname))
381 <    return NULL;
382 <
383 <  if ((len = strlen(chname)) > CHANNELLEN)
384 <  {
385 <    if (IsServer(client_p))
386 <      sendto_realops_flags(UMODE_DEBUG, L_ALL,
387 <                           "*** Long channel name from %s (%d > %d): %s",
388 <                           client_p->name, len, CHANNELLEN, chname);
389 <    return NULL;
390 <  }
391 <
392 <  if ((chptr = hash_find_channel(chname)) != NULL)
393 <  {
394 <    if (isnew != NULL)
395 <      *isnew = 0;
396 <
397 <    return chptr;
398 <  }
399 <
400 <  if (isnew != NULL)
401 <    *isnew = 1;
378 >  assert(!EmptyString(chname));
379  
380    chptr = BlockHeapAlloc(channel_heap);
381 +
382    /* doesn't hurt to set it here */
383 <  chptr->channelts = chptr->last_join_time = CurrentTime;
383 >  chptr->channelts = CurrentTime;
384 >  chptr->last_join_time = CurrentTime;
385  
386    strlcpy(chptr->chname, chname, sizeof(chptr->chname));
387    dlinkAdd(chptr, &chptr->node, &global_channel_list);
# Line 434 | Line 413 | destroy_channel(struct Channel *chptr)
413    dlinkDelete(&chptr->node, &global_channel_list);
414    hash_del_channel(chptr);
415  
437  if (ServerInfo.hub)
438    if ((ptr = dlinkFindDelete(&lazylink_channels, chptr)))
439      free_dlink_node(ptr);
440
416    BlockHeapFree(channel_heap, chptr);
417   }
418  
# Line 446 | Line 421 | destroy_channel(struct Channel *chptr)
421   * \return string pointer "=" if public, "@" if secret else "*"
422   */
423   static const char *
424 < channel_pub_or_secret(struct Channel *chptr)
424 > channel_pub_or_secret(const struct Channel *chptr)
425   {
426    if (SecretChannel(chptr))
427      return "@";
# Line 472 | Line 447 | channel_member_names(struct Client *sour
447    char *t = NULL, *start = NULL;
448    int tlen = 0;
449    int is_member = IsMember(source_p, chptr);
450 +  int multi_prefix = (source_p->localClient->cap_active & CAP_MULTI_PREFIX) != 0;
451  
452    if (PubChannel(chptr) || is_member)
453    {
# Line 491 | Line 467 | channel_member_names(struct Client *sour
467  
468        tlen = strlen(target_p->name) + 1;  /* nick + space */
469  
470 <      if (ms->flags & (CHFL_CHANOP | CHFL_HALFOP | CHFL_VOICE))
471 <        ++tlen;
472 <      if (t + tlen - lbuf > IRCD_BUFSIZE)
470 >      if (!multi_prefix)
471 >      {
472 >        if (ms->flags & (CHFL_CHANOP | CHFL_HALFOP | CHFL_VOICE))
473 >          ++tlen;
474 >      }
475 >      else
476 >      {
477 >        if (ms->flags & CHFL_CHANOP)
478 >          ++tlen;
479 >        if (ms->flags & CHFL_HALFOP)
480 >          ++tlen;
481 >        if (ms->flags & CHFL_VOICE)
482 >          ++tlen;
483 >      }
484 >
485 >      if (t + tlen - lbuf > IRCD_BUFSIZE - 2)
486        {
487          *(t - 1) = '\0';
488          sendto_one(source_p, "%s", lbuf);
489          t = start;
490        }
491  
492 <      t += ircsprintf(t, "%s%s ", get_member_status(ms, NO),
492 >      t += ircsprintf(t, "%s%s ", get_member_status(ms, multi_prefix),
493                        target_p->name);
494      }
495  
# Line 528 | Line 517 | add_invite(struct Channel *chptr, struct
517    /*
518     * delete last link in chain if the list is max length
519     */
520 <  if (dlink_list_length(&who->invited) >=
520 >  if (dlink_list_length(&who->localClient->invited) >=
521        ConfigChannel.max_chans_per_user)
522 <    del_invite(who->invited.tail->data, who);
522 >    del_invite(who->localClient->invited.tail->data, who);
523  
524    /* add client to channel invite list */
525    dlinkAdd(who, make_dlink_node(), &chptr->invites);
526  
527    /* add channel to the end of the client invite list */
528 <  dlinkAdd(chptr, make_dlink_node(), &who->invited);
528 >  dlinkAdd(chptr, make_dlink_node(), &who->localClient->invited);
529   }
530  
531   /*! \brief Delete Invite block from channel invite list
# Line 549 | Line 538 | del_invite(struct Channel *chptr, struct
538   {
539    dlink_node *ptr = NULL;
540  
541 <  if ((ptr = dlinkFindDelete(&who->invited, chptr)))
541 >  if ((ptr = dlinkFindDelete(&who->localClient->invited, chptr)))
542      free_dlink_node(ptr);
543  
544    if ((ptr = dlinkFindDelete(&chptr->invites, who)))
# Line 613 | Line 602 | find_bmask(const struct Client *who, con
602  
603    DLINK_FOREACH(ptr, list->head)
604    {
605 <    const struct Ban *bp = ptr->data;
605 >    struct Ban *bp = ptr->data;
606  
607 <    if (match(bp->name, who->name) &&
608 <        match(bp->username, who->username) &&
609 <        (match(bp->host, who->host) ||
610 <         match(bp->host, who->sockhost) ||
611 <         match_cidr(bp->host, who->sockhost)))
612 <      return 1;
607 >    if (match(bp->name, who->name) && match(bp->username, who->username))
608 >    {
609 >      switch (bp->type)
610 >      {
611 >        case HM_HOST:
612 >          if (match(bp->host, who->host) || match(bp->host, who->sockhost))
613 >            return 1;
614 >          break;
615 >        case HM_IPV4:
616 >          if (who->localClient->aftype == AF_INET)
617 >            if (match_ipv4(&who->localClient->ip, &bp->addr, bp->bits))
618 >              return 1;
619 >          break;
620 > #ifdef IPV6
621 >        case HM_IPV6:
622 >          if (who->localClient->aftype == AF_INET6)
623 >            if (match_ipv6(&who->localClient->ip, &bp->addr, bp->bits))
624 >              return 1;
625 >          break;
626 > #endif
627 >        default:
628 >          assert(0);
629 >      }
630 >    }
631    }
632  
633    return 0;
# Line 632 | Line 639 | find_bmask(const struct Client *who, con
639   * \return 0 if not banned, 1 otherwise
640   */
641   int
642 < is_banned(struct Channel *chptr, struct Client *who)
642 > is_banned(const struct Channel *chptr, const struct Client *who)
643   {
644 <  assert(IsClient(who));
644 >  if (find_bmask(who, &chptr->banlist))
645 >    if (!ConfigChannel.use_except || !find_bmask(who, &chptr->exceptlist))
646 >      return 1;
647  
648 <  return find_bmask(who, &chptr->banlist) && (!ConfigChannel.use_except ||
640 <         !find_bmask(who, &chptr->exceptlist));
648 >  return 0;
649   }
650  
651   /*!
# Line 650 | Line 658 | is_banned(struct Channel *chptr, struct
658   int
659   can_join(struct Client *source_p, struct Channel *chptr, const char *key)
660   {
661 <  if (find_bmask(source_p, &chptr->banlist))
662 <    if (!ConfigChannel.use_except || !find_bmask(source_p, &chptr->exceptlist))
655 <      return ERR_BANNEDFROMCHAN;
661 >  if (is_banned(chptr, source_p))
662 >    return ERR_BANNEDFROMCHAN;
663  
664    if (chptr->mode.mode & MODE_INVITEONLY)
665 <    if (!dlinkFind(&source_p->invited, chptr))
665 >    if (!dlinkFind(&source_p->localClient->invited, chptr))
666        if (!ConfigChannel.use_invex || !find_bmask(source_p, &chptr->invexlist))
667          return ERR_INVITEONLYCHAN;
668  
669 <  if (chptr->mode.key[0] && (EmptyString(key) || irccmp(chptr->mode.key, key)))
669 >  if (chptr->mode.key[0] && (!key || irccmp(chptr->mode.key, key)))
670      return ERR_BADCHANNELKEY;
671  
672    if (chptr->mode.limit && dlink_list_length(&chptr->members) >=
# Line 687 | Line 694 | find_channel_link(struct Client *client_
694  
695    DLINK_FOREACH(ptr, client_p->channel.head)
696      if (((struct Membership *)ptr->data)->chptr == chptr)
697 <      return (struct Membership *)ptr->data;
697 >      return ptr->data;
698  
699    return NULL;
700   }
# Line 695 | Line 702 | find_channel_link(struct Client *client_
702   /*!
703   * \param chptr    pointer to Channel struct
704   * \param source_p pointer to Client struct
705 + * \param ms       pointer to Membership struct (can be NULL)
706   * \return CAN_SEND_OPV if op or voiced on channel\n
707   *         CAN_SEND_NONOP if can send to channel but is not an op\n
708   *         CAN_SEND_NO if they cannot send to channel\n
709   */
710   int
711 < can_send(struct Channel *chptr, struct Client *source_p)
711 > can_send(struct Channel *chptr, struct Client *source_p, struct Membership *ms)
712   {
705  struct Membership *ms = NULL;
706
713    if (IsServer(source_p))
714      return CAN_SEND_OPV;
715  
716 <  if (MyClient(source_p) && !IsExemptResv(source_p) &&
717 <      !(IsOper(source_p) && ConfigFileEntry.oper_pass_resv) &&
718 <      (!hash_find_resv(chptr->chname) == ConfigChannel.restrict_channels))
719 <    return CAN_SEND_NO;
716 >  if (MyClient(source_p) && !IsExemptResv(source_p))
717 >    if (!(IsOper(source_p) && ConfigFileEntry.oper_pass_resv))
718 >      if (!hash_find_resv(chptr->chname) == ConfigChannel.restrict_channels)
719 >        return CAN_SEND_NO;
720  
721 <  if ((ms = find_channel_link(source_p, chptr)) == NULL)
716 <  {
717 <    if (chptr->mode.mode & MODE_NOPRIVMSGS)
718 <      return CAN_SEND_NO;
719 <  }
720 <  else
721 >  if (ms != NULL || (ms = find_channel_link(source_p, chptr)))
722    {
723      if (ms->flags & (CHFL_CHANOP|CHFL_HALFOP|CHFL_VOICE))
724        return CAN_SEND_OPV;
# Line 740 | Line 741 | can_send(struct Channel *chptr, struct C
741        }
742      }
743    }
744 <
744 <  if (chptr->mode.mode & MODE_MODERATED)
744 >  else if (chptr->mode.mode & MODE_NOPRIVMSGS)
745      return CAN_SEND_NO;
746  
747  return CAN_SEND_NONOP;
748 }
749
750 /*! \brief Checks to see if given client can send a part message
751 * \param member     pointer to channel membership
752 * \param chptr      pointer to channel struct
753 * \param source_p   pointer to struct Client to check
754 */
755 int
756 can_send_part(struct Membership *member, struct Channel *chptr,
757              struct Client *source_p)
758 {
759  if (has_member_flags(member, CHFL_CHANOP|CHFL_HALFOP))
760    return CAN_SEND_OPV;
761
747    if (chptr->mode.mode & MODE_MODERATED)
748      return CAN_SEND_NO;
749  
765  if (ConfigChannel.quiet_on_ban && MyClient(source_p) &&
766      is_banned(chptr, source_p))
767    return CAN_SEND_NO;
768
750    return CAN_SEND_NONOP;
751   }
752  
# Line 926 | Line 907 | set_channel_topic(struct Channel *chptr,
907    }
908    else
909    {
910 +    /*
911 +     * Do not reset chptr->topic_time here, it's required for
912 +     * bursting topics properly.
913 +     */
914      if (chptr->topic != NULL)
915        free_topic(chptr);
931
932    chptr->topic_time = 0;
916    }
917   }
935

Comparing:
ircd-hybrid/src/channel.c (property svn:keywords), Revision 32 by knight, Sun Oct 2 20:41:23 2005 UTC vs.
ircd-hybrid-7.2/src/channel.c (property svn:keywords), Revision 1013 by michael, Sun Oct 18 14:26:49 2009 UTC

# Line 1 | Line 1
1 < Revision
1 > Id Revision

Diff Legend

Removed lines
+ Added lines
< Changed lines (old)
> Changed lines (new)