/* Acidblood link list routines */
/*
Acidblood IRC Bot
Copyright (C) 1997-2000 Bryan Schwab
bryan@darkice.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/


#include "acidblood.h"

#include <sys/types.h>
#include <sys/times.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <ctype.h>
#include <netinet/in.h>
#include <netdb.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>


int
insert_channels(
char *data,
char *key)
{  

   curr3=(struct channels *)malloc(sizeof(struct channels));
   if (curr3==NULL) {
      return(-1);
   }

   if ((curr3->channel=malloc(strlen(data)+1))==NULL) {
        return(-1);
   }

   curr3->next=NULL;

   strncpy(curr3->channel,data,strlen(data)+1);

   /* if a key was passed, create an element in the struct */
   if (key!=NULL) {
      if ((curr3->key=malloc(strlen(key)+1))==NULL) {
         return(-1);
      }
      strncpy(curr3->key,key,strlen(key)+1);
   }

   if (top3==NULL) {
      top3=(struct channels *)malloc(sizeof(struct channels));
      top3=curr3;
      prev3=(struct channels *)malloc(sizeof(struct channels));
      prev3=top3;
   }
   else {
      prev3->next=curr3;
      prev3=curr3;
   }

   return(0);
}


int
delete_channel(
char *data)
{     
  
   if (top3==NULL) {
   	return(0);
   }    
   else {
      curr3=top3;

      if (!strncmp(curr3->channel,data,strlen(data)+1)) {
           if (curr3->next!=NULL) {
               top3=curr3->next;
	       return(0);
           }
  	   else {
	       top3=NULL;
	       return(0);
           }
      }

      temp3=prev3;

      while(temp3->next!=NULL) {
         curr3=temp3->next;
         if (!strncmp(curr3->channel,data,strlen(data)+1)) {
            temp3->next=curr3->next;
            temp3=curr3->next; 
	    return(0);
         }
         else {
            temp3=curr3;
         }
      }
      return(0);
   }  
}


int
traverse_users(
struct serverstruct *serverdata,
char *channel,
char *password)
{
   int result;

   if (top==NULL) {
   }
   else {
      curr=top;
      if (!strcasecmp(curr->usernick,serverdata->nick) || !strncmp(curr->usernick,"*",1)) {
         result=match_ip(curr->userip,serverdata->ip);
         if (result) {
            /* check the channel */
	    if (channel!=NULL) {
	       if (check_chan(curr->userchan,channel)) {
       
 		  if (check_pass(curr->userpass,password)) {
                     return(1);
                  }
                  else {
		     return(-1);
                  }

               }
	       else {
	          return(0);
               }
            }
            return (1);
         }
      }
      prev=top;

      while(prev->next!=NULL) {
         curr=prev->next;
         prev=curr;
         if (!strcasecmp(curr->usernick,serverdata->nick) || !strncmp(curr->usernick,"*",1)) {
            result=match_ip(curr->userip,serverdata->ip);
            if (result) {
               /* check the channel */
	       if (channel!=NULL) {
	          if (check_chan(curr->userchan,channel)) {

 		     if (check_pass(curr->userpass,password)) {
                        return(1);
                     }
                     else {
		        return(-1);
                     }

                  }
	          else {
	             return(0);
                  }
               }
               return (1);
            }
         }
      }
   }
   return (0);
}

int 
check_chan(
char *userchan,
char *serverchan)
{

   char temp[100];
   int x=0;

   /* op this person on ALL channels */
   if (!strncmp(userchan,"all",3)) {
        return(1);
   }

   /* channel matches, most likely only one channel next to their username */
   if (!strncmp(userchan,serverchan,strlen(serverchan)+1)) {
        return(1);
   }

   while (*userchan != '\0') {

      /* found a comma, skip and compare */
      if (*userchan==',') {
         temp[x]='\0';
         if (!strncmp(temp,serverchan,strlen(serverchan)+1)) { 
            return(1);
         }
         else {
            x=0;
            userchan++;
         }
      }
      else {
         temp[x++]=*userchan++;
      }
   }
   /* check last one */
   temp[x]='\0';
   if (!strncmp(temp,serverchan,strlen(serverchan)+1)) {
      return(1);
   }  

   return(0);
}


/* check password for ops */
int
check_pass(
char *userpass,
char *serverpass)
{

   /*
	password set, password given        1 if match, 0 if fail
	password set, no password given     0
	no password set, password given	    1
	no password set, no password given  1
   */

   if (userpass == NULL) {
        /* no password set, authentication ok */
	return (1);
   }

   if (userpass !=NULL && serverpass == NULL) {
	return (0);
   }

  

   /* passwords equal - case sensitive */ 
   if (!strncmp(userpass, serverpass, strlen(serverpass)+1)) { 
        return(1);
   }

   return(0);
}

int
check_level(
struct serverstruct *serverdata)
{  
   if (top==NULL) {
   }
   else {
      curr=top;
      if (!strncmp(curr->usernick,serverdata->nick,strlen(serverdata->nick)+1) &&
          (match_ip(curr->userip,serverdata->ip))) {
          return(curr->userstatus);
      }
      prev=top;

      while(prev->next!=NULL) {
         curr=prev->next;
         prev=curr;
         if (!strncmp(curr->usernick,serverdata->nick,strlen(serverdata->nick)+1) &&
            (match_ip(curr->userip,serverdata->ip))) {
            return(curr->userstatus);
         }
      }
   }
   return(0);
}

int
free_list()
{

   while(top) {
      curr = top;
      if(!curr->next) {
            top = NULL;
            break;
      }

      while(curr) {
         if(curr->usernick) {
            free(curr->usernick);
         }
         if(curr->userip) {
            free(curr->userip);
         }

         prev=curr->next;
         if (curr->next==NULL) {
            top=NULL;
         }
         curr->next = NULL;
         curr->usernick = NULL;
         curr->userip = NULL;
         free(curr);
         curr=prev;
      }
   }
   curr=NULL;

   return(0);
}

int
free_list2()
{

   while(top2) {
      curr2=top2;
      if(!curr2->next) {
            top2=NULL;
            break;
      }

      while(curr2) {
         if(curr2->nick) {
            free(curr2->nick);
         }

         prev2=curr2->next;
         if (curr2->next==NULL) {
            top2=NULL;
         }
         curr2->next=NULL;
         curr2->nick=NULL;
         free(curr2);
         curr2=prev2;
      }
   }
   curr2=NULL;

   return(0);
}

/* gather users to massdeop */
int
insert_md_users (
char *nick)
{

   curr2=(struct mddata *)malloc(sizeof(struct mddata));
   if (curr2==NULL) {
      return(-1);
   }

   if ((curr2->nick=malloc(strlen(nick)+1))==NULL) {
      return(-1);
   }

   strncpy(curr2->nick,nick,strlen(nick)+1);

   if (top2==NULL) {
      top2=(struct mddata *)malloc(sizeof(struct mddata));
      top2=curr2;
      prev2=(struct mddata *)malloc(sizeof(struct mddata));
      prev2=curr2;
   }

   else {
      prev2->next=curr2;
      curr2->next=NULL;
      prev2=curr2;
    }

   return (0);
}

int
insert_users(
char *nick,
char *ip,
char *status,
char *channels,
char *password)
{ 
   int x=0;
   char temp;

   curr=(struct userdata *)malloc(sizeof(struct userdata));
   if (curr==NULL) {
      return(-1);
   }
  
   if ((curr->usernick=malloc(strlen(nick)+1))==NULL) {
      return(-1);
   }
  
   if ((curr->userip=malloc(strlen(ip)+1))==NULL) {
      return(-1);
   }

   if ((curr->userchan=malloc(strlen(channels)+1))==NULL) {
      return(-1);
   }

   if (password != NULL) {
      if ((curr->userpass=malloc(strlen(password)+1))==NULL) {
         return(-1);
      }
   }
  
   strncpy(curr->usernick,nick,strlen(nick)+1);
   strncpy(curr->userip,ip,strlen(ip)+1);
   strncpy(curr->userchan,channels,strlen(channels)+1);
  
   if (password != NULL) {
      strncpy(curr->userpass,password,strlen(password)+1);
   }

   curr->userstatus=atoi(status);
  
   while (curr->userip[x]) {
      temp=curr->userip[x];
      curr->userip[x]=tolower(temp);
      x++;
   }
  
   if (top==NULL) {
      top=(struct userdata *)malloc(sizeof(struct userdata));
      top=curr;
      prev=(struct userdata *)malloc(sizeof(struct userdata));
      prev=curr;
   }
   else {
      prev->next=curr;
      curr->next=NULL;
      prev=curr;
    }

   return (0);
}


