#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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; rinuse==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; tinuse!=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; tlocation,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; tlocation,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; kinuse!=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; rgags[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; rinuse==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; rinuse==1) if (users[r]->channel==curr && r!=ID) r=maxconn+6; if (rinuse==1) users[r]->gags[ID/8]&=(unsigned char)((1<<(ID%8))^255); for (r=0; rinuse==1 && users[r]->lastp==ID) users[r]->lastp=-1; for (r=0; rinuse!=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; rlptr; 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; rinuse==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; rinuse!=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; rinuse==1 || users[r]->inuse==100) { FD_SET(users[r]->socketid,&readset); if (msocksocketid) msock=users[r]->socketid; if (users[r]->lrlptr) 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; IDinuse!=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]->lrlptr) { /* 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; rwarnings++; 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<gags[x]&(1<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; tinuse==1 && users[t]->logontimeuser_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; rgags=malloc(gag_size); users[r]->inuse=0; } for (r=0; r