/************************************************************************
 *   psybnc2.2.2, src/p_userfile.c
 *   Copyright (C) 2001 the most psychoid  and
 *                      the cool lam3rz IRC Group, IRCnet
 *			http://www.psychoid.lam3rz.de
 *
 *   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.
 */

#ifndef lint
static char rcsid[] = "@(#)$Id: p_userfile.c, v 2.2.2 2001/03/25 02:02:02 psychoid Exp $";
#endif

#define P_USERFILE

#include <p_global.h>

/* loading a specific user */

int loaduser (int usernum) {
   char fnmuser[100];
   char buf[100];
   char *pt;
   int rc;
   ap_snprintf(fnmuser,sizeof(fnmuser),"USER%d",usernum);
   if (user(usernum)->outstate > 1) {
      writesock(user(usernum)->outsock,"QUIT :simon says: rehashing\n");
      killsocket(user(usernum)->outsock);
      user(usernum)->server[0]=0;
      user(usernum)->outstate=0;
      user(usernum)->outsock=0;
   }
   if (user(usernum)->instate > 1 && user(usernum)->parent==0) {
       ssnprintf(user(usernum)->insock,":-psyBNC!psyBNC@lam3rz.de NOTICE %s :rehashing\n",user(usernum)->nick);
       killsocket(user(usernum)->insock);
       user(usernum)->host[0]=0;
       user(usernum)->instate=0;
       user(usernum)->insock=0;
   }
   clearuser(usernum);
   rc = getini("USER","LOGIN",fnmuser);
   if (rc != 0) {
      return -1;
   }
   U_CREATE=1; /* if not existing, make new */
   nousers=0;
   strmncpy(user(usernum)->login,value,sizeof(user(usernum)->login));
   rc = getini("USER","PARENT",fnmuser);
   if (rc==0)    
      user(usernum)->parent=atoi(value);
   else
      user(usernum)->parent=0;
   rc = getini("USER","USER",fnmuser);
   strmncpy(user(usernum)->user,value,sizeof(user(usernum)->user));    
   rc = getini("USER","NICK",fnmuser);
   if (rc != 0) {
      ap_snprintf(value,sizeof(value),"psy%d",usernum);
   }
   strmncpy(user(usernum)->nick,value,sizeof(user(usernum)->nick));
   strmncpy(user(usernum)->wantnick,value,sizeof(user(usernum)->wantnick));
   rc = getini("USER","PASS",fnmuser);
   if (rc != 0) {
      log(LOG_ERROR,-1,"Warning ! User %s has no password set.",user(usernum)->login);
      strmncpy(value,randstring(16),sizeof(value));
   }
   strcpy(buf,slt1);
   strcat(buf,slt2);
   if (*value!='=')
   {
       if(*value=='+')
       {
	   strmncpy(value,decryptit(value),sizeof(value));
       }
       pt=BLOW_stringencrypt(buf,value);
       ap_snprintf(value,sizeof(value),"=%s",pt);
       free(pt);
       writeini("USER","PASS",fnmuser,value);
       flushconfig();	
   }
   strmncpy(user(usernum)->pass,value,sizeof(user(usernum)->pass));
   rc = getini("USER","VHOST",fnmuser);
   strmncpy(user(usernum)->vhost,value,sizeof(user(usernum)->vhost));
   rc = getini("USER","PROXY",fnmuser);
   strmncpy(user(usernum)->proxy,value,sizeof(user(usernum)->proxy));    
   rc = getini("USER","AWAY",fnmuser);
   strmncpy(user(usernum)->away,value,sizeof(user(usernum)->away));
   rc = getini("USER","AWAYNICK",fnmuser);
   strmncpy(user(usernum)->awaynick,value,sizeof(user(usernum)->awaynick));
   rc = getini("USER","LEAVEMSG",fnmuser);
   strmncpy(user(usernum)->leavemsg,value,sizeof(user(usernum)->leavemsg));
   rc = getini("USER","LASTWHOIS",fnmuser);
   user(usernum)->channels=NULL;
   if(rc==0)
       convertlastwhois(usernum,value);
   else
       loadchannels(usernum);
   rc = getini("USER","NETWORK",fnmuser);
   strmncpy(user(usernum)->network,value,sizeof(user(usernum)->network));
   rc = getini("USER","CRKEY",fnmuser);
   if(rc!=0)
   {
       *user(usernum)->crkey=0;
   } else {
       strmncpy(user(usernum)->crkey,value,sizeof(user(usernum)->crkey));
   }
   rc = getini("USER","RIGHTS",fnmuser);
   if (rc != 0) {
      user(usernum)->rights=RI_USER;
   } else {
      user(usernum)->rights = atoi(value);
   }
#ifdef DYNAMIC
   user(usernum)->quitted=1;
#else
   rc = getini("USER","QUITTED",fnmuser);
   if (rc != 0) {
      user(usernum)->quitted=0;
   } else {
      user(usernum)->quitted = atoi(value);
   }
#endif
   rc = getini("USER","VLINK",fnmuser);
   if (rc != 0) {
      user(usernum)->vlink=0;
   } else {
      user(usernum)->vlink = atoi(value);
   }
   rc = getini("USER","PPORT",fnmuser);
   if (rc != 0) {
      user(usernum)->pport=0;
   } else {
      user(usernum)->pport = atoi(value);
   }
   rc = getini("USER","AUTOGETDCC",fnmuser);
   if (rc != 0) {
      user(usernum)->autogetdcc=0; /* default is off. turn on, if needed */
   } else {
      user(usernum)->autogetdcc = atoi(value);
   }
   rc = getini("USER","DCCENABLED",fnmuser);
   if (rc != 0) {
      user(usernum)->dccenabled=1;
   } else {
      user(usernum)->dccenabled = atoi(value);
   }
   rc = getini("USER","AIDLE",fnmuser);
   if (rc != 0) {
      user(usernum)->antiidle=1;
   } else {
      user(usernum)->antiidle = atoi(value);
   }
   rc = getini("USER","LEAVEQUIT",fnmuser);
   if (rc != 0) {
      user(usernum)->leavequit=0;
   } else {
      user(usernum)->leavequit = atoi(value);
   }
   rc = getini("USER","AUTOREJOIN",fnmuser);
   if (rc != 0) {
      user(usernum)->autorejoin=0; /* default is 0 now. Set it, if needed */
   } else {
      user(usernum)->autorejoin = atoi(value);
   }
   rc = getini("USER","SYSMSG",fnmuser);
   if (rc != 0) {
      user(usernum)->sysmsg=1;
   } else {
      user(usernum)->sysmsg = atoi(value);
   }
   rc = getini("USER","LASTLOG",fnmuser);
   pcontext;
   if (rc != 0) {
      user(usernum)->lastlog=0;
   } else {
      user(usernum)->lastlog = atol(value);
   }
   pcontext;
   user(usernum)->insock = 0;
   user(usernum)->outsock = 0;
   user(usernum)->instate = STD_NOCON;
   user(usernum)->outstate = STD_NOCON;
   pcontext;
   user(usernum)->dcc=(struct linknodes *)pmalloc(sizeof(struct linknodes));
   pcontext;
   loaddccs(usernum);
   pcontext;
   ap_snprintf(fnmuser,sizeof(fnmuser),"USER%d.BAN",usernum);
   user(usernum)->bans=loadlist(fnmuser,user(usernum)->bans);
   pcontext;
   ap_snprintf(fnmuser,sizeof(fnmuser),"USER%d.OP",usernum);
   user(usernum)->ops=loadlist(fnmuser,user(usernum)->ops);
   pcontext;
   ap_snprintf(fnmuser,sizeof(fnmuser),"USER%d.AOP",usernum);
   user(usernum)->aops=loadlist(fnmuser,user(usernum)->aops);
   pcontext;
   ap_snprintf(fnmuser,sizeof(fnmuser),"USER%d.ASK",usernum);
   user(usernum)->askops=loadlist(fnmuser,user(usernum)->askops);
   pcontext;
   ap_snprintf(fnmuser,sizeof(fnmuser),"USER%d.LGI",usernum);
   user(usernum)->logs=loadlist(fnmuser,user(usernum)->logs);
   pcontext;
#ifdef CRYPT
   ap_snprintf(fnmuser,sizeof(fnmuser),"USER%d.ENC",usernum);
   user(usernum)->encrypt=loadlist(fnmuser,user(usernum)->encrypt);
#endif
#ifdef TRANSLATE
   pcontext;
   ap_snprintf(fnmuser,sizeof(fnmuser),"USER%d.TRA",usernum);
   user(usernum)->translates=loadlist(fnmuser,user(usernum)->translates);
#endif
#ifdef TRAFFICLOG
   pcontext;
   ap_snprintf(buf,sizeof(buf),"log/USER%d.TRL",usernum);
   user(usernum)->trafficlog=fopen(buf,"a");
#endif
#ifdef SCRIPTING
   loadscript(usernum);
#endif
   return;
}


/* this writes a user info to the bounce inifile */

int writeuser(int usern)
{
    char iset[8];
    char fname[20];
    char buf[100];
    ap_snprintf(fname,sizeof(fname),"USER%d",usern);
    writeini("USER","NICK",fname,user(usern)->nick);
    writeini("USER","LOGIN",fname,user(usern)->login);
    writeini("USER","USER",fname,user(usern)->user);
    if(*user(usern)->pass!='=')
    {
	strcpy(buf,slt1);
	strcat(buf,slt2);
	ap_snprintf(user(usern)->pass,sizeof(user(usern)->pass),"=%s",BLOW_stringencrypt(buf,user(usern)->pass));
    }
    writeini("USER","PASS",fname,user(usern)->pass);
    writeini("USER","VHOST",fname,user(usern)->vhost);
    writeini("USER","PROXY",fname,user(usern)->proxy);
    writeini("USER","AWAY",fname,user(usern)->away);
    writeini("USER","LEAVEMSG",fname,user(usern)->leavemsg);
    writeini("USER","AWAYNICK",fname,user(usern)->awaynick);
    writeini("USER","NETWORK",fname,user(usern)->network);
    if(*user(usern)->crkey!=0)
	writeini("USER","CRKEY",fname,cryptit(user(usern)->crkey));
    ap_snprintf(iset,sizeof(iset),"%d",user(usern)->rights);
    writeini("USER","RIGHTS",fname,iset);
    ap_snprintf(iset,sizeof(iset),"%d",user(usern)->vlink);
    writeini("USER","VLINK",fname,iset);
    ap_snprintf(iset,sizeof(iset),"%d",user(usern)->pport);
    writeini("USER","PPORT",fname,iset);
    ap_snprintf(iset,sizeof(iset),"%d",user(usern)->parent);
    writeini("USER","PARENT",fname,iset);
    ap_snprintf(iset,sizeof(iset),"%d",user(usern)->quitted);
    writeini("USER","QUITTED",fname,iset);
    ap_snprintf(iset,sizeof(iset),"%d",user(usern)->dccenabled);
    writeini("USER","DCCENABLED",fname,iset);
    ap_snprintf(iset,sizeof(iset),"%d",user(usern)->autogetdcc);
    writeini("USER","AUTOGETDCC",fname,iset);
    ap_snprintf(iset,sizeof(iset),"%d",user(usern)->antiidle);
    writeini("USER","AIDLE",fname,iset);
    ap_snprintf(iset,sizeof(iset),"%d",user(usern)->leavequit);
    writeini("USER","LEAVEQUIT",fname,iset);
    ap_snprintf(iset,sizeof(iset),"%d",user(usern)->autorejoin);
    writeini("USER","AUTOREJOIN",fname,iset);
    ap_snprintf(iset,sizeof(iset),"%d",user(usern)->sysmsg);
    writeini("USER","SYSMSG",fname,iset);
    ap_snprintf(iset,sizeof(iset),"%d",user(usern)->lastlog);
    writeini("USER","LASTLOG",fname,iset);
    writeini("USER","LASTWHOIS",fname,NULL); /* erasing lastwhois */
    flushconfig();
}

/* this writes a link info to the link inifile */

int writelink(int linkn)
{
    char iset[8];
    char fname[20];
    char lname[20];
    ap_snprintf(fname,sizeof(fname),"%s","LINKS");
    ap_snprintf(lname,sizeof(lname),"LINK%d",linkn);
    ap_snprintf(iset,sizeof(iset),"%d",datalink(linkn)->type);
    writeini(lname,"TYPE",fname,iset);
    ap_snprintf(iset,sizeof(iset),"%d",datalink(linkn)->port);
    writeini(lname,"PORT",fname,iset);
    writeini(lname,"NAME",fname,datalink(linkn)->name);
    writeini(lname,"IAM",fname,datalink(linkn)->iam);
    writeini(lname,"HOST",fname,datalink(linkn)->host);
    writeini(lname,"PASS",fname,cryptit(datalink(linkn)->pass));
    if(*datalink(linkn)->crkey!=0)
	writeini(lname,"CRKEY",fname,cryptit(datalink(linkn)->crkey));
    ap_snprintf(iset,sizeof(iset),"%d",datalink(linkn)->allowrelay);
    writeini(lname,"ALLOWRELAY",fname,iset);
    flushconfig();
}

/* erase a link entry */

int eraselinkini(int linkn)
{
    char iset[8];
    char fname[20];
    char lname[20];
    ap_snprintf(fname,sizeof(fname),"%s","LINKS");
    ap_snprintf(lname,sizeof(lname),"LINK%d",linkn);
    writeini(lname,"TYPE",fname,NULL);
    writeini(lname,"PORT",fname,NULL);
    writeini(lname,"NAME",fname,NULL);
    writeini(lname,"IAM",fname,NULL);
    writeini(lname,"HOST",fname,NULL);
    writeini(lname,"PASS",fname,NULL);
    writeini(lname,"CRKEY",fname,NULL);
    writeini(lname,"ALLOWRELAY",fname,NULL);
    flushconfig();
}

/* load all user structures */

int loadusers(void)
{
   struct usernodes *th;    
   int curuser;
   pcontext;
   curuser = 1;
   log(LOG_INFO,-1,"Loading all Users..");
   while (curuser <= MAX_USER) 
   {
       loaduser(curuser);
       curuser++;
   }
   if (nousers) log(LOG_WARNING,-1,"No Users found.");
   th=usernode;
   while (th!=NULL) 
   {
       curuser=th->uid;
       checkparents(curuser);
       th=th->next;
   }
   return 0x0;
}

/* load a special link */

int loadlink(int linkn)
{
    int rc;
    char lname[20];
    char buf[400];
    char lfile[]="LINKS";
    if (datalink(linkn)->type==LI_RELAY) return 0x0; /* not resetting dynamic links */
    if (datalink(linkn)->outstate==STD_CONN) {
        log(LOG_WARNING,-1,"LINK: -> %s (%d) closing\n",datalink(linkn)->host,datalink(linkn)->port);
	killsocket(datalink(linkn)->outsock);
    }
    if (datalink(linkn)->instate==STD_CONN) {
        log(LOG_WARNING,-1,"LINK: <- %s (%d) closing\n",datalink(linkn)->host,datalink(linkn)->port);
	killsocket(datalink(linkn)->insock);
    }
    ap_snprintf(lname,sizeof(lname),"LINK%d",linkn);
    rc=getini(lname,"TYPE",lfile);
    clearlink(linkn);
    if (rc!=0) 
	return 0x0;
    D_CREATE=1;
    datalink(linkn)->type=atoi(value);
    rc=getini(lname,"HOST",lfile);
    if (rc!=0) memset(value,0x0,sizeof(value));
    strmncpy(datalink(linkn)->host,value,sizeof(datalink(linkn)->host));
    rc=getini(lname,"PORT",lfile);
    if (rc!=0)
	datalink(linkn)->port=0;
    else
	datalink(linkn)->port=atoi(value);
    rc=getini(lname,"ALLOWRELAY",lfile);
    if (rc!=0)
	datalink(linkn)->allowrelay=0;
    else
	datalink(linkn)->allowrelay=atoi(value);
    rc=getini(lname,"PASS",lfile);
    strmncpy(datalink(linkn)->pass,decryptit(value),sizeof(datalink(linkn)->pass));
    rc=getini(lname,"CRKEY",lfile);
    if(rc!=0)
    {
	*datalink(linkn)->crkey=0;
    } else {
	strmncpy(datalink(linkn)->crkey,value,sizeof(datalink(linkn)->crkey));
    }
    rc=getini(lname,"NAME",lfile);
    if (rc!=0) memset(value,0x0,sizeof(value));
    strmncpy(datalink(linkn)->name,value,sizeof(datalink(linkn)->name));
    rc=getini(lname,"IAM",lfile);
    if (rc!=0) value[0]=0;
    strmncpy(datalink(linkn)->iam,value,sizeof(datalink(linkn)->iam));
    datalink(linkn)->instate=STD_NOCON;
    datalink(linkn)->outstate=STD_NOCON;
    datalink(linkn)->delayed=1;
    return 0x0;
}

/* load all links */

int loadlinks()
{
    int i=1;
    pcontext;
    while (i<=MAXCONN)
    {
	loadlink(i);
	i++;
    }
    return 0x0;
}

/* check if user exists, returns number of userrecord or 0 if not existant */

int checkuser(char *nick)
{
    struct usernodes *th;
    int uind;
    char *pt;
    th=usernode;
    while (th!=NULL)
    {
	uind=th->uid;
	if (strlen(user(uind)->login) == strlen(nick)) {
	    pt=strstr(user(uind)->login,nick);
	    if (pt != NULL) {
	       if (user(uind)->parent!=0) uind=user(uind)->parent;	
	       return uind;
	    }
	}
	th=th->next;
    }
    return 0x0;
}

