/*****************************************************************
 * PTlink IRCd is (C) CopyRight PTlink Coders Team 1999-2000     *
 * http://www.ptlink.net/Coders - coders@PTlink.net              *
 * This program is distributed under GNU Public License          *
 * Please read the file COPYING for copyright information.       *
 *****************************************************************
 
 File: spam.c
 Desc: anti-spam system
 Author: after@papofacil.net
  
*/

#include "m_commands.h"
#include "client.h"
#include "common.h"
#include "ircd.h"
#include "numeric.h"
#include "s_serv.h"
#include "irc_string.h"
#include "send.h"
#include "s_conf.h"
#include "struct.h"
#include "conf_vars.h"
#include "m_svsinfo.h"

#include <stdlib.h> 
#include <string.h>

typedef struct spam_ spam;
struct spam_ {
    spam *next;
    char *mask;
    char *reason;
};

static struct spam_ *spamlist = (struct spam_ *)NULL;

char *rem_codes(char *text)
{
    static char nocodes[512];
    char *t = text;
    char *a = nocodes;

        while (*t) {
            switch (*t) {
                case 2: //bold
                    t++;
                    continue;
                break;
                case 3: //mIRC colors
                    if (isdigit(t[1])) { /* Is the first char a number? */
                        t += 2;            /* Skip over the ^C and the first digit */
                        if (isdigit(*t))
                            t++;             /* Is this a double digit number? */
                        if (*t == ',') {   /* Do we have a background color next? */
                            if (isdigit(t[1]))
                                t += 2;        /* Skip over the first background digit */
                            if (isdigit(*t))
                                t++;           /* Is it a double digit? */
                        }
                    } else
                          t++;
                    continue;
                break;
                case 7:
                    t++;
                    continue;
                case 32:
                    t++;
                    continue;
                break;
                case 0x16:
                    t++;
                    continue;
                break;
                case 0x1f:
                    t++;
                    continue;
                break;
            }
            *a++ = tolower(*t++);
        }
        *a = 0;
        return nocodes;
}

char *is_spam2(char *text) {
    spam *sp = spamlist;

    while (sp) {
        if (match_wild_nocase(sp->mask, text)) {
            return sp->reason;
        }
        sp = sp->next;
    }
    return (char *)NULL;
}

struct spam_ *find_spamrule(char *server)
{
        spam *sp = spamlist;

        while(sp && !match(sp->mask, server))
          sp = sp->next;

        if (!sp) {
            sp = spamlist;
            while(sp && !match(sp->mask, server))
              sp = sp->next;
        }

        return sp;
}

int     m_spamadd(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
  {
    spam *sp = spamlist, *last_sp;

        if (!IsServer(sptr) && !IsService(sptr) && !IsRoot(sptr)) 
	  {	
		if (IsServer(cptr))
		  { 
                        ts_warn("Got SPAMADD from non-service/server: %s", 
			  sptr->name);
                        sendto_one(cptr, ":%s WALLOPS :ignoring SPAMADD from non-service/server %s",
			  me.name, sptr->name);
		}		
            if(MyClient(sptr))
              sendto_one(sptr,form_str(ERR_NOPRIVILEGES),
                  MENAME(sptr), parv[0]);
		return 0;
	  }

    if(parc<3)
        return 0;

       while (sp && (match(sp->mask, parv[1]) != 0)) {
           last_sp = sp;
           sp = sp->next;
       }

    if (!find_spamrule(parv[1])) // nao encontrou
	{
		sp = MyMalloc(sizeof(spam));
                DupString(sp->mask, parv[1]);
                DupString(sp->reason, parv[2]);

            sp->next = spamlist;
            spamlist = sp;

            sendto_serv_butone(cptr, ":%s SPAMADD %s :%s", parv[0], parv[1], parv[2]);

            if (MyClient(sptr))
                sendto_sanotice("%s added spam rule for '%s' (%s)", parv[0], parv[1], parv[2]);
	  }
	return 0;
  }


int     m_spamdel(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
  {
        spam *last_sp;
	spam *sp = spamlist;
		
        if (!IsServer(sptr) && !IsService(sptr) && !IsRoot(sptr)) 
	  {	
		if (IsServer(cptr))
		  { 
                        ts_warn("Got SPAMDEL from non-service/server: %s", 
			  sptr->name);
                        sendto_one(cptr, ":%s WALLOPS :ignoring SPAMDEL from non-service/server %s",
			  me.name, sptr->name);
		}		
		return 0;
	  }

        if(parc<2)
	  return 0;

	last_sp = NULL;

	while (sp && irccmp(sp->mask, parv[1])) {
           last_sp = sp;
           sp = sp->next;
       }

       if (sp) { //achou
           if (last_sp)
               last_sp->next = sp->next;
           else
               spamlist = sp->next;

                if (MyClient(sptr)) {
                    my_svsinfo_ts = CurrentTime;
                    sendto_sanotice("%s deleted spam rule for '%s'", parv[0], parv[1]);
                }
                sendto_serv_butone(cptr, ":%s SPAMDEL %s", parv[0], parv[1]);

           free(sp->mask);
           free(sp->reason);
           free(sp);

	  }
	  
	return 0;
  }

void send_all_spamrules(struct Client *acptr)
  {
        spam *sp = spamlist;
	
        while(sp)
	  {
              sendto_one(acptr, ":%s SPAMADD %s :%s", me.name, sp->mask, sp->reason );
              sp = sp->next;         
	  }
  }


void clear_spamrules()
  {

    spam *sp;
    spam *sp2=spamlist;

       while(sp2)
         {
               sp = sp2->next;
               free(sp2->mask);
	       free(sp2->reason);
	       free(sp2);
               sp2 = sp;
               }

       spamlist = NULL;

  }



void report_spamrules(struct Client *sptr)
{
    spam *sp = spamlist;
 
    sendto_one(sptr, ":%s NOTICE %s :************* SPAM Rules *************", me.name, sptr->name);
    while (sp) {
    sendto_one(sptr, ":%s NOTICE %s :Mask: %-20s Reason: %s", me.name, sptr->name, sp->mask, sp->reason); 
    sp = sp->next;
    }
}
