#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <netdb.h>
#include <errno.h>
#include <time.h>
#include <ctype.h>
#ifndef NO_CRYPT_DOT_H
#include <crypt.h>
#endif

#include "globals.h"
#include "functions.h"
#include "language.h"

unsigned char help_message[sizeof(HELP)+sizeof(CHAN_HELP)+2];

void safestrncpy(char *dest, char *source, int n)
{
int r;

  for (r=0; r<n; r++)
  { 
    dest[r]=source[r]; 
    if (source[r]==0) break;
  }  

  dest[r]=0;
}

int logfile_on(int ID)
{
  logging=1;
  logfp=fopen(logfile,"a");
  if (logfp==0)
  {
    if (ID!=-1)
    { message(ID,CHAT_LOG_CANT_OPEN,0); }
      else
    { printf("Cannot open chat log for writing!\n"); }

    logging=0;
  }

  return 0;
}

#ifdef LEET

/* 13374 patch donated by Oliver Hillmann (tequila :) */

void leet(unsigned char *buf)
{
char lame_dict[] = "elaszotg";
char leet_dict[] = "314z2076";
int r, i, j, l;

  l=strlen(lame_dict);
  r=strlen(buf);

  for (i = 0; i < r; i++) 
  {

    buf[i] = (char)tolower((int)buf[i]);

    for (j = 0; j < l; j++)
    {
      if (buf[i] == lame_dict[j])
      {
        buf[i] = leet_dict[j];
        break;
      }
    }
  }    
}

#endif

char *strcasestr_m(char *hejstack, char *needle)
{
int hejlen,neelen;
int t,r;

  hejlen=strlen(hejstack);
  neelen=strlen(needle);
  r=hejlen-neelen;

  for(t=0; t<=r; t++)
  {
    if (strncasecmp(&hejstack[t],needle,neelen)==0)
    { return &hejstack[t]; }
  }

  return (char *)0;
}

void destroy()
{

#ifdef DEBUG
  if (debug==1)
  { printf("\nChat server terminated.\n\n"); }
#endif

  exit(0);
}

void broken_pipe()
{
#ifdef DEBUG
  if (debug==1) printf("Signal thrown\n");
#endif

  setsignals();
}

void setsignals()
{
  signal(SIGPIPE,broken_pipe);
  signal(SIGURG,broken_pipe);
  signal(SIGIO,broken_pipe);
  signal(SIGHUP,broken_pipe);

  signal(SIGINT,destroy);
  signal(SIGTERM,destroy);
}

void addtowelcome(char *s)
{
int t,l;

  l=strlen(s);

  for (t=0; t<l; t++)
  {
    if (s[t]=='\n' || s[t]=='\r') break;
    if (s[t]<32) continue;
    welcome[welcomelen++]=s[t];
  }

  welcome[welcomelen++]='\n';
  welcome[welcomelen++]='\r';
  welcome[welcomelen]=0;
}

unsigned char *collapse(unsigned char *d, int c, char *old)
{
unsigned char *s;

  s=d;
  while(s[0]!=0) s++;
  s++;
  while(1)
  {
    if (c<=0) break;
    d[0]=s[0];
    if (d[0]==0) c--;
    d++; s++;
  }
  d++;
  strcpy(d,old);
  return d;
}

unsigned char *unban_number(int i)
{
unsigned char *banptr;
unsigned char temp[1024];
int r;

  banptr=bans;
  for (r=0; r<bancount; r++)
  {
    if (r==i)
    {
      bancount--;
      strcpy(temp,banptr);
      return collapse(banptr,bancount-i,temp);
    }

    banptr=banptr+strlen(banptr)+1;
  }

  return 0;
}

int ban_address(unsigned char *addr)
{
unsigned char *banptr;
int r;

  banptr=bans;
  for (r=0; r<bancount; r++)
  {
    while(banptr[0]!=0) banptr++;
    banptr++;
  }

  if (banptr-bans+strlen(addr)+1>BANS_BUFFER_SIZE)
  { return 1; }
  strcpy(banptr,addr);
  bancount++;

  return 0;
}

void read_config()
{
FILE *fp;
int r=0,w=0,t;
unsigned char name[100];
unsigned char *badwordptr;
unsigned char *allowptr;

  allowcount=0;
  allowptr=allows;
  bancount=0;
  badwordcount=0;
  badwordptr=badword;
  welcomelen=0;

  fp=fopen(configdir,"r");
 
  if (fp==0)
  { 
    printf("Couldn't open %s.  Trying /usr/local/etc/nakenchat.conf\n",configdir);

    strcpy(configdir,"/usr/local/etc/nakenchat.conf");
    fp=fopen(configdir,"r");

    if (fp==0)
    {
      printf("Couldn't open %s. Trying ./nakenchat\n",configdir);

      strcpy(configdir,"./nakenchat.conf");
      fp=fopen(configdir,"r");

      if (fp==0)
      {
        printf("No config file found.  Going with defaults.\n");
      }
    } 
  }

  if (fp!=0)
  {
    printf("Config File: %s\n",configdir);
    while(fgets(name,100,fp)!=NULL)
    {
      t=0;
      while((name[t]!=' ' && name[t]!='\t') && (name[t]!='\n' && name[t]!='\r'))
      { 
        if (t==100) break;
        t++; 
      }

      if (name[0]==0 || (name[0]=='\n' || name[0]=='\r')) name[0]='#';
      name[t++]=0;
      if (name[0]!='#')
      {
        w=0;
        if (strcasecmp(name,"SYSOP_PASSWORD")==0) w=1;
	  else
        if (strcasecmp(name,"BAD_WORD")==0) w=2;
	  else
        if (strcasecmp(name,"ALLOW")==0) w=3;
	  else
        if (strcasecmp(name,"BAN")==0) w=4;
	  else
        if (strcasecmp(name,"INTERNATIONAL")==0) w=5;
	  else
        if (strcasecmp(name,"PORT")==0) w=6;
          else
        if (strcasecmp(name,"HOSTLOOKUPS")==0) w=7;
          else
        if (strcasecmp(name,"SHOWIPS")==0) w=8;
          else
        if (strcasecmp(name,"WELCOME")==0) addtowelcome(&name[t]);
          else
        if (strcasecmp(name,"NODUPIPS")==0) w=9;
          else
        if (strcasecmp(name,"LOGFILE")==0) w=10;
          else
        if (strcasecmp(name,"MAXCONN")==0) w=11;
          else
        if (strcasecmp(name,"MINCONN")==0) w=12;
          else
        if (strcasecmp(name,"MAX_IDLE_TIME")==0) w=13;
          else
        if (strcasecmp(name,"PASSWD")==0) w=14;
          else
        if (strcasecmp(name,"CENSOR")==0) w=15;
          else
        if (strcasecmp(name,"CHANNEL_DISABLE")==0) w=16;
          else
        if (strcasecmp(name,"LOGGING")==0) w=17;
          else
        if (strcasecmp(name,"FORCE_PASSWD")==0) w=18;
          else
        if (strcasecmp(name,"FORCE_NAME")==0) w=19;
          else
        if (strcasecmp(name,"NODUP_NAMES")==0) w=20;

        if (w!=0)
	{ 
          while(name[t]==' ' || name[t]=='\t')
	  {
	    if (name[t]==0 || (name[t]=='\r' || name[t]=='\n')) break;
	    t++;
	  }
	  r=t;
          while((name[t]!=' ' && name[t]!='\t') && ((name[t]!='\n' && name[t]!='\r') && name[t]!=0))
          { t++; }
	  if (r!=t)
	  {
	    name[t]=0;
	    if (w==1) safestrncpy(sysoppw,&name[r],15);
	      else
	    if (w==2)
            {
              if (strlen(&name[r])+badwordptr+1>=badword+BAD_WORD_BUFFER_SIZE)
              {
                printf("Exceeded %d bytes for bad words.  Cannot add word %s\n",BAD_WORD_BUFFER_SIZE,&name[r]);
              }
                else
              {
                strcpy(badwordptr,&name[r]);
                badwordptr=badwordptr+strlen(&name[r])+1;
                badwordcount++;
              }
            }
	      else
	    if (w==3)
            {
              if (strlen(&name[r])+allowptr+1>=allows+ALLOWS_BUFFER_SIZE)
              {
                printf("Exceeded %d bytes for allows.  Cannot add site %s\n",ALLOWS_BUFFER_SIZE,&name[r]);
              }
                else
              {
                strcpy(allowptr,&name[r]);
                allowptr=allowptr+strlen(&name[r])+1;
                allowcount++;
              }
            }
	      else
	    if (w==4)
            {
              if (ban_address(&name[r])==1)
              {
                printf("Exceeded %d bytes for bans.  Cannot add site %s\n",BANS_BUFFER_SIZE,&name[r]);
              }
            }
	      else
	    if (w==5) { if (atoi(&name[r])==1) international=1; }
	      else
	    if (w==6) port=atoi(&name[r]);
              else
	    if (w==7) 
            { if (atoi(&name[r])==1) serverflags=serverflags|2; }
              else
	    if (w==8) 
            { if (atoi(&name[r])==1) serverflags=serverflags|4; }
              else
	    if (w==9) 
            { if (atoi(&name[r])==1) serverflags=serverflags|8; }
              else
	    if (w==10) 
            { strcpy(logfile,&name[r]); }
	      else
	    if (w==11) maxconn=atoi(&name[r]);
	      else
	    if (w==12) minconn=atoi(&name[r]);
	      else
	    if (w==13) max_idle_time=atoi(&name[r])*60;
	      else
	    if (w==14)
            { strcpy(passwd,&name[r]); }
	      else
	    if (w==15) censor=atoi(&name[r]);
              else
	    if (w==16) 
            { if (atoi(&name[r])==1) serverflags=serverflags|1; }
              else
	    if (w==17) 
            { if (atoi(&name[r])==1) logfile_on(-1); }
              else
	    if (w==18) 
            { if (atoi(&name[r])==1) serverflags=serverflags|32; }
              else
	    if (w==19) 
            { if (atoi(&name[r])==1) serverflags=serverflags|64; }
              else
	    if (w==20) 
            { if (atoi(&name[r])==1) serverflags=serverflags|128; }
	  }
	}
      }
    } 
    fclose(fp);
  }

  if (welcomelen==0)
  {
    strcpy(welcome,">> Naken Chat - Copyright 1997-2003 Michael Kohn\n\r\n\r");
    welcomelen=strlen(welcome);
    return;
  }

  sprintf(help_message,HELP,EMOTE_CHAR);

  if ((serverflags&1)==0)
  { strcat(help_message,CHAN_HELP); }
  /* { strcpy(&help_message[sizeof(HELP)-1],CHAN_HELP); } */

  strcat(help_message,"\n\r");
}

void message(int ID, char *daMessage, int att)
{
unsigned char newMessage[2048];
unsigned char tempMessage[2048];
int t;

  if (users[ID]->inuse!=1 && users[ID]->inuse!=100) return;
  if (att==1)
  {
    if ((users[ID]->uflags&1)!=0)
    { sprintf(newMessage,"%c%s",(char)7,daMessage); }
      else
    { strcpy(newMessage,daMessage); }

    if ((users[ID]->uflags&2)!=0)
    { 
      sprintf(tempMessage,"%c[1m%s%c[0m",(char)27,newMessage,(char)27);
      strcpy(newMessage,tempMessage);
    }

    if ((users[ID]->uflags&32)!=0 && time(NULL)-users[ID]->stamptime>600)
    { 
      t=time(NULL);
      sprintf(tempMessage,">> %s\r",ctime((time_t*)&t));
      strcat(newMessage,tempMessage);
      users[ID]->stamptime=time(NULL);
    }

#ifdef LEET
    if ((serverflags&16)==16)
    { leet(newMessage); }
#endif

    if (write(users[ID]->socketid,newMessage,strlen(newMessage))<=0)
    { 
      users[ID]->inuse=4;
      close(users[ID]->socketid);
      kill_user(ID);
    }
  }
    else
  { 
    if ((users[ID]->uflags&32)!=0 && time(NULL)-users[ID]->stamptime>600)
    { 
      t=time(NULL);
      sprintf(newMessage,"%s>> %s\r",daMessage,ctime((time_t*)&t));

#ifdef LEET
      if ((serverflags&16)==16)
      { leet(newMessage); }
#endif

      users[ID]->stamptime=time(NULL);
      if (write(users[ID]->socketid,newMessage,strlen(newMessage))<=0)
      {
        users[ID]->inuse=4;
        close(users[ID]->socketid);
        kill_user(ID);
      }
    }
      else
    {
#ifdef LEET
      strcpy(newMessage,daMessage);

      if ((serverflags&16)==16)
      { leet(newMessage); }

      if (write(users[ID]->socketid,newMessage,strlen(newMessage))<=0)
      {
        users[ID]->inuse=4;
        close(users[ID]->socketid);
        kill_user(ID);
      }
#else
      if (write(users[ID]->socketid,daMessage,strlen(daMessage))<=0)
      {
        users[ID]->inuse=4;
        close(users[ID]->socketid);
        kill_user(ID);
      }
#endif
    }
  }
}

int getNum(char *myString,int ID)
{
int r,len,out=0;

  r=0;
  len=strlen(myString);
  while (r<len && (myString[r]>='0' && myString[r]<='9'))
  {
    if (r<8) out=out*10+(myString[r]-48);
    r++;
  }

  if (r==0) 
  {
    if (ID!=-1)
    { message(ID,UNDERSTAND_MESSAGE,0); }
    return -1;
  }

  if (ID!=-1)
  {
    if (out>maxconn || users[out]->inuse!=1)
    { message(ID,NOT_HERE,0);  return -1; }
  }

  return out;
}

int strip(char *myString)
{
int r=0;

   while(myString[r]>='0' && myString[r]<='9')
   {
     /* if (myString[r]==0) return r; */
     r++;
   }

   while(myString[r]==' ')
   {
     /*  if (myString[r]==0) return r; */
     r++;
   }
   return r;
}

void timediff(int time1,int time2, char *thisString)
{
int temp;
unsigned char tempString[70];

  thisString[0]=0;
  if (time1<time2) { temp=time1; time1=time2; time2=temp; }
  temp=time1-time2;
  if (temp!=0) 
  { sprintf(tempString,"%dsec",temp%60); temp=temp/60; strcpy(thisString,tempString); }
  if (temp!=0)
  { sprintf(tempString,"%dmin %s",temp%60,thisString); temp=temp/60; strcpy(thisString,tempString); }
  if (temp!=0)
  { sprintf(tempString,"%dhours %s",temp%24,thisString); temp=temp/24; strcpy(thisString,tempString); }
  if (temp!=0)
  { sprintf(tempString,"%ddays %s",temp%365,thisString); temp=temp/365; strcpy(thisString,tempString); }
  if (temp!=0)
  { sprintf(tempString,"%dyears %s",temp,thisString); strcpy(thisString,tempString); }
}

void shorttimediff(int time1,int time2, char *thisString)
{
int temp;

  thisString[0]=0;
  if (time1<time2) { temp=time1; time1=time2; time2=temp; }
  temp=time1-time2;
  if (temp!=0) { sprintf(thisString,"%ds",temp%60); temp=temp/60; }
  if (temp!=0) { sprintf(thisString,"%dm",temp%60); temp=temp/60; }
  if (temp!=0) { sprintf(thisString,"%dh",temp%24); temp=temp/24; }
  if (temp!=0) { sprintf(thisString,"%dd",temp%365); temp=temp/365; }
  if (temp!=0) { sprintf(thisString,"%dy",temp); }
}

int channel(int ID,char *oName)
{
int r,curr,oflag;
unsigned char Name[100];

  safestrncpy(Name,oName,99);

#ifdef HIDDEN_CAVES
  if (strcmp(Name,"Hidden Cave")==0) sprintf(Name,"1%d",(int)(time(NULL)%1000));
#endif

  /* if (strcmp(Name,"0")==0 || strcasecmp(Name,MAINCHANNEL)==0) */

  if (strcmp(Name,"0")==0) 
  { strcpy(Name,MAINCHANNEL); }

  if (strcasecmp(Name,channels[users[ID]->channel])==0) return -2;

  for (r=1; r<MAXCHAN; r++)
    if ((strcasecmp(Name,channels[r])==0 && (cflags[r]&1)==1) && users[ID]->user_level<10) return -1;

  oflag=-1;
  for (r=0; r<=MAXCHAN; r++)
  { 
    if (channels[r][0]==0) oflag=-2; 
    if (strcasecmp(Name,channels[r])==0)
    {
      oflag=r;
      break;
    }
  }

  curr=users[ID]->channel;
   
  if (curr!=0 && oflag!=-1)
  {
    for (r=0; r<MAXCONN; r++)
      if (users[r]->inuse==1)
        if (users[r]->channel==curr && r!=ID) r=MAXCONN+6;
    
    if (r<MAXCONN+2)
    { channels[curr][0]=0; channelop[curr]=-1; cflags[curr]=0; }
  }

  if (oflag>=0) return oflag;
    else
  if (oflag==-1) return -3;
       
  for (r=1; r<=MAXCHAN; r++)
  {
    if (channels[r][0]==0)
    {
      strcpy(channels[r],Name);
      if ((serverflags&1)==0)
      { channelop[r]=ID; }
        else
      { channelop[r]=-1; }
      return r;
    }
  }

  return users[ID]->channel;
}

int ConvNum(char *myString)
{
int r=0;
unsigned char tempString[40];

  safestrncpy(tempString,myString,39);
  while(r<39)
  {
    if (tempString[r]<'0' || tempString[r]>'9') break;
    r++;
  }
  tempString[r]=0;
  if (r==0) return -1;

  return atoi(tempString);
}

void channelinfo(int ID)
{
unsigned char myString[WHO_BUFFER_SIZE];
unsigned char tempString[100];
unsigned char cops[128];
int r,buffer_ptr;
#ifdef HIDDEN_CAVES
int t;
#endif
 
  buffer_ptr=0;
 
  strcpy(myString,CHANNEL_HEADER1);
  buffer_ptr=sizeof(CHANNEL_HEADER1)-1;
  strcpy(&myString[buffer_ptr],"------------------------------------------\n\r");
  buffer_ptr+=sizeof("------------------------------------------\n\r")-1;
  strcpy(&myString[buffer_ptr],CHANNEL_HEADER2);
  buffer_ptr+=sizeof(CHANNEL_HEADER2)-1;

  for(r=1; r<=MAXCHAN; r++)
  { 
    if (channels[r][0]!=0)
    {
#ifdef HIDDEN_CAVES
      if ((t=ConvNum(channels[r]))<1000 || t>=2000)
#endif
      {
        if (users[ID]->user_level<10 && channelop[r]>=0) 
        {
          if (users[channelop[r]]->user_level==10 && (users[channelop[r]]->uflags&128)!=0)
          { continue; }
        }

        if (channelop[r]>=0)
        { sprintf(cops,"[%d]%s",channelop[r],users[channelop[r]]->username); }
          else
        { strcpy(cops,NOONE); }

        if ((cflags[r]&1)==1)
        { sprintf(tempString,"%-15s %-20s "YES"\n\r",channels[r],cops); }
          else
        { sprintf(tempString,"%-15s %-20s "NO"\n\r",channels[r],cops); }

	strcpy(&myString[buffer_ptr],tempString);

        buffer_ptr=buffer_ptr+strlen(tempString);

        if (buffer_ptr>WHO_BUFFER_SIZE-150)
        {
          message(ID,myString,0);
          buffer_ptr=0;
          myString[0]=0;
        }
      }
    }
  }
  strcpy(&myString[buffer_ptr],"\n\r");
  message(ID,myString,0);
}

void viewbans(int ID)
{
unsigned char myString[BANS_BUFFER_SIZE+1024];
unsigned char tempString[1024];
unsigned char *banptr;
int r,c;

  strcpy(myString,CURRENTBAN);
  banptr=bans;
  c=0;

  for (r=0; r<bancount; r++)
  {
    sprintf(tempString,">> %d: %s\n\r",r,banptr);
    strcat(myString,tempString);
    banptr=banptr+(strlen(banptr))+1;
    c=c+strlen(tempString);
    if (c>BANS_BUFFER_SIZE)
    {
      message(ID,myString,0);
      tempString[0]=0;
      c=0;
    }
  }

  sprintf(tempString,BANCOUNT,bancount);
  strcat(myString,tempString);
  message(ID,myString,0);
}

int is_number(char *myString)
{
int r=0;

  while((myString[r]!=' ' && myString[r]!='\t') &&
	  ((myString[r]!='\n' && myString[r]!='\r') && myString[r]!=0))
  {
    if (myString[r]<'0' || myString[r]>'9') return 0;
    r++;
  }

  if (r==0) return 0;
  return 1;
}

void update_list(int ID, int add)
{
unsigned char tempString[128];
int r;

  if (add==1)
  { sprintf(tempString,"+[%d]%s\n\r",ID,users[ID]->username); }
    else
  { sprintf(tempString,"-[%d]%s\n\r",ID,users[ID]->username); }

  for (r=0; r<maxconn; r++)
  {
#ifdef USER_LIST_CHAN
    if (users[r]->inuse==1 && ((users[r]->uflags&256)!=0 && 
        users[r]->channel==users[ID]->channel))
#else
    if (users[r]->inuse==1 && (users[r]->uflags&256)!=0)
#endif
    { message(r,tempString,0); }
  }
}

void clientshow(int ID)
{
unsigned char myString[maxconn*20];
unsigned char temp[80];
int r;

  /* strcpy(myString,""); */
  strcpy(myString,"@\n\r");

  for (r=0; r<maxconn; r++)
  {
    if (users[ID]->user_level<10 && (users[r]->user_level==10 && (users[r]->uflags&128)!=0))
    { continue; }

#ifdef USER_LIST_CHAN
    if (users[r]->inuse==1 && users[r]->channel==users[ID]->channel)
#else
    if (users[r]->inuse==1)
#endif
    {
      sprintf(temp,"+[%d]%s\n\r",r,users[r]->username);
      strcat(myString,temp);
    }
  }
  message(ID,myString,0);
}

void show_levels(int ID)
{
unsigned char myString[maxconn*80+500];
unsigned char tempString[1024];
int r;

  strcpy(myString,"----------------------------------\n\r");
  for (r=0; r<maxconn; r++)
  {
    if (users[r]->inuse==1)
    {
      sprintf(tempString,"[%d]%-20s  %d\n\r",r,users[r]->username,users[r]->user_level);
      strcat(myString,tempString);
    }
  }
  strcat(myString,"----------------------------------\n\r");
  message(ID,myString,0);
}

void who(int ID,char *grep)
{
int c,r,num=-2,trim=0,buffer_ptr;
unsigned char myString[WHO_BUFFER_SIZE];
unsigned char tempString[1024];
unsigned char flags[6];
unsigned char channelString[20];
unsigned char location[21];
unsigned char idleString[40];
unsigned char tempf[40];
time_t myTime;
#ifdef HIDDEN_CAVES
int n;
#endif

  sprintf(tempf,"%%-%ds %%-14s %%s ",MAX_USER_NAME_LENGTH+9);
  sprintf(myString,tempf,WHO_NAME,WHO_CHANNEL,WHO_IDLE);

  if ((serverflags&4)!=0 || users[ID]->user_level==10)
  { strcat(myString,WHO_LOCATION); }
  strcat(myString,"\n\r");

  sprintf(tempf,"[%%d]%%-%ds %%-5s %%-14s %%4s %%s\n\r",MAX_USER_NAME_LENGTH);
  strcpy(location,"");
  myTime=time(NULL);
  while (grep[trim]==' ') trim++;
  if (is_number(&grep[trim])==1) 
  { num=getNum(&grep[trim],-1); grep[trim]=0; }
    else
  {
    r=trim;
    while((grep[r]!='\n' && grep[r]!='\r') &&
           ((grep[r]!=' ' && grep[r]!='\t') && grep[r]!=0)) r++;
    grep[r]=0;
  }

  c=0;
  buffer_ptr=strlen(myString);

  for(r=0; r<maxconn; r++)
  {
    if (users[ID]->user_level<10 && (users[r]->user_level==10 && (users[r]->uflags&128)!=0))
    { continue; }

    if ((serverflags&1)==1 && (users[ID]->channel!=users[r]->channel &&
         users[ID]->user_level<8)) continue;

    if (num!=-2 && num!=r) continue;
    strcpy(flags,"-----");
    if (users[r]->inuse==1)
    {
      if ((users[r]->uflags&8)==8) flags[0]='H';
      if ((users[r]->gags[ID/8]&(1<<(ID%8)))!=0) flags[0]='G';

      if ((users[r]->uflags&1)==1) flags[1]='B';
      if ((users[ID]->gags[r/8]&(1<<(r%8)))!=0) flags[1]='g';

      if ((channelop[users[r]->channel]==r) && users[r]->channel!=0) flags[2]='O';

      if ((cflags[users[r]->channel]&1)==1) flags[3]='L';

      if ((users[r]->uflags&4)==4) flags[4]='S';

#ifdef HIDDEN_CAVES
      if ((n=ConvNum(channels[users[r]->channel]))>=1000 && n<=1999)
      { strcpy(channelString,"Hidden Cave"); }
	else
#endif
      { strcpy(channelString,channels[users[r]->channel]); }

      shorttimediff(myTime,users[r]->idletime,idleString);

      if ((serverflags&4)!=0 || users[ID]->user_level==10)
      { safestrncpy(location,users[r]->location,20); }

      sprintf(tempString,tempf,r,users[r]->username,flags,channelString,
	idleString,location);

      if (grep[trim]==0)
      {
        strcpy(&myString[buffer_ptr],tempString);
        buffer_ptr=buffer_ptr+strlen(tempString);
        c++;
      }
	else
      {
	if (strstr(tempString,&grep[trim])!=NULL)
        {
          strcpy(&myString[buffer_ptr],tempString);
          buffer_ptr=buffer_ptr+strlen(tempString);
          c++;
        }
      }

      if (buffer_ptr>WHO_BUFFER_SIZE-150)
      {
        message(ID,myString,0); 
        buffer_ptr=0;
        myString[0]=0;
      }
    }
  }

  strcpy(&myString[buffer_ptr],"--------------------------------------------------------");
  buffer_ptr=buffer_ptr+sizeof("--------------------------------------------------------")-1;
  sprintf(tempString,WHO_TOTAL,c);
  strcpy(&myString[buffer_ptr],tempString);

  message(ID,myString,0); 
}

void who_short(int ID)
{
unsigned char myString[WHO_BUFFER_SIZE];
unsigned char tempString[1024];
int c,r,buffer_ptr;

  buffer_ptr=0;

  strcpy(myString,"--------------------------------------------------------\n\r");
  buffer_ptr=sizeof("--------------------------------------------------------\n\r")-1;

  c=0;
  for (r=0; r<maxconn; r++)
  {
    if (users[r]->inuse==1)
    {
      if (users[ID]->user_level<10 && (users[r]->user_level==10 && (users[r]->uflags&128)!=0))
      { continue; }

    if ((serverflags&1)==1 && (users[ID]->channel!=users[r]->channel &&
         users[ID]->user_level<8)) continue;

      c++;
      sprintf(tempString,"[%d]%-18s",r,users[r]->username);
      strcpy(&myString[buffer_ptr],tempString);
      buffer_ptr=buffer_ptr+strlen(tempString);
      if (c%3==0)
      { strcat(&myString[buffer_ptr],"\n\r"); buffer_ptr=buffer_ptr+2; }
    }

    if (buffer_ptr>WHO_BUFFER_SIZE-150)
    {
      message(ID,myString,0);
      buffer_ptr=0;
      myString[0]=0;
    }
  }
  if (c%3!=0)
  { strcpy(&myString[buffer_ptr],"\n\r"); buffer_ptr=buffer_ptr+2; }

  strcpy(&myString[buffer_ptr],"--------------------------------------------------------\n\r");
  message(ID,myString,0);
}

void sendpriv(int ID,int OID,char *daMessage)
{
unsigned char tempString[9000];

#ifdef DEBUG
  if (debug==1) printf("TO: %d FROM: %d  MESSAGE: %s\n",ID,OID,daMessage);
#endif
  if (logging==1) 
  {
    fprintf(logfp,"TO: %d %s FROM: %d %s  MESSAGE: %s",ID,users[ID]->username,
         OID,users[OID]->username,daMessage);
    fflush(logfp);
  }

  if (ID<maxconn)
  {
    if (users[ID]->inuse==1)
    {
      message(ID,daMessage,1);
      if ((users[OID]->uflags&16)==0)
      { sprintf(tempString,PRIVATE,ID,users[ID]->username); }
	else
      { sprintf(tempString,PRIVATE_ECHO,ID,users[ID]->username,daMessage); }
      message(OID,tempString,0);
    }
      else
    { message(OID,NOT_HERE,0); }
  }
    else
  { message(OID,NOT_HERE,0); }
}

void sendchan(int ID, int channel, char *daMessage)
{
int r;

  if (logging==1) 
  { 
    fprintf(logfp,"[%s]",channels[channel]); 
    fprintf(logfp,"%s",daMessage); 
    fflush(logfp);
  }

  for (r=0; r<maxconn; r++)
  {
    if (users[r]->inuse==1 && users[r]->channel==channel) 
    {
      if (ID==-1) message(r,daMessage,0);
	else
      if ((users[r]->gags[ID/8]&(1<<(ID%8)))==0) 
      { 
        if (users[r]->user_level<10 && (users[ID]->user_level==10 && (users[ID]->uflags&128)!=0))
        { continue; }
        message(r,daMessage,0);
      }
    }
  }
}

void yell(int ID,char *daMessage)
{
int r;

  if (logging==1) 
  { 
    fprintf(logfp,"%s",daMessage); 
    fflush(logfp);
  }

  for(r=0; r<maxconn; r++)
  {
    if(users[r]->inuse==1)
    {
      if ((users[r]->gags[ID/8]&(1<<(ID%8)))==0)
	if ((users[r]->uflags&8)==0) message(r,daMessage,0);
    }
  }
}

void sendchanbut(int ID, int channel, char *daMessage)
{
int r;

  if (logging==1) 
  { 
    fprintf(logfp,"[%s]",channels[channel]); 
    fprintf(logfp,"%s",daMessage); 
    fflush(logfp);
  }

  for (r=0; r<maxconn; r++)
  {
    if ((users[r]->inuse==1 && users[r]->channel==channel) && 
        (r!=ID && (users[r]->uflags&64)==0)) 
    { 
      if (users[r]->user_level<10 && (users[ID]->user_level==10 && (users[ID]->uflags&128)!=0))
      { continue; }
      message(r,daMessage,0); 
    }
  }
}

void sendall(int ID, char *daMessage)
{
int r;

  if (logging==1) 
  { 
    fprintf(logfp,"%s",daMessage); 
    fflush(logfp);
  }

  for (r=0; r<maxconn; r++)
  {
    if (users[r]->inuse==1)
    {
      if (ID==-1) message(r,daMessage,0);
	else
      if ((users[r]->gags[ID/8]&(1<<(ID%8)))==0 && (users[r]->uflags&64)==0) 
      {
        if (users[r]->user_level<10 && (users[ID]->user_level==10 && (users[ID]->uflags&128)!=0))
        { continue; }

        message(r,daMessage,0);
      }
    }
  }
}

void sendallbut(int ID, char *daMessage)
{
int r;

  if (logging==1) 
  { 
    fprintf(logfp,"%s",daMessage); 
    fflush(logfp);
  }

  for (r=0; r<maxconn; r++)
  {
    if (users[r]->inuse==1 && r!=ID)
    {
      if (ID==-1) message(r,daMessage,0);
	else
      if ((users[r]->gags[ID/8]&(1<<(ID%8)))==0 && (users[r]->uflags&64)==0) 
      {
        if (users[r]->user_level<10 && (users[ID]->user_level==10 && (users[ID]->uflags&128)!=0))
        { continue; }
        message(r,daMessage,0);
      }
    }
  }
}

void help(int ID)
{
  message(ID,help_message,0);
}

void setup(int argc, char *argv[])
{
unsigned char *allowptr;
unsigned char *banptr;
int r;

  port=DEFAULT_PORT;
  configdir[0]=0;

  for (r=1; r<argc; r++)
  {
    if (strcasecmp(argv[r],"-f")==0) 
    { strcpy(configdir,argv[++r]); break; }
  }

  logfile[0]=0;
  passwd[0]=0;

  if (configdir[0]==0)
  { strcpy(configdir,"/etc/nakenchat.conf"); }

  strcpy(channels[0],MAINCHANNEL);
  strcpy(sysoppw,"password");
  uptime=time(NULL);
  srand(uptime);

  read_config();

  if (logfile[0]!=0) printf("Logfile: %s\n",logfile);

  printf("Currently banned sites:\n");
  banptr=bans;
  for (r=0; r<bancount; r++)
  {
    printf("%d: %s\n",r,banptr);
    banptr=banptr+strlen(banptr)+1;
  }

  printf("%d bans found\n\n",bancount);

  if (allowcount!=0)
  {
    printf("Only these sites may logon:\n");
    allowptr=allows;
    for (r=0; r<allowcount; r++)
    {
      printf("%d: %s\n",r,allowptr);
      allowptr=allowptr+strlen(allowptr)+1;
    }
  }

  for (r=1; r<argc; r++)
  {
    if (strcmp(argv[r],"-p")==0)
    { port=atoi(argv[++r]); }
      else
    if (strcasecmp(argv[r],"-d")==0) debug=1;
  }
}

int checkname_dup(unsigned char *name)
{
int t;

  for (t=0; t<maxconn; t++)
  {
    if (users[t]->inuse!=0)
    {
      if (strncasecmp(users[t]->username,name,MAX_USER_NAME_LENGTH)==0)
      { return 1; }
    }
  }

  return 0;
}

int read_param(FILE *fp, char *s)
{
int ch;
int r;

  r=0;
  s[0]=0;

  while(1)
  {
    ch=getc(fp);
    if (ch==EOF && r==0) return -1;
    if ((ch=='\n' || ch=='\r') && r==0) continue;
    if (ch=='\\') { s[r++]=getc(fp); continue; }
    if (ch==':' || ch=='\n' || ch=='\r' || ch==EOF) break;
    s[r++]=ch;
  }

  s[r]=0;
  if (ch==':') return 1;

  return 0;
}


int checkname_reg(unsigned char *name, int ID)
{
FILE *in;
unsigned char *p;
unsigned char param[1024];
char seed[3];
char crypted[20];
unsigned int l,t;
int i;

  in=fopen(passwd,"rb");
  if (in==0)
  {
#ifdef DEBUG
    if (debug==1) printf("Couldn't open password file.\n");
#endif
    passwd[0]=0;
    return 1;
  }

  l=strlen(name);
  t=l;
  while (name[l]!='=' && l>0) l--;
  if (l==0)
  {
    p=&name[t];
  }
    else
  {
    name[l]=0;
    p=&name[l+1];
  }

  while(1)
  {
    i=read_param(in,param);

    if (strcasecmp(param,name)==0)
    {
      if (ID==-1) return 1;

      read_param(in,param);
      seed[0]=param[0];
      seed[1]=param[1];
      seed[2]=0;
      strcpy(crypted,crypt(p,seed));
      if (strcmp(crypted,param)!=0)
      { fclose(in); return 1; }

      read_param(in,param);
      users[ID]->user_level=atoi(param);
      read_param(in,param);
      users[ID]->emote_char=param[0];
      read_param(in,param);
      t=atoi(param);
      l=0xffffffff^(1|2|16);
      users[ID]->uflags=users[ID]->uflags&l;
      users[ID]->uflags=users[ID]->uflags|t;
      read_param(in,param);
      i=channel(ID,param);
      if (i>=0)
      {
        users[ID]->channel=i;
        users[ID]->uflags=users[ID]->uflags&65531;
      }

      fclose(in);
      return 0;
    }

    if (i==1)
    { while(read_param(in,param)); }
      else
    { break; }
  }

  fclose(in);

  return 2;
}





syntax highlighted by Code2HTML, v. 0.9.1