#include "melange.h"

int chat_ChangeChannelName(int user, char *channelName);
void logout_unknown_intruder(int sender);
int chat_ChangeNick(int user, char *newNick, int require_colon);
int chat_ChangeOwner(int user, char *owner);
void chat_CloseChannel(int user, int myChannel, int moveToChannel);
void chat_Finger(int user);
int chat_GetChannelId(int user, char *channelName);
int chat_GetLine(int socket);
void chat_Help(int user);
void chat_HelpLogin(int user);
void chat_HelpOnline(int user);
void chat_Id(int user);
int chat_Invite(int user, char *userToInvite);
int chat_JoinChannel(int user, char *newChannel);
int chat_KickOutOfChannel(int user, char *userID);
void chat_ListChannels(int user);
int chat_LockChannel(int user);
int chat_Login(int user,char *nickName);
void chat_Logout(int user, int mode);
int chat_Squelch(int user, char *userToSquelch);
void chat_ShowTime(int user);
void chat_Uptime(int user);
int chat_Whisper(int user, char *receiver, char *message);
int chat_Page(int user, char *receiver, char *message);
void chat_Whois(int user);
void chat_Yell(int user, char *message1, char *message2);
int chat_SetUserGroup(int user, char *group, char *passwd);
int chat_SetChannelGroup(int user, char *group);
int chat_FetchUser(int user, char *userToFetch);

void chat_Yell(int user, char *message1, char *message2) {
    #define MAX_MESSAGE 500 
    int i;
    char message[MAX_MESSAGE + 1];
    int len;
    
    snprintf(message,MAX_MESSAGE + 1,"%s %s",message1, message2);
    *(message + MAX_MESSAGE) = '\0';

    len = strlen(message);
    
    for (i=0;i < len;i++)
	if ((message[i]>96)&&(message[i]<123))
	    message[i]-=32;

    if (len > 0) {
	snprintf(msgText,MAX_MSG_TEXT + 1, MSG_YELL,message);
	*(msgText + MAX_MSG_TEXT) = '\0';
        comm_SendAll(user,msgText);
    }
#undef MAX_MESSAGE    
}



int chat_Whisper(int user, char *receiver, char *message) {
    int myReceiver;

    myReceiver=util_GetUserId(user,receiver);
    if (myReceiver==-1)
	return(-1);
	
    if ((mClient[myReceiver].online!=YES)||(mClient[myReceiver].channel!=mClient[user].channel)) {
	comm_SendTo(SYSMSG,user,MSG_NOTINCH);
	return(-1);
    }
    if (message[0]==0)	{
	comm_SendTo(SYSMSG,user,MSG_DONTSPEAK);
	return(-1);
    }
    strcat(message,"\r\n");
    comm_SendTo(user,myReceiver,message);
    snprintf (msgText,MAX_MSG_TEXT + 1, MSG_MSGSENT,myReceiver,mClient[myReceiver].name);
    *(msgText + MAX_MSG_TEXT) = '\0';
    comm_SendTo(SYSMSG,user,msgText);
    return(0);
}
   

int chat_Page(int user, char *receiver, char *message) {
    int myReceiver;

    myReceiver=util_GetUserId(user,receiver);
    if (myReceiver==-1)
       return(-1);

   if ((mClient[myReceiver].online!=YES)||(mClient[myReceiver].channel!=mClient[user].channel)) {
       comm_SendPage(SYSMSG,user,MSG_NOTINCH);
        return(-1);
    }
    /*if (message[0]==0)  {
       comm_SendTo(SYSMSG,user,MSG_DONTSPEAK);
        return(-1);
    }*/
    strcat(message,"\r\n");
    comm_SendPage(user,myReceiver,message);
    snprintf (msgText,MAX_MSG_TEXT + 1, MSG_MSGPAGE,myReceiver,mClient[myReceiver].name);
    *(msgText + MAX_MSG_TEXT) = '\0';
    comm_SendPage(SYSMSG,user,msgText);
    return(0);
}



int chat_KickOutOfChannel(int user, char *userID) {
    int myUser;
    
    if (mChannel[mClient[user].channel].owner!=user) {
	comm_SendTo(SYSMSG,user,MSG_NOTOWN);
        return(-1);
    }
    myUser=util_GetUserId(user,userID);
    if (myUser==-1)
	return(-1);

    if ((mClient[myUser].online!=YES)||(mClient[myUser].channel!=mClient[user].channel)) {
	comm_SendTo(SYSMSG,user,MSG_NOTINCH);
	return(-1);
    }
    if (user==myUser) {
	comm_SendTo(SYSMSG,user,MSG_KILLYS);
	return(-1);
    }
    snprintf (msgText,MAX_MSG_TEXT + 1, MSG_MOVEDTO,myUser,mClient[myUser].name,mChannel[0].name,0);
    *(msgText + MAX_MSG_TEXT) = '\0';
    comm_SendGroupBut(SYSMSG,myUser,msgText);

    mClient[myUser].channel=0;

    snprintf (msgText,MAX_MSG_TEXT + 1, MSG_COMEIN,myUser,mClient[myUser].name,mChannel[mClient[user].channel].name,mClient[user].channel);
    *(msgText + MAX_MSG_TEXT) = '\0';
    comm_SendGroupBut(SYSMSG,myUser,msgText);

    snprintf (msgText,MAX_MSG_TEXT + 1, MSG_KICKEDBYOWN,mClient[user].channel);
    *(msgText + MAX_MSG_TEXT) = '\0';
    comm_SendTo(SYSMSG,myUser,msgText);
    
    snprintf (msgText,MAX_MSG_TEXT + 1, MSG_KICK,mClient[myUser].name,myUser);
    *(msgText + MAX_MSG_TEXT) = '\0';
    comm_SendTo(SYSMSG,user,msgText);
    
    sys_SendUserUpdate(mClient[user].channel,SYSTEM);
    sys_SendUserUpdate(mClient[myUser].channel,SYSTEM);
    sys_SendAllUserUpdate(SYSTEM);
    return(0);
}

int chat_ChangeChannelName(int user, char *channelName) {
    if (mChannel[mClient[user].channel].owner!=user) {
	comm_SendTo(SYSMSG,user,MSG_NOTOWN);
        return(-1);
    }
    if ((strlen(channelName)<1)||(strlen(channelName)>48)) {
	comm_SendTo(SYSMSG,user,MSG_NOVALIDNAME);
	return(-1);
    }
    snprintf(msgText,MAX_MSG_TEXT + 1, MSG_NEWTOPIC,mClient[user].channel,mChannel[mClient[user].channel].name,channelName);
    *(msgText + MAX_MSG_TEXT) = '\0';
    
    strncpy(mChannel[mClient[user].channel].name,channelName, MAX_CHANNEL_NAME + 1);
    *(mChannel[mClient[user].channel].name + MAX_CHANNEL_NAME) = '\0';

    comm_SendChannel(SYSMSG,mClient[user].channel,msgText);
    sys_SendChannelUpdate(SYSTEM);
    sys_SendUserUpdate(mClient[user].channel,SYSTEM);
    return(0);
}

int chat_Invite(int user, char *userToInvite) {	
    int myGuest;
    
    if (mChannel[mClient[user].channel].owner!=user) {
	comm_SendTo(SYSMSG,user,MSG_NOTOWN);
        return(-1);
    }
    myGuest=util_GetUserId(user,userToInvite);
    if (myGuest==-1)
	return(-1);

    if (mClient[myGuest].online!=YES) {
	comm_SendTo(SYSMSG,user,MSG_NOTINCH);
	return(-1);
    }
    if (mClient[user].channel==mClient[myGuest].channel) {
	comm_SendTo(SYSMSG,user,MSG_ISHERE);
	return(-1);
    }
    mClient[myGuest].invite=mClient[user].channel;
    snprintf(msgText,MAX_MSG_TEXT + 1, MSG_INVITED,mClient[user].name,user,mClient[user].channel,mChannel[mClient[user].channel].name);
    *(msgText + MAX_MSG_TEXT) = '\0';
    
    comm_SendTo(SYSMSG,myGuest,msgText);
    snprintf(msgText,MAX_MSG_TEXT + 1, MSG_INVITE,mClient[myGuest].name,myGuest);
    *(msgText + MAX_MSG_TEXT) = '\0';
    
    comm_SendTo(SYSMSG,user,msgText);
    return(0);
}

int chat_FetchUser(int user, char *userToFetch) {
    int myGuest;
    int myChannel;

    if (mChannel[mClient[user].channel].owner!=user) {
	comm_SendTo(SYSMSG,user,MSG_NOTOWN);
        return(-1);
    }
    myGuest=util_GetUserId(user,userToFetch);
    if ((myGuest==-1)||(user==myGuest))
	return(-1);

    if (mClient[myGuest].online!=YES) {
	comm_SendTo(SYSMSG,user,MSG_NOTINCH);
	return(-1);
    }
    if (mClient[user].channel==mClient[myGuest].channel) {
	comm_SendTo(SYSMSG,user,MSG_ISHERE);
	return(-1);
    }
    mClient[myGuest].invite=NO;
    myChannel=mClient[myGuest].channel;
    
    snprintf (msgText,MAX_MSG_TEXT + 1, MSG_MOVEDTO,myGuest,mClient[myGuest].name,mChannel[mClient[user].channel].name,mClient[user].channel);
    *(msgText + MAX_MSG_TEXT) = '\0';
    
    comm_SendGroupBut(SYSMSG,myGuest,msgText);
    
    snprintf (msgText,MAX_MSG_TEXT + 1, MSG_COMEIN,myGuest,mClient[myGuest].name,mChannel[myChannel].name,myChannel);
    *(msgText + MAX_MSG_TEXT) = '\0';
    
    mClient[myGuest].channel=mClient[user].channel;
    comm_SendGroupBut(SYSMSG,myGuest,msgText);
    sys_SendUserUpdate(mClient[user].channel,SYSTEM);
    sys_SendUserUpdate(myChannel,SYSTEM);
    sys_SendAllUserUpdate(SYSTEM);
    
    snprintf (msgText,MAX_MSG_TEXT + 1, MSG_FETCHED,mChannel[mClient[user].channel].name,mClient[user].channel,mClient[user].name,user);
    *(msgText + MAX_MSG_TEXT) = '\0';
    
    comm_SendTo(SYSMSG,myGuest,msgText);
    return(0);
}

int chat_LockChannel(int user) {
    if (mChannel[mClient[user].channel].owner!=user) {
	comm_SendTo(SYSMSG,user,MSG_NOTOWN);
        return(-1);
    }
    if (mChannel[mClient[user].channel].locked==NO) {
	mChannel[mClient[user].channel].locked=YES;
        snprintf(msgText,MAX_MSG_TEXT + 1, MSG_LOCK,mChannel[mClient[user].channel].name,mClient[user].channel);
        *(msgText + MAX_MSG_TEXT) = '\0';
        
        comm_SendTo(SYSMSG,user,msgText);
	sys_SendChannelUpdate(SYSTEM);
	sys_SendUserUpdate(mClient[user].channel,SYSTEM);
	return(0);
    }
    mChannel[mClient[user].channel].locked=NO;
    comm_SendTo(SYSMSG,user,MSG_UNLOCK);
    sys_SendChannelUpdate(SYSTEM);
    sys_SendUserUpdate(mClient[user].channel,SYSTEM);
    return(0);
}

int chat_ChangeOwner(int user, char *owner) {
    int myOwner;
    
    if (mChannel[mClient[user].channel].owner!=user) {
	comm_SendTo(SYSMSG,user,MSG_NOTOWN);
        return(-1);
    }

    myOwner=util_GetUserId(user,owner);
    if (myOwner==-1)
	return(-1);
	
    if (mClient[myOwner].channel!=mClient[user].channel) {
	comm_SendTo(SYSMSG,user,MSG_NOTINCH);
	return(-1);
    }

    mChannel[mClient[user].channel].owner=myOwner;
    snprintf(msgText,MAX_MSG_TEXT + 1, MSG_NEWOWN,myOwner,mClient[myOwner].name);
    *(msgText + MAX_MSG_TEXT) = '\0';
    
    comm_SendChannelBut(user,mClient[user].channel,myOwner,msgText);
    comm_SendTo(SYSMSG,myOwner,MSG_YOUNEWOWN);
    sys_SendChannelUpdate(SYSTEM);
    sys_SendUserUpdate(mClient[user].channel,SYSTEM);
    return(0);
}

int chat_SetChannelGroup(int user, char *group) {
    int myGroup;
    
    if (mChannel[mClient[user].channel].owner!=user) {
	comm_SendTo(SYSMSG,user,MSG_NOTOWN);
        return(-1);
    }

    if (strcasecmp(group,"SYSTEM")==0) 
	myGroup=SYSTEM;
    else {
	myGroup=atoi(group);
	if ((myGroup<0)||(myGroup>maxGroups)||(mGroup[myGroup].passwd[0]==0)) {
	    snprintf (msgText,MAX_MSG_TEXT + 1, MSG_GRPNOTEXIST,maxGroups);	
	    *(msgText + MAX_MSG_TEXT) = '\0';
    	    comm_SendTo(SYSMSG,user,msgText);
	    return(-1);
	}
    }

    mChannel[mClient[user].channel].group=myGroup;
    snprintf(msgText,MAX_MSG_TEXT + 1, MSG_NEWCHANGRP,mClient[user].channel,mChannel[mClient[user].channel].name,myGroup);
    *(msgText + MAX_MSG_TEXT) = '\0';
    
    comm_SendTo(SYSMSG,user,msgText);
    sys_SendChannelUpdate(SYSTEM);
    return(0);
}



/**** MANHATTAN: this function is no longer used because the /group command
***** has been disabled in interpret.c
*****/
int chat_SetUserGroup(int user, char *group, char *passwd) {
    int myGroup;
    
    if (strcasecmp(group,"SYSTEM")==0) 
	myGroup=SYSTEM;
    else {
	myGroup=atoi(group);
	if ((myGroup<0)||(myGroup>maxGroups)||(mGroup[myGroup].passwd[0]==0)) {
	    snprintf (msgText,MAX_MSG_TEXT + 1, MSG_GRPNOTEXIST,maxGroups);	
	    *(msgText + MAX_MSG_TEXT) = '\0';
    	    comm_SendTo(SYSMSG,user,msgText);
	    return(-1);
	}
    }
    if ((myGroup!=SYSTEM)&&(strcmp(passwd,mGroup[myGroup].passwd)!=0)) {
	comm_SendTo(SYSMSG,user,MSG_WRONGRPPASSWD);
	return(-1);
    }
    mClient[user].group=myGroup;
    /***** MANHATTAN: don't announce this to everyone
                      next two lines commented out    
    snprintf(msgText,MAX_MSG_TEXT + 1, MSG_NEWUSERGRP,myGroup);
    *(msgText + MAX_MSG_TEXT) = '\0';    
    comm_SendTo(SYSMSG,user,msgText);
    *****************************************************/    
    sys_SendUserUpdate(mClient[user].channel,SYSTEM);
    sys_SendAllUserUpdate(SYSTEM);
    return(0);
}

void chat_CloseChannel(int user, int myChannel, int moveToChannel) {
    int i;
    for (i=0;i<maxClients;i++) {
	if ((mClient[i].socket!=0)&&(mClient[i].channel==myChannel)&&(i!=user)) {
	    mClient[i].channel=moveToChannel;
	    snprintf (msgText,MAX_MSG_TEXT + 1, MSG_WASCLOSED,mChannel[moveToChannel].name,moveToChannel,mChannel[myChannel].name,myChannel);
	     *(msgText + MAX_MSG_TEXT) = '\0';    
	    comm_SendTo(SYSMSG,i,msgText);
	    snprintf (msgText,MAX_MSG_TEXT + 1, MSG_COMEIN,i,mClient[i].name,mChannel[myChannel].name,myChannel);
	    *(msgText + MAX_MSG_TEXT) = '\0';    
	    comm_SendGroupBut(SYSMSG,i,msgText);
	}
	if (mClient[i].invite==myChannel) 
	    mClient[i].invite=NO;
    }

    mChannel[myChannel].owner=NOBODY;
    mChannel[myChannel].locked=NO;
    mChannel[myChannel].group=SYSTEM;
    strcpy(mChannel[myChannel].name,"NONAME");

    if (user!=SYSTEM) {        
	snprintf (msgText,MAX_MSG_TEXT + 1, MSG_CLOSED,myChannel);
	*(msgText + MAX_MSG_TEXT) = '\0';
        comm_SendTo(SYSMSG,user,msgText);
	sys_SendChannelUpdate(SYSTEM);
        sys_SendUserUpdate(mClient[user].channel,SYSTEM);
	sys_SendAllUserUpdate(SYSTEM);
    }
}

int chat_GetChannelId(int user, char *channelName) {
    int myChannel;
    char myChannelName[120];

    if (strlen(channelName)==0)
	return(-2);
    if (((channelName[0]>96)&&(channelName[0]<123))||((channelName[0]>64)&&(channelName[0]<91))||(channelName[0]==35)) {
	for (myChannel=0;myChannel<maxChannels;myChannel++)
	    if (strcasecmp(channelName,mChannel[myChannel].name)==0)
		return(myChannel);
	for (myChannel=0;myChannel<maxChannels;myChannel++) {
	    snprintf(myChannelName,120, "#%s",mChannel[myChannel].name);
	    *(myChannelName + 119) = '\0';
	    if (strcasecmp(channelName,myChannelName)==0)
		return(myChannel);
	}
/*	comm_SendTo(SYSMSG,user,MSG_NOTEXIST);	*/
	return(-2);
    }
    myChannel=atoi(channelName);
    if ((myChannel<0)||(myChannel>=maxChannels)||(channelName[0]<48)||(channelName[0]>57)) {
	comm_SendTo(SYSMSG,user,MSG_NOVALIDCH);
	return(-1);
    }
    return(myChannel);
}

int chat_JoinChannel(int user, char *newChannel) {
    int myChannel;
    int myOldChannel;
    char myChannelName[MAX_CHANNEL_NAME + 1];
    int i;
    
    myChannelName[0]=0;
    myOldChannel=mClient[user].channel;
    myChannel=chat_GetChannelId(user,newChannel);
    if (myChannel==-1) 
        return(-1);
    if (myChannel==-2) {
	while ((mChannel[myChannel].owner!=NOBODY)&&(myChannel<maxChannels)) { myChannel++; }
	if (newChannel[0]=='#') {
	    for (i=0; i < (int)strlen(newChannel); i++)
		myChannelName[i]=newChannel[i+1];
	    myChannelName[i]=0;
	}
	else
	    strncpy(myChannelName,newChannel, MAX_CHANNEL_NAME + 1);	
    }
    if (mClient[user].channel==myChannel)
	return(-1);
    if (mChannel[myChannel].locked==PERMANENT) {
	comm_SendTo(SYSMSG,user,MSG_ADMINCLOSED);
	return(-1);
    }
    if ((mChannel[myChannel].group!=SYSTEM)&&(mClient[user].group!=mChannel[myChannel].group)) {
	comm_SendTo(SYSMSG,user,MSG_WRONGGROUP);
	return(-1);
    }
    if (mChannel[mClient[user].channel].owner==user) {
	if (mChannel[myChannel].locked==YES) {
	    snprintf (msgText,MAX_MSG_TEXT + 1, MSG_ISLOCKED,mChannel[myChannel].name,myChannel);
	    *(msgText + MAX_MSG_TEXT) = '\0';
	    comm_SendTo(SYSMSG,user,msgText);
	    return(-1);
	}
        chat_CloseChannel(user,mClient[user].channel,0);
    }
    if (mChannel[myChannel].owner!=NOBODY) {
	if ((mChannel[myChannel].locked==YES)&&(mClient[user].invite!=myChannel)) {
	    snprintf (msgText,MAX_MSG_TEXT + 1, MSG_ISLOCKED,mChannel[myChannel].name,myChannel);
	    *(msgText + MAX_MSG_TEXT) = '\0';
	    comm_SendTo(SYSMSG,user,msgText);
	    return(-1);
	}
	mClient[user].invite=NO;
        snprintf (msgText,MAX_MSG_TEXT + 1, MSG_MOVEDTO,user,mClient[user].name,mChannel[myChannel].name,myChannel);
        *(msgText + MAX_MSG_TEXT) = '\0';
        comm_SendGroupBut(SYSMSG,user,msgText);
        snprintf (msgText,MAX_MSG_TEXT + 1, MSG_COMEIN,user,mClient[user].name,mChannel[mClient[user].channel].name,mClient[user].channel);
        *(msgText + MAX_MSG_TEXT) = '\0';
	mClient[user].channel=myChannel;
	comm_SendGroupBut(SYSMSG,user,msgText);
	sys_SendUserUpdate(myChannel,SYSTEM);
	sys_SendUserUpdate(myOldChannel,SYSTEM);
	sys_SendAllUserUpdate(SYSTEM);
	snprintf (msgText,MAX_MSG_TEXT + 1, MSG_INCH,mChannel[myChannel].name,myChannel);
	*(msgText + MAX_MSG_TEXT) = '\0';
	comm_SendTo(SYSMSG,user,msgText);

	/** MANHATTAN: inform user whether msgs are recorded **/
	if(mClient[user].group==mChannel[myChannel].group) {
   		comm_SendTo(SYSMSG,user,MSG_LOGGED1);	
   		comm_SendTo(SYSMSG,user,MSG_LOGGED2);	
   		comm_SendTo(SYSMSG,user,MSG_LOGGED3);	
   		comm_SendTo(SYSMSG,user,MSG_LOGGED4);	
   		comm_SendTo(SYSMSG,user,MSG_LOGGED5);	
   	}	
   		
        else
               	comm_SendTo(SYSMSG,user,MSG_NOTLOGGED); 		
	return(0);
       /*** end MANHATTAN additions ****/
    
    }
    
    mChannel[myChannel].owner=user;
    if (myChannelName[0]==0)
     {
	snprintf (mChannel[myChannel].name, MAX_CHANNEL_NAME + 1, "Channel %d",myChannel);
	*(mChannel[myChannel].name + MAX_CHANNEL_NAME) = '\0';
     }	
    else
	strncpy (mChannel[myChannel].name,myChannelName, MAX_CHANNEL_NAME + 1);
	
    snprintf (msgText,MAX_MSG_TEXT + 1,MSG_OPENEDCH,user,mClient[user].name,mChannel[myChannel].name);
    *(msgText + MAX_MSG_TEXT) = '\0';
    comm_SendGroupBut(SYSMSG,user,msgText);
    mClient[user].channel=myChannel;
    sys_SendUserUpdate(myOldChannel,SYSTEM);
    snprintf (msgText,MAX_MSG_TEXT + 1,MSG_INNEWCH,mChannel[myChannel].name);
    *(msgText + MAX_MSG_TEXT) = '\0';
    comm_SendTo(SYSMSG,user,msgText);
    
    /*** MANHATTAN: Added following line *****/
    comm_SendTo(SYSMSG,user,MSG_NOTLOGGED); 		    
    
    sys_SendChannelUpdate(SYSTEM);
    sys_SendUserUpdate(myChannel,SYSTEM);
    sys_SendAllUserUpdate(SYSTEM);
    return(0);
}

int chat_Squelch(int user,char *userToSquelch) {
    int mySquelch;

    mySquelch=util_GetUserId(user,userToSquelch);
    if (mySquelch==-1)
	return(-1);    

    if (mClient[mySquelch].online!=YES) {
	comm_SendTo(SYSMSG,user,MSG_NOTINCHAT);
	return(-1);
    }
    if (user==mySquelch) {
	comm_SendTo(SYSMSG,user,MSG_SQUELCHYS);
	return(-1);
    }
    if (mClient[user].squelch[mySquelch]==NO) {
	mClient[user].squelch[mySquelch]=YES;
	snprintf (msgText,MAX_MSG_TEXT + 1,MSG_SILENT,mClient[mySquelch].name,mySquelch);
	*(msgText + MAX_MSG_TEXT) = '\0';
    	comm_SendTo(SYSMSG,user,msgText);
	snprintf (msgText,MAX_MSG_TEXT + 1,MSG_SQUELCHED,mClient[user].name,user);
	*(msgText + MAX_MSG_TEXT) = '\0';
    } else {
    	mClient[user].squelch[mySquelch]=NO;
	snprintf (msgText,MAX_MSG_TEXT + 1,MSG_HEARAGAIN,mClient[mySquelch].name,mySquelch);
	*(msgText + MAX_MSG_TEXT) = '\0';
	comm_SendTo(SYSMSG,user,msgText);
	snprintf (msgText,MAX_MSG_TEXT + 1,MSG_UNSQUELCHED,mClient[user].name,user);
	*(msgText + MAX_MSG_TEXT) = '\0';
    }
    comm_SendTo(SYSMSG,mySquelch,msgText);
    return(0);
}

int chat_Login(int user,char *nickName) {
    if (chat_ChangeNick(user,nickName, 0)==-1) {
	if ((mClient[user].syscap & 0x010)==0x010)
	    sys_SendLoginCommand(user,NO);
	return(-1);
    }
    if ((mClient[user].syscap & 0x010)==0x010)
        sys_SendLoginCommand(user,YES);
    mClient[user].online=YES;
    util_AdjustUserCount(1);             /**** MANHATTAN: this line added */
    snprintf (msgText,MAX_MSG_TEXT + 1,MSG_LOGIN,mClient[user].name,mClient[user].host,user);
    *(msgText + MAX_MSG_TEXT) = '\0';
    comm_SendChannelBut(SYSMSG,mClient[user].channel,user,msgText);
    util_WriteMsgLog(msgText);
    snprintf (msgText,MAX_MSG_TEXT + 1,MSG_WELCOME2,VERSION);
    *(msgText + MAX_MSG_TEXT) = '\0';
    comm_SendTo(SYSMSG,user,msgText);
    sys_SendUserUpdate(mClient[user].channel,SYSTEM);
    return(0);
}


/*** MANHATTAN: added next function ... 
**** searches channel list for a channel owned by SYSTEM
**** with mChannel.name equal to the string channel_requested
*** If found, returns with group set to the index of the channel
****(the channel number).  If such a channel is not found, it is
**** created by filling in an empty slot in the channel list
***/
void  chat_FindSystemChannel(int user, const char *channel_requested, char *group)
{
 int i;
 int open_channel = -1;   /* first open channel */
 
 /* start search at 2, since 0 is MAIN and 1 is reserved for ANONYM */
 for(i=2; i < maxChannels; i++)
 {
  if((mChannel[i].owner == SYSTEM) &&
        (mChannel[i].group == i) && 
  	!strcmp(mChannel[i].name,channel_requested))
    {
     mClient[user].group = i;
     snprintf(group,10, "%d",i);
     return;
    }
  else  
   if( (open_channel == -1) && 
   	(mChannel[i].owner == NOBODY)  &&
          !strcmp(mChannel[i].name,"NONAME"))
            open_channel = i;      /* we can create a new channel here */
 }  
 /* still here? need to create a new SYSTEM channel */
 if(open_channel == -1)  /* all channels are full - should report msg but for now... */
  {
    mClient[user].group = 0;
    strncpy(group,"0", 10);
    return;
   }  
 else
  {
   strncpy(mChannel[open_channel].name,channel_requested,MAX_CHANNEL_NAME + 1);
   mChannel[open_channel].owner = SYSTEM;
   mChannel[open_channel].locked = NO;
   mChannel[open_channel].group = open_channel;
   mClient[user].group = open_channel;
   snprintf(group,10,"%d",open_channel);
  } 
}



/** Added for Manhattan - don't allow two people to have same name
**  in same group
**/
static
void remove_duplicate_users(int user, char *new_name, char *classroom)
{

int i;

  
  for(i=0 ;  i < maxClients; i++)
     if( (i != user) && 
         (mClient[i].online == YES) &&  
         (mClient[i].socket)  &&
         !strcmp(mClient[i].name, new_name) &&
         (mClient[i].group == mClient[user].group)  )
           {    
            comm_SendTo(SYSMSG,i,MSG_BYE);
            close(mClient[i].socket);

            snprintf(infoText,MAX_INFO_TEXT + 1, "FORCED LOGOUT:%s (%s):host %s:line %d:socket %d:duplicate login \r\n", 
		       			 mClient[i].name, classroom, mClient[i].host, i, mClient[i].socket );
            chat_Logout(i, KILL);		       			 
          *(infoText + MAX_INFO_TEXT) = '\0';        
          util_WriteLog(1,infoText);			

          }
}

          
         
         



void
logout_unknown_intruder(int sender)
{
   snprintf(infoText,MAX_INFO_TEXT + 1, "intruder from %s was kicked off!!!\r\n", mClient[sender].host);
   *(infoText + MAX_INFO_TEXT) = '\0';
   util_WriteLog(1,infoText);
   chat_Logout(sender,DEFAULT);		    
}



int chat_ChangeNick(int user,char *newNick, int require_colon) {
    char myNewNick[60];
    int i;
    char channel_requested[50]; /* MANHATTAN */
    char group[50];                /* MANHATTAN */
    char *colon;                   /*MANHATTAN */

/* MANHATTAN newNick contains just the username */    
    colon = strchr(newNick,':');
    if(colon)
        *colon = '\0';
     else
       if(require_colon)   
          {
           logout_unknown_intruder(user);
           return -1;
          } 
/** END MANHATTAN */        
        
    if ((strcasecmp(mClient[user].name,"unknown")!=0)&&(mAdmin.changeNames==NO)) {
	comm_SendTo(SYSMSG,user,MSG_ADMINDIS);
	return(-1);
    }
    
    if ((strlen(newNick)<2)||(strlen(newNick)>48)||
	(strcasecmp(newNick,"nobody")==0)||(strcasecmp(newNick,"unknown")==0)) {
        comm_SendTo(SYSMSG,user,MSG_NOVALIDNAME);
        return(-1);
    }
    if (mAdmin.uniqueNames==YES) {
	if ((mAdmin.guestLogin==YES)&&(strcasecmp(newNick,"guest")==0)) { }
	else {
	    for (i=0;i<maxClients;i++) {
		if ((mClient[i].online==YES)&&(strcasecmp(mClient[i].name,newNick)==0)) {
    		    comm_SendTo(SYSMSG,user,MSG_UNQNOVALIDNAME);
		    return(-1);
		}
	    }
	}
    }
    strcpy(myNewNick,util_FitString(newNick));


    strcpy(mClient[user].name,myNewNick);

    /** start MANHATTAN additions **/
    if(colon)   /* if orig newNick contained a colon, then the class is to the right of the colon */
     {
     strncpy(channel_requested,++colon,50);
     channel_requested[49] = '\0';  
     chat_FindSystemChannel(user, channel_requested,group);
     chat_JoinChannel(user, group);
     
     remove_duplicate_users(user, myNewNick, channel_requested);
     
     snprintf(infoText,MAX_INFO_TEXT + 1, "LOGIN:%s (%s):host %s:line %d, socket %d:normal initial nickname change\r\n", 
     					mClient[user].name, channel_requested, mClient[user].host, user,  mClient[user].socket);
   *(infoText + MAX_INFO_TEXT) = '\0';
   util_WriteLog(1,infoText);

    }     
    /*** end MANHATTAN additions ***/
   


   /****** MANHATTAN: don't make an announcement... next block of code commented out ...
    snprintf(msgText,MAX_MSG_TEXT + 1, MSG_NEWNAME,user,mClient[user].name,myNewNick);
    *(msgText + MAX_MSG_TEXT) = '\0';
    if (mClient[user].online==YES) {
	comm_SendGroupBut(SYSMSG,user,msgText);
	snprintf(msgText,MAX_MSG_TEXT + 1,MSG_YOURNEWNAME,myNewNick,user);
	*(msgText + MAX_MSG_TEXT) = '\0';
	comm_SendTo(SYSMSG,user,msgText);
    }
    
    ****** end MANHATTAN comment out *************************/
    
    sys_SendUserUpdate(mClient[user].channel,SYSTEM);
    sys_SendAllUserUpdate(SYSTEM);
    return(0);
}

int chat_GetLine(int socket) {
    int i;

    for (i=0;i<maxClients;i++)
	if (mClient[i].socket==socket)
	    return(i);
    return(-1);
}



void chat_Logout(int user, int mode) {
    int i;
    int channel=mClient[user].channel;

    if (mChannel[channel].owner==user) {
	if (mode==DEFAULT)
	    chat_CloseChannel(user,channel,0);
	else
	    chat_CloseChannel(SYSTEM,channel,0);
    }

    if ((mClient[user].online==YES) && (mode != KILL)) {
	snprintf(msgText,MAX_MSG_TEXT + 1,MSG_LEAVE,user,mClient[user].name);
	*(msgText + MAX_MSG_TEXT) = '\0';
	comm_SendChannelBut(SYSMSG,channel,user,msgText);
	util_WriteMsgLog(msgText);
    }
    if (mode==DEFAULT) {
	comm_SendTo(SYSMSG,user,MSG_BYE);
	sys_SendShutdownCommand(user);
	if(mClient[user].socket)
	    close(mClient[user].socket);
    }

    if (mAdmin.administrator==user)
	mAdmin.administrator=SYSTEM;

    mClient[user].socket=0;
    strcpy(mClient[user].name,"unknown");
    strcpy(mClient[user].host,"unknown");
    mClient[user].channel=0;
    mClient[user].invite=NO;
    mClient[user].online=NO;

    util_AdjustUserCount(-1);               /**** MANHATTAN: this line added *****/

    mClient[user].idle=0;
    mClient[user].group=SYSTEM;
    mClient[user].syscap=0x00;
    for (i=0;i<maxClients;i++) {
	mClient[user].squelch[i]=NO;
	mClient[i].squelch[user]=NO;
    }
    sys_SendUserUpdate(channel,SYSTEM);
    sys_SendAllUserUpdate(SYSTEM);
}

void chat_Finger(int user) {
    int i;

    comm_SendTo(SYSMSG,user,MSG_FINGERLST);
    comm_SendTo(SYSMSG,user,"----------------------------------------------------------------------\r\n");
    for (i=0;i<maxClients;i++)
	if (mClient[i].online==YES) {
	    snprintf (msgText,MAX_MSG_TEXT + 1,
	      "Line %d: %s (%s), Channel %d (%s)%s%s\r\n",
	            i, mClient[i].name,mClient[i].host,mClient[i].channel,mChannel[mClient[i].channel].name,
	            (mChannel[mClient[i].channel].owner==i)? " [owner]" : "",
	            (mAdmin.administrator==i)? " [admin]":""
	            );
	    *(msgText + MAX_MSG_TEXT) = '\0';
//	    if (mChannel[mClient[i].channel].owner==i)
//		strcat (msgText," [owner]");
//	    if (mAdmin.administrator==i)
//		strcat (msgText," [admin]");
//	    strcat(msgText,"\r\n");
	    comm_SendTo(SYSMSG,user,msgText);
	}
    comm_SendTo(SYSMSG,user,"----------------------------------------------------------------------\r\n");
}

void chat_ListChannels(int user) {
    int i;

    comm_SendTo(SYSMSG,user,MSG_CHANNELLST);
    comm_SendTo(SYSMSG,user,"----------------------------------------------------------------------\r\n");
    for (i=0;i<maxChannels;i++)
      /*** MANHATTAN: added (i!=1) to next - don't show ANONYM channel ***/
        if ((mChannel[i].owner!=NOBODY)&&(mChannel[i].group==SYSTEM)
                           && (i != 1)) {
	    if (mChannel[i].locked==YES)
		snprintf (msgText,MAX_MSG_TEXT + 1,"Channel %3d ( %s ), Owner: %3d [private]\r\n",i,mChannel[i].name,mChannel[i].owner);
	    else
		snprintf (msgText,MAX_MSG_TEXT + 1,"Channel %3d ( %s ), Owner: %3d\r\n",i,mChannel[i].name,mChannel[i].owner);
	    *(msgText + MAX_MSG_TEXT) = '\0';	
	    comm_SendTo(SYSMSG,user,msgText);
	}
    for (i=0;i<maxChannels;i++)
        if ((mChannel[i].owner!=NOBODY)&&
	    (mChannel[i].group!=SYSTEM)&&
	    (mChannel[i].group==mClient[user].group)) {
	    if (mChannel[i].locked==YES)
		snprintf (msgText,MAX_MSG_TEXT + 1,"Channel %3d ( %s ), Owner: %3d [group] [private]\r\n",i,mChannel[i].name,mChannel[i].owner);
	    else
		snprintf (msgText,MAX_MSG_TEXT + 1,"Channel %3d ( %s ), Owner: %3d [group]\r\n",i,mChannel[i].name,mChannel[i].owner);
	    *(msgText + MAX_MSG_TEXT) = '\0';	
	    comm_SendTo(SYSMSG,user,msgText);
	}
    comm_SendTo(SYSMSG,user,"----------------------------------------------------------------------\r\n");
}

void chat_Id(int user) {
    snprintf(msgText,MAX_MSG_TEXT + 1,MSG_ME,user,mClient[user].name,mClient[user].channel,mChannel[mClient[user].channel].name,mClient[user].group);
    *(msgText + MAX_MSG_TEXT) = '\0';
    comm_SendTo(SYSMSG,user,msgText);
}

void chat_Whois(int user) {
    int i;
    
    snprintf (msgText,MAX_MSG_TEXT + 1,MSG_USRLIST,mChannel[mClient[user].channel].name,mClient[user].channel);
    *(msgText + MAX_MSG_TEXT) = '\0';
    comm_SendTo(SYSMSG,user,msgText);
    comm_SendTo(SYSMSG,user,"----------------------------------------------------------------------\r\n");
    for (i=0;i<maxClients;i++)
	if ((mClient[i].online==YES)&&(mClient[i].channel==mClient[user].channel)) {
	    if (mClient[user].squelch[i]==YES)
		snprintf (msgText,MAX_MSG_TEXT + 1,MSG_ISSQUELCHED,i,mClient[i].name);
	    else
		snprintf (msgText,MAX_MSG_TEXT + 1,"[%d] %s, Group: %d",i,mClient[i].name,mClient[i].group);
            *(msgText + MAX_MSG_TEXT) = '\0';		
	    if (mChannel[mClient[i].channel].owner==i)
		strcat (msgText,"  [channel owner]\r\n");
	    else
		strcat (msgText,"\r\n");
	    comm_SendTo(SYSMSG,user,msgText);
    }
    comm_SendTo(SYSMSG,user,"----------------------------------------------------------------------\r\n");
}

void chat_Uptime(int user) {
    time_t timeNow;
    unsigned long diffTime;
    
    int days=0, hours=0, min=0;
    
    timeNow=time(NULL);
    diffTime=difftime(timeNow,mServerStartupTime);
    
    hours=diffTime/3600; diffTime-=hours*3600;
    days=hours/24; hours-=days*24;
    min=diffTime/60; diffTime-=min*60;
    snprintf(msgText,MAX_MSG_TEXT + 1,"%s>> Server started on: %s\r\n",VERSION,ctime(&mServerStartupTime));
    *(msgText + MAX_MSG_TEXT) = '\0';
    comm_SendTo(SYSMSG,user,msgText);
    snprintf(msgText,MAX_MSG_TEXT + 1,"Uptime: %d days, %d hours, %d min, %lu sec\r\n",days,hours,min,diffTime);
    *(msgText + MAX_MSG_TEXT) = '\0';
    comm_SendTo(SYSMSG,user,msgText);
}

void chat_ShowTime(int user) {
    time_t t;
    struct tm *localTime;

    t=time(NULL);
    localTime=localtime(&t);

    snprintf(msgText,MAX_MSG_TEXT + 1,"Date: %d.%d.%d, BMT (Internet Time): @%d, Localtime: %2d:%2d:%2d\r\n",
		    localTime->tm_mday, localTime->tm_mon+1, localTime->tm_year+1900,util_GetBMT(),
		    localTime->tm_hour, localTime->tm_min, localTime->tm_sec);
    *(msgText + MAX_MSG_TEXT) = '\0';		    
    comm_SendTo(SYSMSG,user,msgText);
}

void chat_Help(int user) {
    if (mClient[user].online==YES)
	chat_HelpOnline(user);
    else
	chat_HelpLogin(user);
}

void chat_HelpLogin(int user) {
    comm_SendTo(SYSMSG,user,VERSION);
    comm_SendTo(SYSMSG,user,MSG_HELP1);
    comm_SendTo(SYSMSG,user,MSG_HELP2);
    comm_SendTo(SYSMSG,user,MSG_HELP3);
    comm_SendTo(SYSMSG,user,MSG_HELP16);
    comm_SendTo(SYSMSG,user,MSG_HELP17);
    comm_SendTo(SYSMSG,user,MSG_HELP21);
    comm_SendTo(SYSMSG,user,MSG_HELP22);
    comm_SendTo(SYSMSG,user,MSG_HELP23);
}

void chat_HelpOnline(int user) {
    comm_SendTo(SYSMSG,user,VERSION);
    comm_SendTo(SYSMSG,user,MSG_HELP1);
    comm_SendTo(SYSMSG,user,MSG_HELP2);
    comm_SendTo(SYSMSG,user,MSG_HELP3);
    comm_SendTo(SYSMSG,user,MSG_HELP4);
    comm_SendTo(SYSMSG,user,MSG_HELP5);
    comm_SendTo(SYSMSG,user,MSG_HELP6);
    comm_SendTo(SYSMSG,user,MSG_HELP7);
    comm_SendTo(SYSMSG,user,MSG_HELP8);
    comm_SendTo(SYSMSG,user,MSG_HELP9);
    comm_SendTo(SYSMSG,user,MSG_HELP10);
    comm_SendTo(SYSMSG,user,MSG_HELP11);
    comm_SendTo(SYSMSG,user,MSG_HELP12);
    comm_SendTo(SYSMSG,user,MSG_HELP13);
    comm_SendTo(SYSMSG,user,MSG_HELP14);
    comm_SendTo(SYSMSG,user,MSG_HELP15);
    comm_SendTo(SYSMSG,user,MSG_HELP16);
    comm_SendTo(SYSMSG,user,MSG_HELP17);
    comm_SendTo(SYSMSG,user,MSG_HELP18);
    comm_SendTo(SYSMSG,user,MSG_HELP19);
    comm_SendTo(SYSMSG,user,MSG_HELP20);
    comm_SendTo(SYSMSG,user,MSG_HELP21);
    comm_SendTo(SYSMSG,user,MSG_HELP23);
}
