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-8/src/channel.c (file contents), Revision 1330 by michael, Sun Apr 1 12:12:00 2012 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"
32   #include "hash.h"
33 + #include "hostmask.h"
34   #include "irc_string.h"
35   #include "sprintf_irc.h"
36   #include "ircd.h"
37 #include "list.h"
37   #include "numeric.h"
38   #include "s_serv.h"             /* captab */
39   #include "s_user.h"
40   #include "send.h"
41 < #include "s_conf.h"             /* ConfigFileEntry, ConfigChannel */
41 > #include "conf.h"             /* ConfigFileEntry, ConfigChannel */
42   #include "event.h"
43   #include "memory.h"
44   #include "balloc.h"
45  
46   struct config_channel_entry ConfigChannel;
47   dlink_list global_channel_list = { NULL, NULL, 0 };
49 dlink_list lazylink_channels = { NULL, NULL, 0 };
48   BlockHeap *ban_heap;    /*! \todo ban_heap shouldn't be a global var */
49  
52 static BlockHeap *topic_heap = NULL;
50   static BlockHeap *member_heap = NULL;
51   static BlockHeap *channel_heap = NULL;
52  
# Line 63 | Line 60 | static char parabuf[MODEBUFLEN];
60   void
61   init_channels(void)
62   {
66  /*
67   * XXX - These should get moved to somwhere else once we have
68   * a modular channelmode system
69   */
63    add_capability("EX", CAP_EX, 1);
64    add_capability("IE", CAP_IE, 1);
65    add_capability("CHW", CAP_CHW, 1);
66  
67    channel_heap = BlockHeapCreate("channel", sizeof(struct Channel), CHANNEL_HEAP_SIZE);
68    ban_heap = BlockHeapCreate("ban", sizeof(struct Ban), BAN_HEAP_SIZE);
76  topic_heap = BlockHeapCreate("topic", TOPICLEN+1 + USERHOST_REPLYLEN, TOPIC_HEAP_SIZE);
69    member_heap = BlockHeapCreate("member", sizeof(struct Membership), CHANNEL_HEAP_SIZE*2);
70   }
71  
# Line 127 | Line 119 | add_user_to_channel(struct Channel *chpt
119    ms->flags = flags;
120  
121    dlinkAdd(ms, &ms->channode, &chptr->members);
130
131  if (MyConnect(who))
132    dlinkAdd(ms, &ms->locchannode, &chptr->locmembers);
133
122    dlinkAdd(ms, &ms->usernode, &who->channel);
123   }
124  
# Line 145 | Line 133 | remove_user_from_channel(struct Membersh
133    struct Channel *chptr = member->chptr;
134  
135    dlinkDelete(&member->channode, &chptr->members);
148
149  if (MyConnect(client_p))
150    dlinkDelete(&member->locchannode, &chptr->locmembers);
151
136    dlinkDelete(&member->usernode, &client_p->channel);
137  
138    BlockHeapFree(member_heap, member);
139  
140 <  if (dlink_list_length(&chptr->members) == 0)
157 <  {
158 <    assert(dlink_list_length(&chptr->locmembers) == 0);
140 >  if (chptr->members.head == NULL)
141      destroy_channel(chptr);
160  }
142   }
143  
144   /* send_members()
# Line 190 | Line 171 | send_members(struct Client *client_p, st
171      if (ms->flags & CHFL_CHANOP)
172        tlen++;
173   #ifdef HALFOPS
174 <    if (ms->flags & CHFL_HALFOP)
174 >    else if (ms->flags & CHFL_HALFOP)
175        tlen++;
176   #endif
177      if (ms->flags & CHFL_VOICE)
# Line 199 | Line 180 | send_members(struct Client *client_p, st
180      /* space will be converted into CR, but we also need space for LF..
181       * That's why we use '- 1' here
182       * -adx */
183 <    if (t + tlen - buf > sizeof(buf) - 1)
183 >    if (t + tlen - buf > IRCD_BUFSIZE - 1)
184      {
185        *(t - 1) = '\0';  /* kill the space and terminate the string */
186        sendto_one(client_p, "%s", buf);
187        t = start;
188      }
189  
190 <    strcpy(t, get_member_status(ms, YES));
191 <    t += strlen(t);
190 >    if ((ms->flags & (CHFL_CHANOP | CHFL_HALFOP)))
191 >      *t++ = (!(ms->flags & CHFL_CHANOP) && IsCapable(client_p, CAP_HOPS)) ?
192 >        '%' : '@';
193 >    if ((ms->flags & CHFL_VOICE))
194 >      *t++ = '+';
195  
196      if (IsCapable(client_p, CAP_TS6))
197        strcpy(t, ID(ms->client_p));
# Line 319 | Line 303 | send_channel_modes(struct Client *client
303  
304   /*! \brief check channel name for invalid characters
305   * \param name pointer to channel name string
306 < * \return TRUE (1) if name ok, FALSE (0) otherwise
306 > * \param local indicates whether it's a local or remote creation
307 > * \return 0 if invalid, 1 otherwise
308   */
309   int
310 < check_channel_name(const char *name)
310 > check_channel_name(const char *name, int local)
311   {
312 <  const unsigned char *p = (const unsigned char *)name;
312 >  const char *p = name;
313 >  int max_length = local ? LOCAL_CHANNELLEN : CHANNELLEN;
314    assert(name != NULL);
315  
316 <  for (; *p; ++p)
317 <    if (!IsChanChar(*p))
332 <      return 0;
316 >  if (!IsChanPrefix(*p))
317 >    return 0;
318  
319 <  return 1;
319 >  if (!local || !ConfigChannel.disable_fake_channels)
320 >  {
321 >    while (*++p)
322 >      if (!IsChanChar(*p))
323 >        return 0;
324 >  }
325 >  else
326 >  {
327 >    while (*++p)
328 >      if (!IsVisibleChanChar(*p))
329 >        return 0;
330 >  }
331 >
332 >  return p - name <= max_length;
333   }
334  
335   void
# Line 366 | Line 364 | free_channel_list(dlink_list *list)
364  
365   /*! \brief Get Channel block for chname (and allocate a new channel
366   *         block, if it didn't exist before)
367 < * \param client_p client pointer
368 < * \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
367 > * \param chname channel name
368 > * \return channel block
369   */
370   struct Channel *
371 < get_or_create_channel(struct Client *client_p, const char *chname, int *isnew)
371 > make_channel(const char *chname)
372   {
373    struct Channel *chptr = NULL;
378  int len;
374  
375 <  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;
375 >  assert(!EmptyString(chname));
376  
377    chptr = BlockHeapAlloc(channel_heap);
378 +
379    /* doesn't hurt to set it here */
380 <  chptr->channelts = chptr->last_join_time = CurrentTime;
380 >  chptr->channelts = CurrentTime;
381 >  chptr->last_join_time = CurrentTime;
382  
383    strlcpy(chptr->chname, chname, sizeof(chptr->chname));
384    dlinkAdd(chptr, &chptr->node, &global_channel_list);
# Line 428 | Line 404 | destroy_channel(struct Channel *chptr)
404    free_channel_list(&chptr->exceptlist);
405    free_channel_list(&chptr->invexlist);
406  
431  /* Free the topic */
432  free_topic(chptr);
433
407    dlinkDelete(&chptr->node, &global_channel_list);
408    hash_del_channel(chptr);
409  
437  if (ServerInfo.hub)
438    if ((ptr = dlinkFindDelete(&lazylink_channels, chptr)))
439      free_dlink_node(ptr);
440
410    BlockHeapFree(channel_heap, chptr);
411   }
412  
# Line 446 | Line 415 | destroy_channel(struct Channel *chptr)
415   * \return string pointer "=" if public, "@" if secret else "*"
416   */
417   static const char *
418 < channel_pub_or_secret(struct Channel *chptr)
418 > channel_pub_or_secret(const struct Channel *chptr)
419   {
420    if (SecretChannel(chptr))
421      return "@";
# Line 472 | Line 441 | channel_member_names(struct Client *sour
441    char *t = NULL, *start = NULL;
442    int tlen = 0;
443    int is_member = IsMember(source_p, chptr);
444 +  int multi_prefix = HasCap(source_p, CAP_MULTI_PREFIX) != 0;
445  
446    if (PubChannel(chptr) || is_member)
447    {
# Line 486 | Line 456 | channel_member_names(struct Client *sour
456        ms       = ptr->data;
457        target_p = ms->client_p;
458  
459 <      if (IsInvisible(target_p) && !is_member)
459 >      if (HasUMode(target_p, UMODE_INVISIBLE) && !is_member)
460          continue;
461  
462        tlen = strlen(target_p->name) + 1;  /* nick + space */
463  
464 <      if (ms->flags & (CHFL_CHANOP | CHFL_HALFOP | CHFL_VOICE))
465 <        ++tlen;
466 <      if (t + tlen - lbuf > IRCD_BUFSIZE)
464 >      if (!multi_prefix)
465 >      {
466 >        if (ms->flags & (CHFL_CHANOP | CHFL_HALFOP | CHFL_VOICE))
467 >          ++tlen;
468 >      }
469 >      else
470 >      {
471 >        if (ms->flags & CHFL_CHANOP)
472 >          ++tlen;
473 >        if (ms->flags & CHFL_HALFOP)
474 >          ++tlen;
475 >        if (ms->flags & CHFL_VOICE)
476 >          ++tlen;
477 >      }
478 >
479 >      if (t + tlen - lbuf > IRCD_BUFSIZE - 2)
480        {
481          *(t - 1) = '\0';
482          sendto_one(source_p, "%s", lbuf);
483          t = start;
484        }
485  
486 <      t += ircsprintf(t, "%s%s ", get_member_status(ms, NO),
486 >      t += ircsprintf(t, "%s%s ", get_member_status(ms, multi_prefix),
487                        target_p->name);
488      }
489  
# Line 528 | Line 511 | add_invite(struct Channel *chptr, struct
511    /*
512     * delete last link in chain if the list is max length
513     */
514 <  if (dlink_list_length(&who->invited) >=
514 >  if (dlink_list_length(&who->localClient->invited) >=
515        ConfigChannel.max_chans_per_user)
516 <    del_invite(who->invited.tail->data, who);
516 >    del_invite(who->localClient->invited.tail->data, who);
517  
518    /* add client to channel invite list */
519    dlinkAdd(who, make_dlink_node(), &chptr->invites);
520  
521    /* add channel to the end of the client invite list */
522 <  dlinkAdd(chptr, make_dlink_node(), &who->invited);
522 >  dlinkAdd(chptr, make_dlink_node(), &who->localClient->invited);
523   }
524  
525   /*! \brief Delete Invite block from channel invite list
# Line 549 | Line 532 | del_invite(struct Channel *chptr, struct
532   {
533    dlink_node *ptr = NULL;
534  
535 <  if ((ptr = dlinkFindDelete(&who->invited, chptr)))
535 >  if ((ptr = dlinkFindDelete(&who->localClient->invited, chptr)))
536      free_dlink_node(ptr);
537  
538    if ((ptr = dlinkFindDelete(&chptr->invites, who)))
# Line 613 | Line 596 | find_bmask(const struct Client *who, con
596  
597    DLINK_FOREACH(ptr, list->head)
598    {
599 <    const struct Ban *bp = ptr->data;
599 >    struct Ban *bp = ptr->data;
600  
601 <    if (match(bp->name, who->name) &&
602 <        match(bp->username, who->username) &&
603 <        (match(bp->host, who->host) ||
604 <         match(bp->host, who->sockhost) ||
605 <         match_cidr(bp->host, who->sockhost)))
606 <      return 1;
601 >    if (match(bp->name, who->name) && match(bp->username, who->username))
602 >    {
603 >      switch (bp->type)
604 >      {
605 >        case HM_HOST:
606 >          if (match(bp->host, who->host) || match(bp->host, who->sockhost))
607 >            return 1;
608 >          break;
609 >        case HM_IPV4:
610 >          if (who->localClient->aftype == AF_INET)
611 >            if (match_ipv4(&who->localClient->ip, &bp->addr, bp->bits))
612 >              return 1;
613 >          break;
614 > #ifdef IPV6
615 >        case HM_IPV6:
616 >          if (who->localClient->aftype == AF_INET6)
617 >            if (match_ipv6(&who->localClient->ip, &bp->addr, bp->bits))
618 >              return 1;
619 >          break;
620 > #endif
621 >        default:
622 >          assert(0);
623 >      }
624 >    }
625    }
626  
627    return 0;
# Line 632 | Line 633 | find_bmask(const struct Client *who, con
633   * \return 0 if not banned, 1 otherwise
634   */
635   int
636 < is_banned(struct Channel *chptr, struct Client *who)
636 > is_banned(const struct Channel *chptr, const struct Client *who)
637   {
638 <  assert(IsClient(who));
638 >  if (find_bmask(who, &chptr->banlist))
639 >    if (!ConfigChannel.use_except || !find_bmask(who, &chptr->exceptlist))
640 >      return 1;
641  
642 <  return find_bmask(who, &chptr->banlist) && (!ConfigChannel.use_except ||
640 <         !find_bmask(who, &chptr->exceptlist));
642 >  return 0;
643   }
644  
645   /*!
# Line 650 | Line 652 | is_banned(struct Channel *chptr, struct
652   int
653   can_join(struct Client *source_p, struct Channel *chptr, const char *key)
654   {
655 <  if (find_bmask(source_p, &chptr->banlist))
656 <    if (!ConfigChannel.use_except || !find_bmask(source_p, &chptr->exceptlist))
657 <      return ERR_BANNEDFROMCHAN;
655 >  if (is_banned(chptr, source_p))
656 >    return ERR_BANNEDFROMCHAN;
657 >
658 > #ifdef HAVE_LIBCRYPTO
659 >  if ((chptr->mode.mode & MODE_SSLONLY) && !source_p->localClient->fd.ssl)
660 >    return ERR_SSLONLYCHAN;
661 > #endif
662 >
663 >  if ((chptr->mode.mode & MODE_REGONLY) && !HasUMode(source_p, UMODE_REGISTERED))
664 >    return ERR_NEEDREGGEDNICK;
665 >
666 >  if ((chptr->mode.mode & MODE_OPERONLY) && !HasUMode(source_p, UMODE_OPER))
667 >    return ERR_OPERONLYCHAN;
668  
669    if (chptr->mode.mode & MODE_INVITEONLY)
670 <    if (!dlinkFind(&source_p->invited, chptr))
670 >    if (!dlinkFind(&source_p->localClient->invited, chptr))
671        if (!ConfigChannel.use_invex || !find_bmask(source_p, &chptr->invexlist))
672          return ERR_INVITEONLYCHAN;
673  
674 <  if (chptr->mode.key[0] && (EmptyString(key) || irccmp(chptr->mode.key, key)))
674 >  if (chptr->mode.key[0] && (!key || irccmp(chptr->mode.key, key)))
675      return ERR_BADCHANNELKEY;
676  
677    if (chptr->mode.limit && dlink_list_length(&chptr->members) >=
# Line 687 | Line 699 | find_channel_link(struct Client *client_
699  
700    DLINK_FOREACH(ptr, client_p->channel.head)
701      if (((struct Membership *)ptr->data)->chptr == chptr)
702 <      return (struct Membership *)ptr->data;
702 >      return ptr->data;
703  
704    return NULL;
705   }
# Line 695 | Line 707 | find_channel_link(struct Client *client_
707   /*!
708   * \param chptr    pointer to Channel struct
709   * \param source_p pointer to Client struct
710 + * \param ms       pointer to Membership struct (can be NULL)
711   * \return CAN_SEND_OPV if op or voiced on channel\n
712   *         CAN_SEND_NONOP if can send to channel but is not an op\n
713 < *         CAN_SEND_NO if they cannot send to channel\n
713 > *         ERR_CANNOTSENDTOCHAN or ERR_NEEDREGGEDNICK if they cannot send to channel\n
714   */
715   int
716 < can_send(struct Channel *chptr, struct Client *source_p)
716 > can_send(struct Channel *chptr, struct Client *source_p, struct Membership *ms)
717   {
718 <  struct Membership *ms = NULL;
706 <
707 <  if (IsServer(source_p))
718 >  if (IsServer(source_p) || HasFlag(source_p, FLAGS_SERVICE))
719      return CAN_SEND_OPV;
720  
721 <  if (MyClient(source_p) && !IsExemptResv(source_p) &&
722 <      !(IsOper(source_p) && ConfigFileEntry.oper_pass_resv) &&
723 <      (!hash_find_resv(chptr->chname) == ConfigChannel.restrict_channels))
724 <    return CAN_SEND_NO;
721 >  if (MyClient(source_p) && !IsExemptResv(source_p))
722 >    if (!(HasUMode(source_p, UMODE_OPER) && ConfigFileEntry.oper_pass_resv))
723 >      if (!hash_find_resv(chptr->chname) == ConfigChannel.restrict_channels)
724 >        return ERR_CANNOTSENDTOCHAN;
725  
726 <  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
726 >  if (ms != NULL || (ms = find_channel_link(source_p, chptr)))
727    {
728      if (ms->flags & (CHFL_CHANOP|CHFL_HALFOP|CHFL_VOICE))
729        return CAN_SEND_OPV;
# Line 726 | Line 732 | can_send(struct Channel *chptr, struct C
732      if (ConfigChannel.quiet_on_ban && MyClient(source_p))
733      {
734        if (ms->flags & CHFL_BAN_SILENCED)
735 <        return CAN_SEND_NO;
735 >        return ERR_CANNOTSENDTOCHAN;
736  
737        if (!(ms->flags & CHFL_BAN_CHECKED))
738        {
739          if (is_banned(chptr, source_p))
740          {
741            ms->flags |= (CHFL_BAN_CHECKED|CHFL_BAN_SILENCED);
742 <          return CAN_SEND_NO;
742 >          return ERR_CANNOTSENDTOCHAN;
743          }
744  
745          ms->flags |= CHFL_BAN_CHECKED;
746        }
747      }
748    }
749 +  else if (chptr->mode.mode & MODE_NOPRIVMSGS)
750 +    return ERR_CANNOTSENDTOCHAN;
751  
752    if (chptr->mode.mode & MODE_MODERATED)
753 <    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 <
762 <  if (chptr->mode.mode & MODE_MODERATED)
763 <    return CAN_SEND_NO;
764 <
765 <  if (ConfigChannel.quiet_on_ban && MyClient(source_p) &&
766 <      is_banned(chptr, source_p))
767 <    return CAN_SEND_NO;
753 >    return ERR_CANNOTSENDTOCHAN;
754  
755    return CAN_SEND_NONOP;
756   }
# Line 865 | Line 851 | check_splitmode(void *unused)
851    }
852   }
853  
868 /*! \brief Allocates a new topic
869 * \param chptr Channel to allocate a new topic for
870 */
871 static void
872 allocate_topic(struct Channel *chptr)
873 {
874  void *ptr = NULL;
875
876  if (chptr == NULL)
877    return;
878
879  ptr = BlockHeapAlloc(topic_heap);  
880
881  /* Basically we allocate one large block for the topic and
882   * the topic info.  We then split it up into two and shove it
883   * in the chptr
884   */
885  chptr->topic       = ptr;
886  chptr->topic_info  = (char *)ptr + TOPICLEN+1;
887  *chptr->topic      = '\0';
888  *chptr->topic_info = '\0';
889 }
890
891 void
892 free_topic(struct Channel *chptr)
893 {
894  void *ptr = NULL;
895  assert(chptr);
896  if (chptr->topic == NULL)
897    return;
898
899  /*
900   * If you change allocate_topic you MUST change this as well
901   */
902  ptr = chptr->topic;
903  BlockHeapFree(topic_heap, ptr);    
904  chptr->topic      = NULL;
905  chptr->topic_info = NULL;
906 }
907
854   /*! \brief Sets the channel topic for chptr
855   * \param chptr      Pointer to struct Channel
856   * \param topic      The topic string
# Line 915 | Line 861 | void
861   set_channel_topic(struct Channel *chptr, const char *topic,
862                    const char *topic_info, time_t topicts)
863   {
864 <  if (!EmptyString(topic))
865 <  {
866 <    if (chptr->topic == NULL)
921 <      allocate_topic(chptr);
922 <
923 <    strlcpy(chptr->topic, topic, TOPICLEN+1);
924 <    strlcpy(chptr->topic_info, topic_info, USERHOST_REPLYLEN);
925 <    chptr->topic_time = topicts;
926 <  }
927 <  else
928 <  {
929 <    if (chptr->topic != NULL)
930 <      free_topic(chptr);
931 <
932 <    chptr->topic_time = 0;
933 <  }
864 >  strlcpy(chptr->topic, topic, sizeof(chptr->topic));
865 >  strlcpy(chptr->topic_info, topic_info, sizeof(chptr->topic_info));
866 >  chptr->topic_time = topicts;
867   }
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-8/src/channel.c (property svn:keywords), Revision 1330 by michael, Sun Apr 1 12:12:00 2012 UTC

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

Diff Legend

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