/*****************************************************************
 * 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: stline.c
 Desc: services V:lines
 Author: Lamego@PTlink.net modified for stlines by hardman@brasillink.org
  
*/

#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 "stline.h"
#include "conf_vars.h"
#include "m_svsinfo.h" /* for my_svsinfo_ts */ 
#include "s_user.h" /* for valid_hostname */

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


/* stlines storage */
aConfItem *stlines = (aConfItem *)NULL;

/*
 * m_stline() - add stlines
 *
 *	parv[0] = sender prefix
 *      parv[1] = real name of the server (irc.t7ds.com.br)
 *      parv[2] = virtual name of it
 *      parv[3] = its description
 */
int     m_stline(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
  {
    aConfItem *aconf;
    char *p;
    char name[HOSTLEN+1];

        if (!IsServer(sptr) && !IsService(sptr) && !IsSAdmin(sptr)) 
	  {	
		if (IsServer(cptr))
		  { 
                        ts_warn("Got stline from non-service/server: %s", 
			  sptr->name);
                        sendto_one(cptr, ":%s WALLOPS :ignoring STLINE 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<4)
        return 0;

    if ((strlen(parv[1]) != 2) && (!valid_hostname(parv[1]))) {
        sendto_realops_flags(FLAGS_DEBUG, "Wrong stline real name: %s From %s", parv[1], parv[0]);
        return 0;
    }
    if (!valid_hostname(parv[2])) {
        sendto_realops_flags(FLAGS_DEBUG, "Wrong stline virtual name: %s From %s", parv[2], parv[0]);
        return 0;
    }

    strcpy(name, parv[2]);
    p = (char *)(strchr(name, ' '));
    if (p)
       *p = '\0';

    if (MyClient(sptr))
        if ( (strlen(parv[1]) > HOSTLEN) || (strlen(parv[2]) > HOSTLEN) ) {
            sendto_one(sptr, ":%s NOTICE %s :Arguments too big. Maximum host size: %d",
                me.name, sptr->name, HOSTLEN);
        return 0;
    }

    if (!find_stline(parv[1])) /* if stline does not exist */
	  {
		aconf = make_conf();
                DupString(aconf->name, parv[1]);
                DupString(aconf->passwd, name);
                if (parv[3]) DupString(aconf->host, parv[3]);

            aconf->next = stlines;
            stlines = aconf;
            if (parv[3])
            sendto_serv_butone(cptr, ":%s STLINE %s %s :%s",
                            parv[0], parv[1], name, parv[3]);
            else
                sendto_serv_butone(cptr, ":%s STLINE %s %s",
                            parv[0], parv[1], name);
            if (MyClient(sptr))
                sendto_ops("%s added STLINE for %s (%s) (%s)", parv[0], parv[1], name, parv[3] ? parv[3] : "");
	  }
	return 0;
  }

/*
 * m_unstline() - remove stlines
 *
 *	parv[0] = sender prefix
 *	parv[1] = banned nick (masks are allowed)
 */
int     m_unstline(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
  {
        aConfItem *stl = stlines;
        aConfItem *last_stl;
		
        if (!IsServer(sptr) && !IsService(sptr) && !IsSAdmin(sptr)) 
	  {	
		if (IsServer(cptr))
		  { 
                        ts_warn("Got UNstline from non-service/server: %s", 
			  sptr->name);
                        sendto_one(cptr, ":%s WALLOPS :ignoring UNSTLINE from non-service/server %s",
			  me.name, sptr->name);
		}		
		return 0;
	  }

        if(parc<2)
	  return 0;
	
        last_stl = NULL;
	
        while(stl && irccmp(stl->name, parv[1]))
	  {
                last_stl = stl;
                stl = stl->next;
	  }
	  
    if (stl) /* if stline does exist */
	  {
                if(last_stl) /* this is not the first stline */
                        last_stl->next=stl->next; /* adjust list link -> */
		  else
                        stlines = stl->next;
			
                free_conf(stl);
                if (MyClient(sptr)) {
                    my_svsinfo_ts = CurrentTime;
                    sendto_ops("%s removed STLINE for %s", parv[0], parv[1]);
                }
                sendto_serv_butone(cptr, ":%s UNSTLINE %s",
                        parv[0], parv[1]);
	  }
	  
	return 0;
  }
  

/*
 * find_stline  - checks if server matchs any entry on the stline list
 * inputs       - lookup server
 * output       - return stline entry if found or NULL if not found;
 * side effects - none
 */
struct ConfItem* find_stline(char *server)
{
        aConfItem *stl = stlines;

        while(stl && !match(stl->name, server))
          stl = stl->next;

        if (!stl) {
            stl = stlines;
            while(stl && !match(stl->passwd, server))
              stl = stl->next;
        }

        return stl; 
}

char *vgetdesc(char *server)
{
        aConfItem *stl = stlines;

        while(stl && !match(stl->passwd, server))
          stl = stl->next;

        if (stl && stl->host) return stl->host;
        else
            return "";
}

/* send_all_stlines
 *
 * inputs       - pointer to aClient
 * output       - none
 * Side effects - sends all stlines to the specified server
 *
 */
void send_all_stlines(struct Client *acptr)
  {
        aConfItem *stl = stlines;
	
        while(stl)
	  {
            if (stl->host)
            sendto_one(acptr, ":%s STLINE %s %s :%s",
                          me.name, stl->name, stl->passwd, stl->host);
            else 
              sendto_one(acptr, ":%s STLINE %s %s",
                          me.name, stl->name, stl->passwd);
                stl = stl->next;         
	  }
  }
  
/*
 * report_stlines
 *
 * inputs       - pointer to client to report to
 * output       - none
 * side effects - all stlines are listed to client 
 */
void report_stlines(struct Client *sptr)
{
  struct ConfItem *aconf = stlines;
  char *host;
  char *user;
  char *pass;
  char *name;
  int port;

  while(aconf)
    {
  	  get_printable_conf(aconf, &name, &host, &pass, &user, &port);
          
          sendto_one(sptr, form_str(RPL_STATSQLINE),
                     me.name, sptr->name, name, pass, user, host);
	  aconf=aconf->next;	  
    }
}

/*
 * clear_stlines
 *
 * inputs       - none
 * output       - none
 * side effects - clear the stlines list
 */
void clear_stlines()
  {
  
    aConfItem *aconf;
       aConfItem *stl=stlines;
  
       while(stl)
         {
               aconf = stl->next;
               free_conf(stl);
               stl = aconf;
               }
                         
       stlines = NULL;
 
  }
