Logo Search packages:      
Sourcecode: rageircd version File versions  Download package

m_join.c

/*
 * RageIRCd: an advanced Internet Relay Chat daemon (ircd).
 * (C) 2000-2005 the RageIRCd Development Team, all rights reserved.
 *
 * This software is free, licensed under the General Public License.
 * Please refer to doc/LICENSE and doc/README for further details.
 *
 * $Id: m_join.c,v 1.83.2.3 2005/01/15 23:53:30 amcwilliam Exp $
 */

#include "config.h"
#include "struct.h"
#include "common.h"
#include "sys.h"
#include "numeric.h"
#include "msg.h"
#include "channel.h"
#include "h.h"
#include "memory.h"
#include "send.h"
#include "hook.h"
#include "modules.h"
#include "xmode.h"
#include "user_ban.h"
#include <time.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>

Hook *h_pre_join = NULL;
Hook *h_post_join = NULL;

static int auto_join_connect(HookData *);
static int auto_join_oper(HookData *);

Module MOD_HEADER(m_join) = {
      "m_join",
      "/JOIN command",
      6, "$Revision: 1.83.2.3 $"
};

int MOD_LOAD(m_join)()
{
      Hook *h;
      
      if ((h_pre_join = register_hook(&MOD_HEADER(m_join), "h_pre_join")) == NULL) {
            return MOD_FAILURE;
      }
      if ((h_post_join = register_hook(&MOD_HEADER(m_join), "h_post_join")) == NULL) {
            return MOD_FAILURE;
      }

      if (register_hook_event(&MOD_HEADER(m_join), h_post_register_user, auto_join_connect) == NULL) {
            return MOD_FAILURE;
      }
      
      if ((h = hook_find("h_post_oper")) == NULL) {
            ircdlog(LOG_ERROR, "m_join.so: cannot find h_post_oper hook");
            return MOD_FAILURE;
      }
      if (register_hook_event(&MOD_HEADER(m_join), h, auto_join_oper) == NULL) {
            return MOD_FAILURE;
      }

      if (register_command(&MOD_HEADER(m_join), &CMD_JOIN, m_join) == NULL) {
            return MOD_FAILURE;
      }

      MOD_SET_FLAG(&MOD_HEADER(m_join), MOD_FLAG_PERM);
      return MOD_SUCCESS;
}

int MOD_UNLOAD(m_join)()
{
      return MOD_SUCCESS;
}

static int auto_join_connect(HookData *hdata)
{
      if (!BadPtr(GeneralConfig.join_on_connect)) {
            char *parv[3] = { hdata->sptr->name, GeneralConfig.join_on_connect, NULL };
            m_join(hdata->sptr, hdata->sptr, 2, parv);
      }
      return 0;
}

static int auto_join_oper(HookData *hdata)
{
      ConfigItem_oper *oper = (ConfigItem_oper *)hdata->v;

      if (!BadPtr(oper->join_on_oper)) {
            char *parv[3] = { hdata->sptr->name, oper->join_on_oper, NULL };
            m_join(hdata->sptr, hdata->sptr, 2, parv);
      }
      return 0;
}

static void part_all_channels(aClient *sptr)
{
      chanMember *cm = NULL;

      while ((cm = sptr->user->channel) != NULL) {
            sendto_channel_local_msg_butone(NULL, sptr, cm->chptr, ALL_MEMBERS,
                  &CMD_PART, "%s", cm->chptr->chname);
            remove_user_from_channel(sptr, cm->chptr);
      }

      if (!HasMode(sptr, UMODE_OPER) && MyConnect(sptr)) {
            check_for_spambot(sptr, NULL);
      }

      sendto_serv_msg_butone(sptr, sptr, &CMD_JOIN, "0");
}

static int verify_local_join(aClient *sptr, char *chname, int flags)
{
      if (!HasMode(sptr, UMODE_OPER)) {
            if (sptr->user->joined >= GeneralConfig.max_chans_per_user) {
                  send_me_numeric(sptr, ERR_TOOMANYCHANNELS, chname);
                  return 0;
            }

            if (flags && !GeneralConfig.custom_channels) {
                  send_me_numeric(sptr, ERR_FUNCDISABLED, "JOIN");
                  return 0;
            }

            if (!check_for_spambot(sptr, chname) && FloodConfig.spambot_squelch_time) {
                  return 0;
            }
      }

      if (!HasMode(sptr, UMODE_ADMIN)) {
            simBan *sban;

            if ((sban = find_simban_flags(chname, SBAN_CHAN)) != NULL) {
                  send_me_numeric(sptr, ERR_CHANBANREASON, chname, BanReason(sban));
                  return 0;
            }
      }

      return 1;
}

/*
 * m_join
 *    parv[0] = sender prefix
 *    parv[1] = channel name
 *    parv[2] = channel password (key)
 */
int m_join(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
      static char jbuf[BUFSIZE];
      char *name, *key = NULL, *p, *p2, *j = jbuf;
      aChannel *chptr;
      int flags = 0, len = 0, joined = 0, i;
      HookData hdata = HOOKDATA_INIT;

      ASSERT(sptr->user != NULL);

      if (parc < 2 || *parv[1] == '\0') {
            send_me_numeric(sptr, ERR_NEEDMOREPARAMS, "JOIN");
            return 0;
      }

      *j = '\0';

      for (name = strtoken(&p, parv[1], ","); name != NULL; name = strtoken(&p, NULL, ",")) {
            if (!check_fake_channel_name(sptr, name)) {
                  send_me_numeric(sptr, ERR_BADCHANNAME, name);
                  continue;
            }

            len = strlen(name);
            if (len > CHANNELLEN) {
                  name[CHANNELLEN] = '\0';
                  len = CHANNELLEN;
            }

            if ((*name == '0') && !atoi(name)) {
                  jbuf[0] = '0';
                  jbuf[1] = '\0';
                  j = jbuf;
                  continue;
            }
            else if (!IsChanPrefix(*name)) {
                  send_me_numeric(sptr, ERR_NOSUCHCHANNEL, name);
                  continue;
            }

            if (*jbuf != '\0') {
                  *j++ = ',';
            }
            while (*name != '\0') {
                  *j++ = *name++;
            }
      }

      *j = '\0';

      if (!BadPtr(parv[2])) {
            key = strtoken(&p2, parv[2], ",");
      }

      parv[2] = NULL;
      p = NULL;

      hdata.sptr = sptr;

      for (name = strtoken(&p, jbuf, ","); name != NULL;
        key = (key != NULL) ? strtoken(&p2, NULL, ",") : NULL, name = strtoken(&p, NULL, ",")) {
            if (*name == '0' && !atoi(name)) {
                  if (sptr->user->channel != NULL) {
                        part_all_channels(sptr);
                  }
                  continue;
            }

            if (!MyConnect(sptr)) {
                  ircdlog(LOG_ERROR, "Ignoring JOIN %s from remote client %s", name,
                        get_client_name(sptr, FALSE));
                  continue;
            }

            if ((chptr = find_channel(name, NULL)) != NULL) {
                  if (IsMember(sptr, chptr)) {
                        continue;
                  }
                  flags = 0;
            }
            else {
                  flags = CMODE_CHANOP;
            }

            if (!verify_local_join(sptr, name, flags)) {
                  continue;
            }

            hdata.c = name;
            hdata.i = flags;
            hdata.chptr = chptr;

            if (hook_run_until(h_pre_join, &hdata, FLUSH_BUFFER) == FLUSH_BUFFER) {
                  continue;
            }

            if (chptr == NULL) {
                  chptr = get_channel(sptr, name, CREATE, NULL);
                  chptr->channelts = timeofday;
            }
            else {
                  if ((i = can_join(sptr, chptr, key))) {
                        send_me_numeric(sptr, i, name, (i == ERR_NEEDREGGEDNICK) ? "join" : "");
                        continue;
                  }

                  del_invite(sptr, chptr);
                  joined++;
            }

            add_user_to_channel(chptr, sptr, flags);

            /* Only broadcast joins for non-local channels */
            if (*name != '&') {
                  if (flags & CMODE_CHANOP) {
                        sendto_serv_capab_msg_butone(cptr, &me, NO_CAPS, ID_CAPS, &CMD_SJOIN,
                              "%ld %s + :@%s", chptr->channelts, chptr->chname, sptr->name);
                        sendto_serv_capab_msg_butone(cptr, &me, ID_CAPS, NO_CAPS, &CMD_SJOIN,
                              "%B %s + :@%s", chptr->channelts, chptr->chname, get_id(sptr));
                  }
                  else {
                        sendto_serv_msg_butone(cptr, sptr, &CMD_SJOIN, "%ld %s", chptr->channelts,
                              chptr->chname);
                  }
            }

            sendto_channel_local_msg_butone(NULL, sptr, chptr, ALL_MEMBERS, &CMD_JOIN,
                  "%s", chptr->chname);

            if (*chptr->topic != '\0') {
                  send_me_numeric(sptr, RPL_TOPIC, name, chptr->topic);
                  send_me_numeric(sptr, RPL_TOPICWHOTIME, name, chptr->topic_nick, chptr->topic_time);
            }

            hdata.chptr = chptr; /* chptr may have been null for h_pre_join */
            hook_run(h_post_join, &hdata);
      }

      if (MyClient(sptr) && (joined > 0)) {
            sptr->localUser->last_join_time = timeofday;
      }

      return 0;
}

Generated by  Doxygen 1.6.0   Back to index