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

m_accept.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_accept.c,v 1.40.2.3 2005/07/10 23:05:00 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 "hook.h"
#include "dlink.h"
#include "modules.h"
#include "xmode.h"
#include <time.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>

static int accept_msg(HookData *);
static int del_accepts(HookData *);

Module MOD_HEADER(m_accept) = {
      "m_accept",
      "/ACCEPT command",
      6, "$Revision: 1.40.2.3 $"
};

int MOD_LOAD(m_accept)()
{
      Hook *h1, *h2, *h3, *h4;

      if ((h1 = hook_find("h_usermsg")) == NULL) {
            ircdlog(LOG_ERROR, "m_accept.so: couldn't find hook h_usermsg");
            return MOD_FAILURE;
      }
      if ((h2 = hook_find("h_nick_change_local")) == NULL) {
            ircdlog(LOG_ERROR, "m_accept.so: couldn't find hook h_nick_change_local");
            return MOD_FAILURE;
      }
      if ((h3 = hook_find("h_nick_change_remote")) == NULL) {
            ircdlog(LOG_ERROR, "m_accept.so: couldn't find hook h_nick_change_remote");
            return MOD_FAILURE;
      }
      if ((h4 = hook_find("h_usermsg_remote")) == NULL) {
            ircdlog(LOG_ERROR, "m_accept.so: couldn't find hook h_usermsg_remote");
            return MOD_FAILURE;
      }

      if (register_command(&MOD_HEADER(m_accept), &CMD_ACCEPT, m_accept) == NULL) {
            return MOD_FAILURE;
      }

      if (register_hook_event(&MOD_HEADER(m_accept), h1, accept_msg) == NULL) {
            /* h_usermsg */
            return MOD_FAILURE;
      }
      if (register_hook_event(&MOD_HEADER(m_accept), h2, del_accepts) == NULL) {
            /* h_nick_change_local */
            return MOD_FAILURE;
      }
      if (register_hook_event(&MOD_HEADER(m_accept), h3, del_accepts) == NULL) {
            /* h_nick_change_remote */
            return MOD_FAILURE;
      }
      if (register_hook_event(&MOD_HEADER(m_accept), h4, accept_msg) == NULL) {
            /* h_usermsg_remote */
            return MOD_FAILURE;
      }
      if (register_hook_event(&MOD_HEADER(m_accept), h_exit_user_local, del_accepts) == NULL) {
            return MOD_FAILURE;
      }

      return MOD_SUCCESS;
}

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

static int accept_msg(HookData *hdata)
{
      aClient *from = hdata->sptr;
      aClient *to = hdata->acptr;

      if (to == from || !IsPerson(from) || IsULine(from) || !MyClient(to)) {
            return 0;
      }
      if (!HasMode(to, UMODE_PRIVACY) || (GeneralConfig.no_oper_accept && HasMode(from, UMODE_OPER))) {
            return 0;
      }

      if (dlink_find(&to->user->accept_list, (void *)from) != NULL) {
            return 0;
      }

      send_me_numeric(from, ERR_PRIVATETARG, to->name);

      /* hdata->i is 1 if this is a notice, 0 otherwise */
      if (!hdata->i && ((timeofday - to->user->last_accept_notice) >= FloodConfig.accept_notice_time)) {
            send_me_numeric(from, RPL_NOTIFYTARG, to->name);
            send_me_numeric(to, RPL_MSGTARG, from->name, from->username, MaskedHost(from));
            to->user->last_accept_notice = timeofday;
      }

      return FLUSH_BUFFER;
}

static void show_accept_list(aClient *cptr)
{
      dlink_node *node;
      aClient *acptr;
      char buf[BUFSIZE], *s;
      int len = 0, plen = strlen(cptr->name) + 10, count = 0;

      DLINK_FOREACH_DATA(cptr->user->accept_list.head, node, acptr, aClient) {
            if ((plen + len + strlen(acptr->name) + 1) > BUFSIZE || count > 10) {
                  send_me_numeric(cptr, RPL_ACCEPTLIST, buf);
                  buf[0] = '\0';
                  len = count = 0;
            }
            if (len > 0) {
                  buf[len++] = ' ';
            }
            for (s = acptr->name; *s != '\0'; s++) {
                  buf[len++] = *s;
            }
            buf[len] = '\0';
            count++;
      }
      if (count > 0) {
            send_me_numeric(cptr, RPL_ACCEPTLIST, buf);
      }
      send_me_numericNA(cptr, RPL_ENDOFACCEPT);
}

static void show_accept_help(aClient *cptr)
{
      char **p;
      static char *helptext[] = {
            "/ACCEPT [-]nick[,[-]nick2[,[-]nick3[...]]]",
            "/ACCEPT <*|?>",
            " ",
            "If you are in privacy mode (usermode +p), you can still receive private",
            "messages by accepting users. This is done via the ACCEPT command (syntax",
            "above).",
            " ",
            "For example; if you are in privacy mode (+p), but want to accept any",
            "privmsgs from client Bob, you would issue the following command.",
            " ",
            "/ACCEPT Bob",
            " ",
            "However, you then decide you want to block privmsgs from Bob again. You",
            "simply remove him from your accept list. Syntax is similar to that of",
            "adding clients, but you prefix the nickname with a - (subtract) char.",
            " ",
            "/ACCEPT -Bob",
            " ",
            "You can add and remove more than one client to and from your accept list",
            "at once. Just separate your client list with , (commas), as per the",
            "following example.",
            " ",
            "/ACCEPT Bob,-Joe,-Lisa,Homer",
            " ",
            "NB. If a client on your accept list quits, is lost in a netsplit, or",
            "    changes his or her nickname, all references within your accept list",
            "    to that client will be removed. This functionality prevents users",
            "    being tracked.",
            " ",
            "To view all clients on your accept list, issue an ACCEPT command with",
            "an * (asterisk) as parameter. To view this help, issue an ACCEPT command",
            "with a ? (question mark). You cannot mix *, ? and/or nicknames together.",
            NULL
      };

      for (p = helptext; *p != '\0'; p++) {
            send_me_numeric(cptr, RPL_ACCEPTLIST, *p);
      }
      send_me_numericNA(cptr, RPL_ENDOFACCEPT);
}

static void add_accept(aClient *sptr, aClient *acptr)
{
      dlink_add(&sptr->user->accept_list, acptr);
      dlink_add(&acptr->user->on_accept_list, sptr);
}

static void del_accept(aClient *sptr, aClient *acptr)
{
      dlink_node *anode, *anext = NULL;
      dlink_node *node, *next = NULL;
      aClient *cptr;

      DLINK_FOREACH_SAFE_DATA(acptr->user->accept_list.head, anode, anext, cptr, aClient) {
            if (sptr != cptr) {
                  continue;
            }

            dlink_del(&acptr->user->accept_list, NULL, anode);
            DLINK_FOREACH_SAFE_DATA(sptr->user->on_accept_list.head, node, next, cptr, aClient) {
                  if (acptr == cptr) {
                        dlink_del(&sptr->user->on_accept_list, NULL, node);
                  }
            }
      }
}

static int del_accepts(HookData *hdata)
{
      aClient *sptr = hdata->sptr;
      aClient *acptr = NULL;
      dlink_node *node, *next = NULL;

      DLINK_FOREACH_SAFE_DATA(sptr->user->accept_list.head, node, next, acptr, aClient) {
            if (acptr != NULL) {
                  del_accept(acptr, sptr);
            }
      }
      DLINK_FOREACH_SAFE_DATA(sptr->user->on_accept_list.head, node, next, acptr, aClient) {
            if (acptr != NULL) {
                  del_accept(sptr, acptr);
            }
      }
      return 0;
}

/*
 * m_accept
 *    parv[0] = sender prefix
 *    parv[1] = parameter
 */
int m_accept(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
      char *s, *p;
      aClient *acptr;
      int del;

      if (!MyClient(sptr)) {
            return 0;
      }
      if (parc < 2 || BadPtr(parv[1])) {
            send_me_numeric(sptr, ERR_NEEDMOREPARAMS, "ACCEPT");
            return 0;
      }
      if (*parv[1] == '*') {
            show_accept_list(sptr);
            return 0;
      }
      else if (*parv[1] == '?') {
            show_accept_help(sptr);
            return 0;
      }

      for (s = strtoken(&p, parv[1], ","); s != NULL; s = strtoken(&p, NULL, ",")) {
            while (IsSpace(*s)) {
                  s++;
            }
            if (BadPtr(s)) {
                  continue;
            }

            if (*s == '-') {
                  del = 1;
                  s++;
            }
            else {
                  del = 0;
                  if (*s == '+') {
                        s++;
                  }
            }

            /* If we are adding, make sure we have space */
            if (!del && (GeneralConfig.max_accept > 0)) {
                  if (dlink_length(&sptr->user->accept_list) >= GeneralConfig.max_accept) {
                        send_me_numeric(sptr, ERR_ACCEPTFULL, sptr->name, GeneralConfig.max_accept);
                        continue;
                  }
            }

            if ((acptr = find_person(s, NULL)) == NULL) {
                  send_me_numeric(sptr, ERR_NOSUCHNICK, s);
                  continue;
            }
            else if (acptr == sptr) {
                  continue;
            }

            if (del) {
                  if (dlink_find(&sptr->user->accept_list, acptr) == NULL) {
                        send_me_numeric(sptr, ERR_ACCEPTNOT, acptr->name);
                  }
                  else {
                        del_accept(acptr, sptr);
                  }
            }
            else {
                  if (dlink_find(&sptr->user->accept_list, acptr) != NULL) {
                        send_me_numeric(sptr, ERR_ACCEPTEXISTS, acptr->name);
                  }
                  else {
                        add_accept(sptr, acptr);
                  }
            }
      }

      return 0;
}

Generated by  Doxygen 1.6.0   Back to index