/*
 *	MELANGE		- CHAT server for LINUX
 *			  Version 1.10
 *			  Released Apr-25-1999
 *
 *	Christian Walter
 *	chris@terminal.at
 * 	http://melange.terminal.at
 *	Vienna, Austria
 *
 **************************************
 *
 *	admin.c
 *
 *	REVISIONS:
 *		10-10-98 [cw]	original implementation
 *		12-15-98 [cw]	complete code revision
 *		02-23-99 [cw]	first stable release
 *		04-25-99 [cw]	release 1.10
 */

#include "melange.h"

int admin_CheckIfAllowed(int socket, char *clientIP, char *clientHostName);
int admin_InterpretAdminCommand(int sender, char *option, char *parameter);
int admin_JoinChannel(int user, char *newChannel);
void admin_ShutDown();
int admin_CreateSysChannel(int user, char *syschannelName);
int admin_ChangeTopic(int user, char *newTopic);
int admin_ChangeOwner(int user, char *newOwner);
int admin_SetChangeNames(int user, char *param);
int admin_SetUniqueNames(int user, char *param);
void admin_ShowServerStat(int user);
int admin_AddHostMask(int user, char *hostMask, int mode);
int admin_RemoveHostMask(int user, char *hostMask);
int admin_SetLogLevel(int user, char *newLevel);
int admin_SetIdleTime(int user, char *newTime);
int admin_SetBannTime(int user, char *newTime);
int admin_SetSysMsg(int user, char *newStat);
int admin_KickIdleUsers();
int admin_KickUser(int user, char *userToKick);
void admin_Whois(int user);
void admin_ListChannels(int user);
int admin_CloseChannel(int user, char *channel);
int admin_ListGroup(int user, int group);
int admin_ListGroups(int user, char *group);
void admin_ListAllGroups(int user);
int admin_CreateGroup(int user, char *group, char *passwd);
void admin_Help(int user);
int admin_SetGuestLogin(int user, char *param);

int admin_CheckIfAllowed(int socket, char *clientIP, char *clientHostName) {
    int i;
    time_t currentTime=time(NULL);

    for (i=0;i<maxSecurityProfiles;i++) {
	if (mSecurity[i].hostmask[0]!=0) {
	    if ((mSecurity[i].banntime!=0)&&(mSecurity[i].banntime<currentTime))
		mSecurity[i].hostmask[0]=mSecurity[i].banntime=0;
	}
    }
    if (mAdmin.securityType==ALLOW) {
	for (i=0;i<maxSecurityProfiles;i++) {
	    if (mSecurity[i].hostmask[0]!=0) {
	    	if ((strstr(clientIP,mSecurity[i].hostmask)!=NULL)||
		    (strstr(clientHostName,mSecurity[i].hostmask)!=NULL)) {
		    snprintf(msgText,MAX_MSG_TEXT + 1, "%s\nYou are not allowed to connect to this server !\r\n",VERSION);
		    *(msgText + MAX_MSG_TEXT) = '\0';
    		    write(socket,msgText,strlen(msgText));
	    	    close(socket);
		    return(NO);
		}
	    }
	}
    }
    if (mAdmin.securityType==DENY) {
	for (i=0;i<maxSecurityProfiles;i++) {
	    if (mSecurity[i].hostmask[0]!=0)
	    	if ((strstr(clientIP,mSecurity[i].hostmask)!=NULL)||
		    (strstr(clientHostName,mSecurity[i].hostmask)!=NULL))
		    return(YES);
	}
        snprintf(msgText,MAX_MSG_TEXT + 1, "%s\nYou are not allowed to connect to this server !\r\n",VERSION);
        *(msgText + MAX_MSG_TEXT) = '\0';
        write(socket,msgText,strlen(msgText));
        close(socket);
        return(NO);
    }
    return(YES);
}

int admin_InterpretAdminCommand(int sender, char *option, char *parameter) {
    if (mAdmin.activated==NO) {
	comm_SendTo(SYSMSG,sender,"Administrator features are disabled !\r\n");
	return(-1);
    }
    if (strcasecmp(option,"login")==0) {
	if (strcmp(parameter,mAdmin.password)==0) {
	    mAdmin.administrator=sender;
	    comm_SendTo(SYSMSG,sender,MSG_ADMINNOW);
	    snprintf(infoText,MAX_INFO_TEXT + 1, "User %d (%s) logged in as administrator\r\n",sender,mClient[sender].name);
	    *(infoText + MAX_INFO_TEXT) = '\0';
	    util_WriteLog(1,infoText);
	    return(0);
	}
	comm_SendTo(SYSMSG,sender,MSG_INVLOGIN);
	return(-1);
    }
    if (sender!=mAdmin.administrator) {
        comm_SendTo(SYSMSG,sender,MSG_NOTADMIN);
        return(-1);
    }
    if (strcasecmp(option,"join")==0) {
	admin_JoinChannel(sender,parameter);
	return(0);
    }
    if (strcasecmp(option,"topic")==0) {
	admin_ChangeTopic(sender,parameter);
	return(0);
    }
    if (strcasecmp(option,"own")==0) {
	admin_ChangeOwner(sender,parameter);
	return(0);
    }
    if (strcasecmp(option,"close")==0) {
	admin_CloseChannel(sender,parameter);
	return(0);
    }
    if (strcasecmp(option,"stat")==0) {
	admin_ShowServerStat(sender);
	return(0);
    }
    if ((strcasecmp(option,"deny")==0)||
	(strcasecmp(option,"allow")==0)||
	(strcasecmp(option,"add")==0)) {
	admin_AddHostMask(sender, parameter, PERMANENT);
	return(0);
    }
    if (strcasecmp(option,"remove")==0) {
	admin_RemoveHostMask(sender, parameter);
	return(0);
    }
    if (strcasecmp(option,"kickouttime")==0) {
	admin_SetBannTime(sender, parameter);
	return(0);
    }
    if ((strcasecmp(option,"idletime")==0)||
       (strcasecmp(option,"idle")==0)) {
	admin_SetIdleTime(sender, parameter);
	return(0);
    }
    if (strcasecmp(option,"loglevel")==0) {
	admin_SetLogLevel(sender, parameter);
	return(0);
    }
    if (strcasecmp(option,"syschannel")==0) {
	admin_CreateSysChannel(sender, parameter);
	return(0);
    }
    if (strcasecmp(option,"unique")==0) {
	admin_SetUniqueNames(sender, parameter);
	return(0);
    }
    if (strcasecmp(option,"changenicks")==0) {
	admin_SetChangeNames(sender, parameter);
	return(0);
    }
    if (strcasecmp(option,"guestlogin")==0) {
	admin_SetGuestLogin(sender, parameter);
	return(0);
    }
    if (strcasecmp(option,"kick")==0) {
	admin_KickUser(sender, parameter);
	return(0);
    }
    if ((strcasecmp(option,"help")==0)||
        (strcasecmp(option,"he")==0)) {
	admin_Help(sender);
	return(0);
    }
    if (strcasecmp(option,"sysmsg")==0) {
	admin_SetSysMsg(sender, parameter);
	return(0);
    }
    if ((strcasecmp(option,"group")==0)||
        (strcasecmp(option,"groups")==0)) {
	admin_ListGroups(sender, parameter);
	return(0);
    }
    if ((strcasecmp(option,"whois")==0)||
	(strcasecmp(option,"finger")==0)||
	(strcasecmp(option,"f")==0)) {
	admin_Whois(sender);
	return(0);
    }
    if ((strcasecmp(option,"list")==0)||
	(strcasecmp(option,"a")==0)) {
	admin_ListChannels(sender);
	return(0);
    }
    if ((strcasecmp(option,"shutdown")==0)) {
    	if (strcmp(parameter,mAdmin.password)!=0) {
	    comm_SendTo(SYSMSG,sender,MSG_INVLOGIN);
	    return(-1);
	}
	comm_SendTo(SYSMSG,sender,"You shut down the server !\r\n");
	return(100);
    }
    comm_SendTo(SYSMSG,sender,MSG_AUNKNOWN);
    return(-1);
}

int admin_CreateSysChannel(int user, char *syschannelName) {
    if (chat_JoinChannel(user,syschannelName)!=0)
	return(-1);
    return(admin_ChangeOwner(user,"SYSTEM"));
}

int admin_CloseChannel(int user, char *channel) {
    int myChannel;

    myChannel=chat_GetChannelId(user,channel);
    if (mChannel[myChannel].owner==NOBODY) {
        comm_SendTo(SYSMSG,user,MSG_MUSTEXIST);
        return(-1);
    }
    chat_CloseChannel(user,myChannel,0);
    mClient[user].channel=0;
    sys_SendChannelUpdate(SYSTEM);
    return(0);
}

int admin_JoinChannel(int user, char *newChannel) {
    int myChannel;
    int myOChannel;

    myChannel=chat_GetChannelId(user,newChannel);
    myOChannel=mClient[user].channel;
    if (myChannel==-1) 
        return(-1);

    if (mChannel[myChannel].owner==NOBODY) {
        comm_SendTo(SYSMSG,user,MSG_MUSTEXIST);
        return(-1);
    }
    mClient[user].channel=myChannel;
    snprintf(msgText, MAX_MSG_TEXT + 1,MSG_ADMINCOMING,mClient[user].name,user);
    *(msgText + MAX_MSG_TEXT) = '\0';
    comm_SendChannelBut(SYSMSG,myChannel,user,msgText);
    snprintf(msgText,MAX_MSG_TEXT + 1, MSG_INCH,mChannel[myChannel].name,myChannel);
    *(msgText + MAX_MSG_TEXT) = '\0';
    comm_SendTo(SYSMSG,user,msgText);
    sys_SendChannelUpdate(SYSTEM);
    sys_SendUserUpdate(myChannel,SYSTEM);
    sys_SendUserUpdate(myOChannel,SYSTEM);
    sys_SendAllUserUpdate(SYSTEM);
    return(0);
}

int admin_ChangeTopic(int user, char *newTopic) {
    if ((strlen(newTopic)<1)||(strlen(newTopic)>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,newTopic);
    *(msgText + MAX_MSG_TEXT) = '\0';
    strncpy(mChannel[mClient[user].channel].name,newTopic, 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 admin_ChangeOwner(int user, char *newOwner) {
    int myOwner;
    
    if (strcasecmp(newOwner,"SYSTEM")==0) {
        mChannel[mClient[user].channel].owner=SYSTEM;
        comm_SendTo(SYSMSG,user,MSG_ASYSCHANNEL);
	sys_SendChannelUpdate(SYSTEM);
	sys_SendUserUpdate(mClient[user].channel,SYSTEM);
        return(0);
    }
    
    myOwner=util_GetUserId(user,newOwner);
    if (myOwner==-1)
	return(-1);
    if ((mClient[myOwner].socket==0)||(mClient[myOwner].channel!=mClient[user].channel)) {
	comm_SendTo(SYSMSG,user,MSG_NOTINCH);
        return(-1);
    }
    mChannel[mClient[myOwner].channel].owner=myOwner;
    snprintf(msgText,MAX_MSG_TEXT + 1,MSG_AOWN,myOwner,mClient[myOwner].name);
    *(msgText + MAX_MSG_TEXT) = '\0';
    comm_SendGroupBut(SYSMSG,myOwner,msgText);
    comm_SendTo(SYSMSG,myOwner,MSG_AYOURCH);
    sys_SendChannelUpdate(SYSTEM);
    sys_SendUserUpdate(mClient[user].channel,SYSTEM);
    return(0);
}

int admin_AddHostMask(int user, char *hostMask, int mode) {
    time_t myTime;
    int i;

    if ((strlen(hostMask)<1)||(strlen(hostMask)>48)) {
	comm_SendTo(SYSMSG,user,MSG_NOVALIDNAME);
	return(-1);
    }
    
    if (mode!=PERMANENT) {
	myTime=time(NULL);
	myTime+=mAdmin.defaultBannTime;
    }
    else
	myTime=0;
    
    for (i=0;i<maxSecurityProfiles;i++) {
	if (mSecurity[i].hostmask[0]==0) {
	    strncpy(mSecurity[i].hostmask,hostMask, MAX_HOSTMASK + 1);
	    *(mSecurity[i].hostmask + MAX_HOSTMASK) = '\0';
	    mSecurity[i].banntime=myTime;
	    if (mode==PERMANENT)
		snprintf (msgText,MAX_MSG_TEXT + 1,"Mask %s added to security table [permanently]\r\n",hostMask);
	    else
		snprintf (msgText,MAX_MSG_TEXT + 1,"Mask %s added to security table [temporary]\r\n",hostMask);
	    *(msgText + MAX_MSG_TEXT) = '\0';	
	    comm_SendTo(SYSMSG,user,msgText);
	    return(0);
	}
    }
    comm_SendTo(SYSMSG,user,"Couldn't add hostmask to security table (TABLE FULL) !\r\n");
    return(-1);
}

int admin_RemoveHostMask(int user, char *hostMask) {
    int i;
    
    if ((strlen(hostMask)<1)||(strlen(hostMask)>48)) {
	comm_SendTo(SYSMSG,user,MSG_NOVALIDNAME);
	return(-1);
    }
    for (i=0;i<maxSecurityProfiles;i++) {
	if (mSecurity[i].hostmask[0]!=0) {
	    if (strstr(mSecurity[i].hostmask,hostMask)!=NULL)
		mSecurity[i].hostmask[0]=mSecurity[i].banntime=0;
	}
    }
    snprintf (msgText,MAX_MSG_TEXT + 1,"Mask %s removed from security table.\r\n",hostMask);
    *(msgText + MAX_MSG_TEXT) = '\0';
    comm_SendTo(SYSMSG,user,msgText);
    return(0);
}

int admin_SetBannTime(int user, char *newTime) {
    int myTime;
    
    myTime=atoi(newTime);
    if ((myTime<0)||(myTime>86400)||newTime[0]<48||newTime[0]>57) {
	comm_SendTo(SYSMSG,user,"This is not a valid parameter (required: time in sec)\r\n");
        return(-1);
    }
    mAdmin.defaultBannTime=myTime;
    snprintf (msgText,MAX_MSG_TEXT + 1,"The BannTime parameter has been set to: %d sec\r\n",mAdmin.defaultBannTime);
    *(msgText + MAX_MSG_TEXT) = '\0';
    comm_SendTo(SYSMSG,user,msgText);
    return(0);
}

int admin_SetIdleTime(int user, char *newTime) {
    int myTime;
    
    myTime=atoi(newTime);
    if ((myTime<0)||(myTime>86400)||newTime[0]<48||newTime[0]>57) {
	comm_SendTo(SYSMSG,user,"This is not a valid parameter (required: time in sec)\r\n");
        return(-1);
    }
    mAdmin.maxIdleTime=myTime;
    snprintf (msgText,MAX_MSG_TEXT + 1,"The maxIdleTime parameter has been set to: %d sec\r\n",mAdmin.maxIdleTime);
    *(msgText + MAX_MSG_TEXT) = '\0';
    comm_SendTo(SYSMSG,user,msgText);
    return(0);
}

int admin_SetUniqueNames(int user, char *param) {
    int myStat=SYSTEM;
    
    if (strcasecmp(param,"yes")==0) 
	myStat=YES;
    if (strcasecmp(param,"no")==0) 
	myStat=NO;
    if (myStat==SYSTEM) {
	comm_SendTo(SYSMSG,user,"Not a valid parameter (required: yes/no)\r\n");
        return(-1);
    }
    mAdmin.uniqueNames=myStat;
    snprintf (msgText,MAX_MSG_TEXT + 1,"The UNIQUE parameter has been set to: %d\r\n",myStat);
    *(msgText + MAX_MSG_TEXT) = '\0';
    comm_SendTo(SYSMSG,user,msgText);
    return(0);
}

int admin_SetChangeNames(int user, char *param) {
    int myStat=SYSTEM;
    
    if (strcasecmp(param,"yes")==0) 
	myStat=YES;
    if (strcasecmp(param,"no")==0) 
	myStat=NO;
    if (myStat==SYSTEM) {
	comm_SendTo(SYSMSG,user,"Not a valid parameter (required: yes/no)\r\n");
        return(-1);
    }
    mAdmin.changeNames=myStat;
    snprintf (msgText,MAX_MSG_TEXT + 1,"The CHANGENICKS parameter has been set to: %d\r\n",myStat);
    *(msgText + MAX_MSG_TEXT) = '\0';
    comm_SendTo(SYSMSG,user,msgText);
    return(0);
}

int admin_SetGuestLogin(int user, char *param) {
    int myStat=SYSTEM;
    
    if (strcasecmp(param,"yes")==0) 
	myStat=YES;
    if (strcasecmp(param,"no")==0) 
	myStat=NO;
    if (myStat==SYSTEM) {
	comm_SendTo(SYSMSG,user,"Not a valid parameter (required: yes/no)\r\n");
        return(-1);
    }
    mAdmin.guestLogin=myStat;
    snprintf (msgText,MAX_MSG_TEXT + 1,"The GUESTLOGIN parameter has been set to: %d\r\n",myStat);
    *(msgText + MAX_MSG_TEXT) = '\0';
    comm_SendTo(SYSMSG,user,msgText);
    return(0);
}

int admin_SetLogLevel(int user, char *newLevel) {
    int myLevel;
    
    myLevel=atoi(newLevel);
    if ((myLevel<0)||(myLevel>4)||newLevel[0]<48||newLevel[0]>57) {
	comm_SendTo(SYSMSG,user,"Not a valid LOGLEVEL parameter (required: 0,1,2,3,4)\r\n");
        return(-1);
    }
    mLogLevel=myLevel;
    snprintf (msgText,MAX_MSG_TEXT + 1,"The LOGLEVEL parameter has been set to: %d\r\n",mLogLevel);
    *(msgText + MAX_MSG_TEXT) = '\0';
    comm_SendTo(SYSMSG,user,msgText);
    return(0);
}

int admin_SetSysMsg(int user, char *newStat) {
    int myStat=SYSTEM;
    
    if (strcasecmp(newStat,"off")==0) 
	myStat=NO;
    if (strcasecmp(newStat,"on")==0) 
	myStat=YES;
    if (myStat==SYSTEM) {
	comm_SendTo(SYSMSG,user,"Not a valid parameter (required: on/off)\r\n");
        return(-1);
    }
    mAdmin.sysMsg=myStat;
    snprintf (msgText,MAX_MSG_TEXT + 1,"The SYSMSG parameter has been set to: %d\r\n",myStat);
    *(msgText + MAX_MSG_TEXT) = '\0';
    comm_SendTo(SYSMSG,user,msgText);
    return(0);
}

int admin_KickIdleUsers() {
    int i;
    time_t now;

    if (mAdmin.maxIdleTime==0)
	return(-1);

    now=time(NULL);
    for (i=0;i<maxClients;i++) {
	if ((mClient[i].online==YES)&&
	    (difftime(now,mClient[i].idle)>mAdmin.maxIdleTime)&&
	    (mAdmin.administrator!=i)) {
	    comm_SendTo(SYSMSG,i,MSG_IDLEKICKED);
	    chat_Logout(i,DEFAULT);
	}
    }
    return(0);
}

int admin_KickUser(int user,char *userToKick) {
    int myUser;
    
    myUser=util_GetUserId(user,userToKick);
    if (myUser==-1)
	return(-1);

    if (mClient[myUser].socket==0) {    
        comm_SendTo(SYSMSG,user,MSG_NOTINCHAT);
        return(-1);
    }
    if (myUser==user) {
        comm_SendTo(SYSMSG,user,MSG_KILLYS);
        return(-1);
    }
    comm_SendTo(SYSMSG,myUser,MSG_KICKEDOUT);
    snprintf(msgText,MAX_MSG_TEXT + 1,MSG_WASKICKED,mClient[myUser].name,myUser);
    *(msgText + MAX_MSG_TEXT) = '\0';
    comm_SendAllBut(SYSMSG,myUser,msgText);
    strncpy(infoText,msgText, MAX_INFO_TEXT + 1);
    *(infoText + MAX_INFO_TEXT) = '\0';
    util_WriteLog(2,infoText);
    snprintf(msgText,MAX_MSG_TEXT + 1,MSG_KICK,mClient[myUser].name,myUser);
    *(msgText + MAX_MSG_TEXT) = '\0';
    comm_SendTo(SYSMSG,user,msgText);
    if (mAdmin.securityType==ALLOW)
	admin_AddHostMask(user,mClient[myUser].host,DEFAULT);
    else
	admin_RemoveHostMask(user,mClient[myUser].host);
    chat_Logout(myUser,DEFAULT);
    sys_SendChannelUpdate(SYSTEM);
    sys_SendUserUpdate(mClient[user].channel,SYSTEM);
    sys_SendAllUserUpdate(SYSTEM);
    return(0);
}

void admin_ShutDown() {
    int i;
    
    for (i=0;i<maxClients;i++)
	if (mClient[i].socket!=0) {
	    comm_SendTo(SYSMSG,i,"The administrator shut down the server !\r\n");
	    sys_SendShutdownCommand(i);
	    close(mClient[i].socket);
	    mClient[i].socket = 0;
	    mClient[i].online = NO;
	}
    util_WriteLog(1,"The administrator shut down the server !\r\n");
}



void admin_Whois(int user) {
    int i;
    time_t now;
    
    now=time(NULL);
    comm_SendTo(SYSMSG,user,MSG_FINGERLST);
    comm_SendTo(SYSMSG,user,"----------------------------------------------------------------------\r\n");
    for (i=0;i<maxClients;i++)
	if (mClient[i].socket!=0) {
	    snprintf (msgText,MAX_MSG_TEXT + 1,"[%d]: %s (%s), CH: %d (%s), IDLE: %lu, GRP: %d, [",i, mClient[i].name,mClient[i].host,mClient[i].channel,mChannel[mClient[i].channel].name,(unsigned long)(now-mClient[i].idle),mClient[i].group);
	    *(msgText + MAX_MSG_TEXT) = '\0';
	    if ( (mChannel[mClient[i].channel].owner==i) && (strlen(msgText) < MAX_MSG_TEXT))
		strcat (msgText,"O");
	    if ( (mAdmin.administrator==i) && (strlen(msgText) < MAX_MSG_TEXT))
		strcat (msgText,"A");
	    if ( (mClient[i].online==NO) && (strlen(msgText) < MAX_MSG_TEXT))
	        strcat (msgText,"C");
	    if(strlen(msgText) < (MAX_MSG_TEXT - 3))    
	        strcat(msgText,"]\r\n");
	    comm_SendTo(SYSMSG,user,msgText);
	}
    comm_SendTo(SYSMSG,user,"----------------------------------------------------------------------\r\n");
}

void admin_ListChannels(int user) {
    int i;

    comm_SendTo(SYSMSG,user,MSG_CHANNELLST);
    comm_SendTo(SYSMSG,user,"----------------------------------------------------------------------\r\n");
    for (i=0;i<maxChannels;i++)
	if (mChannel[i].owner!=NOBODY) {
	    if (mChannel[i].locked==YES)
		snprintf (msgText,MAX_MSG_TEXT + 1,"Channel %3d (  %s  ), Owner: %3d, Group: %4d  [private]\r\n",i,mChannel[i].name,mChannel[i].owner,mChannel[i].group);
	    else
		snprintf (msgText,MAX_MSG_TEXT + 1,"Channel %3d (  %s  ), Owner: %3d, Group: %4d\r\n",i,mChannel[i].name,mChannel[i].owner,mChannel[i].group);
            *(msgText + MAX_MSG_TEXT) = '\0';		
	    comm_SendTo(SYSMSG,user,msgText);
	}
    comm_SendTo(SYSMSG,user,"----------------------------------------------------------------------\r\n");
}

int admin_ListGroups(int user, char *group) {
    int myGroup=-1;
    
    if (strlen(group)>0) {
	myGroup=atoi(group);
	if ((myGroup<0)||(myGroup>maxGroups)) {
	    admin_ListAllGroups(user);
	    return(0);
	}
	admin_ListGroup(user,myGroup);
	return(0);
    }
    admin_ListAllGroups(user);
    return(0);
}

void admin_ListAllGroups(int user) { 
    int i;
    
    comm_SendTo(SYSMSG,user,"Available Groups:\r\n");
    comm_SendTo(SYSMSG,user,"----------------------------------------------------------------------\r\n");
    for (i=0;i<maxGroups;i++)
	if (mGroup[i].passwd[0]!=0) {
	    snprintf (msgText,MAX_MSG_TEXT + 1,"Group: %3d, Password: %s\r\n",i,mGroup[i].passwd);
	    *(msgText + MAX_MSG_TEXT) = '\0';
	    comm_SendTo(SYSMSG,user,msgText);
	}
    comm_SendTo(SYSMSG,user,"----------------------------------------------------------------------\r\n");
}

int admin_ListGroup(int user, int group) { 
    int i;
    time_t now;
    
    if (mGroup[group].passwd[0]==0) {
	comm_SendTo(SYSMSG,user,"This group does not exist !\r\n");
	return(-1);
    }
    now=time(NULL);
    snprintf(msgText,MAX_MSG_TEXT + 1,"Group: %d (Password: %s):\r\n",group,mGroup[group].passwd);
    *(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].socket!=0)&&(mClient[i].group==group)) {
	    snprintf (msgText,MAX_MSG_TEXT + 1,"[%d]: %s (%s), CH: %d (%s), IDLE: %lu [",i, mClient[i].name,mClient[i].host,mClient[i].channel,mChannel[mClient[i].channel].name,(unsigned long)(now-mClient[i].idle));
	    *(msgText + MAX_MSG_TEXT) = '\0';
	    if ( (mChannel[mClient[i].channel].owner==i) && (strlen(msgText) < MAX_MSG_TEXT))
		strcat (msgText,"O");
	    if ( (mAdmin.administrator==i) && (strlen(msgText) < MAX_MSG_TEXT))
		strcat (msgText,"A");
	    if ( (mClient[i].online==NO) && (strlen(msgText) < MAX_MSG_TEXT))
	        strcat (msgText,"C");
	    if(strlen(msgText) < (MAX_MSG_TEXT - 3))
	          strcat(msgText,"]\r\n");
	    comm_SendTo(SYSMSG,user,msgText);
	}
    comm_SendTo(SYSMSG,user,"----------------------------------------------------------------------\r\n");
    return(0);
}

int admin_CreateGroup(int user, char *group, char *passwd) {
    int myGroup;

    if (user!=mAdmin.administrator) {
        comm_SendTo(SYSMSG,user,MSG_NOTADMIN);
        return(-1);
    }
    myGroup=atoi(group);
    if ((myGroup<0)||(myGroup>maxGroups)) {
	snprintf(msgText,MAX_MSG_TEXT + 1,MSG_GRPNOTEXIST,maxGroups);
	*(msgText + MAX_MSG_TEXT) = '\0';
	comm_SendTo(SYSMSG,user,msgText);
	return(-1);
    }
    if ((strlen(passwd)<1)||(strlen(passwd)>8)) {
	comm_SendTo(SYSMSG,user,"Password must be 1 - 8 characters long.\r\n");
	return(-1);
    }
    if ((strcasecmp(passwd,"del")==0)||
        (strcasecmp(passwd,"delete")==0)||
        (strcasecmp(passwd,"remove")==0)) {
	if (mGroup[myGroup].passwd[0]==0) {
	    comm_SendTo(SYSMSG,user,"This group doesn't exist.\r\n");
	    return(0);
	}
	mGroup[myGroup].passwd[0]=0;
        comm_SendTo(SYSMSG,user,"The group has been removed from the list.\r\n");
        return(0);
    }
    strncpy(mGroup[myGroup].passwd,passwd, MAX_GROUP_PASSWORD + 1);
    *(mGroup[myGroup].passwd + MAX_GROUP_PASSWORD) = '\0';
    comm_SendTo(SYSMSG,user,"The group has been created/changed.\r\n");
    return(0);
}

void admin_ShowServerStat(int user) {
    int i;
    
    if (mAdmin.activated==YES)
	snprintf(msgText,MAX_MSG_TEXT + 1,"--> Administrator Features: Enabled\r\n");
    else
    	snprintf(msgText,MAX_MSG_TEXT + 1,"--> Administrator Features: Disabled\r\n");
    *(msgText + MAX_MSG_TEXT) = '\0';	
    comm_SendTo(SYSMSG,user,msgText);

    if (mAdmin.sysMsg==YES)
	snprintf(msgText,MAX_MSG_TEXT + 1,"--> System Messages: On\r\n");
    else 
	snprintf(msgText,MAX_MSG_TEXT + 1,"--> System Messages: Off\r\n");
    *(msgText + MAX_MSG_TEXT) = '\0';	
    comm_SendTo(SYSMSG,user,msgText);

    if (mAdmin.allowUserChannels==YES)
	snprintf(msgText,MAX_MSG_TEXT + 1,"--> User Channels: Enabled\r\n");
    else 
	snprintf(msgText,MAX_MSG_TEXT + 1,"--> User Channels: Disabled\r\n");
    *(msgText + MAX_MSG_TEXT) = '\0';	
    comm_SendTo(SYSMSG,user,msgText);

    if (mAdmin.allowAnonymousChannel==YES)
	snprintf(msgText,MAX_MSG_TEXT + 1,"--> Anonymous Channel: Enabled\r\n");
    else
	snprintf(msgText,MAX_MSG_TEXT + 1,"--> Anonymous Channel: Disabled\r\n");
    *(msgText + MAX_MSG_TEXT) = '\0';	
    comm_SendTo(SYSMSG,user,msgText);

    if (mAdmin.uniqueNames==YES)
	snprintf(msgText,MAX_MSG_TEXT + 1,"--> Only unique nicknames allowed: Yes\r\n");
    else
	snprintf(msgText,MAX_MSG_TEXT + 1,"--> Only unique nicknames allowed: No\r\n");
    *(msgText + MAX_MSG_TEXT) = '\0';	
    comm_SendTo(SYSMSG,user,msgText);

    if (mAdmin.uniqueNames==YES)
	snprintf(msgText,MAX_MSG_TEXT + 1,"--> Guest login allowed: Yes\r\n");
    else
	snprintf(msgText,MAX_MSG_TEXT + 1,"--> Guest login allowed: No\r\n");
    *(msgText + MAX_MSG_TEXT) = '\0';	
    comm_SendTo(SYSMSG,user,msgText);

    if (mAdmin.changeNames==YES)
	snprintf(msgText,MAX_MSG_TEXT + 1,"--> Users are allowed to change their nicknames: Yes\r\n");
    else
	snprintf(msgText,MAX_MSG_TEXT + 1,"--> Users are allowed to change their nicknames: No\r\n");
    *(msgText + MAX_MSG_TEXT) = '\0';	
    comm_SendTo(SYSMSG,user,msgText);

    snprintf(msgText,MAX_MSG_TEXT + 1,"--> Default BannTime Setting [sec]: %d\r\n",mAdmin.defaultBannTime);
    *(msgText + MAX_MSG_TEXT) = '\0';
    comm_SendTo(SYSMSG,user,msgText);
    snprintf(msgText,MAX_MSG_TEXT + 1,"--> Max Idle Time [sec]: %d\r\n",mAdmin.maxIdleTime);
    *(msgText + MAX_MSG_TEXT) = '\0';
    comm_SendTo(SYSMSG,user,msgText);
    snprintf(msgText,MAX_MSG_TEXT + 1,"--> LogLevel: %d\r\n",mLogLevel);
    *(msgText + MAX_MSG_TEXT) = '\0';
    comm_SendTo(SYSMSG,user,msgText);
    snprintf(msgText,MAX_MSG_TEXT + 1,"--> ServerPort: %d\r\n",mServerPort);
    *(msgText + MAX_MSG_TEXT) = '\0';
    comm_SendTo(SYSMSG,user,msgText);
    if (logIsActive==YES)
	snprintf(msgText,MAX_MSG_TEXT + 1,"--> Logging activated, logfile: %s\r\n",logFileName);
    else
	snprintf(msgText,MAX_MSG_TEXT + 1,"--> Logging disabled\r\n");
    *(msgText + MAX_MSG_TEXT) = '\0';	
    comm_SendTo(SYSMSG,user,msgText);	
    if (mAdmin.securityType==ALLOW) {
	snprintf(msgText,MAX_MSG_TEXT + 1,"--> Default Security Policy: ALLOW ALL HOSTS\r\n");
	*(msgText + MAX_MSG_TEXT) = '\0';
        comm_SendTo(SYSMSG,user,msgText);    
	snprintf(msgText,MAX_MSG_TEXT + 1,"--> List of hosts NOT allowed to connect:\r\n");
	*(msgText + MAX_MSG_TEXT) = '\0';
    }
    else {
    	snprintf(msgText,MAX_MSG_TEXT + 1,"--> Default Security Policy: DENY ALL HOSTS\r\n");
    	*(msgText + MAX_MSG_TEXT) = '\0';
        comm_SendTo(SYSMSG,user,msgText);    
	snprintf(msgText,MAX_MSG_TEXT + 1,"--> List of hosts ALLOWED to connect:\r\n");
	*(msgText + MAX_MSG_TEXT) = '\0';
    }
    comm_SendTo(SYSMSG,user,msgText);    
    for (i=0;i<maxSecurityProfiles;i++) {
	if (mSecurity[i].hostmask[0]!=0) {
	    if ((mSecurity[i].banntime==0)&&(mAdmin.securityType==ALLOW))
		snprintf (msgText,MAX_MSG_TEXT + 1,"--> Mask #%d: (%s) [permanently]\r\n",i,mSecurity[i].hostmask);
	    else {
		if (mAdmin.securityType==ALLOW)
		    snprintf (msgText,MAX_MSG_TEXT + 1,"--> Mask #%d: (%s) [temporary]\r\n",i,mSecurity[i].hostmask);
		else
		    snprintf (msgText,MAX_MSG_TEXT + 1,"--> Mask #%d: (%s)\r\n",i,mSecurity[i].hostmask);	    		
	    }
            *(msgText + MAX_MSG_TEXT) = '\0'; 
	    comm_SendTo(SYSMSG,user,msgText);
	}
    }
}

void admin_Help(int user) {
    comm_SendTo(SYSMSG,user,MSG_HELP50);
    comm_SendTo(SYSMSG,user,MSG_HELP51);
    comm_SendTo(SYSMSG,user,MSG_HELP52);
    comm_SendTo(SYSMSG,user,MSG_HELP53);
    comm_SendTo(SYSMSG,user,MSG_HELP54);
    comm_SendTo(SYSMSG,user,MSG_HELP55);
    comm_SendTo(SYSMSG,user,MSG_HELP56);
    comm_SendTo(SYSMSG,user,MSG_HELP57);
    comm_SendTo(SYSMSG,user,MSG_HELP58);
    comm_SendTo(SYSMSG,user,MSG_HELP59);
    comm_SendTo(SYSMSG,user,MSG_HELP60);
    comm_SendTo(SYSMSG,user,MSG_HELP61);
    comm_SendTo(SYSMSG,user,MSG_HELP62);
    comm_SendTo(SYSMSG,user,MSG_HELP63);
    comm_SendTo(SYSMSG,user,MSG_HELP64);
    comm_SendTo(SYSMSG,user,MSG_HELP65);
    comm_SendTo(SYSMSG,user,MSG_HELP66);
    comm_SendTo(SYSMSG,user,MSG_HELP67);
    comm_SendTo(SYSMSG,user,MSG_HELP68);
    comm_SendTo(SYSMSG,user,MSG_HELP69);
    comm_SendTo(SYSMSG,user,MSG_HELP70);
    comm_SendTo(SYSMSG,user,MSG_HELP71);
    comm_SendTo(SYSMSG,user,MSG_HELP72);
    comm_SendTo(SYSMSG,user,MSG_HELP73);
}
