#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/time.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 <string.h>
#include <pthread.h>
#include "language.h"
#include "globals.h"
#include "functions.h"
int sockfd,bancount,allowcount,badwordcount,port;
struct User **users;
struct User nulluser;
unsigned char channels[MAXCHAN+2][20];
int channelop[MAXCHAN+2];
int cflags[MAXCHAN+2];
int international,debug,censor;
unsigned int uptime;
unsigned char sysoppw[15];
unsigned char serverflags;
unsigned char bans[BANS_BUFFER_SIZE];
unsigned char allows[ALLOWS_BUFFER_SIZE];
unsigned char badword[BAD_WORD_BUFFER_SIZE];
unsigned char welcome[2048];
unsigned char logfile[256];
unsigned char passwd[256];
char configdir[256];
int welcomelen;
int logging;
int maxconn;
int minconn;
int gag_size;
int max_idle_time=0;
FILE *logfp;
int init(int socketid, struct sockaddr_in *cli_addr, int clilen)
{
int k,r,t,ID;
unsigned char tempString[200];
struct hostent *my_hostent=NULL;
unsigned char *address=0;
unsigned char *fullmessage={ SORRY_FULL };
unsigned char *toomanyconnections={ TOO_MANY_CONNECTIONS };
unsigned char *allowptr;
unsigned char *banptr;
if ((serverflags&2)==2)
{ my_hostent=gethostbyaddr((char *)&(cli_addr->sin_addr.s_addr),4,AF_INET); }
for (r=0; r<maxconn; r++)
{
if (users[r]->inuse==0)
{ break; }
}
if (r>=maxconn)
{
#ifdef DEBUG
if (debug==1) printf("Chat server full\n");
#endif
write(socketid,fullmessage,strlen(fullmessage));
close(socketid);
return -1;
}
if (users[r]->idletime==-1)
{
#ifdef DEBUG
if (debug==1) printf("Allocing new user %d\n",r);
#endif
users[r]=malloc(sizeof(struct User));
users[r]->gags=malloc(gag_size);
}
#ifdef DEBUG
if (debug==1)
{
printf("searched for open User: found %d\n",r);
fflush(stdout);
}
#endif
if (my_hostent!=NULL && (serverflags&2)==2)
{ safestrncpy(users[r]->location,my_hostent->h_name,61); }
else
{
address=(char*)&cli_addr->sin_addr.s_addr;
sprintf(users[r]->location,"%d.%d.%d.%d",address[0],address[1],address[2],address[3]);
}
#ifdef DEBUG
if (debug==1)
{
printf("Connected from location: %s\n",users[r]->location);
fflush(stdout);
}
#endif
if ((serverflags&8)==8)
{
for (t=0; t<maxconn; t++)
{
if (users[t]->inuse!=0)
{
if (t==r) continue;
if (strcmp(users[t]->location,users[r]->location)==0)
{
#ifdef DEBUG
if (debug==1) printf("Too many connections from this IP\n");
#endif
write(socketid,toomanyconnections,strlen(toomanyconnections));
close(socketid);
return -1;
}
}
}
}
banptr=bans;
for (t=0; t<bancount; t++)
{
if (strcasestr_m(users[r]->location,banptr)!=NULL)
{
write(socketid,BANNED,strlen(BANNED));
#ifdef DEBUG
if (debug==1)
{
printf("This site was banned(%d):\n",close(socketid));
fflush(stdout);
}
#endif
close(socketid);
return -1;
}
banptr=banptr+strlen(banptr)+1;
}
if (allowcount!=0 && t==bancount)
{
allowptr=allows;
for (t=0; t<allowcount; t++)
{
if (strcasestr_m(users[r]->location,allowptr)!=NULL) break;
allowptr=allowptr+strlen(allowptr)+1;
}
if (t==allowcount)
{
write(socketid,REFUSED,strlen(REFUSED));
#ifdef DEBUG
if (debug==1)
{
printf("This site was banned(%d):\n",close(socketid));
fflush(stdout);
}
#endif
close(socketid);
return -1;
}
}
k=0;
if ((serverflags&8)==8)
{
for (k=0; k<maxconn; k++)
{
if (users[k]->inuse!=1) continue;
if (strcmp(users[r]->location,users[k]->location)==0)
{ k=-1; break; }
}
}
users[r]->ID=r;
users[r]->socketid=socketid;
ID=r;
users[ID]->spam=0;
users[ID]->channel=0;
users[ID]->user_level=0;
users[ID]->uflags=16;
users[ID]->channel=0;
users[ID]->stamptime=0;
users[ID]->lastp=-1;
users[ID]->ptr=0;
users[ID]->lptr=0;
users[ID]->lr=0;
users[ID]->emote_char=EMOTE_CHAR;
users[ID]->logontime=time(NULL);
users[ID]->idletime=time(NULL);
safestrncpy(users[ID]->username,users[ID]->location,MAX_USER_NAME_LENGTH);
users[ID]->socketfd=fdopen(socketid,"rb+");
if (users[ID]->socketfd==0) printf("Problem opening file desc.\n\n");
fcntl(users[ID]->socketid, F_SETFL, O_NONBLOCK);
/* hmmm
if (setsockopt(sockfd,SOL_SOCKET,SO_RCVLOWAT,&sopt,sizeof(sopt)))
{ printf("socket options SO_RCVLOWAT can't be set.\n"); }
if (setsockopt(sockfd,SOL_SOCKET,SO_SNDLOWAT,&sopt,sizeof(sopt)))
{ printf("socket options SO_SNDLOWAT can't be set.\n"); }
*/
t=0;
while((users[ID]->username[t]!=0 && users[ID]->username[t]!='.') && t<16) t++;
users[ID]->username[t]=0;
if ((serverflags&128)==128)
{
if (checkname_dup(users[ID]->username)==1)
{ strcpy(users[ID]->username,"unnamed"); }
}
if (passwd[0]!=0)
{
if (checkname_reg(users[ID]->username,-1)==1)
{ strcpy(users[ID]->username,"unnamed"); }
}
for (r=0; r<gag_size; r++)
{ users[ID]->gags[r]=0; }
write(users[ID]->socketid,welcome,welcomelen);
if ((serverflags&64)==64)
{
/*
sprintf(tempString,NEED_TO_LOGIN,ID,users[ID]->location);
message(ID,tempString,0);
*/
users[ID]->inuse=100;
}
else
{
users[ID]->inuse=1;
sprintf(tempString,YOU_LOGIN,ID,users[ID]->location);
message(ID,tempString,0);
if ((serverflags&4)!=0)
{ sprintf(tempString,SOMEONE_LOGIN1,ID,users[ID]->location); }
else
{ sprintf(tempString,SOMEONE_LOGIN2,ID); }
sendallbut(ID,tempString);
update_list(ID,1);
}
/*
sprintf(tempString,"+[%d]%s\n\r",ID,users[ID]->username);
for (r=0; r<maxconn; r++)
{
if (users[r]->inuse==1 && (users[r]->uflags&256)!=0)
{ message(r,tempString,0); }
}
*/
return 0;
}
void kill_user(int ID)
{
int r,curr;
unsigned char spa[80];
#ifdef DEBUG
if (debug==1)
{
printf("Getting ready to close socket.\n");
if (users[ID]->inuse!=4)
printf("Socket Close Return value: %d:\n",close(users[ID]->socketid));
}
else
#endif
{ if (users[ID]->inuse!=4) close(users[ID]->socketid); }
curr=users[ID]->channel;
if (curr!=0)
{
if (channelop[curr]==ID) channelop[curr]=-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; }
}
for (r=0; r<maxconn; r++) if (users[r]->inuse==1) users[r]->gags[ID/8]&=(unsigned char)((1<<(ID%8))^255);
for (r=0; r<maxconn; r++) if (users[r]->inuse==1 && users[r]->lastp==ID) users[r]->lastp=-1;
for (r=0; r<maxconn; r++)
{ if (channelop[r]==ID) channelop[r]=-1; }
#ifdef DEBUG
if (debug==1) printf("Connection dead: %d\n",ID);
#endif
if (users[ID]->inuse!=100)
{
users[ID]->inuse=0;
sprintf(spa,JUST_LEFT,ID,users[ID]->username);
if ((serverflags&1)==0)
{ sendallbut(ID,spa); }
else
{ sendchanbut(ID,users[ID]->channel,spa); }
update_list(ID,0);
}
else
{ users[ID]->inuse=0; }
users[ID]->idletime=time(NULL);
}
int buffered_read(int ID)
{
/* char telnet_echo[]={ 255, 251, 34, 255, 250, 34, 1, 1, 240 }; */
/* char telnet_echo[]={ 255, 252, 1 }; */
int r,t=0;
while(1)
{
errno=0;
if (users[ID]->lr>=users[ID]->lptr)
{
users[ID]->lptr=recv(users[ID]->socketid,users[ID]->myString,512-users[ID]->ptr,0);
users[ID]->lr=0;
if (users[ID]->lptr>=0) users[ID]->myString[users[ID]->lptr]=0;
if (users[ID]->lptr==0) return -1;
if (users[ID]->lptr<0)
{
/*
if (users[ID]->inuse==1)
if (errno==EINTR || errno==EAGAIN)
{ errno=0; return 0; }
*/
#ifdef DEBUG
if (debug==1)
{ printf("Lost Connection (NULL): %d\n",ID); fflush(stdout); }
#endif
users[ID]->ptr=0;
users[ID]->lptr=0;
return -1;
}
}
for (r=users[ID]->lr; r<users[ID]->lptr; r++)
{
if ((users[ID]->myString[r]=='\n' || users[ID]->myString[r]=='\r') || users[ID]->myString[r]==0)
{
/*
if (t!=0 || users[ID]->myString[r]==0)
{ t=-1; break; }
*/
t=-1;
break;
}
if (users[ID]->myString[r]==127 || users[ID]->myString[r]==8)
{ if (users[ID]->ptr>0) users[ID]->ptr--; }
else
if (international==0)
{ if (users[ID]->myString[r]>=32 && users[ID]->myString[r]<127) users[ID]->outString[users[ID]->ptr++]=users[ID]->myString[r]; }
else
{ if (users[ID]->myString[r]>=32 && users[ID]->myString[r]<255) users[ID]->outString[users[ID]->ptr++]=users[ID]->myString[r]; }
t=1;
}
users[ID]->lr=r+1;
if ((t==-1 && users[ID]->ptr>0) || users[ID]->ptr>512)
{
users[ID]->outString[users[ID]->ptr]=0;
users[ID]->ptr=0;
if (users[ID]->myString[users[ID]->lr]=='\n' ||
users[ID]->myString[users[ID]->lr]=='\r')
{ users[ID]->lr++; }
return 1;
}
else
{ return 0; }
}
}
void chat(int *params)
{
int t=0,r,trim,x,y;
unsigned int tid;
unsigned char tempString[1500];
unsigned char ch,ch1;
unsigned char *bad;
unsigned char *badwordptr;
unsigned char *trimString;
time_t myTime;
int ID=0;
int msock=0;
fd_set readset;
struct timeval tv;
char *outString;
unsigned char *s;
int gc_time,thread_num;
int dirty_buffer;
thread_num=params[0];
gc_time=time(NULL);
while(1)
{
if (time(NULL)-gc_time>GC_TIME)
{
for (r=minconn+thread_num; r<MAXCONN; r=r+MAX_USER_THREADS)
{
if (users[r]->inuse==0 && users[r]->idletime!=-1)
{
#ifdef DEBUG
if (debug==1) printf("Deallocating line %d\n",r);
#endif
if (time(NULL)-users[r]->idletime>GC_TIME)
free(users[r]->gags);
free(users[r]);
users[r]=&nulluser;
}
}
if (max_idle_time>0)
{
for (r=thread_num; r<MAXCONN; r=r+MAX_USER_THREADS)
{
if ((users[r]->inuse!=0 && users[r]->user_level<5) && time(NULL)-users[r]->idletime>max_idle_time)
{
message(r,KICKED_FOR_IDLING,0);
users[r]->inuse=2;
kill_user(r);
}
}
}
gc_time=time(NULL);
}
/* printf("HERE AGAIN\n"); */
FD_ZERO(&readset);
/*
FD_SET(sockfd,&readset);
msock=sockfd;
*/
msock=0;
dirty_buffer=0;
for (r=thread_num; r<maxconn; r=r+MAX_USER_THREADS)
{
if (users[r]->inuse==1 || users[r]->inuse==100)
{
FD_SET(users[r]->socketid,&readset);
if (msock<users[r]->socketid) msock=users[r]->socketid;
if (users[r]->lr<users[r]->lptr) dirty_buffer=1;
}
}
if (dirty_buffer==0)
{
tv.tv_sec=1;
tv.tv_usec=0;
}
else
{
tv.tv_sec=0;
tv.tv_usec=1;
}
/* if (((t=select(msock+1,&readset,NULL,NULL,&tv))==-1) && (errno!=EINTR)) */
if ((t=select(msock+1,&readset,NULL,NULL,&tv))==-1)
{
if (errno!=EINTR)
{
#ifdef DEBUG
if (debug==1) printf("not EINTR\n");
#endif
}
else
{
#ifdef DEBUG
if (debug==1) printf("Problem with select\n");
#endif
}
}
/*
printf("Heartbeat %d --- %d\n",thread_num,t);
*/
for (ID=thread_num; ID<maxconn; ID=ID+MAX_USER_THREADS)
{
errno=0;
if (users[ID]==0) continue;
if (users[ID]->inuse!=1 && users[ID]->inuse!=100) continue;
/*
printf("Checking line %d %d %d %d\n",ID,users[ID]->lr,users[ID]->lptr,users[ID]->ptr);
*/
if (users[ID]->inuse==100 && time(NULL)-users[ID]->logontime>60)
{ kill_user(ID); }
if (users[ID]->lr<users[ID]->lptr)
{
/* printf("dirty\n"); */
}
else
if (FD_ISSET(users[ID]->socketid,&readset))
{ }
else
continue;
r=buffered_read(ID);
if (r<0) kill_user(ID);
if (r<1) continue;
/*
printf("FILE: %d\n",ID);
fflush(stdout);
printf("READ: %s\n\n",users[ID]->outString);
fflush(stdout);
*/
outString=users[ID]->outString;
trim=0;
while(outString[trim]==' ') trim++;
if (censor>0 && outString[trim+1]!='P')
{
badwordptr=badword;
for (r=0; r<badwordcount; r++)
{
if ((bad=strcasestr_m(&outString[trim],badwordptr))!=0)
{
if (censor==1)
{
while (bad[0]!=0 && bad[0]!=' ') { bad[0]='*'; bad++; }
}
else
if (censor==2)
{
message(ID,PLEASE_CENSOR,0);
outString[trim]=0;
r=999999;
}
else
if (censor==3)
{
users[ID]->warnings++;
if (users[ID]->warnings<4)
{ message(ID,PLEASE_CENSOR,0); }
else
{
message(ID,WARNED,0);
users[ID]->inuse=2;
kill_user(ID);
}
outString[trim]=0;
r=999999;
}
else
if (censor==4)
{
message(ID,PLEASE_CENSOR,0);
users[ID]->inuse=2;
kill_user(ID);
r=999999;
}
r=r-1;
continue;
}
badwordptr=badwordptr+strlen(badwordptr)+1;
}
}
if (r==999999) continue;
if (time(NULL)-users[ID]->idletime<2)
{ if ((outString[trim]!='\n' && outString[trim]!='\r') && outString[trim]!=0) users[ID]->spam++; }
else
{ users[ID]->spam=0; }
if (users[ID]->spam==8)
{
message(ID,SPAM,0);
kill_user(ID);
continue;
}
myTime=time(NULL);
users[ID]->idletime=myTime;
#ifdef DEBUG
if (debug==1)
{
printf("Read in: %d bytes on thread %d.\n",strlen(outString),thread_num);
printf("%s typed: %s\n",users[ID]->username,outString);
fflush(stdout);
}
#endif
ch=outString[0];
if (users[ID]->inuse==100)
{
if ((ch!='.' && ch!='/') || outString[1]!='n')
{
message(ID,NAME_YOURSELF,0);
continue;
}
}
if (ch=='.' || ch=='/')
{
ch=outString[1];
ch1=outString[2];
trim=2;
while(outString[trim]==' ' && outString[trim]!=0) trim++;
trimString=outString+trim+1;
r=strlen(trimString)-1;
while((trimString[r]==' ' || trimString[r]=='\r') || trimString[r]=='\n') trimString[r--]=0;
if (ch=='n')
{
if (outString[trim]!=0)
{
if (passwd[0]!=0)
{
r=checkname_reg(&outString[trim],ID);
if (r==1)
{
message(ID,NAME_IS_REGISTERED,0);
continue;
}
else
if (r==2 && (serverflags&32)==32)
{
message(ID,MUST_REGISTER,0);
continue;
}
}
if ((serverflags&128)==128)
{
if (checkname_dup(&outString[trim])==1)
{
message(ID,NAME_IN_USE,0);
continue;
}
}
update_list(ID,0);
safestrncpy(users[ID]->username,outString+trim,MAX_USER_NAME_LENGTH);
sprintf(outString,YOUR_NAME,users[ID]->username);
message(ID,outString,0);
update_list(ID,1);
if (users[ID]->inuse==100)
{
users[ID]->inuse=1;
if ((serverflags&4)!=0)
{ sprintf(tempString,NAME_LOGIN1,ID,users[ID]->username,users[ID]->location); }
else
{ sprintf(tempString,NAME_LOGIN2,ID,users[ID]->username); }
if ((serverflags&1)==0)
{ sendall(ID,tempString); }
else
{ sendchan(ID,users[ID]->channel,tempString); }
}
}
else
{ message(ID,ILLEGAL_NAME,0); }
}
else
if (ch=='Z')
{
clientshow(ID);
users[ID]->uflags^=256;
}
else
if (ch=='w')
{
who(ID,outString+trim);
}
else
if (ch=='q')
{
message(ID, BYE_BYE,0);
kill_user(ID);
}
else
if (ch=='f') { who_short(ID); }
else
if (ch=='e')
{
if (outString[trim]!=0)
{
users[ID]->emote_char=outString[trim];
sprintf(tempString,NEW_EMOTE_CHAR,users[ID]->emote_char);
message(ID,tempString,0);
}
else
{
if ((users[ID]->uflags&16)==16)
{ message(ID,ECHOS_OFF,0); }
else
{ message(ID,ECHOS_ON,0); }
users[ID]->uflags=users[ID]->uflags^16;
}
}
else
if (ch=='y' && ((serverflags&1)==0 || users[ID]->user_level>=8))
{
if ((users[ID]->uflags&8)!=0)
{ message(ID,CANT_YELL,0); }
else
if ((users[ID]->uflags&4)!=0)
{ message(ID,CANT_YELL,0); }
else
{
if (outString[trim]==users[ID]->emote_char)
{
trim++;
while(outString[trim]==' ' && outString[trim]!=0) trim++;
sprintf(tempString,"#%d#%s %s\n\r",ID,users[ID]->username,outString+trim);
yell(ID,tempString);
}
else
{
sprintf(tempString,"#%d#%s: %s\n\r",ID,users[ID]->username,outString+trim);
yell(ID,tempString);
}
}
}
else
if (ch=='b')
{
if ((users[ID]->uflags&1)==1)
{ message(ID,BEEPS_OFF,0); }
else
{ message(ID,BEEPS_ON,0); }
users[ID]->uflags=users[ID]->uflags^1;
}
else
if (ch=='h' && ch1=='i')
{
if ((users[ID]->uflags&2)==2)
{ message(ID,HILITE_OFF,0); }
else
{ message(ID,HILITE_ON,0); }
users[ID]->uflags=users[ID]->uflags^2;
}
else
if (ch=='h' && ch1=='e') { help(ID); }
else
if (ch=='m')
{
users[ID]->uflags=users[ID]->uflags^64;
if ((users[ID]->uflags&64)==64)
{ message(ID,SYSMES_OFF,0); }
else
{ message(ID,SYSMES_ON,0); }
}
else
if (ch=='d')
{
users[ID]->uflags=users[ID]->uflags^32;
if ((users[ID]->uflags&32)==32)
{ message(ID,TIMESTAMP_ON,0); }
else
{ message(ID,TIMESTAMP_OFF,0); }
}
else
if (ch=='h' && ch1=='u')
{
if ((users[ID]->uflags&8)==8)
{ message(ID,YELLING_ON,0); }
else
{ message(ID,YELLING_OFF,0); }
users[ID]->uflags=users[ID]->uflags^8;
}
else
if (ch=='a' && ((serverflags&1)==0 || users[ID]->user_level>=8))
{ channelinfo(ID); }
else
if (ch=='l')
{
if ((channelop[users[ID]->channel]!=ID || users[ID]->channel==0) && users[ID]->user_level<10)
{ message(ID,CANNOT_LOCK,0); }
else
if (users[ID]->channel==0)
{ message(ID,CANT_LOCK_MAIN,0); }
else
{
cflags[users[ID]->channel]=cflags[users[ID]->channel]^1;
if ((cflags[users[ID]->channel]&1)==1)
{ sendchan(ID,users[ID]->channel,CHANNEL_LOCKED); }
else
{ sendchan(ID,users[ID]->channel,CHANNEL_UNLOCKED); }
}
}
else
if (ch=='o')
{
r=getNum(outString+trim,ID);
if (r==-1)
{ }
else
if ((channelop[users[ID]->channel]!=ID || users[ID]->channel==0) && users[ID]->user_level<10)
{ message(ID,NOT_OWNER,0); }
else
if (users[ID]->channel==0)
{ message(ID,NO_MAIN_OWNER,0); }
else
if (r==ID)
{ message(ID,ALREADY_OWN,0); }
else
if (users[r]->channel!=users[ID]->channel)
{ message(ID,NOT_IN_CHAN,0); }
else
{
channelop[users[ID]->channel]=r;
sprintf(tempString,NEW_OWNER,r,users[r]->username);
sendchan(-1,users[ID]->channel,tempString);
}
}
else
if (ch=='s')
{
if (channelop[users[ID]->channel]==ID && users[ID]->channel!=0)
{
r=getNum(outString+trim,ID);
if (r==-1)
{ }
else
{
if (users[r]->channel==users[ID]->channel)
{
if ((users[r]->uflags&4)==4)
{
message(r,YOU_UNSQUELCH,0);
sprintf(tempString,YOU_UNSQUELCHED,r,users[r]->username);
message(ID,tempString,0);
}
else
{
message(r,YOU_SQUELCH,0);
sprintf(tempString,YOU_SQUELCHED,r,users[r]->username);
message(ID,tempString,0);
}
users[r]->uflags=users[r]->uflags^4;
}
else
{ message(ID,NOT_IN_CHAN,0); }
}
}
else
{ message(ID,CANT_SQUELCH,0); }
}
else
if (ch=='c' && ((serverflags&1)==0 || users[ID]->user_level>=8))
{
if (strlen(outString+trim)>0)
{
outString[14+trim]=0;
r=0;
while(outString[r]!='\n' && outString[r]!='\r' && outString[r]!=0) r++;
outString[r]=0;
if (r==trim)
{
sprintf(tempString,YOU_ARE_IN,channels[users[ID]->channel]);
message(ID,tempString,0);
continue;
}
t=0;
r=channel(ID,outString+trim);
if (r==-2)
{
sprintf(tempString,YOU_ALREADY_IN,outString+trim);
message(ID,tempString,0);
}
else
if (r==-1)
{ message(ID,CHAN_LOCKED,0); }
else
if (r==-3)
{ message(ID,CHAN_FULL,0); }
else
{
if (channelop[users[ID]->channel]==ID && users[ID]->channel!=r)
{ channelop[users[ID]->channel]=-1; }
#ifdef HIDDEN_CAVES
if ((t=ConvNum(outString+trim))>=1000 && t<2000)
{
sprintf(tempString,WENT_TO_CAVE,ID,users[ID]->username);
sendchanbut(ID,users[ID]->channel,tempString);
}
else
#endif
{
sprintf(tempString,WENT_TO_CHAN,ID,users[ID]->username,channels[r]);
sendchanbut(ID,users[ID]->channel,tempString);
}
#ifdef USER_LIST_CHAN
update_list(ID,0);
#endif
users[ID]->channel=r;
users[ID]->uflags=users[ID]->uflags&65531;
sprintf(tempString,HAS_JOINED,ID,users[ID]->username);
sendchan(ID,users[ID]->channel,tempString);
#ifdef USER_LIST_CHAN
update_list(ID,1);
#endif
if ((users[ID]->uflags&256)!=0) clientshow(ID);
}
}
else
{
sprintf(tempString,YOU_ARE_IN,channels[users[ID]->channel]);
message(ID,tempString,0);
}
}
else
if (ch=='u')
{
timediff(time(NULL),uptime,outString);
sprintf(tempString,UPTIME,outString);
message(ID,tempString,0);
}
else
if (ch=='t')
{
users[ID]->stamptime=time(NULL);
sprintf(tempString,THE_TIME,ctime((time_t*)&users[ID]->idletime));
message(ID,tempString,0);
}
else
if (ch=='v')
{
sprintf(tempString,">> %s\n\r",VERSION);
message(ID,tempString,0);
}
else
if (ch=='g')
{
r=getNum(outString+trim,ID);
if (r==-1)
{ }
else
{
if (r==ID)
{ message(ID,CANT_GAG,0); }
else
{
x=r/8;
y=r%8;
users[ID]->gags[x]=(unsigned char)((int)users[ID]->gags[x]^(1<<y));
if ((users[ID]->gags[x]&(1<<y))!=0)
{ sprintf(tempString,YOU_GAGGED,r,users[r]->username); }
else
{ sprintf(tempString,YOU_UNGAGGED,r,users[r]->username); }
message(ID,tempString,0);
}
}
}
else
if (ch=='P')
{
if (strcmp(outString+trim,sysoppw)==0)
{
/* users[ID]->sysop=users[ID]->sysop^1; */
if (users[ID]->user_level==10)
{ users[ID]->user_level=0; }
else
{ users[ID]->user_level=10; }
if (users[ID]->user_level==0) { message(ID,SUPER_OFF,0); }
else
{ message(ID,SUPER_ON,0); }
}
else
if (users[ID]->user_level==10)
{
r=getNum(outString+trim,ID);
if (r==-1)
{ }
else
{
/* users[r]->sysop=users[r]->sysop^1; */
if (users[r]->user_level==10)
{ users[r]->user_level=0; }
else
{ users[r]->user_level=10; }
if (users[r]->user_level==10)
{
message(r,GRANT_SUPER,0);
sprintf(tempString,NOW_SUPER,r,users[r]->username);
}
else
{
message(r,REVOKE_SUPER,0);
sprintf(tempString,NOT_SUPER,r,users[r]->username);
}
message(ID,tempString,0);
}
}
else
{ message(ID,UNDERSTAND_MESSAGE,0); }
}
else
if (ch=='k')
{
if ((channelop[users[ID]->channel]==ID && users[ID]->channel!=0) || (users[ID]->user_level==10 && users[ID]->channel!=0))
{
r=getNum(outString+trim,ID);
if (r==-1)
{ }
else
{
if (users[r]->channel==users[ID]->channel || users[ID]->user_level==10)
{
t=channel(r,"0");
sprintf(tempString,WAS_KICKED,r,users[r]->username);
sendchanbut(r,users[ID]->channel,tempString);
sprintf(tempString,KICKED_YOU,ID,users[ID]->username);
message(r,tempString,0);
users[r]->channel=t;
users[r]->uflags=users[r]->uflags&65531;
sprintf(tempString,HAS_JOINED,r,users[r]->username);
sendchan(r,0,tempString);
}
else
{ message(ID,NOT_IN_CHAN,0); }
}
}
else
{ message(ID,CANNOT_KICK,0); }
}
else
if (ch=='i')
{
r=getNum(outString+trim,-1);
if (r==-1)
{ r=ID; }
if ((r<0 || r>maxconn) || (users[r]->inuse!=1
|| ((users[r]->uflags&128)==128 && users[ID]->user_level<7)))
{ message(ID,NOT_HERE,0); }
else
{
if ((serverflags&4)!=0 || users[ID]->user_level>=7)
{ sprintf(tempString,INFO_LOC,r,users[r]->username,users[r]->location); }
else
{ sprintf(tempString,">> [%d]%s\n\r",r,users[r]->username); }
strcat(tempString,TIME_ONLINE);
timediff(time(NULL),users[r]->logontime,outString);
strcat(tempString,outString);
strcat(tempString,"\n\r");
strcat(tempString,IDLE_TIME);
timediff(time(NULL),users[r]->idletime,outString);
strcat(tempString,outString);
strcat(tempString,"\n\r");
message(ID,tempString,0);
}
}
else
if (ch=='p')
{
r=getNum(outString+trim,-1);
if (r==-1)
{ r=users[ID]->lastp; }
else
{ trim=trim+strip(outString+trim); }
if (r>=maxconn)
{ message(ID,NOT_HERE,0); }
else
if (r!=-1)
{
if (strlen(outString+trim)==0) strcpy(outString," ");
if (users[r]->inuse!=1)
{ message(ID,NOT_HERE,0); }
else
if ((users[r]->gags[ID/8]&(1<<(ID%8)))!=0)
{ message(ID,GAGGED_YOU,0); }
else
if ((serverflags&1)==1 && users[ID]->channel!=users[r]->channel && users[ID]->user_level<8)
{ message(ID,NOT_HERE,0); }
else
if (outString[trim]==users[ID]->emote_char)
{
trim++;
while(outString[trim]==' ' && outString[trim]!=0)
{ trim++; }
sprintf(tempString,PRIVATE1,ID,users[ID]->username,outString+trim);
sendpriv(r,ID,tempString);
users[ID]->lastp=r;
}
else
{
sprintf(tempString,PRIVATE2,ID,users[ID]->username,outString+trim);
sendpriv(r,ID,tempString);
users[ID]->lastp=r;
}
}
else
{ message(ID,UNDERSTAND_MESSAGE,0); }
}
else
if (users[ID]->user_level==10)
{
if (ch=='R')
{
message(ID,RE_READ,0);
read_config();
}
else
if (ch=='U')
{
r=getNum(outString+trim,ID);
trim=trim+strip(outString+trim);
sprintf(tempString,"*%s\n\r",outString+trim);
if (r==-1)
{ sendchanbut(ID,users[ID]->channel,tempString); }
else
{ message(r,tempString,0); }
message(ID,URL_SENT,0);
}
else
if (ch=='G')
{
if ((outString+trim)[0]==0)
{
r=-1; tid=-1;
for (t=0; t<maxconn; t++)
{
if ((users[t]->inuse==1 && users[t]->logontime<tid) &&
(users[t]->user_level<10 && users[t]->channel==0))
{
r=t;
tid=users[t]->logontime;
}
}
if (r==-1)
{ message(ID,NO_ONE_TO_GRAB,0); }
}
else
{ r=getNum(outString+trim,ID); }
if (r==-1)
{ }
else
{
tid=r;
t=0;
r=channel(tid,channels[users[ID]->channel]);
if (r==-2)
{ message(ID,ALREADY_IN,0); }
else
if (r==-3)
{ message(ID,NO_FREE_CHAN,0); }
else
{
r=users[ID]->channel;
if (channelop[users[tid]->channel]==tid && users[tid]->channel!=r)
{ channelop[users[tid]->channel]=-1; }
#ifdef HIDDEN_CAVES
if ((t=ConvNum(outString+trim))>=1000 && t<2000)
{
sprintf(tempString,WENT_TO_CAVE,tid,users[tid]->username);
sendchanbut(tid,users[tid]->channel,tempString);
}
else
#endif
{
sprintf(tempString,WENT_TO_CHAN,tid,users[tid]->username,channels[r]);
sendchanbut(tid,users[tid]->channel,tempString);
}
#ifdef USER_LIST_CHAN
update_list(tid,0);
#endif
users[tid]->channel=r;
users[tid]->uflags=users[tid]->uflags&65531;
sprintf(tempString,HAS_JOINED,tid,users[tid]->username);
sendchan(tid,users[tid]->channel,tempString);
/* clientshow(ID); */
#ifdef USER_LIST_CHAN
update_list(tid,1);
#endif
}
}
}
else
if (ch=='L')
{
safestrncpy(users[ID]->location,outString+trim,32);
sprintf(tempString,YOUR_LOCATION,users[ID]->location);
message(ID,tempString,0);
}
else
if (ch=='N')
{
r=getNum(outString+trim,ID);
trim=trim+strip(outString+trim);
if (r==-1)
{ }
else
if (outString[trim]!=0)
{
update_list(r,0);
safestrncpy(users[r]->username,outString+trim,MAX_USER_NAME_LENGTH);
sprintf(tempString,SYS_CHANGE_NAME,r,users[r]->username);
message(ID,tempString,0);
update_list(r,1);
}
else
{ message(ID,ILLEGAL_NAME,0); }
}
else
if (ch=='S')
{
r=getNum(outString+trim,ID);
if (r==-1)
{ }
else
if ((users[r]->uflags&4)==4)
{
message(r,YOU_UNSQUELCH,0);
sprintf(tempString,YOU_UNSQUELCHED,r,users[r]->username);
message(ID,tempString,0);
}
else
{
message(r,YOU_SQUELCH,0);
sprintf(tempString,YOU_SQUELCHED,r,users[r]->username);
message(ID,tempString,0);
}
users[r]->uflags=users[r]->uflags^4;
}
else
#ifdef LEET
if (ch=='3')
{
if ((serverflags&16)==0)
{ message(ID,">> 3l1t3 writing turned on.\n\r",0); }
else
{ message(ID,">> 3l1t3 writing turned off.\n\r",0); }
serverflags^=16;
}
else
#endif
if (ch=='W')
{
if (logfile[0]==0)
{ message(ID,CHAT_LOG_OFF,0); }
else
if (logging==1)
{
message(ID,CHAT_LOG_OFF,0);
logging=0;
fclose(logfp);
}
else
{
message(ID,CHAT_LOG_ON,0);
logfile_on(ID);
}
}
else
if (ch=='X')
{
r=getNum(outString+trim,ID);
if (r!=-1)
{
ban_address(users[r]->location);
sprintf(tempString,TEMP_BANNED,users[r]->location);
/*
safestrncpy(bans[bancount++],users[r]->location,29);
sprintf(tempString,TEMP_BANNED,bans[bancount-1]);
*/
message(ID,tempString,0);
kill_user(r);
}
else
{ message(ID,UNDERSTAND_MESSAGE,0); }
}
else
if (ch=='B')
{
if (is_number(outString+trim)==0)
{
r=trim;
while((outString[r]!=' ' && outString[r]!='\t') &&
((outString[r]!='\n' && outString[r]!='\r'))
&& outString[r]!=0) r++;
outString[r]=0;
if (r==trim)
{ message(ID,TO_BAN,0); }
else
{
if (ban_address(&outString[trim])==1)
{ message(ID,TOO_MANY_BANS,0); }
else
{
sprintf(tempString,TEMP_BANNED,&outString[trim]);
message(ID,tempString,0);
}
}
}
else
{
r=getNum(outString+trim,-1);
if ((s=unban_number(r))==0)
{
message(ID,NO_SITE_BANNED,0);
}
else
{
sprintf(tempString,UN_BANNED,s);
message(ID,tempString,0);
}
}
}
else
if (ch=='C')
{
r=getNum(outString+trim,-1);
if (r==-1)
{ message(ID,UNDERSTAND_MESSAGE,0); }
else
if (r>4)
{ message(ID,CENSOR_LEVEL,0); }
else
{
censor=r;
sprintf(tempString,CENSOR_LEVEL_AT,censor);
message(ID,tempString,0);
}
}
else
if (ch=='K')
{
r=getNum(outString+trim,ID);
if (r==-1)
{ }
else
{ kill_user(r); }
}
else
if (ch=='V')
{ viewbans(ID); }
else
if (ch=='D')
{
if ((serverflags&8)!=0)
{ message(ID,IP_NODUPOFF,0); }
else
{ message(ID,IP_NODUPON,0); }
serverflags=serverflags^8;
}
else
if (ch=='H')
{
if ((serverflags&4)!=0)
{ message(ID,IP_ADDRESS_HIDE,0); }
else
{ message(ID,IP_ADDRESS_SHOW,0); }
serverflags=serverflags^4;
}
else
if (ch=='Y')
{
if ((users[ID]->uflags&128)==0)
{ message(ID,INVIS_SYSOP_ON,0); }
else
{ message(ID,INVIS_SYSOP_OFF,0); }
users[ID]->uflags=users[ID]->uflags^128;
}
else
if (ch=='I')
{
if (international==1)
{
international=0;
message(ID,INTERNATIONAL_OFF,0);
}
else
{
international=1;
message(ID,INTERNATIONAL_ON,0);
}
}
else
if (ch=='F')
{
r=getNum(outString+trim,-1);
if (r==-1)
{
show_levels(ID);
}
else
{
trim=trim+strip(outString+trim);
t=getNum(outString+trim,-1);
if (t==-1)
{
sprintf(tempString,USER_LEVEL_IS,r,users[r]->username,users[r]->user_level);
message(ID,tempString,0);
}
else
{
if (t>10) t=10;
users[r]->user_level=t;
sprintf(tempString,USER_LEVEL_CHANGE,r,users[r]->username,t);
message(ID,tempString,0);
sprintf(tempString,YOUR_LEVEL_CHANGE,t);
message(r,tempString,0);
}
}
}
else
{ message(ID,UNDERSTAND_MESSAGE,0); }
}
else
{ message(ID,UNDERSTAND_MESSAGE,0); }
}
else
{
/* if (outString[trim]!='\n') */
if (outString[trim]!=0)
{
if ((users[ID]->uflags&4)!=4)
{
if (outString[trim]==users[ID]->emote_char)
{
trim++;
while(outString[trim]==' ' && outString[trim]!=0) trim++;
#ifdef ENGLISH
if (outString[trim]=='\'' && outString[trim+1]=='s')
{
sprintf(tempString,"[%d]%s%s\n\r",ID,users[ID]->username,outString+trim);
}
else
#endif
{
sprintf(tempString,"[%d]%s %s\n\r",ID,users[ID]->username,outString+trim);
}
}
else
{
sprintf(tempString,"[%d]%s: %s\n\r",ID,users[ID]->username,outString+trim);
}
sendchan(ID,users[ID]->channel,tempString);
}
else
{ message(ID,SQUELCHED,0); }
}
}
}
}
}
int main(int argc,char *argv[])
{
struct sockaddr_in serv_addr;
int r,sopt=1;
struct linger mylinger;
int newsockfd,clilen;
struct sockaddr_in cli_addr;
pthread_t pid;
int threads[MAX_USER_THREADS];
maxconn=MAXCONN;
minconn=10;
max_idle_time=0;
setup(argc,argv);
if (debug==0)
{
r=fork();
if (r==-1)
{ perror("Error: Could not fork\n"); exit(3); }
else
if (r==0)
{
close(STDIN_FILENO);
close(STDERR_FILENO);
if (setsid()==-1)
{ exit(4); }
}
else
{ return 0; }
}
#ifdef DEBUG
if (debug==1)
{
printf("minconn: %d\n",minconn);
printf("maxconn: %d\n",maxconn);
}
#endif
if ((sockfd=socket(AF_INET,SOCK_STREAM,0))<0)
{ printf("Can't open socket.\n"); exit(1); }
bzero((char*)&serv_addr,sizeof(serv_addr));
serv_addr.sin_family=AF_INET;
serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);
serv_addr.sin_port=htons(port);
if (setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&sopt,sizeof(sopt)))
{ printf("socket options REUSERADDR can't be set.\n"); exit(1); }
mylinger.l_onoff=0;
mylinger.l_linger=1;
if (setsockopt(sockfd,SOL_SOCKET,SO_LINGER,&mylinger,sizeof(struct linger)))
{ printf("socket options LINGER can't be set.\n"); exit(1); }
if(bind(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr))<0)
{ printf("server can't bind.\n"); exit(1); }
listen(sockfd,5);
setsignals();
/* YOU MAY NOT EDIT THE NEXT LINE OF CODE */
printf("\nNaken Chat 2.00 (c) 1998-2003 - Michael Kohn\n");
printf("Started on port: %d\n",port);
printf(VERSION"\n\n");
fflush(stdout);
if (debug==0) close(STDOUT_FILENO);
nulluser.inuse=0;
nulluser.idletime=-1;
users=malloc(sizeof(char *)*maxconn);
for (r=0; r<MAXCONN; r++)
{
users[r]=&nulluser;
}
gag_size=MAXCONN/8;
if ((MAXCONN%8)!=0) gag_size++;
for (r=0; r<minconn; r++)
{
users[r]=malloc(sizeof(struct User));
users[r]->gags=malloc(gag_size);
users[r]->inuse=0;
}
for (r=0; r<MAX_USER_THREADS; r++)
{
threads[r]=r;
pthread_create(&pid,NULL,(void*)chat,&threads[r]);
}
/* chat(); */
clilen=sizeof(cli_addr);
while(1)
{
newsockfd=accept(sockfd,(struct sockaddr *)&cli_addr,&clilen);
if (newsockfd<0)
{
#ifdef DEBUG
if (debug==1) { printf("server accept error.\n"); }
#endif
}
else
{
#ifdef DEBUG
if (debug==1)
{
printf("New socket accepted\n");
fflush(stdout);
}
#endif
init(newsockfd,&cli_addr,clilen);
}
}
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1