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-7.2/src/channel.c (file contents), Revision 371 by michael, Tue Jan 10 10:45:48 2006 UTC vs.
ircd-hybrid/trunk/src/channel.c (file contents), Revision 1858 by michael, Thu Apr 25 15:00:52 2013 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 "conf.h"
34   #include "hostmask.h"
35   #include "irc_string.h"
36 #include "sprintf_irc.h"
36   #include "ircd.h"
38 #include "list.h"
37   #include "numeric.h"
38   #include "s_serv.h"             /* captab */
39   #include "s_user.h"
40   #include "send.h"
43 #include "s_conf.h"             /* ConfigFileEntry, ConfigChannel */
41   #include "event.h"
42   #include "memory.h"
43 < #include "balloc.h"
43 > #include "mempool.h"
44 > #include "s_misc.h"
45 > #include "resv.h"
46  
47   struct config_channel_entry ConfigChannel;
48   dlink_list global_channel_list = { NULL, NULL, 0 };
49 < dlink_list lazylink_channels = { NULL, NULL, 0 };
51 < BlockHeap *ban_heap;    /*! \todo ban_heap shouldn't be a global var */
49 > mp_pool_t *ban_pool;    /*! \todo ban_pool shouldn't be a global var */
50  
51 < static BlockHeap *topic_heap = NULL;
52 < static BlockHeap *member_heap = NULL;
55 < static BlockHeap *channel_heap = NULL;
51 > static mp_pool_t *member_pool = NULL;
52 > static mp_pool_t *channel_pool = NULL;
53  
54   static char buf[IRCD_BUFSIZE];
55   static char modebuf[MODEBUFLEN];
# Line 62 | Line 59 | static char parabuf[MODEBUFLEN];
59   /*! \brief Initializes the channel blockheap, adds known channel CAPAB
60   */
61   void
62 < init_channels(void)
62 > channel_init(void)
63   {
67  /*
68   * XXX - These should get moved to somwhere else once we have
69   * a modular channelmode system
70   */
64    add_capability("EX", CAP_EX, 1);
65    add_capability("IE", CAP_IE, 1);
66    add_capability("CHW", CAP_CHW, 1);
67  
68 <  channel_heap = BlockHeapCreate("channel", sizeof(struct Channel), CHANNEL_HEAP_SIZE);
69 <  ban_heap = BlockHeapCreate("ban", sizeof(struct Ban), BAN_HEAP_SIZE);
70 <  topic_heap = BlockHeapCreate("topic", TOPICLEN+1 + USERHOST_REPLYLEN, TOPIC_HEAP_SIZE);
78 <  member_heap = BlockHeapCreate("member", sizeof(struct Membership), CHANNEL_HEAP_SIZE*2);
68 >  channel_pool = mp_pool_new(sizeof(struct Channel), MP_CHUNK_SIZE_CHANNEL);
69 >  ban_pool = mp_pool_new(sizeof(struct Ban), MP_CHUNK_SIZE_BAN);
70 >  member_pool = mp_pool_new(sizeof(struct Membership), MP_CHUNK_SIZE_MEMBER);
71   }
72  
73   /*! \brief adds a user to a channel by adding another link to the
# Line 112 | Line 104 | add_user_to_channel(struct Channel *chpt
104        if (!IsSetJoinFloodNoticed(chptr))
105        {
106          SetJoinFloodNoticed(chptr);
107 <        sendto_realops_flags(UMODE_BOTS, L_ALL,
107 >        sendto_realops_flags(UMODE_BOTS, L_ALL, SEND_NOTICE,
108                               "Possible Join Flooder %s on %s target: %s",
109                               get_client_name(who, HIDE_IP),
110                               who->servptr->name, chptr->chname);
# Line 122 | Line 114 | add_user_to_channel(struct Channel *chpt
114      chptr->last_join_time = CurrentTime;
115    }
116  
117 <  ms = BlockHeapAlloc(member_heap);
117 >  ms = mp_pool_get(member_pool);
118 >  memset(ms, 0, sizeof(*ms));
119 >
120    ms->client_p = who;
121    ms->chptr = chptr;
122    ms->flags = flags;
123  
124    dlinkAdd(ms, &ms->channode, &chptr->members);
131
132  if (MyConnect(who))
133    dlinkAdd(ms, &ms->locchannode, &chptr->locmembers);
134
125    dlinkAdd(ms, &ms->usernode, &who->channel);
126   }
127  
# Line 146 | Line 136 | remove_user_from_channel(struct Membersh
136    struct Channel *chptr = member->chptr;
137  
138    dlinkDelete(&member->channode, &chptr->members);
149
150  if (MyConnect(client_p))
151    dlinkDelete(&member->locchannode, &chptr->locmembers);
152
139    dlinkDelete(&member->usernode, &client_p->channel);
140  
141 <  BlockHeapFree(member_heap, member);
141 >  mp_pool_release(member);
142  
143 <  if (dlink_list_length(&chptr->members) == 0)
158 <  {
159 <    assert(dlink_list_length(&chptr->locmembers) == 0);
143 >  if (chptr->members.head == NULL)
144      destroy_channel(chptr);
161  }
145   }
146  
147   /* send_members()
# Line 171 | Line 154 | static void
154   send_members(struct Client *client_p, struct Channel *chptr,
155               char *lmodebuf, char *lparabuf)
156   {
157 <  struct Membership *ms;
175 <  dlink_node *ptr;
157 >  const dlink_node *ptr = NULL;
158    int tlen;              /* length of text to append */
159    char *t, *start;       /* temp char pointer */
160  
161 <  start = t = buf + ircsprintf(buf, ":%s SJOIN %lu %s %s %s:",
162 <                               ID_or_name(&me, client_p),
163 <                               (unsigned long)chptr->channelts,
164 <                               chptr->chname, lmodebuf, lparabuf);
161 >  start = t = buf + snprintf(buf, sizeof(buf), ":%s SJOIN %lu %s %s %s:",
162 >                             ID_or_name(&me, client_p),
163 >                             (unsigned long)chptr->channelts,
164 >                             chptr->chname, lmodebuf, lparabuf);
165  
166    DLINK_FOREACH(ptr, chptr->members.head)
167    {
168 <    ms = ptr->data;
168 >    const struct Membership *ms = ptr->data;
169  
170      tlen = strlen(IsCapable(client_p, CAP_TS6) ?
171        ID(ms->client_p) : ms->client_p->name) + 1;  /* nick + space */
# Line 200 | Line 182 | send_members(struct Client *client_p, st
182      /* space will be converted into CR, but we also need space for LF..
183       * That's why we use '- 1' here
184       * -adx */
185 <    if (t + tlen - buf > sizeof(buf) - 1)
185 >    if (t + tlen - buf > IRCD_BUFSIZE - 1)
186      {
187        *(t - 1) = '\0';  /* kill the space and terminate the string */
188        sendto_one(client_p, "%s", buf);
# Line 236 | Line 218 | send_members(struct Client *client_p, st
218   */
219   static void
220   send_mode_list(struct Client *client_p, struct Channel *chptr,
221 <               dlink_list *top, char flag)
221 >               const dlink_list *top, char flag)
222   {
223    int ts5 = !IsCapable(client_p, CAP_TS6);
224 <  dlink_node *lp;
243 <  struct Ban *banptr;
224 >  const dlink_node *lp = NULL;
225    char pbuf[IRCD_BUFSIZE];
226    int tlen, mlen, cur_len, count = 0;
227    char *mp = NULL, *pp = pbuf;
# Line 249 | Line 230 | send_mode_list(struct Client *client_p,
230      return;
231  
232    if (ts5)
233 <    mlen = ircsprintf(buf, ":%s MODE %s +", me.name, chptr->chname);
233 >    mlen = snprintf(buf, sizeof(buf), ":%s MODE %s +", me.name, chptr->chname);
234    else
235 <    mlen = ircsprintf(buf, ":%s BMASK %lu %s %c :", me.id,
236 <                      (unsigned long)chptr->channelts, chptr->chname, flag);
235 >    mlen = snprintf(buf, sizeof(buf), ":%s BMASK %lu %s %c :", me.id,
236 >                   (unsigned long)chptr->channelts, chptr->chname, flag);
237  
238    /* MODE needs additional one byte for space between buf and pbuf */
239    cur_len = mlen + ts5;
# Line 260 | Line 241 | send_mode_list(struct Client *client_p,
241  
242    DLINK_FOREACH(lp, top->head)
243    {
244 <    banptr = lp->data;
244 >    const struct Ban *banptr = lp->data;
245  
246      /* must add another b/e/I letter if we use MODE */
247      tlen = banptr->len + 3 + ts5;
# Line 290 | Line 271 | send_mode_list(struct Client *client_p,
271        *mp = '\0';
272      }
273  
274 <    pp += ircsprintf(pp, "%s!%s@%s ", banptr->name, banptr->username,
275 <                     banptr->host);
274 >    pp += sprintf(pp, "%s!%s@%s ", banptr->name, banptr->username,
275 >                  banptr->host);
276      cur_len += tlen;
277    }
278  
# Line 306 | Line 287 | send_mode_list(struct Client *client_p,
287   void
288   send_channel_modes(struct Client *client_p, struct Channel *chptr)
289   {
309  if (chptr->chname[0] != '#')
310    return;
311
290    *modebuf = *parabuf = '\0';
291    channel_modes(chptr, client_p, modebuf, parabuf);
292    send_members(client_p, chptr, modebuf, parabuf);
293  
294    send_mode_list(client_p, chptr, &chptr->banlist, 'b');
295 <
296 <  if (IsCapable(client_p, CAP_EX))
319 <    send_mode_list(client_p, chptr, &chptr->exceptlist, 'e');
320 <  if (IsCapable(client_p, CAP_IE))
321 <    send_mode_list(client_p, chptr, &chptr->invexlist, 'I');
295 >  send_mode_list(client_p, chptr, &chptr->exceptlist, 'e');
296 >  send_mode_list(client_p, chptr, &chptr->invexlist, 'I');
297   }
298  
299   /*! \brief check channel name for invalid characters
300   * \param name pointer to channel name string
301 < * \return TRUE (1) if name ok, FALSE (0) otherwise
301 > * \param local indicates whether it's a local or remote creation
302 > * \return 0 if invalid, 1 otherwise
303   */
304   int
305 < check_channel_name(const char *name)
305 > check_channel_name(const char *name, const int local)
306   {
307 <  const unsigned char *p = (const unsigned char *)name;
307 >  const char *p = name;
308 >  const int max_length = local ? LOCAL_CHANNELLEN : CHANNELLEN;
309    assert(name != NULL);
310  
311 <  for (; *p; ++p)
312 <    if (!IsChanChar(*p))
336 <      return 0;
311 >  if (!IsChanPrefix(*p))
312 >    return 0;
313  
314 <  return 1;
314 >  if (!local || !ConfigChannel.disable_fake_channels)
315 >  {
316 >    while (*++p)
317 >      if (!IsChanChar(*p))
318 >        return 0;
319 >  }
320 >  else
321 >  {
322 >    while (*++p)
323 >      if (!IsVisibleChanChar(*p))
324 >        return 0;
325 >  }
326 >
327 >  return p - name <= max_length;
328   }
329  
330   void
# Line 348 | Line 337 | remove_ban(struct Ban *bptr, dlink_list
337    MyFree(bptr->host);
338    MyFree(bptr->who);
339  
340 <  BlockHeapFree(ban_heap, bptr);
340 >  mp_pool_release(bptr);
341   }
342  
343   /* free_channel_list()
# Line 370 | Line 359 | free_channel_list(dlink_list *list)
359  
360   /*! \brief Get Channel block for chname (and allocate a new channel
361   *         block, if it didn't exist before)
362 < * \param client_p client pointer
363 < * \param chname   channel name
375 < * \param isnew    pointer to int flag whether channel was newly created or not
376 < * \return channel block or NULL if illegal name
362 > * \param chname channel name
363 > * \return channel block
364   */
365   struct Channel *
366 < get_or_create_channel(struct Client *client_p, const char *chname, int *isnew)
366 > make_channel(const char *chname)
367   {
368    struct Channel *chptr = NULL;
382  int len;
369  
370 <  if (EmptyString(chname))
385 <    return NULL;
370 >  assert(!EmptyString(chname));
371  
372 <  if ((len = strlen(chname)) > CHANNELLEN)
388 <  {
389 <    if (IsServer(client_p))
390 <      sendto_realops_flags(UMODE_DEBUG, L_ALL,
391 <                           "*** Long channel name from %s (%d > %d): %s",
392 <                           client_p->name, len, CHANNELLEN, chname);
393 <    return NULL;
394 <  }
372 >  chptr = mp_pool_get(channel_pool);
373  
374 <  if ((chptr = hash_find_channel(chname)) != NULL)
397 <  {
398 <    if (isnew != NULL)
399 <      *isnew = 0;
400 <
401 <    return chptr;
402 <  }
374 >  memset(chptr, 0, sizeof(*chptr));
375  
404  if (isnew != NULL)
405    *isnew = 1;
406
407  chptr = BlockHeapAlloc(channel_heap);
376    /* doesn't hurt to set it here */
377 <  chptr->channelts = chptr->last_join_time = CurrentTime;
377 >  chptr->channelts = CurrentTime;
378 >  chptr->last_join_time = CurrentTime;
379  
380    strlcpy(chptr->chname, chname, sizeof(chptr->chname));
381    dlinkAdd(chptr, &chptr->node, &global_channel_list);
# Line 432 | Line 401 | destroy_channel(struct Channel *chptr)
401    free_channel_list(&chptr->exceptlist);
402    free_channel_list(&chptr->invexlist);
403  
435  /* Free the topic */
436  free_topic(chptr);
437
404    dlinkDelete(&chptr->node, &global_channel_list);
405    hash_del_channel(chptr);
406  
407 <  if (ServerInfo.hub)
442 <    if ((ptr = dlinkFindDelete(&lazylink_channels, chptr)))
443 <      free_dlink_node(ptr);
444 <
445 <  BlockHeapFree(channel_heap, chptr);
407 >  mp_pool_release(chptr);
408   }
409  
410   /*!
# Line 450 | Line 412 | destroy_channel(struct Channel *chptr)
412   * \return string pointer "=" if public, "@" if secret else "*"
413   */
414   static const char *
415 < channel_pub_or_secret(struct Channel *chptr)
415 > channel_pub_or_secret(const struct Channel *chptr)
416   {
417    if (SecretChannel(chptr))
418      return "@";
# Line 469 | Line 431 | void
431   channel_member_names(struct Client *source_p, struct Channel *chptr,
432                       int show_eon)
433   {
434 <  struct Client *target_p = NULL;
473 <  struct Membership *ms = NULL;
474 <  dlink_node *ptr = NULL;
434 >  const dlink_node *ptr = NULL;
435    char lbuf[IRCD_BUFSIZE + 1];
436    char *t = NULL, *start = NULL;
437    int tlen = 0;
438    int is_member = IsMember(source_p, chptr);
439 +  int multi_prefix = HasCap(source_p, CAP_MULTI_PREFIX) != 0;
440  
441    if (PubChannel(chptr) || is_member)
442    {
443 <    t = lbuf + ircsprintf(lbuf, form_str(RPL_NAMREPLY),
444 <                          me.name, source_p->name,
445 <                          channel_pub_or_secret(chptr),
485 <                          chptr->chname);
443 >    t = lbuf + snprintf(lbuf, sizeof(lbuf), form_str(RPL_NAMREPLY),
444 >                        me.name, source_p->name,
445 >                        channel_pub_or_secret(chptr), chptr->chname);
446      start = t;
447  
448      DLINK_FOREACH(ptr, chptr->members.head)
449      {
450 <      ms       = ptr->data;
491 <      target_p = ms->client_p;
450 >      const struct Membership *ms = ptr->data;
451  
452 <      if (IsInvisible(target_p) && !is_member)
452 >      if (HasUMode(ms->client_p, UMODE_INVISIBLE) && !is_member)
453          continue;
454  
455 <      tlen = strlen(target_p->name) + 1;  /* nick + space */
455 >      tlen = strlen(ms->client_p->name) + 1;  /* nick + space */
456 >
457 >      if (!multi_prefix)
458 >      {
459 >        if (ms->flags & (CHFL_CHANOP | CHFL_HALFOP | CHFL_VOICE))
460 >          ++tlen;
461 >      }
462 >      else
463 >      {
464 >        if (ms->flags & CHFL_CHANOP)
465 >          ++tlen;
466 >        if (ms->flags & CHFL_HALFOP)
467 >          ++tlen;
468 >        if (ms->flags & CHFL_VOICE)
469 >          ++tlen;
470 >      }
471  
472 <      if (ms->flags & (CHFL_CHANOP | CHFL_HALFOP | CHFL_VOICE))
499 <        ++tlen;
500 <      if (t + tlen - lbuf > IRCD_BUFSIZE)
472 >      if (t + tlen - lbuf > IRCD_BUFSIZE - 2)
473        {
474          *(t - 1) = '\0';
475          sendto_one(source_p, "%s", lbuf);
476          t = start;
477        }
478  
479 <      t += ircsprintf(t, "%s%s ", get_member_status(ms, NO),
480 <                      target_p->name);
479 >      t += sprintf(t, "%s%s ", get_member_status(ms, multi_prefix),
480 >                   ms->client_p->name);
481      }
482  
483      if (tlen != 0)
# Line 617 | Line 589 | find_bmask(const struct Client *who, con
589  
590    DLINK_FOREACH(ptr, list->head)
591    {
592 <    struct Ban *bp = ptr->data;
592 >    const struct Ban *bp = ptr->data;
593  
594 <    if (match(bp->name, who->name) && match(bp->username, who->username))
594 >    if (!match(bp->name, who->name) && !match(bp->username, who->username))
595      {
596        switch (bp->type)
597        {
598          case HM_HOST:
599 <          if (match(bp->host, who->host) || match(bp->host, who->sockhost))
599 >          if (!match(bp->host, who->host) || !match(bp->host, who->sockhost))
600              return 1;
601            break;
602          case HM_IPV4:
# Line 654 | Line 626 | find_bmask(const struct Client *who, con
626   * \return 0 if not banned, 1 otherwise
627   */
628   int
629 < is_banned(struct Channel *chptr, struct Client *who)
629 > is_banned(const struct Channel *chptr, const struct Client *who)
630   {
631 <  assert(IsClient(who));
631 >  if (find_bmask(who, &chptr->banlist))
632 >    if (!find_bmask(who, &chptr->exceptlist))
633 >      return 1;
634  
635 <  return find_bmask(who, &chptr->banlist) && (!ConfigChannel.use_except ||
662 <         !find_bmask(who, &chptr->exceptlist));
635 >  return 0;
636   }
637  
638   /*!
# Line 672 | Line 645 | is_banned(struct Channel *chptr, struct
645   int
646   can_join(struct Client *source_p, struct Channel *chptr, const char *key)
647   {
648 <  if (find_bmask(source_p, &chptr->banlist))
649 <    if (!ConfigChannel.use_except || !find_bmask(source_p, &chptr->exceptlist))
650 <      return ERR_BANNEDFROMCHAN;
648 >  if (is_banned(chptr, source_p))
649 >    return ERR_BANNEDFROMCHAN;
650 >
651 > #ifdef HAVE_LIBCRYPTO
652 >  if ((chptr->mode.mode & MODE_SSLONLY) && !source_p->localClient->fd.ssl)
653 >    return ERR_SSLONLYCHAN;
654 > #endif
655 >
656 >  if ((chptr->mode.mode & MODE_REGONLY) && !HasUMode(source_p, UMODE_REGISTERED))
657 >    return ERR_NEEDREGGEDNICK;
658 >
659 >  if ((chptr->mode.mode & MODE_OPERONLY) && !HasUMode(source_p, UMODE_OPER))
660 >    return ERR_OPERONLYCHAN;
661  
662    if (chptr->mode.mode & MODE_INVITEONLY)
663      if (!dlinkFind(&source_p->localClient->invited, chptr))
664 <      if (!ConfigChannel.use_invex || !find_bmask(source_p, &chptr->invexlist))
664 >      if (!find_bmask(source_p, &chptr->invexlist))
665          return ERR_INVITEONLYCHAN;
666  
667 <  if (chptr->mode.key[0] && (EmptyString(key) || irccmp(chptr->mode.key, key)))
667 >  if (chptr->mode.key[0] && (!key || strcmp(chptr->mode.key, key)))
668      return ERR_BADCHANNELKEY;
669  
670    if (chptr->mode.limit && dlink_list_length(&chptr->members) >=
# Line 692 | Line 675 | can_join(struct Client *source_p, struct
675   }
676  
677   int
678 < has_member_flags(struct Membership *ms, unsigned int flags)
678 > has_member_flags(const struct Membership *ms, const unsigned int flags)
679   {
680    if (ms != NULL)
681      return ms->flags & flags;
# Line 709 | Line 692 | find_channel_link(struct Client *client_
692  
693    DLINK_FOREACH(ptr, client_p->channel.head)
694      if (((struct Membership *)ptr->data)->chptr == chptr)
695 <      return (struct Membership *)ptr->data;
695 >      return ptr->data;
696  
697    return NULL;
698   }
# Line 717 | Line 700 | find_channel_link(struct Client *client_
700   /*!
701   * \param chptr    pointer to Channel struct
702   * \param source_p pointer to Client struct
703 + * \param ms       pointer to Membership struct (can be NULL)
704   * \return CAN_SEND_OPV if op or voiced on channel\n
705   *         CAN_SEND_NONOP if can send to channel but is not an op\n
706 < *         CAN_SEND_NO if they cannot send to channel\n
706 > *         ERR_CANNOTSENDTOCHAN or ERR_NEEDREGGEDNICK if they cannot send to channel\n
707   */
708   int
709 < can_send(struct Channel *chptr, struct Client *source_p)
709 > can_send(struct Channel *chptr, struct Client *source_p, struct Membership *ms)
710   {
711 <  struct Membership *ms = NULL;
711 >  struct MaskItem *conf = NULL;
712  
713 <  if (IsServer(source_p))
713 >  if (IsServer(source_p) || HasFlag(source_p, FLAGS_SERVICE))
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 (!(HasUMode(source_p, UMODE_OPER) && ConfigFileEntry.oper_pass_resv))
718 >      if ((conf = match_find_resv(chptr->chname)) && !resv_find_exempt(source_p, conf))
719 >        return ERR_CANNOTSENDTOCHAN;
720  
721 <  if ((ms = find_channel_link(source_p, chptr)) == NULL)
738 <  {
739 <    if (chptr->mode.mode & MODE_NOPRIVMSGS)
740 <      return CAN_SEND_NO;
741 <  }
742 <  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 748 | Line 727 | can_send(struct Channel *chptr, struct C
727      if (ConfigChannel.quiet_on_ban && MyClient(source_p))
728      {
729        if (ms->flags & CHFL_BAN_SILENCED)
730 <        return CAN_SEND_NO;
730 >        return ERR_CANNOTSENDTOCHAN;
731  
732        if (!(ms->flags & CHFL_BAN_CHECKED))
733        {
734          if (is_banned(chptr, source_p))
735          {
736            ms->flags |= (CHFL_BAN_CHECKED|CHFL_BAN_SILENCED);
737 <          return CAN_SEND_NO;
737 >          return ERR_CANNOTSENDTOCHAN;
738          }
739  
740          ms->flags |= CHFL_BAN_CHECKED;
741        }
742      }
743    }
744 +  else if (chptr->mode.mode & MODE_NOPRIVMSGS)
745 +    return ERR_CANNOTSENDTOCHAN;
746  
747    if (chptr->mode.mode & MODE_MODERATED)
748 <    return CAN_SEND_NO;
768 <
769 <  return CAN_SEND_NONOP;
770 < }
771 <
772 < /*! \brief Checks to see if given client can send a part message
773 < * \param member     pointer to channel membership
774 < * \param chptr      pointer to channel struct
775 < * \param source_p   pointer to struct Client to check
776 < */
777 < int
778 < can_send_part(struct Membership *member, struct Channel *chptr,
779 <              struct Client *source_p)
780 < {
781 <  if (has_member_flags(member, CHFL_CHANOP|CHFL_HALFOP))
782 <    return CAN_SEND_OPV;
783 <
784 <  if (chptr->mode.mode & MODE_MODERATED)
785 <    return CAN_SEND_NO;
786 <
787 <  if (ConfigChannel.quiet_on_ban && MyClient(source_p) &&
788 <      is_banned(chptr, source_p))
789 <    return CAN_SEND_NO;
748 >    return ERR_CANNOTSENDTOCHAN;
749  
750    return CAN_SEND_NONOP;
751   }
# Line 816 | Line 775 | check_spambot_warning(struct Client *sou
775      {
776        /* Its already known as a possible spambot */
777        if (name != NULL)
778 <        sendto_realops_flags(UMODE_BOTS, L_ALL,
778 >        sendto_realops_flags(UMODE_BOTS, L_ALL, SEND_NOTICE,
779                               "User %s (%s@%s) trying to join %s is a possible spambot",
780                               source_p->name, source_p->username,
781                               source_p->host, name);
782        else
783 <        sendto_realops_flags(UMODE_BOTS, L_ALL,
783 >        sendto_realops_flags(UMODE_BOTS, L_ALL, SEND_NOTICE,
784                               "User %s (%s@%s) is a possible spambot",
785                               source_p->name, source_p->username,
786                               source_p->host);
# Line 872 | Line 831 | check_splitmode(void *unused)
831      {
832        splitmode = 1;
833  
834 <      sendto_realops_flags(UMODE_ALL,L_ALL,
834 >      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
835                             "Network split, activating splitmode");
836        eventAddIsh("check_splitmode", check_splitmode, NULL, 10);
837      }
# Line 880 | Line 839 | check_splitmode(void *unused)
839      {
840        splitmode = 0;
841  
842 <      sendto_realops_flags(UMODE_ALL, L_ALL,
842 >      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
843                             "Network rejoined, deactivating splitmode");
844        eventDelete(check_splitmode, NULL);
845      }
846    }
847   }
848  
890 /*! \brief Allocates a new topic
891 * \param chptr Channel to allocate a new topic for
892 */
893 static void
894 allocate_topic(struct Channel *chptr)
895 {
896  void *ptr = NULL;
897
898  if (chptr == NULL)
899    return;
900
901  ptr = BlockHeapAlloc(topic_heap);  
902
903  /* Basically we allocate one large block for the topic and
904   * the topic info.  We then split it up into two and shove it
905   * in the chptr
906   */
907  chptr->topic       = ptr;
908  chptr->topic_info  = (char *)ptr + TOPICLEN+1;
909  *chptr->topic      = '\0';
910  *chptr->topic_info = '\0';
911 }
912
913 void
914 free_topic(struct Channel *chptr)
915 {
916  void *ptr = NULL;
917  assert(chptr);
918  if (chptr->topic == NULL)
919    return;
920
921  /*
922   * If you change allocate_topic you MUST change this as well
923   */
924  ptr = chptr->topic;
925  BlockHeapFree(topic_heap, ptr);    
926  chptr->topic      = NULL;
927  chptr->topic_info = NULL;
928 }
929
849   /*! \brief Sets the channel topic for chptr
850   * \param chptr      Pointer to struct Channel
851   * \param topic      The topic string
# Line 935 | Line 854 | free_topic(struct Channel *chptr)
854   */
855   void
856   set_channel_topic(struct Channel *chptr, const char *topic,
857 <                  const char *topic_info, time_t topicts)
857 >                  const char *topic_info, time_t topicts, int local)
858   {
859 <  if (!EmptyString(topic))
860 <  {
942 <    if (chptr->topic == NULL)
943 <      allocate_topic(chptr);
944 <
945 <    strlcpy(chptr->topic, topic, TOPICLEN+1);
946 <    strlcpy(chptr->topic_info, topic_info, USERHOST_REPLYLEN);
947 <    chptr->topic_time = topicts;
948 <  }
859 >  if (local)
860 >    strlcpy(chptr->topic, topic, IRCD_MIN(sizeof(chptr->topic), ServerInfo.max_topic_length + 1));
861    else
862 <  {
863 <    /*
864 <     * Do not reset chptr->topic_time here, it's required for
865 <     * bursting topics properly.
954 <     */
955 <    if (chptr->topic != NULL)
956 <      free_topic(chptr);
957 <  }
862 >    strlcpy(chptr->topic, topic, sizeof(chptr->topic));
863 >
864 >  strlcpy(chptr->topic_info, topic_info, sizeof(chptr->topic_info));
865 >  chptr->topic_time = topicts;
866   }

Diff Legend

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